static int __devinit rtl8139_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
函数功能描述:赋给pci_driver结构体中的probe函数指针,用于当PCI核心检测到一个需要控制的pci_dev时,对相应的设备进行始化工作。
附注:本函数的主要任务是创建并初始化net_device结构,该结构是网卡设备的抽象。
函数流程:
1.         调用alloc_etherdev函数,创建以太网类型的网卡设备。它是对alloc_netdev函数的封装,内核中给出了用于设置以太网通用属性的setup函数。
2.         使能当前PCI设备,包括唤醒、热插拔等功能的建立。
3.         读取PCI配置空间中的Base Address Register。PCI local bus specification规定,PCI配置空间有6个32位寄存器保存基地址(即bar0-bar5)。8139too网卡驱动程序使用了其中的两个来分别表示I/O空间基地址映射和内存空间基地址映射。
4.         接下来调用pci_request_regions函数申请资源。该函数实际上调用了request_region和request_mem_region,它们分别负责分配I/O端口和内存资源。(内核中资源一般分成四类,分别是I/O 端口,内存,DMA通道和中断线,它们都由resource结构描述,不同的是每一类资源拥有共同的基类对象,这一点上体现出了内核设计上的OO思想。实际上,典型的面向对象思想如封装、继承、多态在内核中都有体现。每一类资源都以树状结构进行组织,源码显示,这种树状结构实际上是一种“双亲表示法”和“孩子、兄弟表示法”的融合)。
5.         设置dev->base_addr字段,它视驱动程序采用I/O空间抑或内存空间而定。如果采用I/O空间,还要将I/O端口地址映射成内存地址(这是一种比较好的做法);否则,把PCI配置空间中bar1寄存器中的内存地址进行重映射,只有经过重映射,驱动程序才能够访问该内存区域,这里涉及到页表项的添加。
6.         复位芯片。
7.         初始化net_device结构中的部分回掉函数,它们负责完成数据包的接收和传输等任务。
static int rtl8139_open (struct net_device *dev)
函数功能描述:申请资源,启动硬件和开启监控线程。
函数流程:
1.         调用request_irq函数,以可共享的方式(IRQF_SHARED)分配给网卡设备中断线,中断号存放在dev->irq中。
2.         申请用于DMA的设备内存。调用pci_alloc_consistent函数,它返回两个地址,一个是供设备驱动程序使用的内核虚地址;另一个是供DMA控制器使用的总线地址(它在某些体系结构下等同与物理地址)。用该函数申请到的设备内存物理上必须是连续的,因为这里DMA操作是将成块物理上连续的数据在主存与网卡的FIFO缓存间传输。pci_alloc_consistent函数实际上是调用__get_free_pages函数获取内存页,并使用vrit_to_phys函数将得到的内存页虚地址转换成物理地址。
3.         初始化ring buffer.。
4.         启动硬件。首先复位网卡设备,接着将从EEPROM设备中读取的硬件地址写入相应的寄存器,然后把第三步中获得的输入输出DMA缓冲区的总线地址赋予相应的寄存器,最后设置组播列表、使能所有已知的中断。
5.         启动传输队列,接受来自网络层的数据包。
6.         启动监控线程,该线程负责在传输超时的情况下做相应处理。该监控线程用工作队列实现。通过使用schedule_delayed_work函数,该线程函数可以在规定的时间点上被执行。
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
函数功能描述:将网络层获得数据拷贝到DMA缓冲区
函数流程:
1.         将sk_buf结构中的数据拷贝到四路DMA输出缓冲区中的一个,保证包的大小至少为ETH_ZLEN。
2.         判断四路缓冲区是否已被用完,如果是,则调用netif_stop_queue函数来暂停网络层传输队列。这里要注意的是,完成sk_buf结构的拷贝后,要更新tp->rx_curr指针,它是一个unsigned long类型,同时,驱动程序还维护tp->rx_dirty指针。这两个指针负责四路DMA输出缓冲区的数据同步。它们都是不断递增的,当二者之差等于NUM_TX_DESC的时候,意味着四路DMA输出缓冲区都已被填满而且尚未被传输,这时候要做的自然是停止网络层继续向驱动程序发送skb。
static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
函数功能描述:中断处理
附注:通常情况下,中断的来临意味着FIFO中的数据已发送或DMA已将接受到的数据由FIFO拷贝到DMA缓冲区。更具体的来说,在禁止early mode的前提下,中断的发生表示一个完整的数据包被发送到了网络介质或者一个完整的数据包已通过DMA的传送到了内存缓冲区。为了不致使大量小数据包的接收给系统带来的频繁中断降低系统性能,Linux内核中提供了NAPI,即在关闭接收中断的状态下,以轮循的方式接收数据。
函数流程:
1.         读取中断状态寄存器,检查该中断是否属于当前网卡设备。由于以可共享的方式使用中断线,这一步是必须的。
2.         如果接收中断位被设置,首先调用netif_rx_schedule_prep函数,将设备对象的dev->poll方法加入到网络层的poll队列,如果函数执行成功,则清除中断状态寄存器的相应位(方法是在要清除的位写1),接着在设备对象上调用__netif_rx_schedule函数,它会在必要的时候出发一个软中断,从而通知网络层开始接受数据包(即调用dev->poll函数)。
3.         如果传输中断被位设置,则对已传送的数据包进行确认。具体的讲,就是通过读取相应的传输状态寄存器,获取传送的信息。芯片手册中规定,当驱动程序将数据包大小写入该寄存器的低12位的同时必须将其13位置0,而当传输DMA操作完成时,该位被自动置1,由此看来,这是与DMA控制器之间的握手操作。这里要明确指出的是,数据包由网络层传递给驱动程序并放置在DMA传输缓冲区的操作由上面谈到的rtl8139_start_xmit函数负责,中断处理函数中仅仅是对已发送的数据包的确认,同时记录一些信息,如发送的数据总量、发送的总数据包数、丢弃的总数据包数等等。
4.         步骤1、2、3都应在自旋锁的保护下进行。
static int rtl8139_poll(struct net_device *dev, int *budget)
函数功能描述:以轮循的方式将DMA输入缓冲区中的数据拷贝到sk_buf结构中并交付给网络层做进一步处理。
附注:本函数被赋值给net_device结构中的poll字段,它由软中断出发并不断被调用直到数据被处理完毕。整个过程要在输入自旋锁的保护下进行。
函数流程:
1.         清除中断状态寄存器的相应位。
2.         从rx_ring输入DMA缓冲区中读取数据包,申请并初始化sk_buf结构,同时用rx_ring中的数据包填充之,接着调用netif_receive_skb函数把sk_buf结构交付给网络层。这里应该注意的是,驱动程序通过在rtl8139_private结构中的unsigned int变量cur_rx来维护rx_ring中多个数据包的处理序列。独立于每个包的头4个字节放置的是接收数据包的状态和长度。
3.         更新CAPR(Current Address of Packet Read)寄存器,地址要双字对齐,应此,在计算cur_rx值时,使用表达式cur_rx = (cur_rx + rx_size + 4 + 3) & ~3。
4.         重复步骤2中的操作直到处理完rx_ring中的所有数据包。
5.         使用__netif_rx_complete函数将当前设备在poll队列中清除,接着使能接收数据中断。由于接收中断和__netif_rx_complete函数间存在竞争,即将设备从poll队列中清除的同时可能会有新的接收中断到来,应此这两个操作要在屏蔽本地cpu中断的状态下进行。
后记:
写这样的文章,对与我来说是比较有压力的。一方面,在Linux设备驱动开发领域,我算是一个新手;另一方面,光是看了几天代码写点总结未免有些纸上谈兵;更重要的是,我对芯片手册中的部分内容还不是很理解,例如early mode的用途等等,因此本文的错误是在所难免的,希望朋友们不吝赐教。此外,这几天惊闻06级硕士要改回2年半,心里颇有不快,那就借此拙文慰藉一下自己和实验室的同胞吧。借用方师兄的qq签名档:改变能够改变的,接收不能改变的。

