;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; PCI32.INC ;; ;; ;; ;; 32 bit PCI driver code ;; ;; ;; ;; Version 0.2 December 21st, 2002 ;; ;; ;; ;; Author: Victor Prodan, victorprodan@yahoo.com ;; ;; Credits: ;; ;; Ralf Brown ;; ;; Mike Hibbett, mikeh@oceanfree.net ;; ;; ;; ;; See file COPYING for details ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;*************************************************************************** ; Function ; pci_api: ; ; Description ; entry point for system PCI calls ;*************************************************************************** align 4 pci_api: cmp [pci_access_enabled],1 jne no_pci_access_for_applications or al,al jnz pci_fn_1 ; PCI function 0: get pci version (AH.AL) movzx eax,word [0x2F0000+0x9022] ret pci_fn_1: cmp al,1 jnz pci_fn_2 ; PCI function 1: get last bus in AL mov al,[0x2F0000+0x9021] ret pci_fn_2: cmp al,2 jne pci_fn_3 ; PCI function 2: get pci access mechanism mov al,[0x2F0000+0x9020] ret pci_fn_3: cmp al,4 jz pci_read_reg ;byte cmp al,5 jz pci_read_reg ;word cmp al,6 jz pci_read_reg ;dword cmp al,8 jz pci_write_reg ;byte cmp al,9 jz pci_write_reg ;word cmp al,10 jz pci_write_reg ;dword no_pci_access_for_applications: mov eax,-1 ret ;*************************************************************************** ; Function ; pci_make_config_cmd ; ; Description ; creates a command dword for use with the PCI bus ; bus # in ah ; device+func in bh (dddddfff) ; register in bl ; ; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 ) ;*************************************************************************** align 4 pci_make_config_cmd: shl eax,8 ; move bus to bits 16-23 mov ax,bx ; combine all and eax,0xffffff or eax,0x80000000 ret ;*************************************************************************** ; Function ; pci_read_reg: ; ; Description ; read a register from the PCI config space into EAX/AX/AL ; IN: ah=bus,device+func=bh,register address=bl ; number of bytes to read (1,2,4) coded into AL, bits 0-1 ;*************************************************************************** align 4 pci_read_reg: cmp byte [0x2F0000+0x9020],2 ;what mechanism will we use? je pci_read_reg_2 ; mechanism 1 push esi ; save register size into ESI mov esi,eax and esi,3 call pci_make_config_cmd mov ebx,eax ; get current state mov dx,0xcf8 in eax, dx push eax ; set up addressing to config data mov eax,ebx and al,0xfc ; make address dword-aligned out dx,eax ; get requested DWORD of config data mov dl,0xfc and bl,3 or dl,bl ; add to port address first 2 bits of register address or esi,esi jz pci_read_byte1 cmp esi,1 jz pci_read_word1 cmp esi,2 jz pci_read_dword1 jmp pci_fin_read1 pci_read_byte1: in al,dx jmp pci_fin_read1 pci_read_word1: in ax,dx jmp pci_fin_read1 pci_read_dword1: in eax,dx jmp pci_fin_read1 pci_fin_read1: ; restore configuration control xchg eax,[esp] mov dx,0xcf8 out dx,eax pop eax pop esi ret pci_read_reg_2: test bh,128 ;mech#2 only supports 16 devices per bus jnz pci_read_reg_err push esi ; save register size into ESI mov esi,eax and esi,3 push eax ;store current state of config space mov dx,0xcf8 in al,dx mov ah,al mov dl,0xfa in al,dx xchg eax,[esp] ; out 0xcfa,bus mov al,ah out dx,al ; out 0xcf8,0x80 mov dl,0xf8 mov al,0x80 out dx,al ; compute addr shr bh,3 ; func is ignored in mechanism 2 or bh,0xc0 mov dx,bx or esi,esi jz pci_read_byte2 cmp esi,1 jz pci_read_word2 cmp esi,2 jz pci_read_dword2 jmp pci_fin_read2 pci_read_byte2: in al,dx jmp pci_fin_read2 pci_read_word2: in ax,dx jmp pci_fin_read2 pci_read_dword2: in eax,dx ; jmp pci_fin_read2 pci_fin_read2: ; restore configuration space xchg eax,[esp] mov dx,0xcfa out dx,al mov dl,0xf8 mov al,ah out dx,al pop eax pop esi ret pci_read_reg_err: xor eax,eax dec eax ret ;*************************************************************************** ; Function ; pci_write_reg: ; ; Description ; write a register from ECX/CX/CL into the PCI config space ; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, ; value to write in ecx ; number of bytes to write (1,2,4) coded into AL, bits 0-1 ;*************************************************************************** align 4 pci_write_reg: cmp byte [0x2F0000+0x9020],2 ;what mechanism will we use? je pci_write_reg_2 ; mechanism 1 push esi ; save register size into ESI mov esi,eax and esi,3 call pci_make_config_cmd mov ebx,eax ; get current state into ecx mov dx,0xcf8 in eax, dx push eax ; set up addressing to config data mov eax,ebx and al,0xfc ; make address dword-aligned out dx,eax ; write DWORD of config data mov dl,0xfc and bl,3 or dl,bl mov eax,ecx or esi,esi jz pci_write_byte1 cmp esi,1 jz pci_write_word1 cmp esi,2 jz pci_write_dword1 jmp pci_fin_write1 pci_write_byte1: out dx,al jmp pci_fin_write1 pci_write_word1: out dx,ax jmp pci_fin_write1 pci_write_dword1: out dx,eax jmp pci_fin_write1 pci_fin_write1: ; restore configuration control pop eax mov dl,0xf8 out dx,eax xor eax,eax pop esi ret pci_write_reg_2: test bh,128 ;mech#2 only supports 16 devices per bus jnz pci_write_reg_err push esi ; save register size into ESI mov esi,eax and esi,3 push eax ;store current state of config space mov dx,0xcf8 in al,dx mov ah,al mov dl,0xfa in al,dx xchg eax,[esp] ; out 0xcfa,bus mov al,ah out dx,al ; out 0xcf8,0x80 mov dl,0xf8 mov al,0x80 out dx,al ; compute addr shr bh,3 ; func is ignored in mechanism 2 or bh,0xc0 mov dx,bx ; write register mov eax,ecx or esi,esi jz pci_write_byte2 cmp esi,1 jz pci_write_word2 cmp esi,2 jz pci_write_dword2 jmp pci_fin_write2 pci_write_byte2: out dx,al jmp pci_fin_write2 pci_write_word2: out dx,ax jmp pci_fin_write2 pci_write_dword2: out dx,eax jmp pci_fin_write2 pci_fin_write2: ; restore configuration space pop eax mov dx,0xcfa out dx,al mov dl,0xf8 mov al,ah out dx,al xor eax,eax pop esi ret pci_write_reg_err: xor eax,eax dec eax ret