Subversion Repositories Kolibri OS

Rev

Rev 5565 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
586 serge 2
;;                                                              ;;
5565 serge 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;                                                              ;;
586 serge 7
;;  PCI32.INC                                                   ;;
8
;;                                                              ;;
9
;;  32 bit PCI driver code                                      ;;
10
;;                                                              ;;
11
;;  Version 0.3  April 9, 2007                                  ;;
12
;;  Version 0.2  December 21st, 2002                            ;;
13
;;                                                              ;;
14
;;  Author: Victor Prodan, victorprodan@yahoo.com               ;;
15
;;          Mihailov Ilia, ghost.nsk@gmail.com                  ;;
16
;;    Credits:                                                  ;;
17
;;          Ralf Brown                                          ;;
18
;;          Mike Hibbett, mikeh@oceanfree.net                   ;;
19
;;                                                              ;;
20
;;  See file COPYING for details                                ;;
21
;;                                                              ;;
431 serge 22
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 23
 
750 victor 24
$Revision: 5577 $
1 ha 25
 
26
;***************************************************************************
27
;   Function
28
;      pci_api:
29
;
30
;   Description
31
;       entry point for system PCI calls
32
;***************************************************************************
1603 art_zh 33
;mmio_pci_addr  equ  0x400               ; set actual PCI address here to activate user-MMIO
1 ha 34
 
1591 lrz 35
iglobal
36
align 4
37
f62call:
2434 Serge 38
        dd      pci_fn_0
39
        dd      pci_fn_1
40
        dd      pci_fn_2
41
        dd      pci_service_not_supported       ;3
42
        dd      pci_read_reg            ;4 byte
43
        dd      pci_read_reg            ;5 word
44
        dd      pci_read_reg            ;6 dword
45
        dd      pci_service_not_supported   ;7
46
        dd      pci_write_reg           ;8 byte
47
        dd      pci_write_reg           ;9 word
48
        dd      pci_write_reg           ;10 dword
1591 lrz 49
if defined mmio_pci_addr
2434 Serge 50
        dd      pci_mmio_init           ;11
51
        dd      pci_mmio_map            ;12
52
        dd      pci_mmio_unmap          ;13
1591 lrz 53
end if
1602 art_zh 54
 
1591 lrz 55
endg
1370 art_zh 56
 
1602 art_zh 57
align 4
1591 lrz 58
 
1 ha 59
pci_api:
60
 
1602 art_zh 61
;cross
2434 Serge 62
        mov     eax, ebx
63
        mov     ebx, ecx
64
        mov     ecx, edx
1602 art_zh 65
 
2434 Serge 66
        cmp     [pci_access_enabled], 1
67
        jne     pci_service_not_supported
1614 serge 68
 
2434 Serge 69
        movzx   edx, al
1614 serge 70
 
1591 lrz 71
if defined mmio_pci_addr
2434 Serge 72
        cmp     al, 13
73
        ja      pci_service_not_supported
1591 lrz 74
else
2434 Serge 75
        cmp     al, 10
76
        ja      pci_service_not_supported
1602 art_zh 77
end if
1603 art_zh 78
 
2434 Serge 79
        call    dword [f62call+edx*4]
80
        mov     dword [esp+32], eax
81
        ret
1629 serge 82
 
83
 
84
align 4
85
pci_api_drv:
86
 
2434 Serge 87
        cmp     [pci_access_enabled], 1
88
        jne     .fail
1629 serge 89
 
2434 Serge 90
        cmp     eax, 2
91
        ja      .fail
1629 serge 92
 
2434 Serge 93
        jmp     dword [f62call+eax*4]
1629 serge 94
 
95
.fail:
2434 Serge 96
        or      eax, -1
97
        ret
1629 serge 98
 
99
 
1602 art_zh 100
;; ============================================
1591 lrz 101
 
1602 art_zh 102
pci_fn_0:
103
; PCI function 0: get pci version (AH.AL)
3908 Serge 104
        movzx   eax, word [BOOT_VARS+0x9022]
2434 Serge 105
        ret
1 ha 106
 
1602 art_zh 107
pci_fn_1:
108
; PCI function 1: get last bus in AL
3908 Serge 109
        mov     al, [BOOT_VARS+0x9021]
2434 Serge 110
        ret
1 ha 111
 
1602 art_zh 112
pci_fn_2:
113
; PCI function 2: get pci access mechanism
3908 Serge 114
        mov     al, [BOOT_VARS+0x9020]
2434 Serge 115
        ret
1 ha 116
 
1602 art_zh 117
pci_service_not_supported:
2434 Serge 118
        or      eax, -1
119
        mov     dword [esp+32], eax
120
        ret
1 ha 121
 
122
;***************************************************************************
123
;   Function
124
;      pci_make_config_cmd
125
;
126
;   Description
127
;       creates a command dword  for use with the PCI bus
1602 art_zh 128
;       bus # in ah
129
;       device+func in bh (dddddfff)
130
;       register in bl
1 ha 131
;
1602 art_zh 132
;      command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 )
1 ha 133
;***************************************************************************
134
 
