Subversion Repositories Kolibri OS

Rev

Rev 3910 | Rev 5577 | 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: 5565 $
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
                ; 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
3908 Serge 290
        cmp     byte [BOOT_VARS+0x9020], 2;what mechanism will we use?
2434 Serge 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 '
3908 Serge 573
        mov     al, [BOOT_VARS + 0x9020]
574
        mov     bx, [BOOT_VARS + 0x9022]
575
        mov     cl, [BOOT_VARS + 0x9021]
2434 Serge 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
 
3908 Serge 662
PCI_VENDOR_ID           equ 0x00
663
PCI_CLASS_REVISION      equ 0x08
664
PCI_HEADER_TYPE         equ 0x0E
665
PCI_SUBSYSTEM_VENDOR_ID equ 0x2c
666
PCI_IRQ_LINE            equ 0x3C
667
 
3500 Serge 668
proc pci_enum
669
        push    ebp
670
        mov     ebp, esp
671
        push    0
672
virtual at ebp-4
673
.devfn          db      ?
674
.bus            db      ?
675
end virtual
676
.loop:
677
        mov     ah, [.bus]
678
        mov     al, 2
679
        mov     bh, [.devfn]
3908 Serge 680
        mov     bl, PCI_VENDOR_ID
3500 Serge 681
        call    pci_read_reg
682
        cmp     eax, 0xFFFFFFFF
683
        jnz     .has_device
684
        test    byte [.devfn], 7
685
        jnz     .next_func
686
        jmp     .no_device
687
.has_device:
688
        push    eax
3626 Serge 689
        movi    eax, sizeof.PCIDEV
3500 Serge 690
        call    malloc
691
        pop     ecx
692
        test    eax, eax
693
        jz      .nomemory
694
        mov     edi, eax
3908 Serge 695
        mov     [edi+PCIDEV.vid_did], ecx
696
        mov     edx, pcidev_list
697
        list_add_tail edi, edx
3500 Serge 698
        mov     eax, dword [.devfn]
699
        mov     word [edi+PCIDEV.devfn], ax
700
        mov     bh, al
701
        mov     al, 2
3908 Serge 702
        mov     bl, PCI_CLASS_REVISION
3500 Serge 703
        call    pci_read_reg
3908 Serge 704
        shr     eax, 8                                ;FIXME use byte mask
3500 Serge 705
        mov     [edi+PCIDEV.class], eax
3908 Serge 706
 
707
        mov     ah, [.bus]
708
        mov     bh, byte [.devfn]
709
        mov     al, 2
710
        mov     bl, PCI_SUBSYSTEM_VENDOR_ID
711
        call    pci_read_reg
712
        mov     [edi+PCIDEV.svid_sdid], eax
713
 
714
        mov     ah, [.bus]
715
        mov     al, 0
716
        mov     bh, [.devfn]
717
        mov     bl, PCI_IRQ_LINE
718
        call    pci_read_reg
719
        mov     [edi+PCIDEV.irq_line], al
720
 
3500 Serge 721
        test    byte [.devfn], 7
722
        jnz     .next_func
723
        mov     ah, [.bus]
724
        mov     al, 0
725
        mov     bh, [.devfn]
3908 Serge 726
        mov     bl, PCI_HEADER_TYPE
3500 Serge 727
        call    pci_read_reg
728
        test    al, al
729
        js      .next_func
730
.no_device:
731
        or      byte [.devfn], 7
732
.next_func:
733
        inc     dword [.devfn]
734
        mov     ah, [.bus]
3908 Serge 735
        cmp     ah, [BOOT_VARS+0x9021]
3500 Serge 736
        jbe     .loop
737
.nomemory:
738
        leave
739
        ret
740
endp
3908 Serge 741
 
742
 
743
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
744
 
745
;internal functions
746
;ecx (bus << 8)|devfn
747
;edx register
748
 
749
align 4
750
pci_bus:
751
.conf1_index:
752
; dword CF8 = (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) | (devfn << 8) | (reg & 0xFC))
753
				push	edx
754
				mov		eax, edx                	; eax = reg
755
				shl		eax, 16                 	; eax = reg << 16
756
				shl   ecx, 8                  	; ecx = (bus << 16)|(devfn<<8)
757
				mov		al, dl                  	; eax = (reg << 16)|reg
758
				and		eax, 0x0F0000FC           ; eax = ((reg & 0xF00) << 16)|(reg & 0xFC)
759
				lea		eax, [0x80000000+eax+ecx]
760
				mov 	dx, 0xCF8
761
				out		dx, eax
762
				pop		edx
763
				xor		eax, eax
764
				ret
765
 
766
align 4
767
.conf2_index:
768
; byte CF8 = 0xF0 | (fn << 1)
769
; byte CFA = bus
770
				push	edx
771
				mov		eax, ecx                ; (bus << 8)|devfn
772
				and		al, 7            				; fn
773
				lea		eax, [0xF0+eax+eax]
774
				mov 	dx, 0xCF8
775
				out		dx, al
776
				mov		al, ch                  ; bus
777
				mov		dx, 0xCFA
778
				out   dx, al
779
				pop		edx
780
				xor		eax, eax
781
				ret
782
 
783
align 4
784
.conf1_read8:
785
				call  .conf1_index
786
				and 	dx, 3
787
				add		dx, 0xCFC
788
				in		al, dx
789
				ret
790
 
791
align 4
792
.conf1_read16:
793
				call  .conf1_index
794
				and 	dx, 2
795
				add		dx, 0xCFC
796
				in		ax, dx
797
				ret
798
 
799
align 4
800
.conf1_read32:
801
				call  .conf1_index
802
				mov  	dx, 0xCFC
803
				in		eax, dx
804
				ret
805
 
806
align 4
807
.conf1_write8:
808
				call  .conf1_index
809
				mov		eax, [esp+4]
810
				and 	dx, 3
811
				add		dx, 0xCFC
812
				out		dx, al
813
				ret   4
814
 
815
align 4
816
.conf1_write16:
817
				call  .conf1_index
818
				mov		eax, [esp+4]
819
				and 	dx, 2
820
				add		dx, 0xCFC
821
				out		dx, ax
822
				ret   4
823
 
824
align 4
825
.conf1_write32:
826
				call  .conf1_index
827
				mov		eax, [esp+4]
828
				mov		dx, 0xCFC
829
				out   dx, eax
830
				ret   4
831
 
832
align 4
833
.conf2_read8:
834
; in (0xC000 | (dev << 8) | reg)
835
				call  .conf2_index
836
				and		ecx, 0xF1               ;ecx = dev << 3
837
				shl		ecx, 5                  ;ecx = dev << 8
838
				lea   edx, [0xC000+edx+ecx]
839
				in		al, dx
840
				ret
841
 
842
align 4
843
.conf2_read16:
844
				call  .conf2_index
845
				and		ecx, 0xF1
846
				shl		ecx, 5
847
				lea   edx, [0xC000+edx+ecx]
848
				in		ax, dx
849
				ret
850
 
851
align 4
852
.conf2_read32:
853
				call  .conf2_index
854
				and		ecx, 0xF1
855
				shl		ecx, 5
856
				lea   edx, [0xC000+edx+ecx]
857
				in		eax, dx
858
				ret
859
 
860
 
861
PCI_R8	equ 0
862
PCI_R16	equ 4
863
PCI_R32 equ 8
864
 
865
PCI_W8	equ 12
866
PCI_W16	equ 16
867
PCI_W32 equ 20
868
 
869
 
870
align 4
3910 Serge 871
pci_conf1_rw:
872
;internal function
873
;eax accessor
874
;ecx (bus << 8)|devfn
3908 Serge 875
 
3910 Serge 876
.val      equ esp+4
877
 
878
; dword CF8 = (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) | (devfn << 8) | (reg & 0xFC))
879
 
880
				pushfd
881
				cli
882
 
883
				push  edx
884
				push  eax
885
				mov		eax, edx                	; eax = reg
886
				shl		eax, 16                 	; eax = reg << 16
887
				shl   ecx, 8                  	; ecx = (bus << 16)|(devfn<<8)
888
				mov		al, dl                  	; eax = (reg << 16)|reg
889
				and		eax, 0x0F0000FC           ; eax = ((reg & 0xF00) << 16)|(reg & 0xFC)
890
				lea		eax, [0x80000000+eax+ecx]
891
				mov 	dx, 0xCF8
892
				out		dx, eax
893
				pop		eax
894
				pop   edx
895
				jmp   dword [.fntab+eax]
896
.r32:
897
				mov  	dx, 0xCFC
898
				in		eax, dx
899
.rdone:
900
				popfd
901
				ret
902
.r16:
903
				and 	dx, 2
904
				add		dx, 0xCFC
905
				in		al, dx
906
				jmp   .rdone
907
.r8:
908
				and 	dx, 3
909
				add		dx, 0xCFC
910
				in		al, dx
911
				jmp   .rdone
912
.w32:
913
				mov		eax, [esp+8]
914
				mov		dx, 0xCFC
915
				out   dx, eax
916
.wdone:
917
				popfd
918
				ret   4
919
.w16:
920
				mov		eax, [esp+8]
921
				and 	dx, 2
922
				add		dx, 0xCFC
923
				out		dx, ax
924
				jmp   .wdone
925
.w8:
926
				mov		eax, [esp+8]
927
				and 	dx, 3
928
				add		dx, 0xCFC
929
				out		dx, al
930
				jmp   .wdone
931
 
3908 Serge 932
align 4
3910 Serge 933
.fntab:
934
				dd .r8
935
				dd .r16
936
				dd .r32
937
				dd .w8
938
				dd .w16
939
				dd .w32
940
 
941
align 4
942
pci_fn_rw	dd pci_conf1_rw
943
 
944
;proc pci_bus_read8   fastcall, busaddr:dword, reg:dword
945
;proc pci_bus_read16  fastcall, busaddr:dword, reg:dword
946
;proc pci_bus_read32  fastcall, busaddr:dword, reg:dword
947
 
