mirror of
https://github.com/stevenhowes/wbios.git
synced 2026-05-26 15:53:34 +01:00
Initial commit of 1.11 source as released by PC Engines
Original source https://www.pcengines.ch/file/wbios111s.zip
This commit is contained in:
@@ -0,0 +1,532 @@
|
||||
;
|
||||
; 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 021021 fix 32 bit call 03 -> pci3class instead of pci3find
|
||||
; (fix courtesy Mark Dieck)
|
||||
; 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 pci3class
|
||||
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
|
||||
Reference in New Issue
Block a user