📄 pcipnp.8
字号:
call pci_rnd
mov si,p_memp ;prefetch memory: 1MB boundaries
;mov dx,P_MEMINC1 ;primary bus
;mov di,P_MEMINC2 ;secondary bus
;mov cl,0fh
call pci_rnd
mov si,p_io ;I/O: 4K boundaries
mov cl,0ffh
mov dx,P_IOINC1 ;primary bus
mov di,P_IOINC2 ;secondary bus
call pci_rnd
;set bridge base and limit registers
mov bl,pb_mem ;memory base / limit
mov eax,[p_mem] ;+ p_memlim
sub eax,10000h ;-> inclusive limit
call pci_setd
mov bl,pb_memp ;prefetchable base / limit
mov eax,[p_memp] ;+ p_memplim
sub eax,10000h ;-> inclusive limit
call pci_setd
mov bl,pb_io ;I/O base / limit
mov al,[p_io+1]
mov ah,[p_iolim+1]
dec ah ;-> inclusive limit
call pci_setw
;clear high registers
xor eax,eax ;clear high memory base
mov bl,pb_mem2
call pci_setd
mov bl,pb_memp2 ;clear high prefetchable base
call pci_setd
mov bl,pb_io2 ;clear high I/O base
call pci_setd
; save variables for recursion
push word [p_capa]
push dword [p_int]
mov word [p_capa],80h ;bus capabilities
mov bl,pb_stat ;read secondary status
call pci_getw
and byte [p_capa],al ;clear fast back to back if not supportd
or byte [p_capa+1],ah ;set devsel timing
mov bl,p_cmd ;command register: enable bus master
call pci_getw
or al,04
mov bl,p_cmd
call pci_setw
push ebx ;save current EBX
rol dword [p_int],8 ;precompensate for interrupt rotation
call pci_bus ;enumerate this bus
call pci_capa ;set capability flags
; limit -> new allocation pointer
mov ax,[p_memlim] ;memory
mov [p_mem],ax
mov ax,[p_memplim] ;prefetchable memory
mov [p_memp],ax
mov ax,[p_iolim] ;I/O
mov [p_io],ax
; restore variables
pop ebx ;restore after recursion
pop dword [p_int]
pop word [p_capa]
pop word [p_iolim]
pop word [p_memplim]
pop word [p_memlim]
pop ax
mov [p_bus],ax
mov al,[p_lastbus] ;set correct subordinate bus number
mov bl,pb_bus3
call pci_setb
mov bl,pb_ctl ;set bridge control register
mov ax,P_BRIDGE
and byte [p_capa],80h ;isolate fast back to back bit
or al,byte [p_capa] ;copy to control register
call pci_setw
ret
;
; get next interrupt assignment
;
pci_nint: test bh,7 ;function 0 ?
jnz pci_nint4 ;no: same interrupts
cmp byte [p_bus],0 ;primary bus ?
jnz pci_nint5 ;:no
cmp word [p_irqpt],pci_tab9 ;end of IRQ table ?
jz pci_nint4 ;yes: don't change
mov si,[p_irqpt] ;get next table entry
cs: lodsd
mov [p_irqpt],si
mov [p_int],eax ;save interrupt setting
pci_nint4: ret
pci_nint5: ror dword [p_int],8 ;rotate interrupts
ret
;
; enumerate a bus - called recursively
;
pci_bus: mov bh,80h ;enable config access
mov bl,[p_bus] ;bus number
shl ebx,16 ;device, function = 0
; check vendor ID, 0 or FFFF = nothing there, skip device
pci_bus0: call pci_nint ;get next interrupt assignment
mov bl,p_id ;get vendor / device ID
call pci_getd
inc ax ;FFFF = not present
jz pci_bus4 ;:skip device
dec ax ;0000 = no more functions
jz pci_bus4 ;:skip device
call pci_airq ;assign interrupts
call pci_vga ;handle PCI VGA
; check header type, different handling if bridge
mov bl,p_hedt ;get header type
call pci_getb
and al,7fh
cmp al,1 ;bridge
jz pci_bus1
#if def PCI_NORST
cmp bh,PCI_NORST ;don't touch base registers on this
jz pci_bus3 ;device (pd 980728: was jz pci_bus2)
#endif
#if def PCI_NORST2
cmp bh,PCI_NORST2
jz pci_bus3
#endif
mov cl,p_cis ;end index for normal device
call pci_dev ;allocate resources
jmp short pci_bus2
pci_bus1: mov cl,pb_bus ;end index for bridge
call pci_dev ;allocate resources
call pci_bri ;enumerate secondary buses
; try next function
pci_bus2: test bh,7 ;function 0 ?
jnz pci_bus4 ;:no, try next subfunction
; function 0 - is this a multifunction device
mov bl,p_hedt ;get header type
call pci_getb
and al,80h
jnz pci_bus4 ;:yes, multifunction device
pci_bus3: or bh,7 ;step to next device
pci_bus4: inc bh
jnz pci_bus0
mov ax,[p_mem] ;check allocation limits
cmp ax,[p_memlim]
ja pci_bus9 ;:error
mov ax,[p_memp]
cmp ax,[p_memplim]
ja pci_bus9 ;:error
mov ax,[p_io]
cmp ax,[p_iolim]
ja pci_bus9
ret
pci_bus9: mov al,0e5h ;error !
pci_err9: call postcode ;pd 980728: don't do direct I/O
pci_err99: jmp pci_err99
;
; handle PCI VGA
;
pci_vga: mov bl,p_class ;read class ID
call pci_getd
shr eax,16 ;check high 16 bits
cmp ax,0300h ;VGA ?
jnz pci_vga9 ;:no
mov bl,p_cmd ;enable memory access
call pci_getw
push ax
or al,2
call pci_setw
mov bl,p_rom ;enable ROM - at P_ROM0
mov esi,P_ROM0 shl 16
mov eax,esi
inc ax ;low bit = 1 -> enable
call pci_setd
push ebx ;save ebx context
call getunreal ;enter unreal mode
mov ax,[esi]
cmp ax,0aa55h ;ROM header ?
jnz pci_vga2 ;:no
call cs_vshad2 ;copy video BIOS to shadow RAM
;(chipset specific)
pci_vga2: pop ebx ;restore ebx
xor eax,eax ;disable ROM
call pci_setd
pop ax ;restore command register
mov bl,p_cmd
call pci_setw
xor ax,ax ;restore segment (from unreal mode)
mov ds,ax
mov es,ax
pci_vga9: ret
;
; set capability bits & enable devices
;
pci_capa: xor bx,bx ;start with device / function 0
mov cx,P_COMMAND ;standard command value
cmp byte [p_capa],80h ;all devices back-to-back capable ?
jnz pci_capa1 ;:no
or ch,02 ;enable fast back-to-back mode
pci_capa1: mov bl,p_id ;get vendor / device ID
call pci_getw
inc ax ;FFFF = not present
jz pci_capa4 ;:skip device
dec ax ;0000 = no more functions
jz pci_capa4 ;:skip device
mov bl,p_cmd ;read command register
call pci_getw
and ax,0ff5fh ;clear stepping, palette snoop bits
or ax,cx ;enable according to P_COMMAND
call pci_setw ;set command register
#if def P_LINSIZE
mov bl,p_linesz
mov al,P_LINSIZE
call pci_setb
#endif
; try next function
test bh,7 ;function 0 ?
jnz pci_capa4 ;:no, try next subfunction
; function 0 - is this a multifunction device
mov bl,p_hedt ;get header type
call pci_getb
; mov eax,ebx ;device address
; mov al,p_hedt and 0fch ;header type
; mov dx,pci_ad
; out dx,eax
; mov dl,low(pci_dat) + 2
; in al,dx
and al,80h
jnz pci_capa4 ;:yes, multifunction device
or bh,7 ;step to next device
pci_capa4: inc bh
jnz pci_capa1
ret
;
; PCI plug & play configuration
;
; EAX = scratch
; EBX = 80 / bus / device / function / index
; CX = scratch
; DX = port address
; SI = scratch
; DI = scratch
; BP = scratch
;
pci_pnp: mov word [p_mem],P_MEM0 ;set starting addresses
mov word [p_memp],P_MEMP0
mov word [p_memr],P_MEMR0
mov word [p_io],P_IO0
mov word [p_memlim],P_MEM9 ;set allocation limits
mov word [p_memplim],P_MEMP9
mov word [p_memrlim],P_MEMR9
mov word [p_iolim],P_IO9
;mov byte [p_bus],0
;mov byte [p_lastbus],0
mov word [p_irqpt],offset pci_tab
call pci_bus ;enumerate bus
call pci_capa ;set capability flags
mov al,[p_lastbus] ;set number of last PCI bus
mov byte [cs:d_lastbus],al
ret
;
; Disable all devices on primary bus
;
; NOTE: Called without stack ! On a chipset with PCI reset
; function, PCI reset is the easier way...
;
pci_rst:
#if def PCI_NOCLR
ret
#else
#if def PCI_NORST
mov eax,p_cmd+80000800h ;start with device 1 (don't cut off
;chipset)
#else
mov eax,p_cmd+80000000h ;access bus 0, device 0, function 0
#endif
pci_rst1:
#if def PCI_NORST
cmp ah,PCI_NORST ;don't reset this device
jnz pci_rst2
add ah,8
pci_rst2:
#endif
mov dx,pci_ad
out dx,eax ;write index
xchg ax,bx
mov dl,low(pci_dat)
in ax,dx ;read command register
and ax,0fff8h ;disable bus master, I/O, memory access
xchg ax,bx
mov dl,low(pci_ad)
out dx,eax ;write index
xchg ax,bx
mov dl,low(pci_dat)
out dx,ax ;write command register
xchg ax,bx
inc ah ;next device / function
jnz pci_rst1
ret
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -