日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 高速PCI信號(hào)采集卡設(shè)計(jì)與實(shí)現(xiàn)綜合實(shí)例之:PCI卡的驅(qū)動(dòng)程序設(shè)計(jì)

          高速PCI信號(hào)采集卡設(shè)計(jì)與實(shí)現(xiàn)綜合實(shí)例之:PCI卡的驅(qū)動(dòng)程序設(shè)計(jì)

          作者: 時(shí)間:2017-06-04 來源:網(wǎng)絡(luò) 收藏

          本文引用地址:http://yuyingmama.com.cn/article/201706/348786.htm

          13.4PCI卡的設(shè)計(jì)

          13.4.1WDM模型

          設(shè)計(jì)完成的信號(hào)采集設(shè)備在插入計(jì)算機(jī)后,在對(duì)其進(jìn)行控制之前,需要編寫基于操作系統(tǒng)平臺(tái)上的。設(shè)備驅(qū)動(dòng)程序是一個(gè)包含了許多操作系統(tǒng)可調(diào)用例程的容器,這些例程可以使硬件設(shè)備執(zhí)行相應(yīng)的動(dòng)作,它是硬件與上層軟件之間溝通的橋梁。

          在本案例中,我們針對(duì)最常使用的操作系統(tǒng)Windows98/2000/XP系統(tǒng),使用了WDM(WindowsDriverModel)驅(qū)動(dòng)程序模型進(jìn)行程序開發(fā)。

          WDM模型是從WinNT3.51和WinNT4的內(nèi)核模式設(shè)備驅(qū)動(dòng)程序發(fā)展而來的。WDM主要的變化是增加了對(duì)即插即用、電源管理、WindowsManagementInterface(WMI)、設(shè)備接口的支持。WDM模型的主要目標(biāo)是實(shí)現(xiàn)能夠跨平臺(tái)使用、更安全、更靈活、編制更簡(jiǎn)單的Windows設(shè)備驅(qū)動(dòng)程序。

          WDM采用了“基于對(duì)象”的技術(shù),建立了一個(gè)分層的驅(qū)動(dòng)程序結(jié)構(gòu)。通過WDM模型的引入,可以減輕設(shè)備驅(qū)動(dòng)程序的開發(fā)難度和周期,逐漸規(guī)范設(shè)備驅(qū)動(dòng)程序的開發(fā),應(yīng)該說,WDM是當(dāng)前基于Windows平臺(tái)的設(shè)備驅(qū)動(dòng)程序的主流。

          WDM模型主要采用分層的方法,模仿面向?qū)ο蟮募夹g(shù),先進(jìn)行邏輯上的“分層”,然后將標(biāo)準(zhǔn)的實(shí)現(xiàn)和低層細(xì)節(jié)“封裝”起來,形成“基類”,客戶程序通過“繼承”的方式來擴(kuò)展“基類”的功能,完成所需要的實(shí)現(xiàn)。

          13.4.2設(shè)備和驅(qū)動(dòng)程序的層次結(jié)構(gòu)

          在WDM模型中,每個(gè)硬件設(shè)備至少有兩個(gè)驅(qū)動(dòng)程序:一個(gè)功能驅(qū)動(dòng)程序(functiondriver)和一個(gè)總線驅(qū)動(dòng)程序(busdriver)。

          如圖13.14所示為WDM中設(shè)備對(duì)象和驅(qū)動(dòng)程序的層次結(jié)構(gòu)。

          圖13.14WDM中設(shè)備對(duì)象和驅(qū)動(dòng)程序的層次結(jié)構(gòu)

          1.

          是一個(gè)可選項(xiàng),當(dāng)一個(gè)用戶需要改變或新添一些功能到一個(gè)設(shè)備、一類設(shè)備或一種總線時(shí),就可以編寫一個(gè)。在設(shè)備棧里,過濾驅(qū)動(dòng)程序安裝在一個(gè)或幾個(gè)設(shè)備驅(qū)動(dòng)程序的上面或下面。

          過濾驅(qū)動(dòng)程序攔截對(duì)具體設(shè)備、類設(shè)備、總線的請(qǐng)求,做相應(yīng)的處理,以改變?cè)O(shè)備的行為或添加新的功能。但過濾驅(qū)動(dòng)程序只處理那些它所關(guān)心的I/O請(qǐng)求,對(duì)于其他的請(qǐng)求可以交給其他的驅(qū)動(dòng)程序來處理,這樣可以非常靈活地改變?cè)O(shè)備的行為。

          2.功能驅(qū)動(dòng)程序

          功能驅(qū)動(dòng)程序是物理設(shè)備的主要驅(qū)動(dòng)程序,它實(shí)現(xiàn)設(shè)備的具體功能,一般由設(shè)備的生產(chǎn)商來編寫。功能驅(qū)動(dòng)程序的主要功能是:提供對(duì)設(shè)備的操作接口、操作對(duì)設(shè)備的讀寫、管理設(shè)備的電源策略等。

          功能驅(qū)動(dòng)程序由類驅(qū)動(dòng)程序和微型驅(qū)動(dòng)程序組成。類驅(qū)動(dòng)程序?qū)崿F(xiàn)了某一類設(shè)備的常用操作,驅(qū)動(dòng)程序的開發(fā)者可以只編寫非常小的微型驅(qū)動(dòng)程序,去處理具體設(shè)備特殊的操作,而對(duì)于其他大量的常規(guī)操作,可以調(diào)用該類的類驅(qū)動(dòng)程序,這也是的優(yōu)點(diǎn)之一。

          微軟公司提供的類驅(qū)動(dòng)程序處理常用的系統(tǒng)任務(wù),比如,即插即用功能和電源管理。類驅(qū)動(dòng)程序保證了操作系統(tǒng)在處理類似的任務(wù)時(shí)的一致性,從而提高了系統(tǒng)的穩(wěn)定性。

          設(shè)備生產(chǎn)商提供微型驅(qū)動(dòng)程序,以實(shí)現(xiàn)自己設(shè)備的特殊功能,同時(shí)調(diào)用合適的類驅(qū)動(dòng)程序完成其他的通用工作。將大量的標(biāo)準(zhǔn)操作的代碼通過各種類驅(qū)動(dòng)程序來實(shí)現(xiàn),并集成在操作系統(tǒng)中,這樣的方式可以有效地減少具體設(shè)備的微型驅(qū)動(dòng)程序的大小,也就減小了程序出錯(cuò)的可能。

          如果某一類設(shè)備存在著工業(yè)標(biāo)準(zhǔn),微軟公司就會(huì)提供一個(gè)該類設(shè)備的WDM類驅(qū)動(dòng)程序。這個(gè)類驅(qū)動(dòng)程序?qū)崿F(xiàn)了該類設(shè)備所有必須的任務(wù),但不實(shí)現(xiàn)任何具體設(shè)備所特有的東西。

          3.總線驅(qū)動(dòng)程序

          總線驅(qū)動(dòng)程序?yàn)閷?shí)際的I/O總線服務(wù)。在WDM的定義中,總線是用來連接其他的物理的、邏輯的、虛擬的設(shè)備。總線包括傳統(tǒng)的總線SCSI和PCI,也包括并口、串口以及i8042端口。微軟公司已經(jīng)為Windows操作系統(tǒng)提供了總線驅(qū)動(dòng)程序。總線驅(qū)動(dòng)程序已經(jīng)包含在操作系統(tǒng)里了,用戶不必安裝。

          一個(gè)總線驅(qū)動(dòng)程序負(fù)責(zé)以下的工作:枚舉總線上的設(shè)備,向操作系統(tǒng)報(bào)告總線上的動(dòng)態(tài)事件,響應(yīng)即插即用和電源管理的I/O請(qǐng)求,提供總線的多路存取,管理總線上的設(shè)備等。

          13.4.3PCI設(shè)備驅(qū)動(dòng)程序例程

          PCI設(shè)備的一般需要使用WindowsDDK(DriversDevelopKits)及C語言進(jìn)行開發(fā)。下面介紹一些PCI設(shè)備最常見的例程,這些例程將告訴我們?nèi)绾螌?duì)PCI設(shè)備進(jìn)行控制。

          1.DriverEntry例程

          每個(gè),不管它的用途是什么,都要對(duì)外界顯示一個(gè)名字為DriverEntry的例程。該例程初始化各種驅(qū)動(dòng)程序數(shù)據(jù)結(jié)構(gòu),并為所有其他驅(qū)動(dòng)程序組件準(zhǔn)備好執(zhí)行環(huán)境。主要的工作是在傳遞的DriverObject中存儲(chǔ)一系列的回調(diào)例程指針。DRIVER_OBJECT結(jié)構(gòu)有操作系統(tǒng)用于存儲(chǔ)與驅(qū)動(dòng)程序有關(guān)的任何信息。

          在DriverEntry例程中通常要完成如下步驟。

          ·DriverEntry找到它將要控制的硬件。那個(gè)硬件是經(jīng)過分配的,即被標(biāo)志為由該驅(qū)動(dòng)程序控制。

          ·通過聲明另一個(gè)驅(qū)動(dòng)程序入口點(diǎn),初始化驅(qū)動(dòng)程序?qū)ο?。通過把函數(shù)指針直接保存到驅(qū)動(dòng)程序?qū)ο笾型瓿陕暶鞴ぷ鳌?/p>

          ·如果成功,DriverEntry應(yīng)該把STATUS_SUCCESS返回給I/O管理程序。

          DriverEntry的函數(shù)原型為:

          NTSTATUSDriverEntry(

          PDRIVER_OBJECTpDriverObject,

          PUNICODE_STRINGpRegistryPath

          )

          它接收一個(gè)指向它本身的驅(qū)動(dòng)程序?qū)ο蟮闹羔?,DriverEntry例程必須對(duì)它(指針)初始化。它還接收一個(gè)UNICODE_STRING,它包含注冊(cè)表中驅(qū)動(dòng)程序服務(wù)鍵的路徑。內(nèi)核模式驅(qū)動(dòng)程序根據(jù)該字符串從系統(tǒng)注冊(cè)表中提取任何驅(qū)動(dòng)程序?qū)S械膮?shù)。注冊(cè)表字符串采用如下形式:

          HKEY_LOCAL_MACHINESystemCurrentControlSetServicesDriverName

          下面是驅(qū)動(dòng)程序的DriverEntry例程的部分代碼,里面定義了將要用到的回調(diào)函數(shù)。

          NTSTATUSDriverEntry(

          PDRIVER_OBJECTpDriverObject,

          PUNICODE_STRINGpRegistryPath

          )

          { …

          //回調(diào)函數(shù)

          pDriverObject->DriverUnload =DriverUnload;

          pDriverObject->MajorFunction[IRP_MJ_CREATE] =Dispatch_Create;

          pDriverObject->MajorFunction[IRP_MJ_CLOSE] =Dispatch_Close;

          pDriverObject->MajorFunction[IRP_MJ_READ] =Dispatch_Read;

          pDriverObject->MajorFunction[IRP_MJ_WRITE] =Dispatch_Write;

          pDriverObject->MajorFunction[IRP_MJ_CLEANUP] =Dispatch_Cleanup;

          pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]

          =Dispatch_IoControl;

          pDriverObject->MajorFunction[IRP_MJ_PNP] =Dispatch_Pnp;

          pDriverObject->MajorFunction[IRP_MJ_POWER] =Dispatch_Power;

          pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]

          =Dispatch_System Control;

          pDriverObject->DriverExtension->AddDevice =AddDevice;

          returnSTATUS_SUCCESS;

          }

          2.AddDevice例程

          大多數(shù)的WDMPDO都是在PnP管理器調(diào)用該程序入口點(diǎn)時(shí)被創(chuàng)建的。插入新設(shè)備后,系統(tǒng)啟動(dòng)時(shí),總線枚舉器會(huì)發(fā)現(xiàn)總線上的所有設(shè)備會(huì)自動(dòng)尋找并安裝設(shè)備的驅(qū)動(dòng)程序,并由驅(qū)動(dòng)程序中的處理PnP功能模塊自動(dòng)處理AddDevice例程及其他的PnP消息。

          AddDevice例程使用IoCreateDevice函數(shù)創(chuàng)建設(shè)備對(duì)象,再使用IoCreateSymbolicLink函數(shù)將設(shè)備組成為一個(gè)特定的設(shè)備接口,供Win32使用。

          其函數(shù)原型為:

          NTSTATUSAddDevice(PDRIVER_OBJECTpDriverObject,PDEVICE_OBJECTpdo)

          必須在DriverEntry入口函數(shù)中進(jìn)行聲明,下面是該函數(shù)的部分代碼:

          NTSTATUSAddDevice(

          PDRIVER_OBJECTpDriverObject,

          PDEVICE_OBJECTpdo

          )

          {…

          //建立設(shè)備名稱并創(chuàng)建它

          for(i=0;i20;i++)

          {

          //轉(zhuǎn)成String格式

          Swprintf(DeviceName,L\Device\PLX_DRIVER_NAME_UNICODEL-%d,i);

          //初始化DeviceName_Unicode

          RtlInitUnicodeString(DeviceName_Unicode,DeviceName);

          //創(chuàng)建設(shè)備

          status=IoCreateDevice(

          pDriverObject,

          sizeof(DEVICE_EXTENSION),

          DeviceName_Unicode,

          FILE_DEVICE_UNKNOWN,

          0,

          FALSE,

          fdo

          );

          //為用戶應(yīng)用程序創(chuàng)建Win32關(guān)聯(lián)名

          //轉(zhuǎn)成String格式

          swprintf(DeviceLinkName,L\DosDevices\PLX_DRIVER_NAME_UNICODEL-%d,i);

          //初始化DeviceLinkName_Unicode

          RtlInitUnicodeString(

          DeviceLinkName_Unicode,

          DeviceLinkName

          );

          //建立設(shè)備關(guān)聯(lián)符號(hào)

          status=IoCreateSymbolicLink(

          DeviceLinkName_Unicode,

          DeviceName_Unicode

          );

          returnSTATUS_SUCCESS;

          }

          3.DispatchPnp例程

          支持即插即用主要是指實(shí)現(xiàn)一個(gè)AddDevice例程和一個(gè)IRP_MJ_PNP處理程序。這個(gè)PnPIRP有8個(gè)主要次功能代碼,大多數(shù)的WDM驅(qū)動(dòng)程序需要支持這些次功能代碼。

          ·IRP_MN_START_DEVICE。

          ·IRP_MN_QUERY_REMOVE_DEVICE。

          ·IRP_MN_REMOVE_DEVICE。

          ·IRP_MN_CANCLE_REMOVE_DEVICE。

          ·IRP_MN_STOP_DEVICE。

          ·IRP_MN_QUERY_STOP_DEVICE。

          ·IRP_MN_CANCLE_STOP_DEVICE。

          ·IRP_MN_QUERY_CAPABILITIES。

          還有一些不太常用的IRP,這里就不再一一介紹,下面是這部分驅(qū)動(dòng)的部分代碼。

          NTSTATUSDispatch_Pnp(

          PDEVICE_OBJECTfdo,

          PIRPpIrp

          )

          { …

          //檢查次功能代碼

          switch(stack->MinorFunction)

          {

          caseIRP_MN_START_DEVICE: //配置并初始化設(shè)備

          status=HandleStartDevice(fdo,pIrp);

          break;

          caseIRP_MN_STOP_DEVICE: //關(guān)閉設(shè)備

          status=HandleStopDevice(fdo,pIrp);

          break;

          caseIRP_MN_REMOVE_DEVICE: //關(guān)閉并刪除設(shè)備

          Unlock=FALSE;

          status=HandleRemoveDevice(fdo,pIrp);

          break;

          caseIRP_MN_QUERY_REMOVE_DEVICE: //查詢?cè)O(shè)備是否可被安全刪除

          status=DefaultPnpHandler(fdo,pIrp);

          break;

          caseIRP_MN_CANCEL_REMOVE_DEVICE: //忽略以前的QUERY_REMOVE

          status=DefaultPnpHandler(fdo,pIrp);

          break;

          caseIRP_MN_QUERY_STOP_DEVICE: //查詢?cè)O(shè)備是否可被安全關(guān)閉

          status=DefaultPnpHandler(fdo,pIrp);

          break;

          caseIRP_MN_CANCEL_STOP_DEVICE: //忽略以前的QUERY_STOP

          status=DefaultPnpHandler(fdo,pIrp);

          break;

          caseIRP_MN_QUERY_CAPABILITIES: //取設(shè)備能力

          status=DefaultPnpHandler(fdo,pIrp);

          break;

          …}

          returnstatus;

          }

          這些功能代碼函數(shù)都在DriverEntry()入口函數(shù)中進(jìn)行了聲明。

          4.DispatchPower例程

          WDM設(shè)備驅(qū)動(dòng)程序支持電源管理,一個(gè)設(shè)備可以改變它的電源使用來響應(yīng)系統(tǒng)電源狀態(tài)變化,且在處于空閑狀態(tài)時(shí)可以減少它自己的電源使用。一個(gè)休眠的設(shè)備可以喚醒系統(tǒng),如當(dāng)調(diào)制解調(diào)器收到到達(dá)的呼叫時(shí)。

          驅(qū)動(dòng)程序的電源管理例程圍繞電源IRP_MJ_POWERIRP進(jìn)行處理,這些例程處理這個(gè)IRP,并在需要時(shí)產(chǎn)生這個(gè)IRP。這個(gè)IRP有4個(gè)電源管理次功能代碼。

          ·IRP_MN_WAIT_WAKE。

          ·IRP_MN_POWER_SEQUENCE。

          ·IRP_MN_SET_POWER。

          ·IRP_MN_QUERY_POWER。

          這部分的代碼如下:

          NTSTATUSDispatch_Power(

          PDEVICE_OBJECTfdo,

          PIRPpIrp

          )

          {

          NTSTATUSstatus;

          PIO_STACK_LOCATIONstack;

          //獲取指向被調(diào)用的Irp的棧位置的指針

          stack=IoGetCurrentIrpStackLocation(pIrp);

          switch(stack->MinorFunction)

          {

          caseIRP_MN_WAIT_WAKE: //喚醒計(jì)算機(jī),響應(yīng)一個(gè)外部事件

          status=DefaultPowerHandler(fdo,pIrp);

          break;

          caseIRP_MN_POWER_SEQUENCE: //確定設(shè)備是否真正進(jìn)入特定的電源狀態(tài)

          status=DefaultPowerHandler(fdo,pIrp);

          break;

          caseIRP_MN_SET_POWER: //設(shè)置系統(tǒng)或設(shè)備電源狀態(tài)

          status=HandleSetPower(fdo,pIrp);

          break;

          caseIRP_MN_QUERY_POWER: //查詢系統(tǒng)或設(shè)備狀態(tài)變化是否可行

          status=HandleQueryPower(fdo,pIrp);

          break;

          default: //確定設(shè)備是否真正進(jìn)入特定的電源狀態(tài)

          status=DefaultPowerHandler(fdo,pIrp);

          break;

          }

          returnstatus;

          }

          5.Unload例程

          在默認(rèn)情況下,驅(qū)動(dòng)程序裝入之后,在重新引導(dǎo)之前就一直保持在系統(tǒng)中。要使系統(tǒng)可卸載,必須有一個(gè)Unload例程。Uload例程在DriverEntry期間聲明,然后,每當(dāng)驅(qū)動(dòng)程序被手動(dòng)或自動(dòng)卸載時(shí),I/O管理程序就調(diào)用該例程。

          該例程函數(shù)原型為:

          VOIDUnload(PDRIVER_OBJECTpDriverObject)

          通常一個(gè)Uload例程執(zhí)行如下工作。

          ·對(duì)于某些種類的硬件,設(shè)備狀態(tài)應(yīng)當(dāng)保存在注冊(cè)表中。那樣,在DriverEntry下一次執(zhí)行時(shí),設(shè)備能夠恢復(fù)到最近已知的狀態(tài)。

          ·如果啟動(dòng)了設(shè)備中斷,Unload例程必須僅用它們,并斷開它們與中斷對(duì)象的連接。

          ·必須釋放屬于驅(qū)動(dòng)程式的硬件。

          ·必須從Win32名字空間中刪除符號(hào)鏈接名字,這可以用IoDeleteSymbolicLink完成。

          ·必須用IoDeleteDevice刪除設(shè)備對(duì)象自身。

          ·釋放驅(qū)動(dòng)程序占據(jù)的任何池內(nèi)存。

          驅(qū)動(dòng)中的部分代碼如下:

          VOIDDriverUnload(PDRIVER_OBJECTpDriverObject)

          {

          //釋放公共緩沖區(qū)

          if(Gbl_CommonBuffer.PciMem.PhysicalAddr!=(U32)NULL)

          {

          //釋放內(nèi)存描述列表(MDL)

          if(Gbl_CommonBuffer.pMdl!=NULL)

          {

          IoFreeMdl(Gbl_CommonBuffer.pMdl);

          Gbl_CommonBuffer.pMdl=NULL;

          }

          //釋放公共緩沖區(qū)

          if(Gbl_CommonBuffer.pKernelVa!=NULL)

          {

          MmFreeContiguousMemory(Gbl_CommonBuffer.pKernelVa);

          Gbl_CommonBuffer.pKernelVa=NULL;

          }

          }

          //釋放DMA使用的緩沖區(qū)

          #ifdefined(DMA_SUPPORT)

          DriverBufferTerminate();

          #endif

          }

          6.Dispatch例程

          驅(qū)動(dòng)程序裝載是第一步工作,但是最終驅(qū)動(dòng)程序的作業(yè)是響應(yīng)I/O請(qǐng)求——來自用戶模式應(yīng)用程序的請(qǐng)求或者來自系統(tǒng)其他地方的請(qǐng)求。Windows2000驅(qū)動(dòng)程序通過Dispatch例程來處理這些請(qǐng)求。I/O管理程序調(diào)用這些例程以響應(yīng)請(qǐng)求。

          要啟用特定的I/O函數(shù)代碼,驅(qū)動(dòng)函數(shù)必須首先“聲明”響應(yīng)這樣一個(gè)請(qǐng)求的Dispatch例程。聲明機(jī)制是DriverEntry執(zhí)行的工作,它把Dispatch例程函數(shù)地址保存在驅(qū)動(dòng)程序?qū)ο蟮腗ajorFunction表的合適位置上。

          I/O函數(shù)代碼是用于表的索引。其中,每個(gè)I/O函數(shù)代碼(表索引)由一個(gè)IRP_MJ_XXX形式的惟一符號(hào)標(biāo)示,在NTDDK.h(或WDM.h)包含文件中定義。

          所有驅(qū)動(dòng)程序必須支持函數(shù)代碼IRP_MJ_CREATE,因?yàn)榫帉懘舜a的目的是響應(yīng)Win32CreateFile調(diào)用。如果不支持該代碼,Win32應(yīng)用程序?qū)o法獲取設(shè)備的句柄。同樣也必須支持IRP_MJ_CLOSE,以處理Win32CloserHandle調(diào)用。

          驅(qū)動(dòng)程序應(yīng)當(dāng)支持的其他函數(shù)代碼取決它控制的設(shè)備的本質(zhì)。表13.3將用到的I/O函數(shù)代碼與產(chǎn)生它們的Win32調(diào)用相關(guān)聯(lián)。

          表13.3 Dispatch例程表

          Win32函數(shù)

          IRP主功能代碼

          驅(qū)動(dòng)程序例程的名稱

          說明

          CreateFile

          IRP_MJ_CREATE

          Dispatch_Create

          請(qǐng)求一個(gè)句柄

          CloseHandle

          IRP_MJ_CLEANUP

          Dispatch_Cleanup

          關(guān)閉句柄

          CloseHandle

          IRP_MJ_CLOSE

          Dispatch_Close

          取消掛起的IRP

          ReadFile

          IRP_MJ_READ

          Dispatch_Read

          從設(shè)備獲取數(shù)據(jù)

          WriteFile

          IRP_MJ_WRITE

          Dispatch_Write

          將數(shù)據(jù)發(fā)送到設(shè)備

          DeviceIoControl

          IRP_MJ_DEVICE_CONTROL

          Dispatch_IoControl

          控制操作



          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