?? pci.8
字號:
;
; PCI BIOS
;
; (C)1997-2001 Pascal Dornier / PC Engines; All rights reserved.
; This file is licensed pursuant to the COMMON PUBLIC LICENSE 0.5.
;
; pd 990525 rewrite 32 bit BIOS to avoid any data accesses
; (Linux hang)
;
; Limitations:
;
; - Interrupt probe / reassign functions not implemented.
;
; I/O ports
;
pci_ver equ 0210h ;PCI version reported
bios3seg equ 000fh ;$f000 / 4096
;
; 32 bit pusha stack frame
;
_eax equ 1ch
_ebx equ 10h
_ecx equ 18h
_edx equ 14h
_ebp equ 08h
_esi equ 04h
_edi equ 00h
_efl equ 24h ;flags
;
; PCI INT1A functions
;
pci_i1a: pushad ;build stack frame
mov bp,sp
mov ah,0 ;command code -> vector
cmp al,0fh ;max command
ja pci_badc0 ;:bad
add ax,ax
mov si,ax
call [cs:si+pci_vec] ;dispatch command
pci_i1a2: jb pci_i1a4 ;:error
mov al,0 ;ok status
and byte [bp._efl],0feh ;clear carry flag
pci_i1a3: mov byte [bp._eax+1],al ;return status code -> AH
popad
iret
;
; bad command
;
pci_badc: pop ax ;pop return address
pci_badc0: mov al,81h ;bad command
;
; return error
;
pci_i1a4: or byte [bp._efl],1 ;set carry flag
jmp pci_i1a3
;
; dispatch table
;
even
pci_vec: dw pci_badc ;00: bad command
dw pci_pres ;01: PCI BIOS present
dw pci_find ;02: find PCI device
dw pci_class ;03: find PCI class code
dw pci_badc ;04: invalid
dw pci_badc ;05: invalid
dw pci_spec ;06: generate special cycle
dw pci_badc ;07: invalid
dw pci_readb ;08: read config byte
dw pci_readw ;09: read config word
dw pci_readd ;0A: read config dword
dw pci_writb ;0B: write config byte
dw pci_writw ;0C: write config word
dw pci_writd ;0D: write config dword
dw pci_badc ;0E: get IRQ routing options
;not implemented
dw pci_badc ;0F: set PCI IRQ
;not implemented
;
; 01: PCI BIOS present
;
pci_pres: mov word [bp._ebx],pci_ver ;PCI 2.1 -> BX
mov dword [bp._edx],20494350h ;"PCI " -> DX
mov al,byte [cs:d_lastbus] ;number of last PCI bus -> CL
mov byte [bp._ecx],al
mov byte [bp._eax],11h ;hardware mechanism 1 -> AL
clc
ret
;
; 08: read config byte
;
pci_readb: mov ax,0ff00h ;address mask (forbidden bits)
call pci_idx ;set index
in al,dx ;read data
mov [bp._ecx],al ;return in CL
ret
;
; 09: read config word
;
pci_readw: mov ax,0ff01h ;address mask
call pci_idx ;set index
in ax,dx ;read data
mov [bp._ecx],ax ;return in CX
ret
;
; 0A: read config dword
;
pci_readd: mov ax,0ff03h ;address mask
call pci_idx ;set index
in eax,dx ;read data
mov [bp._ecx],eax ;return in ECX
ret
;
; 0B: write config byte
;
pci_writb: mov ax,0ff00h ;address mask
call pci_idx ;set index
out dx,al ;write data
ret
;
; 0C: write config word
;
pci_writw: mov ax,0ff01h ;address mask
call pci_idx ;set index
out dx,ax ;write data
ret
;
; 06: generate special cycle
;
pci_spec: cmp bh,byte [cs:d_lastbus] ;bus number ok ?
ja pci_badc ;:bad
mov bl,0ffh ;device number = FF
mov ecx,edx ;special cycle data -> ECX
xor di,di ;register number 0
;fall through
;
; 0D: write config dword
;
pci_writd: mov ax,0ff03h ;address mask
call pci_idx ;set index
out dx,eax ;write data
ret
;
; set PCI configuration index
;
pci_idx: test di,ax ;any "forbidden" bits set ?
jnz pci_idx1
mov dx,pci_ad
mov ah,80h ;configuration enable
mov al,bh ;bus number
shl eax,16 ;-> high word
mov ax,di ;register number
and al,0fch ;clear lower bits
mov ah,bl ;device number / function number
out dx,eax ;set index
mov dl,low(pci_dat)
and di,3 ;low bits of register
add dx,di ;update register pointer (implicit clc)
mov eax,ecx ;write data -> EAX
ret
pci_idx1: pop ax ;return address
mov al,87h ;bad register number
stc
ret ;return to dispatcher
;
; 02: find PCI device
;
pci_find: inc dx ;vendor ID FFFF ?
jnz pci_find2 ;:ok
mov al,83h ;bad vendor ID
stc
ret
pci_find2: dec dx ;restore vendor ID
mov ebx,80000000h ;bus address
shl ecx,16 ;device ID -> bits 31..16
mov cx,dx ;vendor ID -> bits 15..00
mov esi,0ffffffffh ;mask
jmp short pci_find3
;
; 03: find PCI class code
;
pci_class: shl ecx,8 ;class code is bits 31..08
mov esi,0ffffff00h ;mask
mov ebx,80000000h+p_class ;bus address
pci_find3: mov di,[bp._esi] ;restore device index
;
; search all buses / devices
;
pci_find4: mov dx,pci_ad
mov eax,ebx ;device address
mov al,p_id ;vendor / device ID
out dx,eax
mov dl,low(pci_dat)
in eax,dx ;read device / vendor ID
cmp ax,0ffffh ;not present ?
jz pci_find7 ;:skip entire device
cmp bl,0 ;looking for class code ?
jz pci_find5 ;:no
mov dl,low(pci_ad)
mov eax,ebx ;restore register offset
out dx,eax
mov dl,low(pci_dat)
in eax,dx ;read class code
pci_find5: and eax,esi ;mask relevant bits
cmp eax,ecx ;same ?
jnz pci_find6 ;:no
dec di ;device count
js pci_found ;:this is the one
; try next function
pci_find6: test bh,7 ;function 0 ?
jnz pci_find8 ;:no
mov dl,low(pci_ad)
mov eax,ebx ;index
mov al,p_hedt and 0fch ;header type
out dx,eax
mov dl,low(pci_dat) + 2
in al,dx ;read header type
test al,80h ;multifunction device ?
jnz pci_find8 ;:yes
pci_find7: or bh,7 ;skip the rest of this device
; try next device / function
pci_find8: inc bh ;next device / function
jnz pci_find4 ;:ok
; try next bus
ror ebx,16
inc bx ;next bus
cmp bl,byte [cs:d_lastbus]
ja pci_find9 ;:not found
ror ebx,16 ;restore
jmp pci_find4
; didn't find it
pci_find9: mov al,86h ;device not found
stc
ret
; found device
pci_found: shr ebx,8 ;return bus, device number in BX
mov [bp._ebx],bx
clc ;ok return
ret
#if ! def NO_PCI32
;
; 32 bit PCI BIOS entry point
;
use32
pci_32: pushad ;build stack frame
mov ebp,esp
cmp al,0ah ;0A: read config dword
jnz pci_3a
call pci3readd
jmp short pci_3z
pci_3a: cmp al,09 ;09: read config word
jnz pci_3b
call pci3readw
jmp short pci_3z
pci_3b: cmp al,08 ;08: read config byte
jnz pci_3c
call pci3readb
jmp short pci_3z
pci_3c: cmp al,0dh ;0D: write config dword
jnz pci_3d
call pci3writd
jmp short pci_3z
pci_3d: cmp al,0ch ;0C: write config word
jnz pci_3e
call pci3writw
jmp short pci_3z
pci_3e: cmp al,0bh ;0B: write config byte
jnz pci_3f
call pci3writb
jmp short pci_3z
pci_3f: cmp al,01 ;01: PCI BIOS present
jnz pci_3g
call pci3pres
jmp short pci_3z
pci_3g: cmp al,02 ;02: find PCI device
jnz pci_3h
call pci3find
jmp short pci_3z
pci_3h: cmp al,03 ;03: find PCI class code
jnz pci_3j
call pci3find
jmp short pci_3z
pci_3j: cmp al,06 ;06: generate special cycle
jnz pci_3k
call pci3spec
jmp short pci_3z
pci_3k: call pci3badc ;others: bad commands
pci_3z: jb pci_32b ;:error
mov al,0 ;return ok status
pci_32b: mov [ebp._eax+1],al ;status code -> AH
popad ;restore registers
retf
;
; bad command
;
pci3badc: mov al,81h ;return error code
stc
ret
;
; 01: PCI BIOS present
;
pci3pres: mov word [ebp._ebx],pci_ver ;PCI 2.1 -> BX
mov dword [ebp._edx],20494350h ;"PCI " -> EDX
call getlbus ;get number of last PCI bus -> AL
mov [ebp._ecx],al ;-> return in CL
mov byte [ebp._eax],11h ;hardware mechanism 1 -> AL
clc
ret
;
; 08: read config byte
;
pci3readb: mov al,0 ;address mask (forbidden bits)
call pci3idx ;set index
in al,dx ;read data
mov [ebp._ecx],al ;return in CL
ret
;
; 09: read config word
;
pci3readw: mov al,1 ;address mask
call pci3idx ;set index
in ax,dx ;read data
mov [ebp._ecx],ax ;return in CX
ret
;
; 0A: read config dword
;
pci3readd: mov al,03 ;address mask
call pci3idx ;set index
in eax,dx ;read data
mov [ebp._ecx],eax ;return in ECX
ret
;
; 0B: write config byte
;
pci3writb: mov al,00 ;address mask
call pci3idx ;set index
out dx,al ;write data
ret
;
; 0C: write config word
;
pci3writw: mov al,01 ;address mask
call pci3idx ;set index
out dx,ax ;write data
ret
;
; 06: generate special cycle
;
pci3spec: call getlbus ;bus number ok ?
cmp bh,al
ja pci3badc ;:bad
mov bl,0ffh ;device number = FF
mov ecx,edx ;special cycle data -> ECX
xor edi,edi ;register number 0
;fall through
;
; 0D: write config dword
;
pci3writd: mov al,03 ;address mask
call pci3idx ;set index
out dx,eax ;write data
ret
;
; set PCI configuration index
;
pci3idx: ror ebx,8
mov bh,80h
rol ebx,16
mov dx,[ebp._edi] ;get index
test dl,al ;forbidden bits set ?
jnz pci3idx1 ;:yes
and dh,dh ;high byte ?
jnz pci3idx1 ;:yes
mov bl,dl ;set index
mov dx,pci_ad ;set port address
mov eax,ebx ;get index -> eax
and al,0fch ;mask low bits
out dx,eax ;set index
mov dl,bl ;get low address
or dl,low(pci_dat) ;assume pci_dat $fc (implicit clc)
mov eax,ecx ;write data -> EAX
ret
pci3idx1: pop eax ;return address
mov al,87h ;bad register number
stc
ret ;return to dispatcher
;
; 02: find PCI device
;
pci3find: inc dx ;vendor ID FFFF ?
jnz pci3find2 ;:ok
mov al,83h ;bad vendor ID
stc
ret
pci3find2: dec dx ;restore vendor ID
mov ebx,80000000h ;bus address
shl ecx,16 ;device ID -> bits 31..16
mov cx,dx ;vendor ID -> bits 15..00
mov edi,0ffffffffh ;mask
jmp short pci3find4
;
; 03: find PCI class code
;
pci3class: shl ecx,8 ;class code is bits 31..08
mov edi,0ffffff00h ;mask
mov ebx,80000000h+p_class ;bus address
;
; search all buses / devices
;
pci3find4: mov dx,pci_ad
mov eax,ebx ;device address
mov al,p_id ;vendor / device ID
out dx,eax
mov dl,low(pci_dat)
in eax,dx ;read device / vendor ID
cmp ax,0ffffh ;not present ?
jz pci3find7 ;:skip entire device
cmp bl,0 ;looking for class code ?
jz pci3find5 ;:no
mov dl,low(pci_ad)
mov eax,ebx ;restore register offset
out dx,eax
mov dl,low(pci_dat)
in eax,dx ;read class code
pci3find5: and eax,edi ;mask relevant bits
cmp eax,ecx ;same ?
jnz pci3find6 ;:no
dec si ;device count
js pci3found ;:this is the one
; try next function
pci3find6: test bh,7 ;function 0 ?
jnz pci3find8 ;:no
mov dl,low(pci_ad)
mov eax,ebx ;index
mov al,p_hedt and 0fch ;header type
out dx,eax
mov dl,low(pci_dat) + 2
in al,dx ;read header type
test al,80h ;multifunction device ?
jnz pci3find8 ;:yes
pci3find7: or bh,7 ;skip the rest of this device
; try next device / function
pci3find8: inc bh ;next device / function
jnz pci3find4 ;:ok
; try next bus
ror ebx,16
inc bl ;next bus
call getlbus
cmp bl,al
ja pci3find9 ;:not found
ror ebx,16 ;restore
jmp short pci3find4
; didn't find it
pci3find9: mov al,86h ;device not found
stc
ret
; found device
pci3found: shr ebx,8 ;return bus, device number in BX
mov [ebp._ebx],bx
clc ;ok return
ret
;
; 32 bit BIOS entry point
;
bios_32: and ebx,ebx ;valid function code ?
jz bios_32a ;:ok
mov al,81h ;unimplemented function
retf
bios_32a: cmp eax,49435024h ;$PCI
jz bios_32b ;:ok
mov al,80h ;service is not present
retf
bios_32b: mov al,0 ;ok status
mov ebx,bios3seg shl 16 ;BIOS segment base = $000f 0000
mov ecx,10000h ;length of BIOS service = 64K
mov edx,pci_32 ;offset from ebx base
retf
use16
;
; 32 bit BIOS header
;
db (($+15) and 0fff0h)-$ dup 0ffh ;even 16
bios_32hd db "_32_"
dw bios_32 ;entry point
dw bios3seg ;BIOS segment
db 0 ;revision level 0
db 1 ;length (16 byte units)
db 0 ;checksum (bios_32hd) - filled in
;by BIOSSUM.EXE.
db 0,0,0,0,0 ;reserved
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -