复杂设备Word文档格式.docx
《复杂设备Word文档格式.docx》由会员分享,可在线阅读,更多相关《复杂设备Word文档格式.docx(12页珍藏版)》请在冰豆网上搜索。
0x100&
&
pos<
PAGE_SIZE/2;
devfn++)
{
structpci_dev*dev=NULL;
dev=pci_find_slot(bus,devfn);
if(!
dev)
continue;
/*Ok,we'
vefoundadevice,copyitscfgspacetothebuffer*/
for(i=0;
i<
256;
i+=sizeof(u32),pos+=sizeof(u32))pci_read_config_dword(dev,i,(u32*)(buf+pos));
pci_release_device(dev);
/*2.0compatibility*/
}
}
*eof=1;
returnpos;
}
其中使用的pci_find_slot()函数定义为:
structpci_dev*pci_find_slot(unsignedintbus,
unsignedintdevfn)
structpci_dev*pptr=kmalloc(sizeof(*pptr),GFP_KERNEL);
intindex=0;
unsignedshortvendor;
intret;
pptr)returnNULL;
pptr->
index=index;
/*0*/
ret=pcibios_read_config_word(bus,devfn,PCI_VENDOR_ID,&
vendor);
if(ret/*==PCIBIOS_DEVICE_NOT_FOUNDorwhatevererror*/
||vendor==0xffff||vendor==0x0000){
kfree(pptr);
returnNULL;
printk("
ok(%i,%i%x)\n"
bus,devfn,vendor);
/*fillotherfields*/
bus=bus;
devfn=devfn;
pcibios_read_config_word(pptr->
bus,pptr->
devfn,PCI_VENDOR_ID,&
pptr->
devfn,PCI_DEVICE_ID,&
device);
returnpptr;
(3)根据设备的配置信息申请I/O空间及IRQ资源;
(4)注册设备。
USB设备的驱动主要处理probe(探测)、disconnect(断开)函数及usb_device_id(设备信息)数据结构,如:
staticstructusb_device_idsample_id_table[]=
USB_INTERFACE_INFO(3,1,1),driver_info:
(unsignedlong)"
keyboard"
},
USB_INTERFACE_INFO(3,1,2),driver_info:
mouse"
,
0,/*nomorematches*/
};
staticstructusb_driversample_usb_driver=
name:
"
sample"
probe:
sample_probe,disconnect:
sample_disconnect,id_table:
sample_id_table,
当一个USB设备从系统拔掉后,设备驱动程序的disconnect函数会自动被调用,在执行了disconnect函数后,所有为USB设备分配的数据结构,内存空间都会被释放:
staticvoidsample_disconnect(structusb_device*udev,void*clientdata)
/*theclientdataisthesample_devicewepassedoriginally*/
structsample_device*sample=clientdata;
/*removetheURB,removetheinputdevice,freememory*/
usb_unlink_urb(&
sample->
urb);
kfree(sample);
printk(KERN_INFO"
sample:
USB%sdisconnected\n"
sample->
name);
*hereyoumightMOD_DEC_USE_COUNT,butonlyifyouincrement
*thecountinsample_probe()below
return;
当驱动程序向子系统注册后,插入一个新的USB设备后总是要自动进入probe函数。
驱动程序会为这个新加入系统的设备向内部的数据结构建立一个新的实例。
通常情况下,probe函数执行一些功能来检测新加入的USB设备硬件中的生产厂商和产品定义以及设备所属的类或子类定义是否与驱动程序相符,若相符,再比较接口的数目与本驱动程序支持设备的接口数目是否相符。
一般在probe函数中也会解析USB设备的说明,从而确认新加入的USB设备会使用这个驱动程序:
staticvoid*sample_probe(structusb_device*udev,unsignedintifnum,
conststructusb_device_id*id)
*Theprobeprocedureisprettystandard.Devicematchinghasalready
*beenperformedbasedontheid_tablestructure(definedlater)
structusb_interface*iface;
structusb_interface_descriptor*interface;
structusb_endpoint_descriptor*endpoint;
structsample_device*sample;
usbsample:
probecalledfor%sdevice\n"
(char*)id->
driver_info/*"
or"
*/);
iface=&
udev->
actconfig->
interface[ifnum];
interface=&
iface->
altsetting[iface->
act_altsetting];
if(interface->
bNumEndpoints!
=1)returnNULL;
endpoint=interface->
endpoint+0;
(endpoint->
bEndpointAddress&
0x80))returnNULL;
if((endpoint->
bmAttributes&
3)!
=3)returnNULL;
usb_set_protocol(udev,interface->
bInterfaceNumber,0);
usb_set_idle(udev,interface->
bInterfaceNumber,0,0);
/*allocateandzeroanewdatastructureforthenewdevice*/
sample=kmalloc(sizeof(structsample_device),GFP_KERNEL);
sample)returnNULL;
/*failure*/
memset(sample,0,sizeof(*sample));
sample->
name=(char*)id->
driver_info;
/*filltheURBdatastructureusingtheFILL_INT_URBmacro*/
intpipe=usb_rcvintpipe(udev,endpoint->
bEndpointAddress);
intmaxp=usb_maxpacket(udev,pipe,usb_pipeout(pipe));
if(maxp>
8)maxp=8;
sample->
maxp=maxp;
/*rememberforlater*/
FILL_INT_URB(&
urb,udev,pipe,sample->
data,maxp,
sample_irq,sample,endpoint->
bInterval);
/*registertheURBwithintheUSBsubsystem*/
if(usb_submit_urb(&
urb)){
kfree(sample);
returnNULL;
/*announceyourself*/
probesuccessfulfor%s(maxpis%i)\n"
sample->
name,sample->
maxp);
*hereyoumightMOD_INC_USE_COUNT;
ifyoudo,you'
llneedtounplug
*thedeviceorthedevicesbeforebeingabletounloadthemodule
/*andreturnthenewstructure*/
returnsample;
在网络设备驱动的编写中,我们特别关心的就是数据的收、发及中断。
网络设备驱动程序的层次如下:
网络设备接收到报文后将其传入上层:
/*
*Receiveapacket:
retrieve,encapsulateandpassovertoupperlevels
*/
voidsnull_rx(structnet_device*dev,intlen,unsignedchar*buf)
structsk_buff*skb;
structsnull_priv*priv=(structsnull_priv*)dev->
priv;
*Thepackethasbeenretrievedfromthetransmission
*medium.Buildanskbaroundit,soupperlayerscanhandleit
skb=dev_alloc_skb(len+2);
skb){
printk("
snullrx:
lowonmem-packetdropped\n"
priv->
stats.rx_dropped++;
return;
skb_reserve(skb,2);
/*alignIPon16Bboundary*/
memcpy(skb_put(skb,len),buf,len);
/*Writemetadata,andthenpasstothereceivelevel*/
skb->
dev=dev;
protocol=eth_type_trans(skb,dev);
ip_summed=CHECKSUM_UNNECESSARY;
/*don'
tcheckit*/
priv->
stats.rx_packets++;
#ifndefLINUX_20
stats.rx_bytes+=len;
#endif
netif_rx(skb);
在中断到来时接收报文信息:
voidsnull_interrupt(intirq,void*dev_id,structpt_regs*regs)
intstatusword;
structsnull_priv*priv;
*Asusual,checkthe"
device"
pointerforsharedhandlers.
*Thenassign"
structdevice*dev"
structnet_device*dev=(structnet_device*)dev_id;
/*...andcheckwithhwifit'
sreallyours*/
dev/*paranoid*/)return;
/*Lockthedevice*/
priv=(structsnull_priv*)dev->
spin_lock(&
priv->
lock);
/*retrievestatusword:
realnetdevicesuseI/Oinstructions*/
statusword=priv->
status;
if(statusword&
SNULL_RX_INTR){
/*sendittosnull_rxforhandling*/
snull_rx(dev,priv->
rx_packetlen,priv->
rx_packetdata);
SNULL_TX_INTR){
/*atransmissionisover:
freetheskb*/
stats.tx_packets++;
stats.tx_bytes+=priv->
tx_packetlen;
dev_kfree_skb(priv->
skb);
/*Unlockthedeviceandwearedone*/
spin_unlock(&
而发送报文则分为两个层次,一个层次是内核调用,一个层次完成真正的硬件上的发送:
*Transmitapacket(calledbythekernel)
intsnull_tx(structsk_buff*skb,structnet_device*dev)
intlen;
char*data;
#ifndefLINUX_24
if(dev->
tbusy||skb==NULL){
PDEBUG("
tintfor%p,tbusy%ld,skb%p\n"
dev,dev->
tbusy,skb);
snull_tx_timeout(dev);
if(skb==NULL)
return0;
#endif
len=skb->
len<
ETH_ZLEN?
ETH_ZLEN:
skb->
len;
data=skb->
data;
dev->
trans_start=jiffies;
/*savethetimestamp*/
/*Remembertheskb,sowecanfreeitatinterrupttime*/
skb=skb;
/*actualdeliverofdataisdevice-specific,andnotshownhere*/
snull_hw_tx(data,len,dev);
return0;
/*Oursimpledevicecannotfail*/
*Transmitapacket(lowlevelinterface)
voidsnull_hw_tx(char*buf,intlen,structnet_device*dev)
*Thisfunctiondealswithhwdetails.Thisinterfaceloops
*backthepackettotheothersnullinterface(ifany).
*Inotherwords,thisfunctionimplementsthesnullbehaviour,
*whileallotherproceduresareratherdevice-independent
structiphdr*ih;
structnet_device*dest;
u32*saddr,*daddr;
/*Iamparanoid.Ain'
tI?
*/
if(len<
sizeof(structethhdr)+sizeof(structiphdr)){
snull:
Hmm...packettooshort(%ioctets)\n"
len);
if(0){/*enablethisconditionaltolookatthedata*/
inti;
lenis%i\n"
KERN_DEBUG"
data:
"
for(i=14;
i<
i++)
printk("
%02x"
buf[i]&
0xff);
\n"
*Ethhdris14bytes,butthekernelarrangesforiphdr
*tobealigned(i.e.,ethhdrisunaligned)
ih=(structiphdr*)(buf+sizeof(structethhdr));
saddr=&
ih->
saddr;
daddr=&
daddr;
((u8*)saddr)[2]^=1;
/*changethethirdoctet(classC)*/
((u8*)daddr)[2]^=1;
ih->
check=0;
/*andrebuildthechecksum(ipneedsit)*/
check=ip_fast_csum((unsignedchar*)ih,ih->
ihl);
if(dev==snull_devs)
PDEBUGG("
%08x:
%05i-->
%08x:
%05i\n"
ntohl(ih->
saddr),ntohs(((structtcphdr*)(ih+1))->
source),
ntohl(ih->
daddr),ntohs(((structtcphdr*)(ih+1))->
dest));
else
%05i<
--%08x:
ntohl(ih->
daddr),ntoh