135
align 4
136
 
137
pci_make_config_cmd:
2434 Serge 138
        shl     eax, 8     ; move bus to bits 16-23
139
        mov     ax, bx     ; combine all
140
        and     eax, 0xffffff
141
        or      eax, 0x80000000
142
        ret
1 ha 143
 
144
;***************************************************************************
145
;   Function
146
;      pci_read_reg:
147
;
148
;   Description
149
;       read a register from the PCI config space into EAX/AX/AL
1602 art_zh 150
;       IN: ah=bus,device+func=bh,register address=bl
151
;           number of bytes to read (1,2,4) coded into AL, bits 0-1
586 serge 152
;           (0 - byte, 1 - word, 2 - dword)
1 ha 153
;***************************************************************************
154
 
155
align 4
156
 
157
pci_read_reg:
3500 Serge 158
        push    ebx esi
3908 Serge 159
        cmp     byte [BOOT_VARS+0x9020], 2;what mechanism will we use?
2434 Serge 160
        je      pci_read_reg_2
1 ha 161
 
2434 Serge 162
                ; mechanism 1
3500 Serge 163
        mov     esi, eax ; save register size into ESI
2434 Serge 164
        and     esi, 3
1 ha 165
 
2434 Serge 166
        call    pci_make_config_cmd
167
        mov     ebx, eax
168
        mov     dx, 0xcf8
169
        in      eax, dx
170
        push    eax
171
                ; set up addressing to config data
172
        mov     eax, ebx
173
        and     al, 0xfc; make address dword-aligned
174
        out     dx, eax
175
                ; get requested DWORD of config data
176
        mov     dl, 0xfc
177
        and     bl, 3
178
        or      dl, bl   ; add to port address first 2 bits of register address
1 ha 179
 
2434 Serge 180
        or      esi, esi
181
        jz      pci_read_byte1
182
        cmp     esi, 1
183
        jz      pci_read_word1
184
        cmp     esi, 2
185
        jz      pci_read_dword1
186
        jmp     pci_fin_read1
1 ha 187
 
1602 art_zh 188
pci_read_byte1:
2434 Serge 189
        in      al, dx
190
        jmp     pci_fin_read1
1602 art_zh 191
pci_read_word1:
2434 Serge 192
        in      ax, dx
193
        jmp     pci_fin_read1
1602 art_zh 194
pci_read_dword1:
2434 Serge 195
        in      eax, dx
196
        jmp     pci_fin_read1
1602 art_zh 197
pci_fin_read1:
2434 Serge 198
                ; restore configuration control
199
        xchg    eax, [esp]
200
        mov     dx, 0xcf8
201
        out     dx, eax
1 ha 202
 
2434 Serge 203
        pop     eax
3500 Serge 204
        pop     esi ebx
2434 Serge 205
        ret
1 ha 206
pci_read_reg_2:
207
 
2434 Serge 208
        test    bh, 128 ;mech#2 only supports 16 devices per bus
209
        jnz     pci_read_reg_err
1 ha 210
 
3500 Serge 211
        mov     esi, eax ; save register size into ESI
2434 Serge 212
        and     esi, 3
1 ha 213
 
2434 Serge 214
        push    eax
215
                ;store current state of config space
216
        mov     dx, 0xcf8
217
        in      al, dx
218
        mov     ah, al
219
        mov     dl, 0xfa
220
        in      al, dx
1 ha 221
 
2434 Serge 222
        xchg    eax, [esp]
223
                ; out 0xcfa,bus
224
        mov     al, ah
225
        out     dx, al
226
                ; out 0xcf8,0x80
227
        mov     dl, 0xf8
228
        mov     al, 0x80
229
        out     dx, al
230
                ; compute addr
231
        shr     bh, 3; func is ignored in mechanism 2
232
        or      bh, 0xc0
233
        mov     dx, bx
1 ha 234
 
2434 Serge 235
        or      esi, esi
236
        jz      pci_read_byte2
237
        cmp     esi, 1
238
        jz      pci_read_word2
239
        cmp     esi, 2
240
        jz      pci_read_dword2
241
        jmp     pci_fin_read2
1 ha 242
 
1602 art_zh 243
pci_read_byte2:
2434 Serge 244
        in      al, dx
245
        jmp     pci_fin_read2
1602 art_zh 246
pci_read_word2:
2434 Serge 247
        in      ax, dx
248
        jmp     pci_fin_read2
1602 art_zh 249
pci_read_dword2:
2434 Serge 250
        in      eax, dx
1 ha 251
;       jmp pci_fin_read2
1602 art_zh 252
pci_fin_read2:
1 ha 253
 
2434 Serge 254
                ; restore configuration space
255
        xchg    eax, [esp]
256
        mov     dx, 0xcfa
257
        out     dx, al
258
        mov     dl, 0xf8
259
        mov     al, ah
260
        out     dx, al
1 ha 261
 
2434 Serge 262
        pop     eax
3500 Serge 263
        pop     esi ebx
2434 Serge 264
        ret
1 ha 265
 
1602 art_zh 266
pci_read_reg_err:
2434 Serge 267
        xor     eax, eax
268
        dec     eax
3500 Serge 269
        pop     esi ebx
2434 Serge 270
        ret
1 ha 271
 
272
 
273
;***************************************************************************
274
;   Function
275
;      pci_write_reg:
276
;
277
;   Description
278
;       write a register from ECX/CX/CL into the PCI config space
1602 art_zh 279
;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
280
;           value to write in ecx
281
;           number of bytes to write (1,2,4) coded into AL, bits 0-1
586 serge 282
;           (0 - byte, 1 - word, 2 - dword)
1 ha 283
;***************************************************************************
284
 
285
align 4
286
 
287
pci_write_reg:
3500 Serge 288
        push    esi ebx
3908 Serge 289
        cmp     byte [BOOT_VARS+0x9020], 2;what mechanism will we use?
2434 Serge 290
        je      pci_write_reg_2
1 ha 291
 
2434 Serge 292
                ; mechanism 1
3500 Serge 293
        mov     esi, eax ; save register size into ESI
2434 Serge 294
        and     esi, 3
1 ha 295
 
2434 Serge 296
        call    pci_make_config_cmd
297
        mov     ebx, eax
298
                ; get current state into ecx
299
        mov     dx, 0xcf8
300
        in      eax, dx
301
        push    eax
302
                ; set up addressing to config data
303
        mov     eax, ebx
304
        and     al, 0xfc; make address dword-aligned
305
        out     dx, eax
306
                ; write DWORD of config data
307
        mov     dl, 0xfc
308
        and     bl, 3
309
        or      dl, bl
310
        mov     eax, ecx
1 ha 311
 
2434 Serge 312
        or      esi, esi
313
        jz      pci_write_byte1
314
        cmp     esi, 1
315
        jz      pci_write_word1
316
        cmp     esi, 2
317
        jz      pci_write_dword1
318
        jmp     pci_fin_write1
1602 art_zh 319
 
320
pci_write_byte1:
2434 Serge 321
        out     dx, al
322
        jmp     pci_fin_write1
1602 art_zh 323
pci_write_word1:
2434 Serge 324
        out     dx, ax
325
        jmp     pci_fin_write1
1602 art_zh 326
pci_write_dword1:
2434 Serge 327
        out     dx, eax
328
        jmp     pci_fin_write1
1602 art_zh 329
pci_fin_write1:
1 ha 330
 
2434 Serge 331
                ; restore configuration control
332
        pop     eax
333
        mov     dl, 0xf8
334
        out     dx, eax
1 ha 335
 
2434 Serge 336
        xor     eax, eax
3500 Serge 337
        pop     ebx esi
1602 art_zh 338
 
2434 Serge 339
        ret
1 ha 340
pci_write_reg_2:
341
 
2434 Serge 342
        test    bh, 128 ;mech#2 only supports 16 devices per bus
343
        jnz     pci_write_reg_err
1 ha 344
 
345
 
3500 Serge 346
        mov     esi, eax ; save register size into ESI
2434 Serge 347
        and     esi, 3
1 ha 348
 
2434 Serge 349
        push    eax
350
                ;store current state of config space
351
        mov     dx, 0xcf8
352
        in      al, dx
353
        mov     ah, al
354
        mov     dl, 0xfa
355
        in      al, dx
356
        xchg    eax, [esp]
357
                ; out 0xcfa,bus
358
        mov     al, ah
359
        out     dx, al
360
                ; out 0xcf8,0x80
361
        mov     dl, 0xf8
362
        mov     al, 0x80
363
        out     dx, al
364
                ; compute addr
365
        shr     bh, 3; func is ignored in mechanism 2
366
        or      bh, 0xc0
367
        mov     dx, bx
368
                ; write register
369
        mov     eax, ecx
1 ha 370
 
2434 Serge 371
        or      esi, esi
372
        jz      pci_write_byte2
373
        cmp     esi, 1
374
        jz      pci_write_word2
375
        cmp     esi, 2
376
        jz      pci_write_dword2
377
        jmp     pci_fin_write2
1602 art_zh 378
 
379
pci_write_byte2:
2434 Serge 380
        out     dx, al
381
        jmp     pci_fin_write2
1602 art_zh 382
pci_write_word2:
2434 Serge 383
        out     dx, ax
384
        jmp     pci_fin_write2
1602 art_zh 385
pci_write_dword2:
2434 Serge 386
        out     dx, eax
387
        jmp     pci_fin_write2
1602 art_zh 388
pci_fin_write2:
2434 Serge 389
                ; restore configuration space
390
        pop     eax
391
        mov     dx, 0xcfa
392
        out     dx, al
393
        mov     dl, 0xf8
394
        mov     al, ah
395
        out     dx, al
1 ha 396
 
2434 Serge 397
        xor     eax, eax
3500 Serge 398
        pop     ebx esi
2434 Serge 399
        ret
1 ha 400
 
1602 art_zh 401
pci_write_reg_err:
2434 Serge 402
        xor     eax, eax
403
        dec     eax
3500 Serge 404
        pop     ebx esi
2434 Serge 405
        ret
586 serge 406
 
2434 Serge 407
if defined mmio_pci_addr        ; must be set above
1348 art_zh 408
;***************************************************************************
409
;   Function
1603 art_zh 410
;      pci_mmio_init
1348 art_zh 411
;
412
;   Description
1602 art_zh 413
;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
1358 art_zh 414
;   Returns  eax = user heap space available (bytes)
1348 art_zh 415
;   Error codes
416
;       eax = -1 : PCI user access blocked,
417
;       eax = -2 : device not registered for uMMIO service
418
;       eax = -3 : user heap initialization failure
419
;***************************************************************************
420
pci_mmio_init:
2434 Serge 421
        cmp     bx, mmio_pci_addr
422
        jz      @f
423
        mov     eax, -2
424
        ret
1348 art_zh 425
@@:
2434 Serge 426
        call    init_heap  ; (if not initialized yet)
427
        or      eax, eax
428
        jz      @f
429
        ret
1348 art_zh 430
@@:
2434 Serge 431
        mov     eax, -3
432
        ret
1348 art_zh 433
 
434
 
435
;***************************************************************************
436
;   Function
1603 art_zh 437
;      pci_mmio_map
1348 art_zh 438
;
439
;   Description
440
;       maps a block of PCI memory to user-accessible linear address
441
;
442
;       WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
443
;       The target device address should be set in kernel var mmio_pci_addr
444
;
1602 art_zh 445
;       IN:  ah = BAR#;
446
;       IN: ebx = block size (bytes);
447
;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
1348 art_zh 448
;
449
;   Returns eax = MMIO block's linear address in the userspace (if no error)
450
;
451
;
452
;   Error codes
453
;       eax = -1 : user access to PCI blocked,
454
;       eax = -2 : an invalid BAR register referred
455
;       eax = -3 : no i/o space on that BAR
456
;       eax = -4 : a port i/o BAR register referred
457
;       eax = -5 : dynamic userspace allocation problem
458
;***************************************************************************
459
 
460
pci_mmio_map:
2434 Serge 461
        and     edx, 0x0ffff
462
        cmp     ah, 6
463
        jc      .bar_0_5
464
        jz      .bar_rom
465
        mov     eax, -2
466
        ret
1353 art_zh 467
.bar_rom:
2434 Serge 468
        mov     ah, 8   ; bar6 = Expansion ROM base address
1353 art_zh 469
.bar_0_5:
2434 Serge 470
        push    ecx
471
        add     ebx, 4095
472
        and     ebx, -4096
473
        push    ebx
474
        mov     bl, ah  ; bl = BAR# (0..5), however bl=8 for BAR6
475
        shl     bl, 1
476
        shl     bl, 1
477
        add     bl, 0x10; now bl = BAR offset in PCI config. space
478
        mov     ax, mmio_pci_addr
479
        mov     bh, al  ; bh = dddddfff
480
        mov     al, 2   ; al : DW to read
481
        call    pci_read_reg
482
        or      eax, eax
483
        jnz     @f
484
        mov     eax, -3 ; empty I/O space
485
        jmp     mmio_ret_fail
1348 art_zh 486
@@:
2434 Serge 487
        test    eax, 1
488
        jz      @f
489
        mov     eax, -4 ; damned ports (not MMIO space)
490
        jmp     mmio_ret_fail
1348 art_zh 491
@@:
2434 Serge 492
        pop     ecx     ; ecx = block size, bytes (expanded to whole page)
493
        mov     ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx
494
        and     eax, 0xFFFFFFF0
495
        push    eax           ; store MMIO physical address + keep 2DWords in the stack
496
        stdcall user_alloc, ecx
497
        or      eax, eax
498
        jnz     mmio_map_over
499
        mov     eax, -5 ; problem with page allocation
1348 art_zh 500
 
501
mmio_ret_fail:
2434 Serge 502
        pop     ecx
503
        pop     edx
504
        ret
1348 art_zh 505
 
506
mmio_map_over:
2434 Serge 507
        mov     ecx, ebx; ecx = size (bytes, expanded to whole page)
508
        shr     ecx, 12 ; ecx = number of pages
509
        mov     ebx, eax; ebx = linear address
510
        pop     eax     ; eax = MMIO start
511
        pop     edx     ; edx = MMIO shift (pages)
512
        shl     edx, 12 ; edx = MMIO shift (bytes)
513
        add     eax, edx; eax = uMMIO physical address
514
        or      eax, PG_SHARED
515
        or      eax, PG_UW
516
        or      eax, PG_NOCACHE
517
        mov     edi, ebx
518
        call    commit_pages
519
        mov     eax, edi
520
        ret
1348 art_zh 521
 
