Материал из Wiki.
<!-- start content -->
CF8h - регистр адреса
CFCh - регистр данных
Если читали Пинчакку, или смотрели описаловку на Intel-чипсеты, то понято что адрес требуемого регистра задается значением 8000ХХХХh, где ХХХХ адрес регистра в виде Dev, Func, Reg.
Если эти ХХХХ перевести в двоичный код, то первые пять разрядов слева задают номер устройства (максимальное значение 31 десятичное), потом три разряда номер функции и последние восемь - номер регистра (hex).
Пример:
0F01Ch -> 1111000000011100b -> 11110 000 00011100b -> Dev 30 (11110b), Func 0 (000b), Reg 1Ch
Загвоздка обычно в том, что device считается в десятичной системе счисления (d), тогда как все остальное в шестнадцатиричной (hex).
Ну и пример кода без объяснений:
Заходим в подпрограмму с параметром, например cx (задаем адрес)
mov cx, 0F8A4h ; dev31 func0 regA4
call Read_PCI
Read_PCI:
mov ax, 8000h ;
shl eax, 10h ; Shift Logical Left
mov ax, cx
and al, 0FCh ; Logical AND
mov dx, 0CF8h
out dx, eax
add dl, 4 ; Add
mov al, cl
and al, 3 ; Logical AND
add dl, al ; Add
in al, dx
retn ; Return Near from Procedure
Соответственно в подпрограмме записи будет out dx, al или ax или eax.
Например:
Root-регистры (база Root Complex Base Address) - огромное количество низкоуровневых настроек чипсета (смотрите даташиты на южный мосты, как пример ICH7)
MCHBAR - регистры конфигурирования памяти и контроллера памяти (правда подробного описания регистров относительно этой базы не встречал)
и многие другие....
Функция поиска PCI устройства по классу
_F000:EB7C _F000:EB7C ; =============== S U B R O U T I N E ======================================= _F000:EB7C _F000:EB7C ; return: _F000:EB7C ; found device in ecx, _F000:EB7C ; error in carry flag, _F000:EB7C ; return at the <bx> address (jmp bx) _F000:EB7C _F000:EB7C ; __int32 __usercall PCI_FindByClass<ecx>(unsigned __int16 class<ax>) _F000:EB7C PCI_FindByClass proc near ; CODE XREF: sub_FE414+9j _F000:EB7C ; sub_FE543+9j ... _F000:EB7C 8B C8 mov cx, ax _F000:EB7E 66 B8 08 00 00 80 mov eax, 80000008h ; 0:0.0 - with offset 8 _F000:EB7E ; _F000:EB7E ; RID - Revision Identification _F000:EB7E ; _F000:EB7E _F000:EB84 _F000:EB84 pci_read_loop: ; CODE XREF: PCI_FindByClass+4Fj _F000:EB84 BA F8 0C mov dx, PCI_ADDRESS_PORT _F000:EB87 66 EF out dx, eax _F000:EB89 BA FC 0C mov dx, PCI_DATA_PORT _F000:EB8C 66 8B F8 mov edi, eax _F000:EB8F 66 ED in eax, dx _F000:EB91 66 C1 E8 10 shr eax, 16 ; check SubClass and BaseClass _F000:EB95 3B C1 cmp ax, cx ; Compare Two Operands _F000:EB97 74 37 jz short return_carry_0 ; Jump if Zero (ZF=1) _F000:EB97 _F000:EB99 66 8B C7 mov eax, edi _F000:EB9C A9 F0 07 test ax, 11111110000b ; function 7 offset 0xF0 _F000:EB9F 75 19 jnz short increment ; Jump if Not Zero (ZF=0) _F000:EB9F _F000:EBA1 83 C0 04 add ax, 4 ; Add _F000:EBA4 BA F8 0C mov dx, PCI_ADDRESS_PORT _F000:EBA7 66 EF out dx, eax _F000:EBA9 BA FC 0C mov dx, PCI_DATA_PORT _F000:EBAC 66 ED in eax, dx _F000:EBAE 66 C1 E8 10 shr eax, 16 ; Shift Logical Right _F000:EBB2 3D 80 00 cmp ax, 10000000b ; Compare Two Operands _F000:EBB5 75 08 jnz short next_part ; Jump if Not Zero (ZF=0) _F000:EBB5 _F000:EBB7 66 8B C7 mov eax, edi _F000:EBB7 _F000:EBBA _F000:EBBA increment: ; CODE XREF: PCI_FindByClass+23j _F000:EBBA 05 00 01 add ax, 256 ; Add _F000:EBBD EB 09 jmp short check_if_all_read ; Jump _F000:EBBD _F000:EBBF ; --------------------------------------------------------------------------- _F000:EBBF _F000:EBBF next_part: ; CODE XREF: PCI_FindByClass+39j _F000:EBBF 66 8B C7 mov eax, edi _F000:EBC2 66 05 00 08 00 00 add eax, 2048 ; Add _F000:EBC2 _F000:EBC8 _F000:EBC8 check_if_all_read: ; CODE XREF: PCI_FindByClass+41j _F000:EBC8 3D 08 FF cmp ax, 0FF08h ; Compare Two Operands _F000:EBCB 76 B7 jbe short pci_read_loop ; Jump if Below or Equal (CF=1 | ZF=1) _F000:EBCB _F000:EBCD F9 stc ; Set Carry Flag _F000:EBCE EB 04 jmp short return ; Jump _F000:EBCE _F000:EBD0 ; --------------------------------------------------------------------------- _F000:EBD0 _F000:EBD0 return_carry_0: ; CODE XREF: PCI_FindByClass+1Bj _F000:EBD0 66 8B C7 mov eax, edi _F000:EBD3 F8 clc ; Clear Carry Flag _F000:EBD3 _F000:EBD4 _F000:EBD4 return: ; CODE XREF: PCI_FindByClass+52j _F000:EBD4 66 8B C8 mov ecx, eax _F000:EBD7 B1 00 mov cl, 0 _F000:EBD9 FF E3 jmp bx ; jump to 0xED08 _F000:EBD9 _F000:EBD9 PCI_FindByClass endp _F000:EBD9Функции чтения и записи в PCI
_F000:FF4C ; =============== S U B R O U T I N E ======================================= _F000:FF4C _F000:FF4C ; Stack Less version, return at the address, written in bx (jmp bx) _F000:FF4C _F000:FF4C ; __int8 __usercall ReadPCI_byte_SL<ah>(__int32 address<eax>) _F000:FF4C ReadPCI_byte_SL proc near ; CODE XREF: ReadPCI_SL_jmpj _F000:FF4C ; ReadPCI_byte_S+7j _F000:FF4C 66 8B F8 mov edi, eax _F000:FF4F 8B F2 mov si, dx _F000:FF51 66 0F B6 C0 movzx eax, al ; Move with Zero-Extend _F000:FF55 66 0F BA E8 1F bts eax, 31 ; Bit Test and Set _F000:FF5A 24 FC and al, 0FCh ; Logical AND _F000:FF5C BA F8 0C mov dx, PCI_ADDRESS_PORT _F000:FF5F 66 EF out dx, eax _F000:FF61 66 8B C7 mov eax, edi _F000:FF64 8A D0 mov dl, al _F000:FF66 80 CA FC or dl, 0FCh ; Logical Inclusive OR _F000:FF69 86 C4 xchg al, ah ; Exchange Register/Memory with Register _F000:FF6B EC in al, dx _F000:FF6C 86 C4 xchg al, ah ; Exchange Register/Memory with Register _F000:FF6E 8B D6 mov dx, si _F000:FF70 FF E3 jmp bx ; Indirect Near Jump _F000:FF70 _F000:FF70 ReadPCI_byte_SL endp _F000:FF70 _F000:FF72 _F000:FF72 ; =============== S U B R O U T I N E ======================================= _F000:FF72 _F000:FF72 ; Stack Less version, return to the address, written in bx (jmp bx) _F000:FF72 _F000:FF72 ; __int32 __cdecl WritePCI_byte_SL(__int32 address, __int32 value) _F000:FF72 WritePCI_byte_SL proc near ; CODE XREF: WritePCI_SL_jmpj _F000:FF72 ; WritePCI_byte_S+7j _F000:FF72 66 8B F8 mov edi, eax _F000:FF75 8B F2 mov si, dx _F000:FF77 66 0F B6 C0 movzx eax, al ; Move with Zero-Extend _F000:FF7B 66 0F BA E8 1F bts eax, 11111b ; Bit Test and Set _F000:FF80 24 FC and al, 0FCh ; Logical AND _F000:FF82 BA F8 0C mov dx, PCI_ADDRESS_PORT _F000:FF85 66 EF out dx, eax _F000:FF87 66 8B C7 mov eax, edi _F000:FF8A 8A D0 mov dl, al _F000:FF8C 80 CA FC or dl, 0FCh ; Logical Inclusive OR _F000:FF8F 86 C4 xchg al, ah ; Exchange Register/Memory with Register _F000:FF91 EE out dx, al _F000:FF92 86 C4 xchg al, ah ; Exchange Register/Memory with Register _F000:FF94 8B D6 mov dx, si _F000:FF96 FF E3 jmp bx ; Indirect Near Jump _F000:FF96 _F000:FF96 WritePCI_byte_SL endp _F000:FF96 _F000:FF98 _F000:FF98 ; =============== S U B R O U T I N E ======================================= _F000:FF98 _F000:FF98 ; Stack version _F000:FF98 _F000:FF98 ; __int8 __cdecl ReadPCI_byte_S(__int32 address) _F000:FF98 ReadPCI_byte_S proc near _F000:FF98 _F000:FF98 address = dword ptr 2 _F000:FF98 _F000:FF98 53 push bx _F000:FF99 66 57 push edi _F000:FF9B 56 push si _F000:FF9C BB A1 FF mov bx, offset return _F000:FF9F EB AB jmp short ReadPCI_byte_SL ; Stack Less version, return at the address, written in bx (jmp bx) _F000:FF9F _F000:FFA1 ; --------------------------------------------------------------------------- _F000:FFA1 _F000:FFA1 return: ; DATA XREF: ReadPCI_byte_S+4o _F000:FFA1 5E pop si _F000:FFA2 66 5F pop edi _F000:FFA4 5B pop bx _F000:FFA5 C3 retn ; Return Near from Procedure _F000:FFA5 _F000:FFA5 ReadPCI_byte_S endp _F000:FFA5 _F000:FFA6 _F000:FFA6 ; =============== S U B R O U T I N E ======================================= _F000:FFA6 _F000:FFA6 ; Stack version _F000:FFA6 _F000:FFA6 ; __int32 __cdecl WritePCI_byte_S(__int32 address, __int32 value) _F000:FFA6 WritePCI_byte_S proc near _F000:FFA6 _F000:FFA6 address = dword ptr 2 _F000:FFA6 value = dword ptr 6 _F000:FFA6 _F000:FFA6 53 push bx _F000:FFA7 66 57 push edi _F000:FFA9 56 push si _F000:FFAA BB AF FF mov bx, offset return _F000:FFAD EB C3 jmp short WritePCI_byte_SL ; Stack Less version, return to the address, written in bx (jmp bx) _F000:FFAD _F000:FFAF ; --------------------------------------------------------------------------- _F000:FFAF _F000:FFAF return: ; DATA XREF: WritePCI_byte_S+4o _F000:FFAF 5E pop si _F000:FFB0 66 5F pop edi _F000:FFB2 5B pop bx _F000:FFB3 C3 retn ; Return Near from Procedure _F000:FFB3 _F000:FFB3 WritePCI_byte_S endp