;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; By Dex.                                  ;;
;; PCIFindDevice: scan through PCI space,   ;;
;; looking for a device+vendor ID.          ;;
;; C:\fasm pci.asm pci.com                  ;;   
;;                                          ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use16
org 0x100
;====================================================;
; Start.                                             ;
;====================================================;
start:
mov	ax,cs
mov	ds,ax
mov	es,ax
call	Cls
call	Cursor
call	Welcome
mov	ax,0801h			    ; put your Device ID here
shl	eax,16
mov	ax,1319h			    ; put your Vendor ID here
call	pciFindDevice
jnc	@f
mov	dx,NotFound			    ; couldn't find graphic card
mov	ah,9
int	21h
jmp	exit

WelcomeMessage db "Press any key to test for your card ",10,13,"$"
NotFound       db "Error: Unable to find graphic card",10,13,"$"
Found	       db "Found graphic card",10,13,"$"
@@:
mov	dx,Found			   ; Found graphic card
mov	ah,9
int	21h
exit:
xor	ax,ax
int	16h
int	20h
;===============================================================
; 8/16/32bit PCI reader
;
; Entry: EAX=PCI Bus/Device/fn/register number
;           BIT30 set if 32 bit access requested
;           BIT29 set if 16 bit access requested
;           otherwise defaults to 8bit read
;
; Exit:  DL,DX,EDX register data depending on requested read size
;
; Note: this routine is meant to be called via pciRegRead8, pciRegread16,
;  or pciRegRead32, listed below.
;
; Note2: don't attempt to read 32bits of data from a non dword aligned reg
;    number.  Likewise, don't do 16bit reads from non word aligned reg #
;
BIT30		EQU 40000000h
BIT31		EQU 80000000h
PCI_INDEX_PORT	EQU	0CF8h
PCI_DATA_PORT	EQU	0CFCh
PCI32		EQU	BIT31	       ; bitflag to signal 32bit access
PCI16		EQU	BIT30	       ; bitflag for 16bit access

VIA_VID 	equ	1106h	       ; VIAPCI vendor ID
VIA_DID 	equ	3058h	       ; VIA device ID

pciRegRead:
push	ebx
push	cx
mov	ebx,eax 		       ; save eax, dh
mov	cl,dh
and	eax,NOT PCI32+PCI16	       ; clear out data size request
or	eax,BIT31		       ; make a PCI access request
and	al,NOT 3		       ; force index to be dword
mov	dx,PCI_INDEX_PORT
out	dx,eax			       ; write PCI selector

mov	dx,PCI_DATA_PORT
mov	al,bl
and	al,3			       ; figure out which port to
add	dl,al			       ; read to

in	eax,dx			       ; do 32bit read
test	ebx,PCI32
jz	@f

mov	edx,eax 		       ; return 32bits of data
@@:
mov	dx,ax			       ; return 16bits of data
test	ebx,PCI32+PCI16
jnz	@f
mov	dh,cl			       ; restore dh for 8 bit read
@@:
mov	eax,ebx 		       ; restore eax
and	eax,NOT PCI32+PCI16	       ; clear out data size request
pop	cx
pop	ebx
ret

pciRegRead8:
and	eax,NOT PCI32+PCI16	       ; clear out data size request
jmp	pciRegRead		       ; call generic PCI access

pciRegRead16:
and	eax,NOT PCI32+PCI16	       ; clear out data size request
or	eax,PCI16		       ; call generic PCI access
jmp	pciRegRead

pciRegRead32:
and	eax,NOT PCI32+PCI16	       ; clear out data size request
or	eax,PCI32		       ; call generic PCI access
jmp	pciRegRead

;===============================================================
; PCIFindDevice: scan through PCI space looking for a device+vendor ID
;
; Entry: EAX=Device+vendor ID
;
;  Exit: EAX=PCI address if device found
;        CY clear if found, set if not found. EAX invalid if CY set.
;
; [old stackless] Destroys: ebx, edx, esi, edi, cl
;
pciFindDevice: 
push	cx
push	edx
push	esi
push	edi

mov	esi,eax 		     ; save off vend+device ID
mov	edi,(80000000h - 100h)	     ; start with bus 0, dev 0 func 0

nextPCIDevice:
add	edi,100h
cmp	edi,80fff800h		     ; scanned all devices?
stc
jz	PCIscanExit		     ; not found

mov	eax, edi		     ; read PCI registers
call	pciRegRead32
cmp	edx, esi		     ; found device?
jnz	nextPCIDevice
clc

PCIscanExit :
pushf
mov	eax,edi 		     ; return found PCI address
and	eax,NOT BIT31		     ; return only bus/dev/fn #
popf

pop	edi
pop	esi
pop	edx
pop	cx
ret

;====================================================;
;  Clear screen.                                     ;
;====================================================;
Cls:
mov	ax,0x0600
mov	bh,0x07
mov	cx,0x0000
mov	dx,0x184f
int	10h
ret
;====================================================;
;  Set cursor.                                       ;
;====================================================;
Cursor:
mov	ah,02
mov	bh,00
mov	dx,0x0100
int	10h
ret
;====================================================;
;  Welcome.                                          ;
;====================================================;
Welcome:
mov	dx,WelcomeMessage			    
mov	ah,9
int	21h
xor	ax,ax
int	16h
ret

VendorDeviceID dd 0