522
;***************************************************************************
523
;   Function
1603 art_zh 524
;      pci_mmio_unmap_page
1348 art_zh 525
;
526
;   Description
527
;       unmaps the linear space previously tied to a PCI memory block
528
;
529
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
530
;       returns eax = 1 if successfully unmapped
531
;
532
;   Error codes
533
;       eax = -1 if no user PCI access allowed,
534
;       eax =  0 if unmapping failed
535
;***************************************************************************
536
 
537
pci_mmio_unmap:
2434 Serge 538
        stdcall user_free, ebx
539
        ret
1348 art_zh 540
 
1354 diamond 541
end if
1348 art_zh 542
 
586 serge 543
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1375 Lrz 544
uglobal
545
align 4
586 serge 546
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
2434 Serge 547
pci_emu_dat:
548
                times   30*10 db 0
1375 Lrz 549
endg
586 serge 550
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
551
align 4
552
sys_pcibios:
2434 Serge 553
        cmp     [pci_access_enabled], 1
554
        jne     .unsupported_func
555
        cmp     [pci_bios_entry], 0
556
        jz      .emulate_bios
586 serge 557
 
2434 Serge 558
        push    ds
559
        mov     ax, pci_data_sel
560
        mov     ds, ax
561
        mov     eax, ebp
562
        mov     ah, 0B1h
563
        call    pword [cs:pci_bios_entry]
564
        pop     ds
586 serge 565
 
2434 Serge 566
        jmp     .return
567
        ;-=-=-=-=-=-=-=-=
586 serge 568
.emulate_bios:
2434 Serge 569
        cmp     ebp, 1                  ; PCI_FUNCTION_ID
570
        jnz     .not_PCI_BIOS_PRESENT
571
        mov     edx, 'PCI '
3908 Serge 572
        mov     al, [BOOT_VARS + 0x9020]
573
        mov     bx, [BOOT_VARS + 0x9022]
574
        mov     cl, [BOOT_VARS + 0x9021]
2434 Serge 575
        xor     ah, ah
576
        jmp     .return_abcd
586 serge 577
 
578
.not_PCI_BIOS_PRESENT:
2434 Serge 579
        cmp     ebp, 2                  ; FIND_PCI_DEVICE
580
        jne     .not_FIND_PCI_DEVICE
581
        mov     ebx, pci_emu_dat
582
..nxt:
583
        cmp     [ebx], dx
584
        jne     ..no
585
        cmp     [ebx + 2], cx
586
        jne     ..no
587
        dec     si
588
        jns     ..no
589
        mov     bx, [ebx + 4]
590
        xor     ah, ah
591
        jmp     .return_ab
592
..no:
593
        cmp     word[ebx], 0
594
        je      ..dev_not_found
595
        add     ebx, 10
596
        jmp     ..nxt
586 serge 597
..dev_not_found:
2434 Serge 598
        mov     ah, 0x86                ; DEVICE_NOT_FOUND
599
        jmp     .return_a
586 serge 600
 
601
.not_FIND_PCI_DEVICE:
2434 Serge 602
        cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
603
        jne     .not_FIND_PCI_CLASS_CODE
604
        mov     esi, pci_emu_dat
605
        shl     ecx, 8
606
..nxt2:
607
        cmp     [esi], ecx
608
        jne     ..no2
609
        mov     bx, [esi]
610
        xor     ah, ah
611
        jmp     .return_ab
612
..no2:
613
        cmp     dword[esi], 0
614
        je      ..dev_not_found
615
        add     esi, 10
616
        jmp     ..nxt2
586 serge 617
 
618
.not_FIND_PCI_CLASS_CODE:
2434 Serge 619
        cmp     ebp, 8                  ; READ_CONFIG_*
620
        jb      .not_READ_CONFIG
621
        cmp     ebp, 0x0A
622
        ja      .not_READ_CONFIG
623
        mov     eax, ebp
624
        mov     ah, bh
625
        mov     edx, edi
626
        mov     bh, bl
627
        mov     bl, dl
628
        call    pci_read_reg
629
        mov     ecx, eax
630
        xor     ah, ah                  ; SUCCESSFUL
631
        jmp     .return_abc
586 serge 632
.not_READ_CONFIG:
2434 Serge 633
        cmp     ebp, 0x0B               ; WRITE_CONFIG_*
634
        jb      .not_WRITE_CONFIG
635
        cmp     ebp, 0x0D
636
        ja      .not_WRITE_CONFIG
637
        lea     eax, [ebp+1]
638
        mov     ah, bh
639
        mov     edx, edi
640
        mov     bh, bl
641
        mov     bl, dl
642
        call    pci_write_reg
643
        xor     ah, ah                  ; SUCCESSFUL
644
        jmp     .return_abc
586 serge 645
.not_WRITE_CONFIG:
646
.unsupported_func:
2434 Serge 647
        mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
648
.return:
649
        mov     dword[esp + 4 ], edi
650
        mov     dword[esp + 8], esi
594 diamond 651
.return_abcd:
2434 Serge 652
        mov     dword[esp + 24], edx
594 diamond 653
.return_abc:
2434 Serge 654
        mov     dword[esp + 28], ecx
594 diamond 655
.return_ab:
2434 Serge 656
        mov     dword[esp + 20], ebx
