Subversion Repositories Kolibri OS

Rev

Rev 2465 | Rev 3626 | 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
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2011. 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: 3500 $
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)
2434 Serge 104
        movzx   eax, word [BOOT_VAR+0x9022]
105
        ret
1 ha 106
 
1602 art_zh 107
pci_fn_1:
108
; PCI function 1: get last bus in AL
2434 Serge 109
        mov     al, [BOOT_VAR+0x9021]
110
        ret
1 ha 111
 
1602 art_zh 112
pci_fn_2:
113
; PCI function 2: get pci access mechanism
2434 Serge 114
        mov     al, [BOOT_VAR+0x9020]
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
2434 Serge 159
        cmp     byte [BOOT_VAR+0x9020], 2;what mechanism will we use?
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
                ; get current state
169
        mov     dx, 0xcf8
170
        in      eax, dx
171
        push    eax
172
                ; set up addressing to config data
173
        mov     eax, ebx
174
        and     al, 0xfc; make address dword-aligned
175
        out     dx, eax
176
                ; get requested DWORD of config data
177
        mov     dl, 0xfc
178
        and     bl, 3
179
        or      dl, bl   ; add to port address first 2 bits of register address
1 ha 180
 
2434 Serge 181
        or      esi, esi
182
        jz      pci_read_byte1
183
        cmp     esi, 1
184
        jz      pci_read_word1
185
        cmp     esi, 2
186
        jz      pci_read_dword1
187
        jmp     pci_fin_read1
1 ha 188
 
1602 art_zh 189
pci_read_byte1:
2434 Serge 190
        in      al, dx
191
        jmp     pci_fin_read1
1602 art_zh 192
pci_read_word1:
2434 Serge 193
        in      ax, dx
194
        jmp     pci_fin_read1
1602 art_zh 195
pci_read_dword1:
2434 Serge 196
        in      eax, dx
197
        jmp     pci_fin_read1
1602 art_zh 198
pci_fin_read1:
2434 Serge 199
                ; restore configuration control
200
        xchg    eax, [esp]
201
        mov     dx, 0xcf8
202
        out     dx, eax
1 ha 203
 
2434 Serge 204
        pop     eax
3500 Serge 205
        pop     esi ebx
2434 Serge 206
        ret
1 ha 207
pci_read_reg_2:
208
 
2434 Serge 209
        test    bh, 128 ;mech#2 only supports 16 devices per bus
210
        jnz     pci_read_reg_err
1 ha 211
 
3500 Serge 212
        mov     esi, eax ; save register size into ESI
2434 Serge 213
        and     esi, 3
1 ha 214
 
2434 Serge 215
        push    eax
216
                ;store current state of config space
217
        mov     dx, 0xcf8
218
        in      al, dx
219
        mov     ah, al
220
        mov     dl, 0xfa
221
        in      al, dx
1 ha 222
 
2434 Serge 223
        xchg    eax, [esp]
224
                ; out 0xcfa,bus
225
        mov     al, ah
226
        out     dx, al
227
                ; out 0xcf8,0x80
228
        mov     dl, 0xf8
229
        mov     al, 0x80
230
        out     dx, al
231
                ; compute addr
232
        shr     bh, 3; func is ignored in mechanism 2
233
        or      bh, 0xc0
234
        mov     dx, bx
1 ha 235
 
2434 Serge 236
        or      esi, esi
237
        jz      pci_read_byte2
238
        cmp     esi, 1
239
        jz      pci_read_word2
240
        cmp     esi, 2
241
        jz      pci_read_dword2
242
        jmp     pci_fin_read2
1 ha 243
 
1602 art_zh 244
pci_read_byte2:
2434 Serge 245
        in      al, dx
246
        jmp     pci_fin_read2
1602 art_zh 247
pci_read_word2:
2434 Serge 248
        in      ax, dx
249
        jmp     pci_fin_read2
1602 art_zh 250
pci_read_dword2:
2434 Serge 251
        in      eax, dx
1 ha 252
;       jmp pci_fin_read2
1602 art_zh 253
pci_fin_read2:
1 ha 254
 
2434 Serge 255
                ; restore configuration space
256
        xchg    eax, [esp]
257
        mov     dx, 0xcfa
258
        out     dx, al
259
        mov     dl, 0xf8
260
        mov     al, ah
261
        out     dx, al
1 ha 262
 
2434 Serge 263
        pop     eax
