网卡驱动架构分析
阅读原文时间:2021年04月21日阅读:1

1.Linux网络子系统

系统调用接口层

为应用程序提供访问网络子系统的统一方法。

协议无关层

提供通用的方法来使用传输层协议。

协议栈的实现

实现具体的网络协议

设备无关层

协议与设备驱动之前通信的通用接口

设备驱动程序

2.重要数据结构

2.1 网卡描述结构

在Linux内核中,每个网卡都由一个net_device结构来 描述,其中的一些重要成员有:

char name[IFNAMSIZ]

设备名,如:eth%d

unsigned long base_addr

I/O 基地址

const struct net_device_ops *netdev_ops;
记录了网卡所支持的操作

2.2 网卡操作集合

类似于字符设备驱动中的file_operations结构, net_device_ops结构记录了网卡所支持的操作。

static const struct net_device_ops dm9000_netdev_ops =

{

.ndo_open = dm9000_open,

.ndo_stop = dm9000_stop,

.ndo_start_xmit = dm9000_start_xmit,

.ndo_do_ioctl = dm9000_ioctl,

.ndo_validate_addr = eth_validate_addr,

.ndo_set_mac_address = eth_mac_addr,

};

2.3 网络数据包

Linux内核中的每个网络数据包都由一个套接字 缓冲区结构 struct sk_buff 描述,即一个 sk_buff结构就是一个网络包,指向sk_buff的指 针通常被称做skb。