594 diamond 657
.return_a:
2434 Serge 658
        mov     dword[esp + 32], eax
659
        ret
3500 Serge 660
 
3908 Serge 661
PCI_VENDOR_ID           equ 0x00
662
PCI_CLASS_REVISION      equ 0x08
663
PCI_HEADER_TYPE         equ 0x0E
664
PCI_SUBSYSTEM_VENDOR_ID equ 0x2c
665
PCI_IRQ_LINE            equ 0x3C
666
 
3500 Serge 667
proc pci_enum
668
        push    ebp
669
        mov     ebp, esp
670
        push    0
671
virtual at ebp-4
672
.devfn          db      ?
673
.bus            db      ?
674
end virtual
675
.loop:
676
        mov     ah, [.bus]
677
        mov     al, 2
678
        mov     bh, [.devfn]
3908 Serge 679
        mov     bl, PCI_VENDOR_ID
3500 Serge 680
        call    pci_read_reg
681
        cmp     eax, 0xFFFFFFFF
682
        jnz     .has_device
683
        test    byte [.devfn], 7
684
        jnz     .next_func
685
        jmp     .no_device
686
.has_device:
687
        push    eax
3626 Serge 688
        movi    eax, sizeof.PCIDEV
3500 Serge 689
        call    malloc
690
        pop     ecx
691
        test    eax, eax
692
        jz      .nomemory
693
        mov     edi, eax
5577 serge 694
        mov     [edi+PCIDEV.vendor_device_id], ecx
3908 Serge 695
        mov     edx, pcidev_list
696
        list_add_tail edi, edx
3500 Serge 697
        mov     eax, dword [.devfn]
698
        mov     word [edi+PCIDEV.devfn], ax
699
        mov     bh, al
700
        mov     al, 2
3908 Serge 701
        mov     bl, PCI_CLASS_REVISION
3500 Serge 702
        call    pci_read_reg
3908 Serge 703
        shr     eax, 8                                ;FIXME use byte mask
3500 Serge 704
        mov     [edi+PCIDEV.class], eax
3908 Serge 705
 
5577 serge 706
;        mov     ah, [.bus]
707
;        mov     bh, byte [.devfn]
708
;        mov     al, 2
709
;        mov     bl, PCI_SUBSYSTEM_VENDOR_ID
710
;        call    pci_read_reg
711
;        mov     [edi+PCIDEV.svid_sdid], eax
3908 Serge 712
 
5577 serge 713
;        mov     ah, [.bus]
714
;        mov     al, 0
715
;        mov     bh, [.devfn]
716
;        mov     bl, PCI_IRQ_LINE
717
;        call    pci_read_reg
718
;        mov     [edi+PCIDEV.irq_line], al
3908 Serge 719
 
3500 Serge 720
        test    byte [.devfn], 7
721
        jnz     .next_func
722
        mov     ah, [.bus]
723
        mov     al, 0
724
        mov     bh, [.devfn]
3908 Serge 725
        mov     bl, PCI_HEADER_TYPE
3500 Serge 726
        call    pci_read_reg
727
        test    al, al
728
        js      .next_func
729
.no_device:
730
        or      byte [.devfn], 7
731
.next_func:
732
        inc     dword [.devfn]
733
        mov     ah, [.bus]
3908 Serge 734
        cmp     ah, [BOOT_VARS+0x9021]
3500 Serge 735
        jbe     .loop
736
.nomemory:
737
        leave
738
        ret
739
endp
3908 Serge 740
 
5577 serge 741
; Export for drivers. Just returns the pointer to the pci-devices list.
742
proc get_pcidev_list
743
        mov     eax, pcidev_list
744
        ret
745
endp
3908 Serge 746
 
747
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
748
 
749
;internal functions
750
;ecx (bus << 8)|devfn
751
;edx register
752
 
753
align 4
754
pci_bus:
755
.conf1_index:
756
; dword CF8 = (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) | (devfn << 8) | (reg & 0xFC))
757
				push	edx
758
				mov		eax, edx                	; eax = reg
759
				shl		eax, 16                 	; eax = reg << 16
760
				shl   ecx, 8                  	; ecx = (bus << 16)|(devfn<<8)
761
				mov		al, dl                  	; eax = (reg << 16)|reg
762
				and		eax, 0x0F0000FC           ; eax = ((reg & 0xF00) << 16)|(reg & 0xFC)
763
				lea		eax, [0x80000000+eax+ecx]
764
				mov 	dx, 0xCF8
765
				out		dx, eax
766
				pop		edx
767
				xor		eax, eax
768
				ret
769
 
770
align 4
771
.conf2_index:
772
; byte CF8 = 0xF0 | (fn << 1)
773
; byte CFA = bus
774
				push	edx
775
				mov		eax, ecx                ; (bus << 8)|devfn
776
				and		al, 7            				; fn
777
				lea		eax, [0xF0+eax+eax]
778
				mov 	dx, 0xCF8
779
				out		dx, al
780
				mov		al, ch                  ; bus