948
align 4
949
pci_bus_read8:
950
				xor	eax, eax
951
				jmp	dword [pci_fn_rw]
952
 
953
align 4
954
pci_bus_read16:
3908 Serge 955
				mov		eax, PCI_R16
3910 Serge 956
				jmp	dword [pci_fn_rw]
3908 Serge 957
 
958
align 4
3910 Serge 959
pci_bus_read32:
3908 Serge 960
				mov		eax, PCI_R32
3910 Serge 961
				jmp	dword [pci_fn_rw]
3908 Serge 962
 
3910 Serge 963
;proc pci_bus_write8  fastcall, busaddr:dword, reg:dword, val: dword
964
;proc pci_bus_write16 fastcall, busaddr:dword, reg:dword, val: dword
965
;proc pci_bus_write32 fastcall, busaddr:dword, reg:dword, val: dword
966
 
3908 Serge 967
align 4
3910 Serge 968
pci_bus_write8:
969
				mov	  eax, PCI_W8
970
				jmp	dword [pci_fn_rw]
971
 
972
align 4
973
pci_bus_write16:
974
				mov		eax, PCI_W16
975
				jmp	dword [pci_fn_rw]
976
 
977
align 4
978
pci_bus_write32:
979
				mov		eax, PCI_W32
980
				jmp	dword [pci_fn_rw]
981
 
982
;deprecated proc pci_read8   stdcall, bus:dword, devfn:dword, reg:dword
983
;deprecated proc pci_read16  stdcall, bus:dword, devfn:dword, reg:dword
984
;deprecated proc pci_read32  stdcall, bus:dword, devfn:dword, reg:dword
985
 
986
align 4
987
pci_read8:
3908 Serge 988
.bus			equ esp+4
989
.devfn 		equ esp+8
990
.pci_reg 	equ esp+12
3910 Serge 991
.val      equ esp+16
3908 Serge 992
 
3910 Serge 993
				movzx ecx, byte [.devfn]
3908 Serge 994
				mov   ch, [.bus]
995
				movzx edx, word [.pci_reg]
3910 Serge 996
				call	pci_bus_read8
997
				ret 	12
3908 Serge 998
 
3910 Serge 999
align 4
1000
pci_read16:
1001
.bus			equ esp+4
1002
.devfn 		equ esp+8
1003
.pci_reg 	equ esp+12
1004
.val      equ esp+16
3908 Serge 1005
 
3910 Serge 1006
				movzx ecx, byte [.devfn]
1007
				mov   ch, [.bus]
1008
				movzx edx, word [.pci_reg]
1009
				call	pci_bus_read16
1010
				ret 	12
3908 Serge 1011
 
3910 Serge 1012
align 4
1013
pci_read32:
1014
.bus			equ esp+4
1015
.devfn 		equ esp+8
1016
.pci_reg 	equ esp+12
1017
.val      equ esp+16
3908 Serge 1018
 
3910 Serge 1019
				movzx ecx, byte [.devfn]
1020
				mov   ch, [.bus]
1021
				movzx edx, word [.pci_reg]
1022
				call	pci_bus_read32
3908 Serge 1023
				ret 	12
1024
 
3910 Serge 1025
;deprecated proc pci_write8  stdcall, bus:dword, devfn:dword, reg:dword, val:dword
1026
;deprecated proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
1027
;deprecated proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
1028
 
3908 Serge 1029
align 4
1030
pci_write8:
3910 Serge 1031
.bus			equ esp+4
1032
.devfn 		equ esp+8
1033
.pci_reg 	equ esp+12
1034
.val      equ esp+16
3908 Serge 1035
 
3910 Serge 1036
				movzx ecx, byte [.devfn]
1037
				mov   ch, [.bus]
1038
				movzx edx, word [.pci_reg]
1039
				push	dword [esp+16]
1040
				call	pci_bus_write8
1041
				ret 	16
1042
 
3908 Serge 1043
align 4
1044
pci_write16:
3910 Serge 1045
.bus			equ esp+4
1046
.devfn 		equ esp+8
1047
.pci_reg 	equ esp+12
1048
.val      equ esp+16
3908 Serge 1049
 
3910 Serge 1050
				movzx ecx, byte [.devfn]
1051
				mov   ch, [.bus]
1052
				movzx edx, word [.pci_reg]
1053
				push	dword [esp+16]
1054
				call	pci_bus_write16
1055
				ret 	16
1056
 
3908 Serge 1057
align 4
1058
pci_write32:
1059
.bus			equ esp+4
1060
.devfn 		equ esp+8
1061
.pci_reg 	equ esp+12
1062
.val      equ esp+16
1063
 
3910 Serge 1064
				movzx ecx, byte [.devfn]
3908 Serge 1065
				mov   ch, [.bus]
1066
				movzx edx, word [.pci_reg]
3910 Serge 1067
				push	dword [esp+16]
1068
				call	pci_bus_write32
1069
				ret 	16
3908 Serge 1070
 
1071
 
1072