13.5 主机应用程序和驱动程序的接口设计
13.5.1 驱动程序例程的封装
通过调用PCI设备驱动程序的例程,我们可以实现操作系统对PCI设备的控制。但是直接调用例程进行编程往往显得不够直接,也不具有足够的针对性。因此在高级语言里面对PCI设备或者信号采集设备的控制,往往是调用已经封装过的例程。
将例程进行封装,形成一些可以调用的具有针对性的PCI信号采集设备API函数,是驱动开发者比较头疼的问题。因为这个过程需要了解Windows WDM模型,熟悉Windows DDK的开发过程,而这些往往需要花费硬件开发者的大量时间。
幸运的是,有一些很好的集成开发环境帮助我们完成了这个工作。用户只需要将具体设备的参数导入开发工具的向导中,即可自动生成对应该设备的驱动程序。这些开发工具包括Driver Studio、Windriver等。
另外,针对基于PCI9054的PCI设备,PLX公司已经为用户提供了较为完备的API函数包。用户只需要根据需要调用其中的API函数,即可轻松实现对PCI9054采集设备的控制。下面介绍几个常用的PLX API函数。
13.5.2 PLX API函数
PLX公司为其提供的动态链接库中包含了丰富的API函数,可以用于PCI9054卡的控制与传输。在这些API函数中,有如下的几个是常常用到的(注:在2007年5月提供的PLX SDK Version 5.0中,API函数名有所更新,下面仍然按照V5版之前的函数名进行介绍)。
1.PlxPciDeviceOpen函数
用于设备启动,在对设备进行任何操作之前都应该先打开设备,其函数原型为:
RETURN_CODE PlxPciDeviceOpen(
DEVICE_LOCATION *pDevice, //指向包含设备信息的数据结构的指针
HANDLE *pHandle //指向用于存放已打开设备的句柄的指针
);
DEVICE_LOCATION数据结构的定义如下:
typedef struct _DEVICE_LOCATION{
U8 BusNumber; //PCI设备所在的总线号
U8 SlotNumber; //PCI设备所在的插槽号
U16 DeviceId; //PCI设备的设备号
U16 VendorId; //PCI设备的厂商号
U8 SerialNumber[12]; //PCI设备的惟一标识码
} DEVICE_LOCATION;
对于PCI9054来说,DeviceId为10b5,VendorId为5406(不同的版本可能为9054)。SerialBumber的格式为“<device name> - <index number>”。如:有PLX9054的PCI卡,如果它的序列号为“Pci9054-1”,表示这是第二个PLX9054设备,第一个为“Pci9054-0”。
2.PlxPciDeviceClose函数
用于关闭已打开的PCI设备,其函数原型为:
RETURN_CODE PlxPciDeviceClose (HANDLE hDevice); //已打开的PCI设备的句柄
3.PlxPciBoardReset函数
用于复位已经打开的PCI设备,其函数原型为:
VOID PlxPciBoardReset (HANDLE hDevice); //已打开的PCI设备的句柄
4.PlxBusIopRead函数
用于从本地总线读取数据(常指Direct Slave读模式),其函数原型为:
RETURN_CODE PlxBusIopRead (
HANDLE hDevice, //已打开的PCI设备的句柄
IOP_SPACE IopSpace, //PCI总线至本地总线,映射空间0/1
U32 address, //若bRemap = FALSE,代表IOPSpace相对地址,否则是绝对地址
BOOLEAN bRemap, //绝对地址与相对地址布尔值
VOID *pBuffer, //指向用户用于存放读取数据的缓冲区
U32 ByteCount,
ACCESS_TYPE AccessType);//读数据方式,支持本地总线使用8位、16位或32位进行传输
5.PlxBusIopWrite函数
用于从本地总线写数据(常指Direct Slave写模式),其函数原型为:
RETURN_CODE PlxBusIopWrite (
HANDLE hDevice, //已打开的PCI 设备的句柄
IOP_SPACE IopSpace, //PCI总线至本地总线,映射空间0/1
U32 address, //若bRemap = FALSE,代表IOPSpace相对地址,否则是绝对地址
BOOLEAN bRemap, //绝对地址与相对地址布尔值
VOID *pBuffer, //指向用户用于存放读取数据的缓冲区
U32 ByteCount, //读取的数据量大小
ACCESS_TYPE AccessType);//读数据方式,支持本地总线使用8位、16位或32位进行传输
6.PlxIntrAttach函数
用于链接中断,当有效中断产生时,将事件传递给指针句柄,其函数原型为:
RETURN_CODE PlxIntrAttach (
HANDLE hDevice, //已打开的PCI 设备的句柄
PLX_INTR intrTypes, //含有需要指定的中断信息的数据结构(PLX_INTR)
HANDLE *pEventHdl); //指向接收中断事件的指针句柄
7.PlxIntrDisable函数
用于禁止某类中断,其函数原型为:
RETURN_CODE PlxIntrDisable (
HANDLE hDevice, //已打开的PCI设备的句柄
PLX_INTR *pPlxIntr); //含有需要指定的中断信息的数据结构(PLX_INTR)
8.PlxIntrEnable函数
用于使能某类中断,其函数原型为:
RETURN_CODE PlxIntrEnable (
HANDLE hDevice, //已打开的PCI设备的句柄
PLX_INTR *pPlxIntr); //含有需要指定的中断信息的数据结构(PLX_INTR)
9.PlxIntrStatusGet函数
用于返回当前终端状态,其函数原型为:
RETURN_CODE PlxIntrStatusGet (
HANDLE hDevice, //已打开的PCI设备的句柄
PLX_INTR *pPlxIntr); //含有需要指定的中断信息的数据结构(PLX_INTR)
10.PlxIntrWait函数
用于等待中断,并可设定等待时间长度,其函数原型为:
RETURN_CODE PlxIntrWait (
HANDLE hDevice, //已打开的PCI设备的句柄
HANDLE hEvent, //被等待的事件句柄
U32 Timeout_ms //为等待的时间长度,单位为ms
);
由于此函数只能用在Linux系统中,因此在Windows系统中使用PLX API函数包等待中断时,使用另外两个Windows API函数进行中断等待,即WaitSingleObject()函数和WaitMultipleObject()函数。
11.PlxDmaSglChannelOpen函数
用于开启Scatter/Gather模式DMA通道,其函数原型为:
RETURN_CODE PlxDmaSglChannelOpen (
HANDLE hDevice, //已打开的PCI设备的句柄
DMA_CHANNEL channel, //为被开启的DMA通道
DMA_CHANNEL_DESC *pDesc); //包含DMA通道的参数描述结构体(DMA_CHANNEL_DESC)指针
12.PlxDmaSglChannelClose函数
用于关闭已经打开的Scatter/Gather模式DMA通道,其函数原型为:
RETURN_CODE PlxDmaSglChanneClose (
HANDLE hDevice, //已打开的PCI设备的句柄
DMA_CHANNEL channel); //将要关闭的已被开启的DMA通道
13.PlxDmaSglTransfer函数
用于开始进行Scatter/Gather模式的DMA传输,其函数原型为:
RETURN_CODE PlxDmaSglTransfer (
HANDLE hDevice, //已打开的PCI设备的句柄
DMA_CHANNEL channel, //进行Scatter/Gather模式DMA传输的通道
DMA_TRANSFER_ELEMENT *dmaData, //指向用于DMA数据缓冲区结构(DMA_TRANSFER_
//ELEMENT)指针
BOOLEAN returnImmediate); //取值为FALSE表示程序等待DMA传输结束后再执行下一
//条指令
//,反之,则不等待结束就执行下一条指令
13.5.3 API函数调用
有了这些丰富的API函数资源,用户即可根据自己的需要为信号采集设备设计功能多样的应用程序。在进行应用程序的设计时,只需要将API函数库包含在用户的程序中即可。
PLX公司提供的PLX SDK开发包中包含了完整的API函数库文件。将这些API库文件复制到用户的应用程序目录下,并在程序中include进去,即可调用这些API函数。更多的函数及用法详见PLX SDK的编程者开发手册。
13.5.4 PCI9054驱动程序安装
INF文件是安装设备驱动程序时必须使用的文件,其扩展名为.inf。驱动程序安装后将它保存在windows/inf目录中,是Winodws操作系统下用来描述设备或文件等数据信息的文件。
INF文件全称Information File文件。在操作系统发现新硬件之后向系统指明应该安装的驱动程序,系统为设备提供的服务以及注册表项要修改的内容。它为该设备提供一个全面描述硬件参数和相应驱动文件(动态链接库等文件)的信息。
驱动程序安装的最终结果包括对系统的两个永久更改。
· 描述驱动程序的系统注册表项、它的卸载顺序以及任何正确的配置资料。
· 将驱动程序文件复制到一个指定的系统目录中。
INF文件是由标准的ASCII码组成,可以用任何一款文字编辑器查看修改其中的内容。它是分节的,每节以“[ ]”扩起来,每一个节名最长为255个字符(Windows 2000/XP/2003操作系统中)或28个字符(Windows 98操作系统中)。
节与节之间的内容叫条目,每一个节是由许多的条目组成的。每一个条目都由“=”分开,如“a=b”。如果每一个条目的等号后有多个值,则每一个值之间用逗号分隔开。INF对大小写不敏感,行注释语句命令是“;”,类似Visual Basic里的“’”。如果一行写不下,使用“”来换行。更多关于INF文件的规则和说明可以查看Windows DDK的说明,这里不再详述。
通过INF文件,用户可以允许系统自动安装信号采集设备的驱动程序,或者在对话支持下按照系统安装向导一步一步完成驱动程序安装过程。