781
				mov		dx, 0xCFA
782
				out   dx, al
783
				pop		edx
784
				xor		eax, eax
785
				ret
786
 
787
align 4
788
.conf1_read8:
789
				call  .conf1_index
790
				and 	dx, 3
791
				add		dx, 0xCFC
792
				in		al, dx
793
				ret
794
 
795
align 4
796
.conf1_read16:
797
				call  .conf1_index
798
				and 	dx, 2
799
				add		dx, 0xCFC
800
				in		ax, dx
801
				ret
802
 
803
align 4
804
.conf1_read32:
805
				call  .conf1_index
806
				mov  	dx, 0xCFC
807
				in		eax, dx
808
				ret
809
 
810
align 4
811
.conf1_write8:
812
				call  .conf1_index
813
				mov		eax, [esp+4]
814
				and 	dx, 3
815
				add		dx, 0xCFC
816
				out		dx, al
817
				ret   4
818
 
819
align 4
820
.conf1_write16:
821
				call  .conf1_index
822
				mov		eax, [esp+4]
823
				and 	dx, 2
824
				add		dx, 0xCFC
825
				out		dx, ax
826
				ret   4
827
 
828
align 4
829
.conf1_write32:
830
				call  .conf1_index
831
				mov		eax, [esp+4]
832
				mov		dx, 0xCFC
833
				out   dx, eax
834
				ret   4
835
 
836
align 4
837
.conf2_read8:
838
; in (0xC000 | (dev << 8) | reg)
839
				call  .conf2_index
840
				and		ecx, 0xF1               ;ecx = dev << 3
841
				shl		ecx, 5                  ;ecx = dev << 8
842
				lea   edx, [0xC000+edx+ecx]
843
				in		al, dx
844
				ret
845
 
846
align 4
847
.conf2_read16:
848
				call  .conf2_index
849
				and		ecx, 0xF1
850
				shl		ecx, 5
851
				lea   edx, [0xC000+edx+ecx]
852
				in		ax, dx
853
				ret
854
 
855
align 4
856
.conf2_read32:
857
				call  .conf2_index
858
				and		ecx, 0xF1
859
				shl		ecx, 5
860
				lea   edx, [0xC000+edx+ecx]
861
				in		eax, dx
862
				ret
863
 
864
 
865
PCI_R8	equ 0
866
PCI_R16	equ 4
867
PCI_R32 equ 8
868
 
869
PCI_W8	equ 12
870
PCI_W16	equ 16
871
PCI_W32 equ 20
872
 
873
 
874
align 4
3910 Serge 875
pci_conf1_rw:
876
;internal function
877
;eax accessor
878
;ecx (bus << 8)|devfn
3908 Serge 879
 
3910 Serge 880
.val      equ esp+4
881
 
882
; dword CF8 = (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) | (devfn << 8) | (reg & 0xFC))
883
 
884
				pushfd
885
				cli
886
 
887
				push  edx
888
				push  eax
889
				mov		eax, edx                	; eax = reg
890
				shl		eax, 16                 	; eax = reg << 16
891
				shl   ecx, 8                  	; ecx = (bus << 16)|(devfn<<8)
892
				mov		al, dl                  	; eax = (reg << 16)|reg
893
				and		eax, 0x0F0000FC           ; eax = ((reg & 0xF00) << 16)|(reg & 0xFC)
894
				lea		eax, [0x80000000+eax+ecx]
895
				mov 	dx, 0xCF8
896
				out		dx, eax
897
				pop		eax
898
				pop   edx
899
				jmp   dword [.fntab+eax]
900
.r32:
901
				mov  	dx, 0xCFC
902
				in		eax, dx
903
.rdone:
904
				popfd
905
				ret
906
.r16:
907
				and 	dx, 2
908
				add		dx, 0xCFC
909
				in		al, dx
910
				jmp   .rdone
911
.r8:
912
				and 	dx, 3
913
				add		dx, 0xCFC
914
				in		al, dx
915
				jmp   .rdone
916
.w32:
917
				mov		eax, [esp+8]
918
				mov		dx, 0xCFC
919
				out   dx, eax
920
.wdone:
921
				popfd
922
				ret   4
923
.w16:
924
				mov		eax, [esp+8]
925
				and 	dx, 2
926
				add		dx, 0xCFC
927
				out		dx, ax
928
				jmp   .wdone
929
.w8:
930
				mov		eax, [esp+8]
931
				and 	dx, 3
932
				add		dx, 0xCFC
933
				out		dx, al
934
				jmp   .wdone
935
 
3908 Serge 936
align 4
3910 Serge 937
.fntab:
938
				dd .r8
939
				dd .r16
940
				dd .r32
941
				dd .w8
942
				dd .w16
943
				dd .w32
944
 
945
align 4
946
pci_fn_rw	dd pci_conf1_rw
947
 
948
;proc pci_bus_read8   fastcall, busaddr:dword, reg:dword
949
;proc pci_bus_read16  fastcall, busaddr:dword, reg:dword
950
;proc pci_bus_read32  fastcall, busaddr:dword, reg:dword
951
 
