QNX操作系统及网络设备驱动模块
②初始化函数向io-net注册驱动和相应的函数。
③初始化函数告诉io-net和它的模块自己的通信能力。
经过以上流程以后,io-net中就建立起有关此驱动程序的数据和函数调用列表。驱动程序必须正确编写初始化函数,并将该函数正确链接至io_net_dll_entry。
(2)从网络设备接收数据
当有包到达网络设备的时候,网络设备就会用某种方式通知驱动程序(例如中断),此时,驱动程序就要采取某种策略来处理到来的帧或数据。通常驱动程序这时候需要做以下工作:
①通过DMA将包取回来;
②做相应的必要处理,如通知网络设备释放当前帧的缓存,配置寄存器让网络设备等待下一帧到来等;
③通过调用io-net的tx_up_start()函数把包传递给上层模块。
当上层所有的模块都完成对这个包的处理以后,io-net调用我们驱动中的tx_done()函数,它来做最后的处理工作。
tx_up_start()函数是设备驱动中比较关键的函数,下面简要部分一下这个函数的入口参数。
npkt_t*(*tx_up_start)(int registrant_hdl,
nptk_t *npkt,
int off,
int framelen_sub,
uint16_t cell,
uint 16_t endpoint,
uint16_t iface,
void *done_hdl)
其中:int registrant_hdl--本驱动在io-net中的句柄,注册时由io-net生成;
nptk_t *npkt --需要处理的包的指针;
int off--底层协议包头长度,如以太网帧头部长度;
int framelen_sub--尾部填充的长度,对于以太网这个值为零;
uint16_t cell、uint16_t endpoint--endpoint和cell是io-net在注册的时候分配的用来区别不同的驱动;
uint16_t iface--接口号,可以让同一个驱动负现多个相同硬件;
void *done_hdl--该指针指向tx_done()函数需要的额外数据。
(3)向网络设备发送数据
当上层模块需要硬件传送包的时候,会调用io-net管理器的rx_down()函数。
int(*rx_down)(npkt_t*npkt,
void *func_hdl)
rx_down函数入口参数中,npkt是指向需要传送的数据的结构指针,func_hdl是相应驱动模块在io-net中的句柄。其中npt结构包含许多成员,其中的重要成员如表1所列。
表1
cell、endpoint、iface | 需要处理该包的硬件标识 |
buffers | 指向包的指针 |
tot_iov | 包含数据包的所有I/O矢量 |
Framelen | 所有数据的长度,以字节为单位 |
驱动模块在接收到io-net的调用后,就要配置网络设备,让它完成数据的发送工作。网络设备发送数据所需要的信息都会在相应的数据结构中,如net_buf_t结构中保存了等待传送的数据包的链接列表,配置DMA所需的物理地址在net_iov_t中等。驱动模块要等待硬件完成这些包的传送,并调用io-net的tx)done()函数通知上层模块驱动程序已经完成了数据的发送。
4 网络设备信息的统计
应用程序或者用户可以通过网络信息接口nicinfo工具来了解网络工作状态。信息的查询都是通过io-net来进行的。驱动程序必须维护相应的状态数据,方便io-net的查询。网络设备有一些共同的状态属性,如收到和发出的包的个数、发送错误的包的个数等,不同的网络设备还会具有不同的属性和状态,这些都可以在驱动程序中用数据结构详细列明。
需要维护的数据结构中,主要的是Nic_t,它包括四个子结构;
CustNicStats--网络信息入口;
EthernesStats_t--以太网状态;
GenStats_t--常用统计信息;
>NetStats_t--网络信息(包含常用统计信息)。
以上是驱动程序需要维护的数据。当用户或应用程序要查询这些信息的时候,它们就通过Nicinfo工具对/dev/io-net/en0调用devctl()函数来取得网络信息。信息的取得是必须通过io-net来完成的,io-net对信息的查询则是通过调用io_net_register_funs_t结构中所指向的函数来取得信息的。例:
#include<sys/nic.h>
int generic_eth_devctl(void *hdl,int dcmd,void *data,size_t size,int *ret)
{
Nic_t *nic=(Nic_t *)hdl;javascript:window.open(this.src);" style="cursor:pointer;"/>
int status;
status=EOK;
switch(dcmd){
case DCMD_IO_NET_NICINFO;
memcpy(data,nic,min(size,sizeof(Nic_t)));
break;
default:
status=ENOTSUP;
break;
}
return(status);
}
结语
网络设备的驱动是网络系统的最低层和最基础的模块,是如今嵌入式开发中首先要解决的问题之一。由于QNX具有微内核的特点,其网络设备驱动程序的开发不需要内核调试,更适合初学者掌握。本文对QNX操作系统及网络设备驱动程序的介绍,可以帮助读者对相关内容作初步了解。