3500 Serge 264
        pop     esi ebx
2434 Serge 265
        ret
1 ha 266
 
1602 art_zh 267
pci_read_reg_err:
2434 Serge 268
        xor     eax, eax
269
        dec     eax
3500 Serge 270
        pop     esi ebx
2434 Serge 271
        ret
1 ha 272
 
273
 
274
;***************************************************************************
275
;   Function
276
;      pci_write_reg:
277
;
278
;   Description
279
;       write a register from ECX/CX/CL into the PCI config space
1602 art_zh 280
;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
281
;           value to write in ecx
282
;           number of bytes to write (1,2,4) coded into AL, bits 0-1
586 serge 283
;           (0 - byte, 1 - word, 2 - dword)
1 ha 284
;***************************************************************************
285
 
286
align 4
287
 
288
pci_write_reg:
3500 Serge 289
        push    esi ebx
2434 Serge 290
        cmp     byte [BOOT_VAR+0x9020], 2;what mechanism will we use?
291
        je      pci_write_reg_2
1 ha 292
 
2434 Serge 293
                ; mechanism 1
3500 Serge 294
        mov     esi, eax ; save register size into ESI
2434 Serge 295
        and     esi, 3
1 ha 296
 
2434 Serge 297
        call    pci_make_config_cmd
298
        mov     ebx, eax
299
                ; get current state into ecx
300
        mov     dx, 0xcf8
301
        in      eax, dx
302
        push    eax
303
                ; set up addressing to config data
304
        mov     eax, ebx
305
        and     al, 0xfc; make address dword-aligned
306
        out     dx, eax
307
                ; write DWORD of config data
308
        mov     dl, 0xfc
309
        and     bl, 3
310
        or      dl, bl
311
        mov     eax, ecx
1 ha 312
 
2434 Serge 313
        or      esi, esi
314
        jz      pci_write_byte1
315
        cmp     esi, 1
316
        jz      pci_write_word1
317
        cmp     esi, 2
318
        jz      pci_write_dword1
319
        jmp     pci_fin_write1
1602 art_zh 320
 
321
pci_write_byte1:
2434 Serge 322
        out     dx, al
323
        jmp     pci_fin_write1
1602 art_zh 324
pci_write_word1:
2434 Serge 325
        out     dx, ax
326
        jmp     pci_fin_write1
1602 art_zh 327
pci_write_dword1:
2434 Serge 328
        out     dx, eax
329
        jmp     pci_fin_write1
1602 art_zh 330
pci_fin_write1:
1 ha 331
 
2434 Serge 332
                ; restore configuration control
333
        pop     eax
334
        mov     dl, 0xf8
335
        out     dx, eax
1 ha 336
 
2434 Serge 337
        xor     eax, eax
3500 Serge 338
        pop     ebx esi
1602 art_zh 339
 
2434 Serge 340
        ret
1 ha 341
pci_write_reg_2:
342
 
2434 Serge 343
        test    bh, 128 ;mech#2 only supports 16 devices per bus
344
        jnz     pci_write_reg_err
1 ha 345
 
346
 
3500 Serge 347
        mov     esi, eax ; save register size into ESI
2434 Serge 348
        and     esi, 3
1 ha 349
 
2434 Serge 350
        push    eax
351
                ;store current state of config space
352
        mov     dx, 0xcf8
353
        in      al, dx
354
        mov     ah, al
355
        mov     dl, 0xfa
356
        in      al, dx
357
        xchg    eax, [esp]
358
                ; out 0xcfa,bus
359
        mov     al, ah
360
        out     dx, al
361
                ; out 0xcf8,0x80
362
        mov     dl, 0xf8
363
        mov     al, 0x80
364
        out     dx, al
365
                ; compute addr
366
        shr     bh, 3; func is ignored in mechanism 2
367
        or      bh, 0xc0
368
        mov     dx, bx
369
                ; write register
370
        mov     eax, ecx
1 ha 371
 
2434 Serge 372
        or      esi, esi
373
        jz      pci_write_byte2
374
        cmp     esi, 1
375
        jz      pci_write_word2
376
        cmp     esi, 2
377
        jz      pci_write_dword2
378
        jmp     pci_fin_write2
1602 art_zh 379
 
380
pci_write_byte2:
2434 Serge 381
        out     dx, al
382
        jmp     pci_fin_write2
