第三階段:獲取注冊(cè)庫(kù)中各種控制信息,如用戶定義的非頁(yè)內(nèi)存大;第四階段:初始化注冊(cè)庫(kù) registrymachine下system和hardware并創(chuàng)建currentcontrolset,為裝入相關(guān)硬件設(shè)備驅(qū)動(dòng)程序作準(zhǔn)備;
第五階段:裝入基本核心驅(qū)動(dòng)程序;
第六階段:釋放一些已經(jīng)完成使命的裝入初始數(shù)據(jù)塊;
第七階段:進(jìn)一步初始化注冊(cè)庫(kù),以便有些依賴于基本核心驅(qū)動(dòng)程序的上層驅(qū)動(dòng)程序能順利裝入;
第八階段:服務(wù)控制器裝入應(yīng)該由該服務(wù)控制器裝入的各種驅(qū)動(dòng)程序。
§2.2.2 fddi網(wǎng)卡驅(qū)動(dòng)程序的加載過(guò)程
在windows nt啟動(dòng)的第五個(gè)階段,將加載核心驅(qū)動(dòng)程序。而對(duì)于ndis網(wǎng)卡驅(qū)動(dòng)程序是在ndis接口(ndis.sys)加載后調(diào)入運(yùn)行,向ndis wrapper注冊(cè)、初始化、查詢?cè)O(shè)置參數(shù)等。
windows nt啟動(dòng)時(shí),相應(yīng)的實(shí)體如nt的服務(wù)控制器根據(jù)注冊(cè)庫(kù)中yhfddi驅(qū)動(dòng)程序的配置注冊(cè)信息,初始化ndis wrapper,并裝入相應(yīng)的驅(qū)動(dòng)程序,生成驅(qū)動(dòng)程序管理塊結(jié)構(gòu),申請(qǐng)內(nèi)存以保存各種信息,向ndis wrapper注冊(cè)驅(qū)動(dòng)程序。初始化和注冊(cè)完畢后,再由服務(wù)控制器讀取注冊(cè)庫(kù)中相應(yīng)的鏈接信息。
在ndis wrapper和yhfddi驅(qū)動(dòng)程序初始化和注冊(cè)成功后,ndis wrapper根據(jù)系統(tǒng)相應(yīng)的注冊(cè)信息,加入和yhfddi驅(qū)動(dòng)程序所對(duì)應(yīng)的fddi網(wǎng)卡,同時(shí)讀入網(wǎng)卡的注冊(cè)信息,并進(jìn)行網(wǎng)卡注冊(cè)和網(wǎng)卡初始化。
在以上過(guò)程成功后,wrapper將查詢和設(shè)置驅(qū)動(dòng)程序的各種參數(shù),了解驅(qū)動(dòng)程序?qū)δ男┎僮髦С,決定對(duì)上層驅(qū)動(dòng)程序的支持范圍。
第三節(jié)fddi網(wǎng)卡驅(qū)動(dòng)程序的注冊(cè)
driverentry函數(shù)是windows nt ddk規(guī)定的核心驅(qū)動(dòng)程序的入口點(diǎn),wrapper識(shí)別到入口點(diǎn)后,調(diào)入驅(qū)動(dòng)程序,在driverentry函數(shù)內(nèi)完成兩個(gè)基本注冊(cè)任務(wù):
調(diào)用ndisminitializewapper函數(shù)向ndis接口報(bào)告驅(qū)動(dòng)程序?qū)⒁詍iniport類(lèi)網(wǎng)卡驅(qū)動(dòng)程序注冊(cè)。ndis建立它需要記錄的驅(qū)動(dòng)程序狀態(tài)信息,同時(shí)返回ndiswrapperhandle,驅(qū)動(dòng)程序保存這個(gè)句柄,以利后來(lái)調(diào)用ndisxxxconfiguration和initialization等函數(shù)。
填寫(xiě)ndisxx_miniport_characteristics屬性結(jié)構(gòu),主要記錄ndis版本號(hào)和驅(qū)動(dòng)程序支持的miniportxxx函數(shù)的入口點(diǎn),然后調(diào)用ndismregisterminiport函數(shù)實(shí)現(xiàn)驅(qū)動(dòng)程序的整體注冊(cè)。
以yhfddi為例所要注冊(cè)的屬性結(jié)構(gòu)的內(nèi)容大致如下:
ndis_miniport_characteristics yhfddichar;
(ndis_miniport_characteristics這個(gè)結(jié)構(gòu)將在第三章介紹)
yhfddichar.majorndisversion=yhfddi_ndis_major_version;
yhfddichar.minorndisversion=yhfddi_ndis_minor_version;
這兩個(gè)屬性決定驅(qū)動(dòng)程序是ndis的哪個(gè)版本所支持,我們所用的是ndis3.0
yhfddichar.disableinterrupthandler=yhfddidisableinterrupt;
yhfddichar.enableinterrupthandler=yhfddienableinterrupt;
yhfddichar.isrhandle=yhfddiinterruptservice;
yhfddichar.handleinterrupthandler=yhfddihandleinterrupt;
以上四項(xiàng)屬性是中斷處理所需的上邊緣服務(wù)函數(shù)的入口點(diǎn)(句柄)。fddi網(wǎng)卡驅(qū)動(dòng)程序需要有smt站管理功能,而smt是以中斷處理方式進(jìn)行的,故這四項(xiàng)屬性在fddi網(wǎng)卡驅(qū)動(dòng)程序中是很重要的。
yhfddichar.initializehandler=yhfddiinitialize;
此項(xiàng)注冊(cè)的是驅(qū)動(dòng)程序的初始化函數(shù)句柄。
yhfddichar.queryinformationhandler= yhfddiqueryinformation;
yhfddichar.setinformationhandler=yhfddisetinformation;
這兩項(xiàng)注冊(cè)的是參數(shù)查詢和設(shè)置函數(shù)的句柄。
yhfddichar.sendhanler= yhfddisend;
yhfddichar.transferdatahandler= yhfdditransferdata;
主要提供數(shù)據(jù)發(fā)送和接收函數(shù)句柄!
yhfddichar.resethandler=yhfddireset;
此項(xiàng)注冊(cè)網(wǎng)卡軟硬件重置函數(shù)句柄。
yhfddichar.halthandler= yhfddihalt;
此項(xiàng)注冊(cè)網(wǎng)卡驅(qū)動(dòng)程序掛起函數(shù)句柄。
yhfddichar.checkforhandler=null;
yhfddichar.reconfigurehandler=null;
這兩個(gè)上邊緣服務(wù)函數(shù)是fddi網(wǎng)卡驅(qū)動(dòng)程序所不提供的,故置為null。
填好這些結(jié)構(gòu)以后,調(diào)用以下函數(shù)實(shí)現(xiàn)驅(qū)動(dòng)程序的注冊(cè):
ndismregisterminiport(
yhfddiwrapperhandle,
&yhfddichar,
sizeof(yhfddichar));
其中yhfddiwrapperhandle是在此之前初始化wrapper調(diào)用ndisminitializewrapper所得的句柄。
如果調(diào)用ndismregisterminiport不能返回ndis_status_success,必須在退出driverentry之前釋放已經(jīng)分配的資源(如yhfddiwrapperhandle等),故調(diào)用
ndisterminatewrapper(yhfddiwrapperhandle,null)。
這樣驅(qū)動(dòng)程序沒(méi)能正確注冊(cè),亦不能正常運(yùn)行。
第四節(jié) 網(wǎng)卡驅(qū)動(dòng)程序?qū)ο蟛樵兣c設(shè)置
如果ndis的管理實(shí)體要查詢或設(shè)置一個(gè)特定的網(wǎng)絡(luò)對(duì)象,它必須提供一個(gè)32位的oid。oid的結(jié)構(gòu)如下: 圖2.3.0 oid結(jié)構(gòu)圖
由上可以看到,oid可分為三大類(lèi):
所有ndis驅(qū)動(dòng)程序都有的一般對(duì)象;
特定介質(zhì)的對(duì)象;
特殊的與具體實(shí)現(xiàn)相關(guān)的對(duì)象(如多目地址表的長(zhǎng)度)。
一般的和特定介質(zhì)的oid被記錄在windows nt ddk中,對(duì)于這些oid ddk文本指明了相關(guān)的對(duì)象能否通過(guò)miniportqueryinformation查詢參數(shù)和通過(guò)miniportsetinformation設(shè)置參數(shù)。
oid也可被分為操作特性(如多目地址表長(zhǎng)度參數(shù))和統(tǒng)計(jì)參數(shù)(如廣播包接收)。最后oid可分為必須的和可選的兩種。
oid的前三個(gè)字節(jié)表明oid的不同類(lèi)別,而最后一個(gè)字節(jié)確定這一類(lèi)別內(nèi)特定的信息管理對(duì)象。
針對(duì)于fddi網(wǎng)卡,被查詢的oid的第一個(gè)字節(jié)為0x03。而ndis所查詢的介質(zhì)相關(guān)參數(shù)為:
0x03010104 oid_fddi_long_max_list_size
0x03010108 oid_fddi_short_max_list_size
0x03010102 oid_fddi_long_current_addr
0x03010106 oid_fddi_short_current_addr
tcp/ip傳輸驅(qū)動(dòng)程序所要查詢的fddi oid為:
0x03010102 oid_fddi_long_current_addr
0x03010103 oid_fddi_long_multicast_list
0x03010107 oid_fddi_short_multicast_list
通過(guò)以上兩階段的查詢,ndis和tcp/ip驅(qū)動(dòng)程序就分別了解了網(wǎng)卡驅(qū)動(dòng)程序?qū)ζ涞闹С郑瑥亩M(jìn)行相應(yīng)的捆綁,以便數(shù)據(jù)傳輸時(shí)正確選擇網(wǎng)卡驅(qū)動(dòng)程序。
第五節(jié) 開(kāi)發(fā)環(huán)境與調(diào)試方法
開(kāi)發(fā)環(huán)境:
fddi網(wǎng)卡驅(qū)動(dòng)程序的開(kāi)發(fā)環(huán)境為nt server 3.51,sdk,ddk for workstation 3.51, vc++4.1,硬件平臺(tái)為586。
調(diào)試平臺(tái):
主機(jī)為nt server 3.51,windbg32
目標(biāo)機(jī)為nt workstation3.51 (check 944)
調(diào)試方法:
※利用dbgprint把目標(biāo)機(jī)上關(guān)鍵信息通過(guò)串口傳到主機(jī)進(jìn)行分析,以得出ndis驅(qū)動(dòng)程序的調(diào)度機(jī)制和運(yùn)轉(zhuǎn)狀況;
※利用assert產(chǎn)生異常斷點(diǎn),由主機(jī)對(duì)異常進(jìn)行控制
※自定義宏,進(jìn)行分級(jí)控制,以根據(jù)不同情況產(chǎn)生不同調(diào)試信息
第四章 與smt移植相關(guān)的問(wèn)題討論
在本yhfddi網(wǎng)卡驅(qū)動(dòng)程序中,smt的移植是極其關(guān)鍵的一部分,主要承擔(dān)了驅(qū)動(dòng)程序中硬件初始化和中斷延遲處理。但由于smt是相對(duì)獨(dú)立的軟件,這樣就有一個(gè)ndis wrapper與smt間參數(shù)傳遞的問(wèn)題。所以本章主要討論miniport驅(qū)動(dòng)程序與smt的關(guān)系和移植smt過(guò)程中初始化的要求、中斷處理的要求,ndis wrapper與smt如何傳遞參數(shù)。
(一)miniport fddi網(wǎng)卡驅(qū)動(dòng)程序與smt的關(guān)系。
在第一章已經(jīng)談及網(wǎng)卡驅(qū)動(dòng)程序主要實(shí)現(xiàn)osi參考模型中的物理層和mac層。而對(duì)于fddi網(wǎng)絡(luò)的物理層又可分為介質(zhì)相關(guān)子層和介質(zhì)無(wú)關(guān)子層。
對(duì)于我們的fddi/pci是基于x.3.19、x3.148、x3.166和x3.229而實(shí)現(xiàn)的。
smt在整個(gè)iso七層模型中屬低兩層范疇。下圖是iso模型與fddi層次的對(duì)應(yīng)關(guān)系,從而可知fddi miniport驅(qū)動(dòng)程序在nt網(wǎng)絡(luò)結(jié)構(gòu)中的位置。
即在windows nt fddi網(wǎng)卡驅(qū)動(dòng)程序應(yīng)包含smt,實(shí)現(xiàn)fddi拓?fù)洵h(huán)上的站管理!
而在驅(qū)動(dòng)程序內(nèi)部smt主要是在miniport驅(qū)動(dòng)程序中的中斷延遲處理上邊緣服務(wù)中實(shí)現(xiàn)的,也可以說(shuō)是將smt嵌入中斷延遲處理程序中,實(shí)現(xiàn)ndis接口對(duì)smt的正確調(diào)度。
yh-fddi驅(qū)動(dòng)程序的實(shí)現(xiàn)可分為硬件無(wú)關(guān)部分和硬件相關(guān)部分!
移植smt過(guò)程中初始化的要求.
這里的初始化主要是指硬件初始化,包括寄存器的初始化和數(shù)據(jù)結(jié)構(gòu)的初始化,由smt共用的硬件相關(guān)例程庫(kù)中硬件初始化部分來(lái)完成. 我們?cè)陂_(kāi)發(fā)過(guò)程序是調(diào)用fddi_main(bdd_t*bdd)這個(gè)函數(shù)來(lái)調(diào)用smt共用的硬件相關(guān)例程庫(kù)的.可見(jiàn)使用fddi_main(bdd_t*bdd)時(shí),需要傳遞bdd這個(gè)參量,而bdd_t這個(gè)數(shù)據(jù)結(jié)構(gòu)的定義如下:
它包含了各類(lèi)硬件寄存器的基址,所以要對(duì)其進(jìn)行正確賦值就必須首先在nt的內(nèi)存中映射一塊虛存與網(wǎng)卡內(nèi)存相對(duì)應(yīng),也就實(shí)現(xiàn)了bdd_t結(jié)構(gòu)的賦值,對(duì)fddi_main(bdd_t *bdd)的正確調(diào)用.
因此,我們?cè)谡{(diào)用fddi_main前首先將網(wǎng)卡上寄存器內(nèi)存空間映射到nt的虛存空間上,并將bdd結(jié)構(gòu)正確賦值.以映射bsi_phy_base為例,具體過(guò)程如下:
pchar destination;
bdd_t *bdd;
ndis_physical_address physicaladdress;
ulong baseaddress;
ndis_status status;
baseadress =0x0d0000+bsi_phy_base;
ndissetphysicaladdresshigh(physicaladdress,0);
ndissetphysicaladdresslow(physicaladdress,baseaddress);
status=ndismmapiospace(
(pvoid *)&destination,
miniportadapterhandle,
physicaladdress,
bsi_phy_len
);
bdd->bsi_vir_base=(pchar) destination;
adapter-> bdd->bsi_vir_base= bsi_vir_base;
/*對(duì)adapter結(jié)構(gòu)中的bdd結(jié)構(gòu)賦值,以便在其它上邊緣函數(shù)中使用這些虛存基地址*/
中斷處理要求.
對(duì)于中斷處理,在smt中主要調(diào)用cspintrhandandler()來(lái)實(shí)現(xiàn).我們的fddi網(wǎng)卡驅(qū)動(dòng)程序是miniport方式的,若在isr中做此處理將占用大量系統(tǒng)資源,使系統(tǒng)崩潰,所以我們采用只在isr中進(jìn)行中斷的排隊(duì),而在dpc中調(diào)用cspintrhandler()來(lái)完成中斷處理.
在中斷處理方面還有一個(gè)中斷屏蔽和中斷使能的問(wèn)題,這兩方面smt并不提供,故我們要正確處理.
具體處理方法見(jiàn)第三章.
ndis wrapper與smt間參數(shù)如何傳遞.
miniport方式的網(wǎng)卡驅(qū)動(dòng)程序中,網(wǎng)卡上有中斷時(shí),系統(tǒng)反映給ndiswrapper,再由wrapper調(diào)度中斷處理上邊緣服務(wù)實(shí)現(xiàn)中斷處理,在我們的yhfddi網(wǎng)卡驅(qū)動(dòng)程序的中斷具體處理是smt完成的所以在調(diào)用cspintrhandler時(shí)應(yīng)將adapter結(jié)構(gòu)傳進(jìn)smt以便在以后應(yīng)用.
如在處理接收中斷時(shí),處理的最后應(yīng)調(diào)用ndisindicatefddireceive,向ndiswrapper指示以接收到一個(gè)數(shù)據(jù)包,而ndisindicaterfddireceive的調(diào)用需要adapterminiporthandle作為參數(shù),這就必須一級(jí)級(jí)從中斷延遲處理函數(shù)(yhfddi handleinterrupt)中將adapter結(jié)構(gòu)傳遞下來(lái). 當(dāng)然,其它方面如發(fā)送,也會(huì)有類(lèi)似的問(wèn)題需要考慮.
總之,對(duì)于smt的移植,需要詳盡的在程序中做好接口,才能實(shí)現(xiàn)與
smt的數(shù)據(jù)交換.
結(jié)束語(yǔ)
ndis規(guī)范在網(wǎng)絡(luò)兩層間提供了一個(gè)統(tǒng)一界面,ndis對(duì)網(wǎng)絡(luò)本身而言,是一個(gè)帶有協(xié)議功能的標(biāo)準(zhǔn)接口,對(duì)實(shí)現(xiàn)者而言,它應(yīng)該是一個(gè)環(huán)境,這種環(huán)境不僅帶有協(xié)議功能,更重要的是帶有和軟、硬平臺(tái)無(wú)關(guān)的核心功能支持,它不會(huì)受軟、硬平臺(tái)的變化嚴(yán)重影響,無(wú)疑,它是軟件的移植和兼容的可靠保證,ndis把網(wǎng)絡(luò)的一部分共性抽象出來(lái),并根據(jù)具體的操作系統(tǒng)實(shí)現(xiàn)系統(tǒng)和平臺(tái)相關(guān)的基礎(chǔ)庫(kù)以保證ndis的標(biāo)準(zhǔn)性和對(duì)開(kāi)發(fā)者提供最大的功能支持,這也將加速和規(guī)范開(kāi)發(fā)過(guò)程,但是,在操作系統(tǒng)之上提供ndis基礎(chǔ)庫(kù)獲得標(biāo)準(zhǔn)同時(shí)也失去直接作用于操作系統(tǒng)帶來(lái)的靈活性以及更強(qiáng)的功能支持,同時(shí),ndis處于網(wǎng)絡(luò)中層和低層之間,低層網(wǎng)絡(luò)的快速發(fā)展和ndis對(duì)網(wǎng)絡(luò)部分共性的抽象必然導(dǎo)致ndis對(duì)實(shí)現(xiàn)者的滯后,例如ddk3.51提供的ndis開(kāi)發(fā)環(huán)境只支持10m以太網(wǎng)、fddi、令牌網(wǎng)(802.5)、localtalk、arcnet等,而對(duì)新出現(xiàn)的快速以太網(wǎng)及atm不提供支持,這對(duì)我們?nèi)绾卧趎dis環(huán)境下實(shí)現(xiàn)諸如atm的lan emulation,ip over atm、快速以太網(wǎng)帶來(lái)很大問(wèn)題!
smt是實(shí)現(xiàn)fddi網(wǎng)卡驅(qū)動(dòng)程序的關(guān)鍵,然而由于應(yīng)用ddk開(kāi)發(fā)miniport驅(qū)動(dòng)程序時(shí)要遵循其結(jié)構(gòu)框架,所以要想完整地按其結(jié)構(gòu)移植smt,就必須分解smt適應(yīng)之,即要求對(duì)smt有一個(gè)很好的理解。但smt是龐大的給開(kāi)發(fā)帶來(lái)了一定的困難。
參考文獻(xiàn)
【1】《device driver kit用戶手冊(cè)》
【2】《device driver kit核心驅(qū)動(dòng)程序設(shè)計(jì)》
【3】《device driver kit網(wǎng)絡(luò)驅(qū)動(dòng)程序設(shè)計(jì)》
【4】《windows nt核心內(nèi)幕》
【5】《windows nt資源》之三《性能評(píng)測(cè)》