952
align 4
953
pci_bus_read8:
954
				xor	eax, eax
955
				jmp	dword [pci_fn_rw]
956
 
957
align 4
958
pci_bus_read16:
3908 Serge 959
				mov		eax, PCI_R16
3910 Serge 960
				jmp	dword [pci_fn_rw]
3908 Serge 961
 
962
align 4
3910 Serge 963
pci_bus_read32:
3908 Serge 964
				mov		eax, PCI_R32
3910 Serge 965
				jmp	dword [pci_fn_rw]
3908 Serge 966
 
3910 Serge 967
;proc pci_bus_write8  fastcall, busaddr:dword, reg:dword, val: dword
968
;proc pci_bus_write16 fastcall, busaddr:dword, reg:dword, val: dword
969
;proc pci_bus_write32 fastcall, busaddr:dword, reg:dword, val: dword
970
 
3908 Serge 971
align 4
3910 Serge 972
pci_bus_write8:
973
				mov	  eax, PCI_W8
974
				jmp	dword [pci_fn_rw]
975
 
976
align 4
977
pci_bus_write16:
978
				mov		eax, PCI_W16
979
				jmp	dword [pci_fn_rw]
980
 
981
align 4
982
pci_bus_write32:
983
				mov		eax, PCI_W32
984
				jmp	dword [pci_fn_rw]
985
 
986
;deprecated proc pci_read8   stdcall, bus:dword, devfn:dword, reg:dword
987
;deprecated proc pci_read16  stdcall, bus:dword, devfn:dword, reg:dword
988
;deprecated proc pci_read32  stdcall, bus:dword, devfn:dword, reg:dword
989
 
990
align 4
991
pci_read8:
3908 Serge 992
.bus			equ esp+4
993
.devfn 		equ esp+8
994
.pci_reg 	equ esp+12
3910 Serge 995
.val      equ esp+16
3908 Serge 996
 
3910 Serge 997
				movzx ecx, byte [.devfn]
3908 Serge 998
				mov   ch, [.bus]
999
				movzx edx, word [.pci_reg]
3910 Serge 1000
				call	pci_bus_read8
1001
				ret 	12
3908 Serge 1002
 
3910 Serge 1003
align 4
1004
pci_read16:
1005
.bus			equ esp+4
1006
.devfn 		equ esp+8
1007
.pci_reg 	equ esp+12
1008
.val      equ esp+16
3908 Serge 1009
 
3910 Serge 1010
				movzx ecx, byte [.devfn]
1011
				mov   ch, [.bus]
1012
				movzx edx, word [.pci_reg]
1013
				call	pci_bus_read16
1014
				ret 	12
3908 Serge 1015
 
3910 Serge 1016
align 4
1017
pci_read32:
1018
.bus			equ esp+4
1019
.devfn 		equ esp+8
1020
.pci_reg 	equ esp+12
1021
.val      equ esp+16
3908 Serge 1022
 
3910 Serge 1023
				movzx ecx, byte [.devfn]
1024
				mov   ch, [.bus]
1025
				movzx edx, word [.pci_reg]
1026
				call	pci_bus_read32
3908 Serge 1027
				ret 	12
1028
 
3910 Serge 1029
;deprecated proc pci_write8  stdcall, bus:dword, devfn:dword, reg:dword, val:dword
1030
;deprecated proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
1031
;deprecated proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
1032
 
3908 Serge 1033
align 4
1034
pci_write8:
3910 Serge 1035
.bus			equ esp+4
1036
.devfn 		equ esp+8
1037
.pci_reg 	equ esp+12
1038
.val      equ esp+16
3908 Serge 1039
 
3910 Serge 1040
				movzx ecx, byte [.devfn]
1041
				mov   ch, [.bus]
1042
				movzx edx, word [.pci_reg]
1043
				push	dword [esp+16]
1044
				call	pci_bus_write8
1045
				ret 	16
1046
 
3908 Serge 1047
align 4
1048
pci_write16:
3910 Serge 1049
.bus			equ esp+4
1050
.devfn 		equ esp+8
1051
.pci_reg 	equ esp+12
1052
.val      equ esp+16
3908 Serge 1053
 
3910 Serge 1054
				movzx ecx, byte [.devfn]
1055
				mov   ch, [.bus]
1056
				movzx edx, word [.pci_reg]
1057
				push	dword [esp+16]
1058
				call	pci_bus_write16
1059
				ret 	16
1060
 
3908 Serge 1061
align 4
1062
pci_write32:
1063
.bus			equ esp+4
1064
.devfn 		equ esp+8
1065
.pci_reg 	equ esp+12
1066
.val      equ esp+16
1067
 
3910 Serge 1068
				movzx ecx, byte [.devfn]
3908 Serge 1069
				mov   ch, [.bus]
1070
				movzx edx, word [.pci_reg]
3910 Serge 1071
				push	dword [esp+16]
1072
				call	pci_bus_write32
1073
				ret 	16
3908 Serge 1074
 
1075
 
1076