1602 art_zh 383
pci_write_word2:
2434 Serge 384
        out     dx, ax
385
        jmp     pci_fin_write2
1602 art_zh 386
pci_write_dword2:
2434 Serge 387
        out     dx, eax
388
        jmp     pci_fin_write2
1602 art_zh 389
pci_fin_write2:
2434 Serge 390
                ; restore configuration space
391
        pop     eax
392
        mov     dx, 0xcfa
393
        out     dx, al
394
        mov     dl, 0xf8
395
        mov     al, ah
396
        out     dx, al
1 ha 397
 
2434 Serge 398
        xor     eax, eax
3500 Serge 399
        pop     ebx esi
2434 Serge 400
        ret
1 ha 401
 
1602 art_zh 402
pci_write_reg_err:
2434 Serge 403
        xor     eax, eax
404
        dec     eax
3500 Serge 405
        pop     ebx esi
2434 Serge 406
        ret
586 serge 407
 
2434 Serge 408
if defined mmio_pci_addr        ; must be set above
1348 art_zh 409
;***************************************************************************
410
;   Function
1603 art_zh 411
;      pci_mmio_init
1348 art_zh 412
;
413
;   Description
1602 art_zh 414
;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
1358 art_zh 415
;   Returns  eax = user heap space available (bytes)
1348 art_zh 416
;   Error codes
417
;       eax = -1 : PCI user access blocked,
418
;       eax = -2 : device not registered for uMMIO service
419
;       eax = -3 : user heap initialization failure
420
;***************************************************************************
421
pci_mmio_init:
2434 Serge 422
        cmp     bx, mmio_pci_addr
423
        jz      @f
424
        mov     eax, -2
425
        ret
1348 art_zh 426
@@:
2434 Serge 427
        call    init_heap  ; (if not initialized yet)
428
        or      eax, eax
429
        jz      @f
430
        ret
1348 art_zh 431
@@:
2434 Serge 432
        mov     eax, -3
433
        ret
1348 art_zh 434
 
435
 
436
;***************************************************************************
437
;   Function
1603 art_zh 438
;      pci_mmio_map
1348 art_zh 439
;
440
;   Description
441
;       maps a block of PCI memory to user-accessible linear address
442
;
443
;       WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
444
;       The target device address should be set in kernel var mmio_pci_addr
445
;
1602 art_zh 446
;       IN:  ah = BAR#;
447
;       IN: ebx = block size (bytes);
448
;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
1348 art_zh 449
;
450
;   Returns eax = MMIO block's linear address in the userspace (if no error)
451
;
452
;
453
;   Error codes
454
;       eax = -1 : user access to PCI blocked,
455
;       eax = -2 : an invalid BAR register referred
456
;       eax = -3 : no i/o space on that BAR
457
;       eax = -4 : a port i/o BAR register referred
458
;       eax = -5 : dynamic userspace allocation problem
459
;***************************************************************************
460
 
461
pci_mmio_map:
2434 Serge 462
        and     edx, 0x0ffff
463
        cmp     ah, 6
464
        jc      .bar_0_5
465
        jz      .bar_rom
466
        mov     eax, -2
467
        ret
1353 art_zh 468
.bar_rom:
2434 Serge 469
        mov     ah, 8   ; bar6 = Expansion ROM base address
1353 art_zh 470
.bar_0_5:
2434 Serge 471
        push    ecx
472
        add     ebx, 4095
473
        and     ebx, -4096
474
        push    ebx
475
        mov     bl, ah  ; bl = BAR# (0..5), however bl=8 for BAR6
476
        shl     bl, 1
477
        shl     bl, 1
478
        add     bl, 0x10; now bl = BAR offset in PCI config. space
479
        mov     ax, mmio_pci_addr
480
        mov     bh, al  ; bh = dddddfff
481
        mov     al, 2   ; al : DW to read
482
        call    pci_read_reg
483
        or      eax, eax
484
        jnz     @f
485
        mov     eax, -3 ; empty I/O space
486
        jmp     mmio_ret_fail
1348 art_zh 487
@@:
2434 Serge 488
        test    eax, 1
489
        jz      @f
490
        mov     eax, -4 ; damned ports (not MMIO space)
491
        jmp     mmio_ret_fail
1348 art_zh 492
@@:
2434 Serge 493
        pop     ecx     ; ecx = block size, bytes (expanded to whole page)
494
        mov     ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx
