1、 0x100 & pos PAGE_SIZE / 2; devfn+)struct pci_dev *dev = NULL;dev = pci_find_slot(bus, devfn);if (!dev)continue;/* Ok, weve found a device, copy its cfg space to the buffer*/for (i = 0; i index = index; /* 0 */ret = pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor);if (ret /* = PCIBIOS_DE
2、VICE_NOT_FOUND or whatever error */| vendor=0xffff | vendor=0x0000) kfree(pptr); return NULL;printk(ok (%i, %i %x)n, bus, devfn, vendor);/* fill other fields */bus = bus;devfn = devfn;pcibios_read_config_word(pptr-bus, pptr-devfn,PCI_VENDOR_ID, &pptr-devfn,PCI_DEVICE_ID, &device);return pptr;(3)根据设备
3、的配置信息申请I/O空间及IRQ资源;(4)注册设备。USB设备的驱动主要处理probe(探测)、disconnect(断开)函数及usb_device_id(设备信息)数据结构,如:static struct usb_device_id sample_id_table =USB_INTERFACE_INFO(3, 1, 1), driver_info: (unsigned long)keyboard ,USB_INTERFACE_INFO(3, 1, 2), driver_info:mouse,0, /* no more matches */;static struct usb_driver
4、 sample_usb_driver =name: sample, probe: sample_probe, disconnect: sample_disconnect, id_table:sample_id_table,当一个USB 设备从系统拔掉后,设备驱动程序的disconnect 函数会自动被调用,在执行了disconnect 函数后,所有为USB 设备分配的数据结构,内存空间都会被释放:static void sample_disconnect(struct usb_device *udev, void *clientdata)/* the clientdata is the sam
5、ple_device we passed originally */struct sample_device *sample = clientdata;/* remove the URB, remove the input device, free memory */usb_unlink_urb(&sample-urb);kfree(sample);printk(KERN_INFO sample: USB %s disconnectedn, sample-name);* here you might MOD_DEC_USE_COUNT, but only if you increment* t
6、he count in sample_probe() belowreturn;当驱动程序向子系统注册后,插入一个新的USB设备后总是要自动进入probe函数。驱动程序会为这个新加入系统的设备向内部的数据结构建立一个新的实例。通常情况下,probe 函数执行一些功能来检测新加入的USB 设备硬件中的生产厂商和产品定义以及设备所属的类或子类定义是否与驱动程序相符,若相符,再比较接口的数目与本驱动程序支持设备的接口数目是否相符。一般在probe 函数中也会解析USB 设备的说明,从而确认新加入的USB 设备会使用这个驱动程序:static void *sample_probe(struct usb_
7、device *udev, unsigned int ifnum,const struct usb_device_id *id)* The probe procedure is pretty standard. Device matching has already* been performed based on the id_table structure (defined later)struct usb_interface *iface;struct usb_interface_descriptor *interface;struct usb_endpoint_descriptor *
8、endpoint;struct sample_device *sample;usbsample: probe called for %s devicen,(char *)id-driver_info /* or */ );iface = &udev-actconfig-interfaceifnum;interface = &iface-altsettingiface-act_altsetting;if (interface-bNumEndpoints != 1) return NULL;endpoint = interface-endpoint + 0;(endpoint-bEndpointA
9、ddress & 0x80) return NULL;if (endpoint-bmAttributes & 3) != 3) return NULL;usb_set_protocol(udev, interface-bInterfaceNumber, 0);usb_set_idle(udev, interface-bInterfaceNumber, 0, 0);/* allocate and zero a new data structure for the new device */sample = kmalloc(sizeof(struct sample_device), GFP_KER
10、NEL);sample) return NULL; /* failure */memset(sample, 0, sizeof(*sample);sample-name = (char *)id-driver_info;/* fill the URB data structure using the FILL_INT_URB macro */int pipe = usb_rcvintpipe(udev, endpoint-bEndpointAddress);int maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe);if (maxp 8) ma
11、xp = 8; sample-maxp = maxp; /* remember for later */FILL_INT_URB(&urb, udev, pipe, sample-data, maxp,sample_irq, sample, endpoint-bInterval);/* register the URB within the USB subsystem */if (usb_submit_urb(&urb) kfree(sample);return NULL;/* announce yourself */ probe successful for %s (maxp is %i)n
12、,sample-name, sample-maxp);* here you might MOD_INC_USE_COUNT; if you do, youll need to unplug* the device or the devices before being able to unload the module/* and return the new structure */return sample;在网络设备驱动的编写中,我们特别关心的就是数据的收、发及中断。网络设备驱动程序的层次如下:网络设备接收到报文后将其传入上层:/* Receive a packet: retrieve,
13、 encapsulate and pass over to upper levels*/void snull_rx(struct net_device *dev, int len, unsigned char *buf)struct sk_buff *skb;struct snull_priv *priv = (struct snull_priv *) dev-priv;* The packet has been retrieved from the transmission* medium. Build an skb around it, so upper layers can handle
14、 itskb = dev_alloc_skb(len+2);skb) printk(snull rx: low on mem - packet droppednpriv-stats.rx_dropped+;return;skb_reserve(skb, 2); /* align IP on 16B boundary */ memcpy(skb_put(skb, len), buf, len);/* Write metadata, and then pass to the receive level */skb-dev = dev;protocol = eth_type_trans(skb, d
15、ev);ip_summed = CHECKSUM_UNNECESSARY; /* dont check it */priv-stats.rx_packets+;#ifndef LINUX_20 stats.rx_bytes += len;#endif netif_rx(skb);在中断到来时接收报文信息:void snull_interrupt(int irq, void *dev_id, struct pt_regs *regs)int statusword;struct snull_priv *priv;* As usual, check the device pointer for sh
16、ared handlers.* Then assign struct device *devstruct net_device *dev = (struct net_device *)dev_id;/* . and check with hw if its really ours */dev /*paranoid*/ ) return;/* Lock the device */priv = (struct snull_priv *) dev-spin_lock(&priv-lock);/* retrieve statusword: real netdevices use I/O instruc
17、tions */statusword = priv-status;if (statusword & SNULL_RX_INTR) /* send it to snull_rx for handling */snull_rx(dev, priv-rx_packetlen, priv-rx_packetdata); SNULL_TX_INTR) /* a transmission is over: free the skb */stats.tx_packets+;stats.tx_bytes += priv-tx_packetlen;dev_kfree_skb(priv-skb);/* Unloc
18、k the device and we are done */spin_unlock(&而发送报文则分为两个层次,一个层次是内核调用,一个层次完成真正的硬件上的发送:* Transmit a packet (called by the kernel)int snull_tx(struct sk_buff *skb, struct net_device *dev)int len;char *data;#ifndef LINUX_24if (dev-tbusy | skb = NULL) PDEBUG(tint for %p, tbusy %ld, skb %pn, dev, dev-tbusy,
19、 skb);snull_tx_timeout (dev);if (skb = NULL)return 0;#endiflen = skb-len len;data = skb-data;dev-trans_start = jiffies; /* save the timestamp */* Remember the skb, so we can free it at interrupt time */skb = skb;/* actual deliver of data is device-specific, and not shown here */snull_hw_tx(data, len
20、, dev);return 0; /* Our simple device can not fail */* Transmit a packet (low level interface)void snull_hw_tx(char *buf, int len, struct net_device *dev)* This function deals with hw details. This interface loops* back the packet to the other snull interface (if any).* In other words, this function
21、 implements the snull behaviour,* while all other procedures are rather device-independentstruct iphdr *ih;struct net_device *dest;u32 *saddr, *daddr;/* I am paranoid. Aint I? */if (len sizeof(struct ethhdr) + sizeof(struct iphdr) snull: Hmm. packet too short (%i octets)n,len);if (0) /* enable this
22、conditional to look at the data */int i;len is %in KERN_DEBUG data:for (i=14 ; isaddr;daddr = &daddr;(u8 *)saddr)2 = 1; /* change the third octet (class C) */(u8 *)daddr)2 = 1;ih-check = 0; /* and rebuild the checksum (ip needs it) */check = ip_fast_csum(unsigned char *)ih,ih-ihl);if (dev = snull_devs)PDEBUGG(%08x:%05i - %08x:%05in,ntohl(ih-saddr),ntohs(struct tcphdr *)(ih+1)-source),ntohl(ih-daddr),ntohs(struct tcphdr *)(ih+1)-dest);else%05i daddr),ntoh
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1