3.网卡驱动架构分析
cs89x0.c:

  1. /* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0

  2. * driver for linux.

  3. */

  4. static const struct net_device_ops net_ops = {                                                                     //net_device_ops结构,各种网卡操作函数接口

  5. .ndo_open = net_open,

  6. .ndo_stop = net_close,

  7. .ndo_tx_timeout = net_timeout,

  8. .ndo_start_xmit = net_send_packet,

  9. .ndo_get_stats = net_get_stats,

  10. .ndo_set_multicast_list = set_multicast_list,

  11. .ndo_set_mac_address = set_mac_address,

  12. #ifdef CONFIG_NET_POLL_CONTROLLER

  13. .ndo_poll_controller = net_poll_controller,

  14. #endif

  15. .ndo_change_mtu = eth_change_mtu,

  16. .ndo_validate_addr = eth_validate_addr,

  17. };

  18. static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev)                                     //网卡的发送函数

  19. {

  20. struct net_local *lp = netdev_priv(dev);

  21. unsigned long flags;

  22. if (net_debug > 3) {

  23. printk("%s: sent %d byte packet of type %x\n",

  24. dev->name, skb->len,

  25. (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);

  26. }

  27. /* keep the upload from being interrupted, since we

  28. ask the chip to start transmitting before the

  29. whole packet has been completely uploaded. */

  30. spin_lock_irqsave(&lp->lock, flags);

  31. netif_stop_queue(dev);                                                                                         //驱动程序通知网络子系统暂停数据包传输,从来进行实现流量控制。

  32. /* initiate a transmit sequence */

  33. writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);

  34. writeword(dev->base_addr, TX_LEN_PORT, skb->len);

  35. /* Test to see if the chip has allocated memory for the packet */

  36. if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {

  37. /*

  38. * It hasn't. But that shouldn't happen since

  39. * we're waiting for TxOk, so return 1 and requeue this packet.

  40. */

  41. spin_unlock_irqrestore(&lp->lock, flags);

  42. if (net_debug) printk("cs89x0: Tx buffer not free!\n");

  43. return NETDEV_TX_BUSY;

  44. }

  45. /* Write the contents of the packet */

  46. writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);                                         //将skb的内容写入寄存器,发送

  47. spin_unlock_irqrestore(&lp->lock, flags);

  48. dev->stats.tx_bytes += skb->len;

  49. dev_kfree_skb (skb);                                                                                          //释放skb

  50. /*

  51. * We DO NOT call netif_wake_queue() here.

  52. * We also DO NOT call netif_start_queue().

  53. *

  54. * Either of these would cause another bottom half run through

  55. * net_send_packet() before this packet has fully gone out. That causes

  56. * us to hit the "Gasp!" above and the send is rescheduled. it runs like

  57. * a dog. We just return and wait for the Tx completion interrupt handler

  58. * to restart the netdevice layer

  59. */

  60. return NETDEV_TX_OK;

  61. }

  62. /* The typical workload of the driver:

  63. Handle the network interface interrupts. */

  64. static irqreturn_t net_interrupt(int irq, void *dev_id)                                                                   //网卡中断处理函数

  65. {

  66. struct net_device *dev = dev_id;

  67. struct net_local *lp;

  68. int ioaddr, status;

  69. int handled = 0;

  70. ioaddr = dev->base_addr;

  71. lp = netdev_priv(dev);

  72. /* we MUST read all the events out of the ISQ, otherwise we'll never

  73. get interrupted again. As a consequence, we can't have any limit

  74. on the number of times we loop in the interrupt handler. The

  75. hardware guarantees that eventually we'll run out of events. Of

  76. course, if you're on a slow machine, and packets are arriving

  77. faster than you can read them off, you're screwed. Hasta la

  78. vista, */

  79. while ((status = readword(dev->base_addr, ISQ_PORT))) {

  80. if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);

  81. handled = 1;

  82. switch(status & ISQ_EVENT_MASK) {

  83. case ISQ_RECEIVER_EVENT:

  84. /* Got a packet(s). */

  85. net_rx(dev);

  86. break;

  87. case ISQ_TRANSMITTER_EVENT:

  88. dev->stats.tx_packets++;

  89. netif_wake_queue(dev); /* Inform upper layers. */                                                         //发送中停止设备,在这里被唤醒

  90. if ((status & ( TX_OK |

  91. TX_LOST_CRS |

  92. TX_SQE_ERROR |

  93. TX_LATE_COL |

  94. TX_16_COL)) != TX_OK) {

  95. if ((status & TX_OK) == 0)

  96. dev->stats.tx_errors++;

  97. if (status & TX_LOST_CRS)

  98. dev->stats.tx_carrier_errors++;

  99. if (status & TX_SQE_ERROR)

  100. dev->stats.tx_heartbeat_errors++;

  101. if (status & TX_LATE_COL)

  102. dev->stats.tx_window_errors++;

  103. if (status & TX_16_COL)

  104. dev->stats.tx_aborted_errors++;

  105. }

  106. break;

  107. case ISQ_BUFFER_EVENT:

  108. if (status & READY_FOR_TX) {

  109. /* we tried to transmit a packet earlier,

  110. but inexplicably ran out of buffers.

  111. That shouldn't happen since we only ever

  112. load one packet. Shrug. Do the right

  113. thing anyway. */

  114. netif_wake_queue(dev); /* Inform upper layers. */

  115. }

  116. if (status & TX_UNDERRUN) {

  117. if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);

  118. lp->send_underrun++;

  119. if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;

  120. else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;

  121. /* transmit cycle is done, although

  122. frame wasn't transmitted - this

  123. avoids having to wait for the upper

  124. layers to timeout on us, in the

  125. event of a tx underrun */

  126. netif_wake_queue(dev); /* Inform upper layers. */

  127. }

  128. #if ALLOW_DMA

  129. if (lp->use_dma && (status & RX_DMA)) {

  130. int count = readreg(dev, PP_DmaFrameCnt);

  131. while(count) {

  132. if (net_debug > 5)

  133. printk("%s: receiving %d DMA frames\n", dev->name, count);

  134. if (net_debug > 2 && count >1)

  135. printk("%s: receiving %d DMA frames\n", dev->name, count);

  136. dma_rx(dev);

  137. if (--count == 0)

  138. count = readreg(dev, PP_DmaFrameCnt);

  139. if (net_debug > 2 && count > 0)

  140. printk("%s: continuing with %d DMA frames\n", dev->name, count);

  141. }

  142. }

  143. #endif

  144. break;

  145. case ISQ_RX_MISS_EVENT:

  146. dev->stats.rx_missed_errors += (status >> 6);

  147. break;

  148. case ISQ_TX_COL_EVENT:

  149. dev->stats.collisions += (status >> 6);

  150. break;

  151. }

  152. }

  153. return IRQ_RETVAL(handled);

  154. }

  155. ………..

  156. /* We have a good packet(s), get it/them out of the buffers. */

  157. static void

  158. net_rx(struct net_device *dev)                                                                                             //网卡的接收函数

  159. {

  160. struct sk_buff *skb;

  161. int status, length;

  162. int ioaddr = dev->base_addr;

  163. status = readword(ioaddr, RX_FRAME_PORT);                                                                              //读取待接收的数据状态

  164. length = readword(ioaddr, RX_FRAME_PORT);                                                                              //读取接收数据的长度

  165. if ((status & RX_OK) == 0) {

  166. count_rx_errors(status, dev);

  167. return;

  168. }

  169. /* Malloc up new buffer. */

  170. skb = dev_alloc_skb(length + 2);                                                                                       //分配skb长度+2的结构

  171. if (skb == NULL) {

  172. #if 0 /* Again, this seems a cruel thing to do */

  173. printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);

  174. #endif

  175. dev->stats.rx_dropped++;

  176. return;

  177. }

  178. skb_reserve(skb, 2); /* longword align L3 header */

  179. readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);                                                    //从网卡寄存器中读出数据,存入skb

  180. if (length & 1)

  181. skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);

  182. if (net_debug > 3) {

  183. printk( "%s: received %d byte packet of type %x\n",

  184. dev->name, length,

  185. (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);

  186. }

  187. skb->protocol=eth_type_trans(skb,dev);

  188. netif_rx(skb);                                                                                                          //将接收到的数据包skb交给协议栈-netif_rx

  189. dev->stats.rx_packets++;

  190. dev->stats.rx_bytes += length;

  191. }

  192. #if ALLOW_DMA

  193. static void release_dma_buff(struct net_local *lp)

  194. {

  195. if (lp->dma_buff) {

  196. free_pages((unsigned long)(lp->dma_buff), get_order(lp->dmasize * 1024));

  197. lp->dma_buff = NULL;

  198. }

  199. }

  200. #endif

  201. /* The inverse routine to net_open(). */

  202. static int

  203. net_close(struct net_device *dev)

  204. {

  205. #if ALLOW_DMA

  206. struct net_local *lp = netdev_priv(dev);

  207. #endif

  208. netif_stop_queue(dev);

  209. writereg(dev, PP_RxCFG, 0);

  210. writereg(dev, PP_TxCFG, 0);

  211. writereg(dev, PP_BufCFG, 0);

  212. writereg(dev, PP_BusCTL, 0);

  213. free_irq(dev->irq, dev);

  214. #if ALLOW_DMA

  215. if (lp->use_dma && lp->dma) {

  216. free_dma(dev->dma);

  217. release_dma_buff(lp);

  218. }

  219. #endif

  220. /* Update the statistics here. */

  221. return 0;

  222. }

  223. ……..

  224. int __init init_module(void)                                                                               //网卡初始化

  225. {

  226. struct net_device *dev = alloc_etherdev(sizeof(struct net_local));                                     //分配net_device结构空间

  227. struct net_local *lp;

  228. int ret = 0;

  229. #if DEBUGGING

  230. net_debug = debug;

  231. #else

  232. debug = 0;

  233. #endif

  234. if (!dev)

  235. return -ENOMEM;

  236. dev->irq = irq;                                                                                        //初始化分配的dev

  237. dev->base_addr = io;

  238. lp = netdev_priv(dev);

  239. #if ALLOW_DMA

  240. if (use_dma) {

  241. lp->use_dma = use_dma;

  242. lp->dma = dma;

  243. lp->dmasize = dmasize;

  244. }

  245. #endif

  246. spin_lock_init(&lp->lock);

  247. /* boy, they'd better get these right */

  248. if (!strcmp(media, "rj45"))

  249. lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;

  250. else if (!strcmp(media, "aui"))

  251. lp->adapter_cnf = A_CNF_MEDIA_AUI | A_CNF_AUI;

  252. else if (!strcmp(media, "bnc"))

  253. lp->adapter_cnf = A_CNF_MEDIA_10B_2 | A_CNF_10B_2;

  254. else

  255. lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;

  256. if (duplex==-1)

  257. lp->auto_neg_cnf = AUTO_NEG_ENABLE;

  258. if (io == 0) {

  259. printk(KERN_ERR "cs89x0.c: Module autoprobing not allowed.\n");

  260. printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n");

  261. ret = -EPERM;

  262. goto out;

  263. } else if (io <= 0x1ff) {

  264. ret = -ENXIO;

  265. goto out;

  266. }

  267. #if ALLOW_DMA

  268. if (use_dma && dmasize != 16 && dmasize != 64) {

  269. printk(KERN_ERR "cs89x0.c: dma size must be either 16K or 64K, not %dK\n", dmasize);

  270. ret = -EPERM;

  271. goto out;

  272. }

  273. #endif

  274. ret = cs89x0_probe1(dev, io, 1);                                                                                //这里依然在初始化:硬件初始化、MAC地址、注册网卡驱动(register_netdev)

  275. if (ret)

  276. goto out;

  277. dev_cs89x0 = dev;

  278. return 0;

  279. out:

  280. free_netdev(dev);

  281. return ret;

  282. }

  283. void __exit

  284. cleanup_module(void)

  285. {

  286. unregister_netdev(dev_cs89x0);

  287. writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);

  288. release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);

  289. free_netdev(dev_cs89x0);

  290. }

  291. #endif /* MODULE */

  292. /*

  293. * Local variables:

  294. * version-control: t

  295. * kept-new-versions: 5

  296. * c-indent-level: 8

  297. * tab-width: 8

  298. * End:

  299. *

  300. */

阅读(69) | 评论(0) | 转发(0) |

0

上一篇:串口驱动编程实现

下一篇:linux shell 数组建立及使用技巧

相关热门文章

给主人留下些什么吧!~~

评论热议

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器