495
        and     eax, 0xFFFFFFF0
496
        push    eax           ; store MMIO physical address + keep 2DWords in the stack
497
        stdcall user_alloc, ecx
498
        or      eax, eax
499
        jnz     mmio_map_over
500
        mov     eax, -5 ; problem with page allocation
1348 art_zh 501
 
502
mmio_ret_fail:
2434 Serge 503
        pop     ecx
504
        pop     edx
505
        ret
1348 art_zh 506
 
507
mmio_map_over:
2434 Serge 508
        mov     ecx, ebx; ecx = size (bytes, expanded to whole page)
509
        shr     ecx, 12 ; ecx = number of pages
510
        mov     ebx, eax; ebx = linear address
511
        pop     eax     ; eax = MMIO start
512
        pop     edx     ; edx = MMIO shift (pages)
513
        shl     edx, 12 ; edx = MMIO shift (bytes)
514
        add     eax, edx; eax = uMMIO physical address
515
        or      eax, PG_SHARED
516
        or      eax, PG_UW
517
        or      eax, PG_NOCACHE
518
        mov     edi, ebx
519
        call    commit_pages
520
        mov     eax, edi
521
        ret
1348 art_zh 522
 
523
;***************************************************************************
524
;   Function
1603 art_zh 525
;      pci_mmio_unmap_page
1348 art_zh 526
;
527
;   Description
528
;       unmaps the linear space previously tied to a PCI memory block
529
;
530
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
531
;       returns eax = 1 if successfully unmapped
532
;
533
;   Error codes
534
;       eax = -1 if no user PCI access allowed,
535
;       eax =  0 if unmapping failed
536
;***************************************************************************
537
 
538
pci_mmio_unmap:
2434 Serge 539
        stdcall user_free, ebx
540
        ret
1348 art_zh 541
 
1354 diamond 542
end if
1348 art_zh 543
 
586 serge 544
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1375 Lrz 545
uglobal
546
align 4
586 serge 547
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
2434 Serge 548
pci_emu_dat:
549
                times   30*10 db 0
1375 Lrz 550
endg
586 serge 551
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
552
align 4
553
sys_pcibios:
2434 Serge 554
        cmp     [pci_access_enabled], 1
555
        jne     .unsupported_func
556
        cmp     [pci_bios_entry], 0
557
        jz      .emulate_bios
586 serge 558
 
2434 Serge 559
        push    ds
560
        mov     ax, pci_data_sel
561
        mov     ds, ax
562
        mov     eax, ebp
563
        mov     ah, 0B1h
564
        call    pword [cs:pci_bios_entry]
565
        pop     ds
586 serge 566
 
2434 Serge 567
        jmp     .return
568
        ;-=-=-=-=-=-=-=-=
586 serge 569
.emulate_bios:
2434 Serge 570
        cmp     ebp, 1                  ; PCI_FUNCTION_ID
571
        jnz     .not_PCI_BIOS_PRESENT
572
        mov     edx, 'PCI '
573
        mov     al, [BOOT_VAR + 0x9020]
574
        mov     bx, [BOOT_VAR + 0x9022]
575
        mov     cl, [BOOT_VAR + 0x9021]
576
        xor     ah, ah
577
        jmp     .return_abcd
586 serge 578
 
579
.not_PCI_BIOS_PRESENT:
2434 Serge 580
        cmp     ebp, 2                  ; FIND_PCI_DEVICE
581
        jne     .not_FIND_PCI_DEVICE
582
        mov     ebx, pci_emu_dat
583
..nxt:
584
        cmp     [ebx], dx
585
        jne     ..no
586
        cmp     [ebx + 2], cx
587
        jne     ..no
588
        dec     si
589
        jns     ..no
590
        mov     bx, [ebx + 4]
591
        xor     ah, ah
592
        jmp     .return_ab
593
..no:
594
        cmp     word[ebx], 0
595
        je      ..dev_not_found
596
        add     ebx, 10
597
        jmp     ..nxt
586 serge 598
..dev_not_found:
2434 Serge 599
        mov     ah, 0x86                ; DEVICE_NOT_FOUND
600
        jmp     .return_a
586 serge 601
 
602
.not_FIND_PCI_DEVICE:
2434 Serge 603
        cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
604
        jne     .not_FIND_PCI_CLASS_CODE
605
        mov     esi, pci_emu_dat
606
        shl     ecx, 8
