深入浅出Linux设备驱动编程--复杂设备驱动
作者 佚名技术
来源 Linux系统
浏览
发布时间 2012-05-16
the URB within the USB subsystem */ if (usb_submit_urb(&sample->urb)) { kfree(sample); return NULL; } /* announce yourself */ printk(KERN_INFO "usbsample: probe successful for %s (maxp is %i)n", sample->name, sample->maxp); /* * here you might MOD_INC_USE_COUNT; if you do, you''ll 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, 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 it */ skb = dev_alloc_skb(len 2); if (!skb) { printk("snull rx: low on mem - packet droppedn"); priv->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; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_UNNECESSARY; /* don''t check it */ priv->stats.rx_packets ; #ifndef LINUX_20 priv->stats.rx_bytes = len; #endif netif_rx(skb); return; } 在中断到来时接收报文信息: 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 shared handlers. * Then assign "struct device *dev" */ struct net_device *dev = (struct net_device *)dev_id; /* ... and check with hw if it''s really ours */if (!dev /*paranoid*/ ) return; /* Lock the device */ priv = (struct snull_priv *) dev->priv; spin_lock(&priv->lock); /* retrieve statusword: real netdevices use I/O instructions */ statusword = priv->status; if (statusword & SNULL_RX_INTR) { /* send it to snull_rx for handling */ snull_rx(dev, priv->rx_packetlen, priv->rx_packetdata); } if (statusword & SNULL_TX_INTR) { /* a transmission is over: free the skb */ priv->stats.tx_packets ; priv->stats.tx_bytes = priv->tx_packetlen; dev_kfree_skb(priv->skb); } /* Unlock the device and we are done */ spin_unlock(&priv->lock); return; } 而发送报文则分为两个层次,一个层次是内核调用,一个层次完成真正的硬件上的发送: /* * Transmit a packet (called by the kernel) */ int snull_tx(struct sk_buff *skb, struct net_device *dev) { int len; char *data; struct snull_priv *priv = (struct snull_priv *) dev->priv; #ifndef LINUX_24 if (dev->tbusy || s |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |
你可能对下面的文章感兴趣
关于深入浅出Linux设备驱动编程--复杂设备驱动的所有评论