
QNX驱动程序的编写
·55·
一个线程如果想要对端口进行I/O操作,它必须
具有适当的权限,必须调用这个函数来保证线程可以
访问I/O端口。
ThreadCtl(一NTO_TCTL_IO,O);
如果不调用这个函数,系统就会对其提供默认的
保护而使用户无法访问。
得到权限之后,还必须通过mmap—device—io()进
行I/0地址的映射,只有这样才能获取设备的I/O资
源。
在QNX中提供了丰富的PCI操作函数,可以自动
的查找资源,读写PCI配置寄存器。
下面简要分析程序中的关键部分:
pci—attach();
将程序连接到PCI
server上,使得整个程序可以使用QNX
系统提供的pci一+()函数。
do{
iRet=pei—find—device(Deviceid,Vendorid,index++,
&busnum,&devfunenum);
if(iRet==PCI—SUCCESS)then找到设备;
}while(iRet!=PCI_DEVICE—NOT_FOUND);
if(iRet!=PCI_SUCCESS)then不能找到设备;
查找PCI设备,使用pci—find—device,传给该函数
两个主要参数:设备号和厂家号,并遍历查找所有的
PCI插槽,直到匹配为止。找到设备以后可以利用pci
—attach_device()函数把pci—dev—info()与设备连接,
然后读出内存与端口的基地址和中断资源,为Et后的
操作做准备。
(2)建立与资源管理器的交互机制并初始化消息
处理函数。
dispatch—create()函数实现了用户函数与资源管
理器的交互。通过这个函数资源管理器可以作为服务
器为用户函数提供消息分发。
QNX为驱动程序开发者提供了可靠的默认处理
函数,但是用户也可以根据需要定义自己的消息处理
函数,以io—devctl为例:
iofune_fune——init(..RESMGR..CONNECT_NFUNCS,&connect
_runes,一RESMGR—IO—NFUNCS,&io_funcs);
io_funcs.devctl=io—devetl;//用户将使用自己的io—devctl
处理函数。
(3)设备驱动程序与应用程序的接口。
驱动程序不但要完成对硬件的操作,还要与操作
系统进行数据的传输,在驱动程序加载以后,用户程序
就可以像操作文件一样操作设备,比较简单快捷的方
法是使用devctl()作为应用程序与驱动程序的接口。
devctl()函数的格式是:
devcfl(int
fd,int
dcmd,void}data,size_t
nbytes,int%return
—info);
下面的值直接映射一IO—DEVCTL消息本身:
struct—io—devcfl{
uintl6_t
type;
uintl6_t
eombine_len;
int32_t
dcmd;
int32一t
nbytes;
int32_t
zero;
}
struct—io_devctl_reply{
uint32_t
zero;
int32_t
ret_val;
int32一t
nbytes;
int32_t
zer02;
typedef
umon{
struct—io—devctl
i;
struct_io_devctl_reply
O;
}io_devctl_t;
对于大多数资源管理器消息来说,定义的联合包
括输入结构(发送给资源管理器)和输出结构(发送回
客户端)。Io_devctl处理函数的参数说明如下:
io_devctlj木msg:指向包含消息的联合。
type:值为jO—DEVCTL。
combine—len:只对混合消息有意义。
nbyte:是传递给devctl()函数的,这个值包含传递
给驱动程序的数据的大小,或从驱动程序接受的
数据的最大值。
dcmd:传递给devctl()函数的,这个命令是使用定
义在<devcfl.h>的宏形成的。
如上面的结构体所示,上层的用户,把要与设备驱
动程序通信的数据填入结构体中,再由系统进行重新
的解析,以消息的方式传给底层驱动程序,驱动程序再
把消息中的功能号和要传递的参数取出使用j
下面是一IO—DEVCTL消息的处理函数的关键代
码:
int
io_devctl(resmgr—context—t¥ctp,io—devctl—t}msg,
RESMGR_OCB_T%ocb)
{union{
data_t
data;
im
data32:
}十rx_data;
if((status=iofunc—devctl~default(ctp,msg,ocb))!=一
RESMGR—DEFAULT){
return(status);}
rx_data=一DEVCTL_DATA(msg一>i);//从消息中取得数
据结构
/+以下就是一个使用devetl的操作,完成从驱动程序取
一些数据传给应用程序中;-/
switch(msg一>i.dcmd)
{case
MY_DEVCTL_GETVAL:
rx—data一>data32=dobM_integer;
nbytes=sizeof(rx—data一>data32);
break;
default:
万方数据