607
..nxt2:
608
        cmp     [esi], ecx
609
        jne     ..no2
610
        mov     bx, [esi]
611
        xor     ah, ah
612
        jmp     .return_ab
613
..no2:
614
        cmp     dword[esi], 0
615
        je      ..dev_not_found
616
        add     esi, 10
617
        jmp     ..nxt2
586 serge 618
 
619
.not_FIND_PCI_CLASS_CODE:
2434 Serge 620
        cmp     ebp, 8                  ; READ_CONFIG_*
621
        jb      .not_READ_CONFIG
622
        cmp     ebp, 0x0A
623
        ja      .not_READ_CONFIG
624
        mov     eax, ebp
625
        mov     ah, bh
626
        mov     edx, edi
627
        mov     bh, bl
628
        mov     bl, dl
629
        call    pci_read_reg
630
        mov     ecx, eax
631
        xor     ah, ah                  ; SUCCESSFUL
632
        jmp     .return_abc
586 serge 633
.not_READ_CONFIG:
2434 Serge 634
        cmp     ebp, 0x0B               ; WRITE_CONFIG_*
635
        jb      .not_WRITE_CONFIG
636
        cmp     ebp, 0x0D
637
        ja      .not_WRITE_CONFIG
638
        lea     eax, [ebp+1]
639
        mov     ah, bh
640
        mov     edx, edi
641
        mov     bh, bl
642
        mov     bl, dl
643
        call    pci_write_reg
644
        xor     ah, ah                  ; SUCCESSFUL
645
        jmp     .return_abc
586 serge 646
.not_WRITE_CONFIG:
647
.unsupported_func:
2434 Serge 648
        mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
649
.return:
650
        mov     dword[esp + 4 ], edi
651
        mov     dword[esp + 8], esi
594 diamond 652
.return_abcd:
2434 Serge 653
        mov     dword[esp + 24], edx
594 diamond 654
.return_abc:
2434 Serge 655
        mov     dword[esp + 28], ecx
594 diamond 656
.return_ab:
2434 Serge 657
        mov     dword[esp + 20], ebx
594 diamond 658
.return_a:
2434 Serge 659
        mov     dword[esp + 32], eax
660
        ret
3500 Serge 661
 
662
proc pci_enum
663
        push    ebp
664
        mov     ebp, esp
665
        push    0
666
virtual at ebp-4
667
.devfn          db      ?
668
.bus            db      ?
669
end virtual
670
.loop:
671
        mov     ah, [.bus]
672
        mov     al, 2
673
        mov     bh, [.devfn]
674
        mov     bl, 0
675
        call    pci_read_reg
676
        cmp     eax, 0xFFFFFFFF
677
        jnz     .has_device
678
        test    byte [.devfn], 7
679
        jnz     .next_func
680
        jmp     .no_device
681
.has_device:
682
        push    eax
683
        push    sizeof.PCIDEV
684
        pop     eax
685
        call    malloc
686
        pop     ecx
687
        test    eax, eax
688
        jz      .nomemory
689
        mov     edi, eax
690
        mov     [edi+PCIDEV.vendor_device_id], ecx
691
        mov     eax, pcidev_list
692
        mov     ecx, [eax+PCIDEV.bk]
693
        mov     [edi+PCIDEV.bk], ecx
694
        mov     [edi+PCIDEV.fd], eax
695
        mov     [ecx+PCIDEV.fd], edi
696
        mov     [eax+PCIDEV.bk], edi
697
        mov     eax, dword [.devfn]
698
        mov     word [edi+PCIDEV.devfn], ax
699
        mov     bh, al
700
        mov     al, 2
701
        mov     bl, 8
702
        call    pci_read_reg
703
        shr     eax, 8
704
        mov     [edi+PCIDEV.class], eax
705
        test    byte [.devfn], 7
706
        jnz     .next_func
707
        mov     ah, [.bus]
708
        mov     al, 0
709
        mov     bh, [.devfn]
710
        mov     bl, 0Eh
711
        call    pci_read_reg
712
        test    al, al
713
        js      .next_func
714
.no_device:
715
        or      byte [.devfn], 7
716
.next_func:
717
        inc     dword [.devfn]
718
        mov     ah, [.bus]
719
        cmp     ah, [BOOT_VAR+0x9021]
720
        jbe     .loop
721
.nomemory:
722
        leave
723
        ret
724
endp