|
再說軟件驅(qū)動,我說過我編的是vxd,用vtools編的,可以用vc++直接編譯成vxd文件,至于為什么必須用vxd驅(qū)動我想就不用說了。我的vxd的主要任務(wù)就是在系統(tǒng)中找到我的pci卡,并讀出本地芯片所映射的內(nèi)存物理地址,在windows系統(tǒng)中,用戶程序不能直接訪問物理地址,只能使用線性地址,所以vxd還有做的一件事就是將物理地址轉(zhuǎn)換成線性地址供win app使用。 vxd查找pci卡就是靠搜索vendorID和deviceID,它是通過依次搜索總線號和設(shè)備號(具體什么意思我也說不清,反正知道就行了),看是否有符合指定的vendorID和deviceID,如果符合則認為找到了pci卡的配置空間,因為配置空間的第一個雙字就是vendorID和deviceID.然后向下面的地址依次讀就可以讀出pci卡的配置空間其他信息,包括space0映射的內(nèi)存基地址。讀出此地址來再進行物理地址到線性地址的轉(zhuǎn)換,就可以完全供win app使用了(可以通過指針訪問),來讀取9052 local上掛的芯片了。 具體的查找方式主要通過vxd程序中首先向io地址0xcf8寫入最高位為1的雙字0x80000000,這個數(shù)的第16到23位代表了總線號,第11到15位代表了設(shè)備號,第8到14位代表了功能號,然后就可以讀取io地址0xcfc的雙字,如果有效的話說明此pci配置空間地址上掛了一個pci卡,從0xcfc讀出的數(shù)則為此pci卡配置空間的第一個雙字,即vendorID和deviceID,我是將vendorID和deviceID一起使用的,即判斷讀出的雙字是否等于我在9052配置eeprom中標定的數(shù),如果是則說明找到了我的pci卡,如果不是則繼續(xù)找。向0xcf8寫入的數(shù)+0x800,在繼續(xù) 讀0xcfc,依次下去,直到找到。如果當(dāng)此數(shù)加到0x80ffff00時還沒找到(即總線號搜索完畢),則表明沒法找到,那就要找找自己的原因了,可能是板子的配置錯了。 找到了pci卡的配置空間后,讀出space0的基地址,然后進行物理地址到線性地址的轉(zhuǎn)換,我又偷了懶,vtools提供的example中有實現(xiàn)此功能的vxd源代碼,直接用vc++編譯成vxd就可以共win app使用了。所以實際上我的app程序使用了兩個vxd,一個用來專門找卡,一個用來地址轉(zhuǎn)換。 至于app如何調(diào)用vxd,可以參看vc的參考書,一般都有介紹。 下面將一下如何安裝vxd到系統(tǒng)中,我編的vxd都是動態(tài)加載的(pnp一般都用動態(tài)加載vxd)要編寫一個inf文件以便系統(tǒng)將vxd安裝進去。我用的是windriver生成的inf文件模板,然后再按照需要進行修改,自然加上我的大名了。編完了inf文件后,就可以安裝了。一般情況如果你插上pci卡windows啟動后就會發(fā)現(xiàn)新硬件,你只要按照以前安裝硬件的步驟進行就可以了只是在選擇安裝文件時選擇自己編寫的inf文件就可以了。我覺得一般的安裝過程就是將vxd文件拷入系統(tǒng)的文件夾,即windows目錄下,以便當(dāng)app加載vxd時,系統(tǒng)可以找到vxd程序,進行動態(tài)加載。 下面是我的inf文件 : [Version] Signature=$CHICAGO$ ;必須這么寫 Class=PLX ;可以自己改 Provider=%SHENLI% ;制作者
[Manufacturer] %Manufacture%=SECTION0
[SECTION0] %my_card%=my.install,PCI\VEN_10b5&DEV_9050 ;my.install表示了安裝過程所要做的事,
[my.install] CopyFiles=CopyFiles_PLX10b5 ;主要做拷貝文件和注冊表添加 AddReg=AddReg_PLX10b5
[CopyFiles_PLX10b5] Vxd8_25.vxd
[AddReg_PLX10b5] HKR,,DevLoader,0,Vxd8_25.vxd
[Strings] Manufacture="BUAA202" ;這些信息會在安裝時顯示 my_card="PLX9052"
下面提供了vxd中查詢pci卡的代碼,這個代碼是參考清華bbs驅(qū)動版精華區(qū)huyuguang大蝦的大作,他提供了更詳細的代碼 有興趣可以參考。
BOOL findpci(DWORD DeviceVendor,PCIINF *pciinf)//我的卡的DeviceVendor=0x905210b5 { DWORD io_cf8; DWORD io_cfc; int i; DWORD buf[16];
io_cf8=0x80000000; for(;;) { DWORD_OUT(0xcf8,io_cf8);//向0xcf8輸出雙字 io_cf8 io_cfc=DWORD_IN(0xcfc); //從0xcfc讀入雙字 if(io_cfc==DeviceVendor)//find pci9052 { for(i=0;i<16;i++) { DWORD_OUT(0xcf8,io_cf8+4*i); buf[i]=DWORD_IN(0xcfc); } pciinf->VendorID=(WORD)(buf[0]&0xffff); pciinf->DeviceID=(WORD)((buf[0]&0xffff0000)/0x10000); pciinf->Command=(WORD)(buf[1]&0xffff); pciinf->Status=(WORD)((buf[1]&0xffff0000)/0x10000); pciinf->RevisionID=(UCHAR)(buf[2]&0xff); pciinf->CacheLineSize=(UCHAR)(buf[3]&0xff); pciinf->LatencyTimer=(UCHAR)((buf[3]&0xff00)/0x100); pciinf->HeaderType=(UCHAR)((buf[3]&0xff0000)/0x10000); pciinf->BIST=(UCHAR)((buf[3]&0xff000000)/0x1000000); pciinf->BaseAddresses[0]=buf[4]; pciinf->BaseAddresses[1]=buf[5]; pciinf->BaseAddresses[2]=buf[6]; pciinf->BaseAddresses[3]=buf[7]; pciinf->BaseAddresses[4]=buf[8]; pciinf->BaseAddresses[5]=buf[9]; pciinf->SubsystemVendorID=(USHORT)(buf[11]&0xffff); pciinf->SubsystemID=(USHORT)((buf[12]&0xffff0000)/0x10000); pciinf->InterruptLine=(UCHAR)(buf[15]&0xff); pciinf->InterruptPin=(UCHAR)((buf[15]&0xff00)/0x100); pciinf->MinimumGrant=(UCHAR)((buf[15]&0xff0000)/0x10000); pciinf->MaximumLatency=(UCHAR)((buf[15]&0xff000000)/0x1000000); break; } else io_cf8+=0x800; if(io_cf8>=0x80ffff00) return 1; } return 0; }
以上都是我這次制作卡的一些心得,還有很多不清楚的地方,寫出來只是想讓感興趣的pci門外漢了解一下,但愿能有所幫助?隙ㄓ泻芏噱e誤,希望各位大蝦指正,但求不會誤人子弟。pci大蝦見笑了。
|