Linux网卡驱动程序编写
前保留好硬件帧头的空间。这样hard_header程序只要调用skb_push然后正确填入硬件帧头就可以了。
在协议层调用hard_header时,传送的参数包括(2.0.xx):数据的sk_buff,device指针,protocol,目的地址(daddr),源地址(saddr),数据长度(len)。数据长度不要使用sk_buff中的参数,因为调用hard_header时数据可能还没完全组织好。saddr是NULL的话是使用缺省地址(default)。daddr是NULL表明协议层不知道硬件目的地址。如果hard_header完全填好了硬件帧头,则返回添加的字节数。如果硬件帧头中的信息还不完全(比如daddr为NULL,但是帧头中需要目的硬件地址。典型的情况是以太网需要地址解析(arp)),则返回负字节数。hard_header返回负数的情况下,协议层会做进一步的buildheader的工作。目前Linux系统里就是做arp(如果hard_header返回正,dev->arp=1,表明不需要做arp,返回负,dev->arp=0,做arp)。
对hard_header的调用在每个协议层的处理程序里。如ip_output。
2.2.7地址解析(xarp)
有些网络有硬件地址(比如Ethernet),并且在发送硬件帧时需要知道目的硬件地址。这样就需要上层协议地址(ip、ipx)和硬件地址的对应。这个对应是通过地址解析完成的。需要做arp的的设备在发送之前会调用驱动程序的rebuild_header方法。调用的主要参数包括指向硬件帧头的指针,协议层地址。如果驱动程序能够解析硬件地址,就返回1,如果不能,返回0。
对rebuild_header的调用在net/core/dev.c的do_dev_queue_xmit()里。
2.2.8参数设置和统计数据
在驱动程序里还提供一些方法供系统对设备的参数进行设置和读取信息。一般只有超级用户(root)权限才能对设备参数进行设置。设置方法有:
dev->set_mac_address()
当用户调用ioctl类型为SIOCSIFHWADDR时是要设置这个设备的mac地址。一般对mac地址的设置没有太大意义的。
dev->set_config()
当用户调用ioctl时类型为SIOCSIFMAP时,系统会调用驱动程序的set_config方法。用户会传递一个ifmap结构包含需要的I/O、中断等参数。
dev->do_ioctl()
如果用户调用ioctl时类型在SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间,系统会调用驱动程序的这个方法。一般是设置设备的专用数据。
读取信息也是通过ioctl调用进行。除次之外驱动程序还可以提供一个
dev->get_stats方法,返回一个enet_statistics结构,包含发送接收的统计信息。ioctl的处理在net/core/dev.c的dev_ioctl()和dev_ifsioc()里。
linuxman@263.net
.3网络驱动程序中用到的数据结构
最重要的是网络设备的数据结构。定义在include/linux/netdevice.h里。它的注释已经足够详尽。
structdevice
{
/*
*Thisisthefirstfieldofthevisiblepartofthisstructure
*(i.e.asseenbyusersintheSpace.cfile).Itisthename
*theinterface.
*/
char*name;
/*I/Ospecificfields-FIXME:Mergetheseandstructifmapintoone*/
unsignedlongrmem_end;/*shmemrecvend*/
unsignedlongrmem_start;/*shmemrecvstart*/
unsignedlongmem_end;/*sharedmemend*/
unsignedlongmem_start;/*sharedmemstart*/
unsignedlongbase_addr;/*deviceI/Oaddress*/
unsignedcharirq;/*deviceIRQnumber*/
/*Low-levelstatusflags.*/
volatileunsignedcharstart,/*startanoperation*/
interrupt;/*interruptarrived*/
/*在处理中断时interrupt设为1,处理完清0。*/
unsignedlongtbusy;/*transmitterbusymustbelongfor
bitops*/
structdevice*next;
/*Thedeviceinitializationfunction.Calledonlyonce.*/
/*指向驱动程序的初始化方法。*/
int(*init)(structdevice*dev);
/*Somehardwarealsoneedsthesefields,buttheyarenotpartofthe
usualsetspecifiedinSpace.c.*/
/*一些硬件可以在一块板上支持多个接口,可能用到if_port。*/
unsignedcharif_port;/*SelectableAUI,TP,..*/
unsignedchardma;/*DMAchannel*/
structenet_statistics*(*get_stats)(structdevice*dev);
/*
*Thismarkstheendofthevisiblepartofthestructure.All
*fieldshereafterareinternaltothesystem,andmaychangeat
*will(read:maybecleanedupatwill).
*/
/*Thesemaybeneededforfuturenetwork-power-downcode.*/
/*trans_start记录最后一次成功发送的时间。可以用来确定硬件是否工作正常。*/
unsignedlongtrans_start;/*Time(injiffies)oflastTx*/
unsignedlonglast_rx;/*TimeoflastRx*/
/*flags里面有很多内容,定义在include/linux/if.h里。*/
unsignedshortflags;/*interfaceflags(alaBSD)*/
unsignedshortfamily;/*addressfamilyID(
- Proteus运行Keil编写的C语言步骤(12-02)
- 基于51单片机的红外线遥控程序编写代码(11-30)
- 分享一年的程序调试经验(11-29)
- 关于51单片机中C语言编写的精确延时函数(11-25)
- 用keil编写程序并download到单片机中(11-24)
- 使用Keil软件编写汇编源程序应注意事项(11-23)