转载于:https://blog.51cto.com/enchen/191920

Linux下Rtl8139too网卡设备驱动程序关键函数剖析相关推荐

  1. linux下Led的设备驱动程序实验总结,Linux让LED灯闪起来

    众所周知,LED灯闪烁实验,就相当于编程中的helloworld,是最简单入门,也是可以帮助广大爱好学习者建立自信的,看了设备驱动一个多月,终于我也让自己的led灯闪亮了. 要让led灯闪烁,就是要控 ...

  2. linux 设备数 of,linux下devicetree中惯用的of函数

    linux下devicetree中常用的of函数 从device_node中获取信息: int of_property_read_u8_array(const struct device_node * ...

  3. Linux下双网卡绑定技术实现负载均衡和失效保护

    保持服务器的高可用性是企业级 IT 环境的重要因素.其中最重要的一点是服务器网络连接的高可用性.网卡(NIC)绑定技术有助于保证高可用性特性并提供其它优势以提高网络性能.       我们在这介绍的L ...

  4. Linux下双网卡绑定(bonding技术)

    Linux网卡绑定探析 2013-08-20 15:39:31 现在很多服务器都自带双千兆网口,利用网卡绑定既能增加网络带宽,同时又能做相应的冗余,目前应用于很多的场景.linux操作系统下自带的网卡 ...

  5. linux 有线网卡,linux下有线网卡出现ADDRCONF(NETDEV_UP): eth0: link is not ready的解决方法...

    一.背景 2018年5月24日,笔者的pc已经连续运转两天了,突然要使用有线网卡,却发现有线网卡无法正常工作,于是查看了一下内核日志: r8169 0000:05:00.0 eth0: link do ...

  6. linux u盘插入事件,Linux 下监控USB设备拔插事件

    Linux 下监控USB设备拔插事件 发布时间:2018-01-29 00:00, 浏览次数:1111 , 标签: Linux USB * 使用Netlink来实现 这是一个特殊的socket,可以接 ...

  7. 什么是 Linux 下的 platform 设备驱动

    Linux下的字符设备驱动一般都比较简单,只是对IO进行简单的读写操作.但是I2C.SPI.LCD.USB等外设的驱动就比较复杂了,需要考虑到驱动的可重用性,以避免内核中存在大量重复代码,为此人们提出 ...

  8. Linux下多网卡MAC配置问题

    HWADDR=, 其中 以AA:BB:CC:DD:EE:FF形式的以太网设备的硬件地址.在有多个网卡设备的机器上,这个字段是非常有用的,它保证设备接口被分配了正确的设备名,而不考虑每个网卡模块被配置的 ...

  9. ​Linux下C如何调用PCI Lib函数

    Linux下C如何调用PCI Lib函数 在Linux下,可以通过"setpci"和"setpci"命令来访问PCI设备的配置空间,那么能否用程序来访问PCI ...

最新文章

  1. Python 三十大实践、建议和技巧
  2. Codeforces Round 550 (Div.3) 题解
  3. 安装exchange server 2003服务器
  4. [大數據、Big Data、巨量資料、海量資料]之分析模式工具
  5. 推荐 10 个好用的 Vue3 的开源项目,开发效率又能提升了!
  6. web模块化规范和实现
  7. 洛谷P3357:最长k可重线段集问题(网络流)
  8. 知识图谱最新权威综述论文解读:实体发现
  9. LwIP应用开发笔记之五:LwIP无操作系统TCP服务器
  10. java正则获取数字_Java通过正则表达式获取字符串中数字的方法示例
  11. Numpy学习---Task03---数组的操作
  12. Win11进桌面闪屏,亲测恢复正常
  13. 2019小程序没必要做了_2019,小程序会更好吗?
  14. spring boot 邮箱验证总结
  15. 金彩教育:怎么布局人群标签
  16. 怎么用计算机测出来体脂,如何测自己的体脂率?
  17. 新浪和腾讯微博教程(一)
  18. 微信域名防拦截的最新方案,域名防举报投诉原理
  19. 使用VNC远程连接云服务器,连接超时问题
  20. AI与大数据分析结合,就像给大象装上翅膀

热门文章

  1. 【Vue】数据改变,DOM不渲染问题
  2. Activiti流程定义删除
  3. 埃文科技受邀参展2018中国(郑州)新型智慧城市建设暨产业高峰论坛
  4. windows中hid操作api介绍
  5. 服务器主板bios信息修改,服务器主板bios设置
  6. linux一些常用指令(根据尚硅谷韩顺平老师视频所写,都是自己手打的)
  7. Spring基础入门7 - JPA/Hibernate
  8. 学前儿童计算机应用基础试卷,福建师范大学2020年2月课程考试《计算机应用基础》期末试卷A(在线考核).doc...
  9. 函数的返回值return
  10. QT如何与xbox手柄连接