;
; GRDB
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
; this module donated by:
;
;  Trung Nguyen <trungn@texmicro.com>
;
; a BIOS developer at texas micro inc.
;
;
; PCI.ASM
;
; Function: PCI commands
;
;
	;MASM MODE
	.MODEL SMALL
	.386

include  eprints.inc 
include  einput.inc 
include  emtrap.inc 

IODELAY MACRO
        out     0EDh, al
ENDM

	PUBLIC pci

	.data

	.CODE
pci	PROC
	lodsb
	cmp	al,'?'		; verify subcommand
        jz      pfaCmd          ; PFA command
	call	ReadNumber	; PFA
	jc	pciErr
        cmp     eax, 0FFFFh     ; Q:Valid PFA
        ja      pciErr          ;   N:
        mov     ebx, eax
	call	WadeSpace	; 
	jz	pciErr
	call	ReadNumber	; Reg
	jc	pciErr
        cmp     eax, 0FFh       ; Q:Valid Reg
        ja      pciErr          ;   N:
        mov     ah, al
        push    ax
	call	WadeSpace	; 
        pop     ax
	jnz	pciDoWrite
        call    PciByteRead
        push    ax
	call	crlf
        pop     ax        
        call    PrintByte
        jmp     pciNoErr

pciDoWrite:
        push    ax
	call	ReadNumber	; Value
	jc	pciErr
        cmp     eax, 0FFh       ; Q:Valid val
        ja      pciErr          ;   N:
        mov     cl, al
        pop     ax
        mov     al, cl
        push    ax
	call	WadeSpace	;
        pop     ax
	jnz	pciErr
        call    pciByteWrite
        jmp     pciNoErr

pfaCmd:
	call	WadeSpace	; get operator
	jz	pciErr
        xor     ebx, ebx
	call	ReadNumber	; Bus
	jc	pciErr
        cmp     eax, 0FFh       ; Q:Valid Bus
        ja      pciErr          ;   N:
        mov     bl, al          ;   Y: Get bus
        shl     bx, 8
	call	WadeSpace	; get operator
	jz	pciErr
	call	ReadNumber	; Dev
	jc	pciErr
        cmp     eax, 01Fh       ; Q:Valid Dev
        ja      pciErr          ;   N:
        mov     bl, al          ;   Y: Get Dev
        shl     bl, 3
	call	WadeSpace	; get operator
	jz	pciErr
	call	ReadNumber	; Func
	jc	pciErr
        cmp     eax, 07h        ; Q:Valid Func
        ja      pciErr          ;   N:
        or      bl, al
	call	WadeSpace
	jnz	pciErr
	call	crlf
        mov     ax, bx
        call    PrintWord

pciNoErr:
        clc
        jmp     pciDone

pciErr:
        stc

pciDone:
        ret        
pci	endp


;----------------------------------------------------------------------------
;       PciByteRead -
;       This proc will read the byte from the register and device
;
;       Entry:  BX = PFA 
;                    Bit<15..8>=Bus
;                    Bit<7...3>=Dev
;                    Bit<2..0>=Func
;               AH = Reg
;       Exit:
;               AL = register contents.
;       Affected registers:
;               AL is destroyed, all other registers are preserved.
;
PciByteRead PROC
        push    cx
        push    dx
        push    eax
        mov     ch, ah          ; Save register in CH
        mov     eax,0800000h
        or      ax, bx          ; Get PFA
        shl     eax, 8          ; Make room for register
        mov     al, ch          ; Place register info in location
        and     al,0FCh         ; Strip off alignment data.
        mov     dx,0CF8h        ;
        out     dx,eax
        IODELAY
        call    PointToByte     ; Align the PCI data port to out byte.
        in      al,dx           ; Fetch the data.
        IODELAY
        mov     cl, al          ; Save data first
        pop     eax
        mov     al, cl          ; Place data back
        pop     dx
        pop     cx
        ret
PciByteRead ENDP

;----------------------------------------------------------------------------
;       PciByteWrite - 
;       This proc will write a byte to the register and device
;
;       Entry:  BX = PFA 
;                    Bit<15..8>=Bus
;                    Bit<7...3>=Dev
;                    Bit<2..0>=Func
;               AH = Reg
;               AL = Value
;       Exit:
;               None.
;       Affected registers:
;               All registers are preserved.
;
PciByteWrite PROC
        push    cx
        push    dx
        push    eax
        mov     cx, ax          ; Save register and value in CX
        mov     eax,0800000h
        or      ax, bx          ; Get PFA
        shl     eax, 8          ; Make room for register
        mov     al, ch          ; Place register info in location
        and     al,0FCh         ; Strip off alignment data.
        mov     dx,0CF8h        ;
        out     dx,eax
        IODELAY
        call    PointToByte     ; Align the PCI data port to out byte.
        mov     al, cl          ; Get value back
        out     dx, al          ; BlastIT!!!!
        IODELAY
        pop     eax
        pop     dx
        pop     cx
        ret
PciByteWrite ENDP

;----------------------------------------------------------------------------
;       PointToByte
;       This proc provides the appropriate PCI IO port address to properly
;       access data in the PCI CFG space.
;       Entry:
;               CH = Register to use.
;       Exit:
;               DX = PCI data port IO address.
;       Affected registers:
;               DX is modified, all other registers are preserved.
;
PointToByte PROC
        push    cx
        and     cx,0300h        ; Strip all but byte information.
        xchg    ch, cl          ; Swap the LSB and MSB
        mov     dx,0CFCh        ; Base PCI IO port.
        add     dx,cx           ; Point to our register.
        pop     cx
        ret
PointToByte ENDP

end