Linux网络驱动程序功能分析

合集下载

Linux内核驱动之网络驱动(三)PHY寄存器分析

Linux内核驱动之网络驱动(三)PHY寄存器分析

一PHY简介以太网PHY和MAC对应OSI模型的两个层:物理层和数据链路层物理层的芯片称之为PHY以太网卡中数据链路层的芯片称之为MAC控制器物理层定义了数据传送与接收所需要的电与光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层设备提供标准接口RGMII/GMII/MII数据链路层则提供寻址机构、数据帧的构建、数据差错检查、传送控制、向网络层(IP层)提供标准的数据接口二以太网PHY芯片标准寄存器分析对于PHY标准寄存器control register和status register是最常用的。

下面是详细分析Control Register(BMCR)bit15:reset bit置1实现复位操作,复位后会导致外围管脚对PHY芯片的配置失效同时该端口的控制、状态寄存器将恢复为默认值,需要重新进行配置。

复位过程中bit15保持为1,复位完成后该位自动清零。

bit14:loopback主要用于调试以及故障诊断bit13:speed selection LSBbit13和Bit6两位联合实现对端口的速率控制功能, 需要注意的是speed selection只有在自动协商关闭的情况下才起作用bit12: Auto-Negotiation Enable自动协商(AN)开关,置1表示打开自动协商功能,此时端口的工作模式通过和对端(Link partner)进行AN来确定,必须注意的是,对于1000BASE-T接口,自动协商必须打开bit11: Power Down置1将进入低功耗模式,需要注意的是端口从Power Down 模式恢复,需要复位端口以保证端口可靠的连接bit10: Isolate隔离开关,一般不用bit9 : Restart Auto-Negotiation重新启动自动协商,一般修改端口的自动协商能力信息(ANAR)后通过bit9置1重新启动自动协商来使端口按照新的配置建立linkbit8 : Duplex Mode双工模式设置,只有在自动协商关闭的情况下才起作用bit7 : Collision Test冲突信号(COL)测试开关,一般不使用bit6 : Speed Selection (MSB)bit13和Bit6两位联合实现对端口的速率控制功能,当然只有在自动协商关闭的情况下才起作用1 0 = 1000 Mb/s0 1 = 100 Mb/s0 0 = 10 Mb/sbit5 ~ bit0 Reservedstatus register(BMSR)该寄存器主要是用来描述PHY芯片的工作模式能力和当前工作状态bit15:100BASE-T4bit14:100BASE-X Full Duplexbit13:100BASE-X Half Duplexbit12:10 Mb/s Full Duplexbit11:10 Mb/s Half Duplexbit10:100BASE-T2 Full Duplexbit9 : 100BASE-T2 Half Duplex寄存器中的bit9~bit15都是描述PHY芯片工作模式能力,1表示具备该能力,0表示不具备bit8 : Extended Statusbit7 : Reservedbit6 : MF Preamble Suppressionbit5 : Auto-Negotiation Completebit5=1表示自动协商进程已经成功结束,此时PHY芯片的其他和Link状态相关的寄存器才是正确可靠的bit4 : Remote Faultbit4=1表示连接对端(Link Partner)出错,一般会在其他寄存器(register16-31)中定义具体错误类型bit3 : Auto-Negotiation Abilitybit2 : Link StatusLink up则该位为1,0则代表Link down,Link status 只有在自动协商完成后才有效bit1 : Jabber Detect100M和1000M模式下没有意义bit0 : Extended CapabilityPHY Identifier Register寄存器2和3存放PHY芯片的型号代码,由芯片商自行定义,一般用来定义PHY芯片的型号和版本Auto-Negotiation Advertisement Register寄存器ANAR是自动协商的能力通告寄存器,在AN Enable 的前提下,端口根据该寄存器的相关配置与对端(Link partner)进行自动协商。

设计Linux系统网络设备驱动程序

设计Linux系统网络设备驱动程序

1 n u x / i in c 1U d e / 1 n u x / i
net vi e. 。 de c h

网络物 理 设备 媒介
2 初 始 化
网 络 设 备 的 初 始 化 主 要 是 由
设 备 媒 介 层
图 1 iu L n x网络驱 动程 序体 系结 构 图
开藏豸 统世界奠 ; ≯
维普资讯
开 放 系统 世界
一 [ i u ] Ln x 技 术 开 发 一

序 会 很 轻 松 , 并 且 能 够 形 成 固 定 的 模
备 接 口 f r (hi_ v = 0: t s de < o t s de hi _ v
数 h — a rd
s art x m  ̄ t _ t,
d vc e i e数 据 结 构 中 的 i i n t函 数 指 针 所 指 的 初 始 化 函 数 来 完 成 的 。当 内 核 启 动 或 加 载 网 络 驱 动 模 块 的 时 候 ,就 会 调 用 初 始 化 过 程 。这 个 过 程 将 首 先 检 测 网 络 物
计 Li nux 防 火 墙 和 网 络 入 侵 检 测 系 统 时, 可 以在 网络 驱 动程 序 的基 础上 拦 截 网 络 数 据 包 ,继 而 对 其 进 行 分 析 。由 于 Li nux是 开 放 源 代 码 的 ,所 以 给 我 们 提 供 了一个分析 和改造 网络驱r c e i e tu td vc
网络 设 备接 口层
ne _de c t vie)
的 详 细 内容 , 请 参 看 /
数 据包 发 送 h r tr mi a d sa tx t O
中 断处 理 ( 据 包 数 接收)

NAPI 技术在 Linux 网络驱动上的应用和完善

NAPI 技术在 Linux 网络驱动上的应用和完善

NAPI 是Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以POLL 的方法来轮询数据,类似于底半方式(bottom-half 的处理模式);但是目前在Linux 的NAPI 工作效率比较差,本文在分析NAPI 的同时,提供了一种高效的改善方式供大家参考。

前言:NAPI 是Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收的服务程序,然后POLL 的方法来轮询数据,(类似于底半(bottom-half)处理模式);从我们在实验中所得到的数据来看,在随着网络的接收速度的增加,NIC 触发的中断能做到不断减少,目前NAPI 技术已经在网卡驱动层和网络层得到了广泛的应用,驱动层次上已经有E1000 系列网卡,RTL8139 系列网卡,3c50X 系列等主流的网络适配器都采用了这个技术,而在网络层次上,NAPI 技术已经完全被应用到了著名的netif_rx 函数中间,并且提供了专门的POLL 方法--process_backlog 来处理轮询的方法;根据实验数据表明采用NAPI技术可以大大改善短长度数据包接收的效率,减少中断触发的时间;由于RTL8139CP 是一种应用比较广泛的网络适配器,所以本文以其为例,说明了NAPI技术在网络适配器上的应用和基本原理。

但是NAPI 存在一些比较严重的缺陷:而对于上层的应用程序而言,系统不能在每个数据包接收到的时候都可以及时地去处理它,而且随着传输速度增加,累计的数据包将会耗费大量的内存,经过实验表明在Linux 平台上这个问题会比在FreeBSD 上要严重一些;另外采用NAPI 所造成的另外一个问题是对于大的数据包处理比较困难,原因是大的数据包传送到网络层上的时候耗费的时间比短数据包长很多(即使是采用DMA 方式),所以正如前面所说的那样,NAPI 技术适用于对高速率的短长度数据包的处理,在本文的末尾提出了NAPI 的改善方法,和实验数据。

Linux设备驱动程序原理及框架-内核模块入门篇

Linux设备驱动程序原理及框架-内核模块入门篇

Linux设备驱动程序原理及框架-内核模块入门篇内核模块介绍应用层加载模块操作过程内核如何支持可安装模块内核提供的接口及作用模块实例内核模块内核模块介绍Linux采用的是整体式的内核结构,这种结构采用的是整体式的内核结构,采用的是整体式的内核结构的内核一般不能动态的增加新的功能。

为此,的内核一般不能动态的增加新的功能。

为此,Linux提供了一种全新的机制,叫(可安装) 提供了一种全新的机制,可安装) 提供了一种全新的机制模块” )。

利用这个机制“模块”(module)。

利用这个机制,可以)。

利用这个机制,根据需要,根据需要,在不必对内核重新编译链接的条件将可安装模块动态的插入运行中的内核,下,将可安装模块动态的插入运行中的内核,成为内核的一个有机组成部分;成为内核的一个有机组成部分;或者从内核移走已经安装的模块。

正是这种机制,走已经安装的模块。

正是这种机制,使得内核的内存映像保持最小,的内存映像保持最小,但却具有很大的灵活性和可扩充性。

和可扩充性。

内核模块内核模块介绍可安装模块是可以在系统运行时动态地安装和卸载的内核软件。

严格来说,卸载的内核软件。

严格来说,这种软件的作用并不限于设备驱动,并不限于设备驱动,例如有些文件系统就是以可安装模块的形式实现的。

但是,另一方面,可安装模块的形式实现的。

但是,另一方面,它主要用来实现设备驱动程序或者与设备驱动密切相关的部分(如文件系统等)。

密切相关的部分(如文件系统等)。

课程内容内核模块介绍应用层加载模块操作过程内核如何支持可安装模块内核提供的接口及作用模块实例内核模块应用层加载模块操作过程内核引导的过程中,会识别出所有已经安装的硬件设备,内核引导的过程中,会识别出所有已经安装的硬件设备,并且创建好该系统中的硬件设备的列表树:文件系统。

且创建好该系统中的硬件设备的列表树:/sys 文件系统。

(udev 服务就是通过读取该文件系统内容来创建必要的设备文件的。

)。

linux usb wifi驱动开发原理

linux usb wifi驱动开发原理

linux usb wifi驱动开发原理Linux USB WiFi驱动开发原理一、引言随着无线网络的普及,WiFi成为了人们生活中不可或缺的一部分。

而在Linux操作系统中,为了支持各种WiFi设备,需要进行对应的驱动开发。

本文将介绍Linux USB WiFi驱动开发的原理和过程。

二、USB WiFi驱动开发的基本原理1. USB接口USB(Universal Serial Bus)是一种通用的串行总线标准,用于连接计算机与外部设备。

USB WiFi设备通过USB接口与计算机通信,传输数据和控制命令。

2. 驱动程序驱动程序是用于操作和控制硬件设备的软件。

USB WiFi驱动程序负责与USB WiFi设备进行通信,实现数据的传输和接收。

驱动程序需要与操作系统紧密结合,通过操作系统提供的API接口与设备进行交互。

三、USB WiFi驱动开发的过程1. 设备识别与初始化USB WiFi设备插入计算机后,操作系统会通过USB子系统进行设备的识别和初始化。

在Linux系统中,USB设备的识别和初始化由USB核心驱动完成。

核心驱动会根据设备的VID(Vendor ID)和PID (Product ID)来匹配对应的驱动程序。

2. 驱动程序注册驱动程序需要在Linux系统中进行注册,以便系统能够正确识别和加载驱动。

注册过程通常包括向系统注册设备类型、设备ID等信息。

3. 设备操作接口的实现驱动程序需要实现设备操作接口,包括设备的打开、关闭、读取数据、写入数据等功能。

这些操作接口是通过USB子系统提供的API 来实现的。

4. 数据传输与控制USB WiFi驱动程序需要实现数据的传输和控制功能。

数据传输主要包括从设备读取数据和向设备写入数据,而控制功能包括设置设备参数、配置网络等操作。

5. 错误处理与调试在USB WiFi驱动开发中,错误处理和调试是非常重要的一部分。

驱动程序需要处理各种异常情况,如设备断开连接、传输错误等。

网络驱动程序

网络驱动程序

网络驱动程序我们已经讨论了字符设备和块设备驱动程序,接着要讨论的是迷人的网络世界。

网络接口是Linux设备中的第三标准类,这一章就是讲述它们是如何与核心的其余部分交互的。

网络接口并不象字符和块设备那样存在于文件系统。

相反,它在核心层处理包的发送和接收,并不与进程中的某个打开的文件绑定在一起。

网络接口在文件系统中的角色就象被安装的块设备。

一个块设备在blk_dev数组和其它核心结构中注册它的特征,接着按照要求通过它的request_fn函数“发送”和“接收”块。

类似地,一个网络接口必须在特定的数据结构中注册自己,从而在与外部世界交换包时可以被调用。

安装的磁盘与包发送接口有几个重要的不同。

首先,磁盘以一个结点的形式存在于/dev 目录,而网络接口并不在文件系统中出现。

不过两者之间最大的不同在于:磁盘是被请求向核心发送一个缓冲区,而网络接口则是请求向核心推送进来的包。

Linux的网络子系统被设计成完全协议无关的。

这对网络协议(IP vs. IPX 或其它协议)和硬件协议(以太网vs.令牌环等)都是如此。

网络驱动程序和核心之间的交互一次处理一个网络包;这允许协议可以干净地对驱动程序隐`藏起来,而物理传输则可以对协议隐藏起来。

本章描述网络接口如何与核心的其它部分紧密合作,并给出一个基于内存的模块化的网络接口,称之为(你可能已经猜到了)snull。

为简化讨论,这个接口使用以太网硬件协议并传送IP包。

通过snull获得的知识可以很好地应用于IP以外的协议,从以太网移到其它硬件协议只要求你对使用的物理协议有所了解。

snull的另一个限制是它不能在Linux1.2中编译。

再说一遍,这样做只是为了保持代码简单,并避免在snull中加入一些另人厌倦的条件。

不过,本章将会提到与网络驱动程序相关的可移植性问题。

本章并不介绍IP的编号原则,网络协议,以及其它普通的网络概念。

这个主题与驱动程序作者无关,而且以不到几百页的篇幅想对网络技术有一个令人满意的概述是不可能的。

Linux命令行中的硬件信息查看和驱动管理

Linux命令行中的硬件信息查看和驱动管理

Linux命令行中的硬件信息查看和驱动管理在Linux命令行中,我们可以通过一些命令来查看硬件信息和管理驱动,这对于系统维护和故障排除非常重要。

本文将介绍几个常用的命令及其用法,帮助您快速获取硬件信息和管理驱动。

1. 查看硬件信息1.1 lshw命令lshw(或者lswhw)是一个用于查看硬件信息的命令,可以列出系统中所有硬件的详细信息,包括处理器、内存、硬盘、网卡等。

使用示例:```$ sudo lshw```运行以上命令后,您将看到完整的硬件信息列表,可以通过滚动查看或者使用管道和grep命令过滤感兴趣的部分。

1.2 lspci命令lspci命令用于列出系统中所有PCI设备的信息,包括显卡、网卡、声卡等。

使用示例:```$ lspci```该命令会输出PCI设备的详细信息,可以通过管道和grep进行过滤。

1.3 lsusb命令lsusb命令用于列出系统中所有USB设备的信息。

使用示例:```$ lsusb```该命令会输出USB设备的详细信息,可以通过管道和grep进行过滤。

2. 管理驱动2.1 modprobe命令modprobe命令用于加载和卸载Linux内核模块,包括驱动程序。

使用示例:```$ sudo modprobe <module_name> // 加载模块$ sudo modprobe -r <module_name> // 卸载模块```其中,`<module_name>`为要加载或卸载的模块名称。

2.2 lsmod命令lsmod命令用于列出当前已加载的内核模块。

使用示例:```$ lsmod```该命令会输出已加载模块的列表,包括模块名称、使用次数等信息。

2.3 rmmod命令rmmod命令用于卸载已加载的内核模块。

使用示例:```$ sudo rmmod <module_name>```其中,`<module_name>`为要卸载的模块名称。

基于Linux的网络设备高效驱动程序的开发技术

基于Linux的网络设备高效驱动程序的开发技术
重庆 邮 电大 学信 号与信 息 处理重 点 实验 室, 重庆 406 005 摘 要: 统 的 Lnx网络 驱动 程序 对 于高数据 传输 速 率 的 支持 有 局 限性 , 文提 出一 种 改 传 i u 本
进 的 网络 设备驱 动开发 技 术 , 可提 高数 据 包处 理性 能。本 文 首 先介 绍 了 Ln x网络 设备 驱 iu
因此 其应 用领域 很 广泛 ,iu 对 网络 应用 的支持 Lnx
尤其 出色 , 前大部分的网络服务器、 目 交换设备等 均 使用 Lnx 为操作 系统 … 。Ln x 统 的网络 iu 作 i 系 u
p o e s g is y h s p p ri to u e h r me r f L n x n t r e ie d ie . An h n i a a y e r c s i .F rt ,t i a e n r d c s t e f n l a wo k o i u ewo k d v c r r v d t e t n lz s
第 4期
21 年 1 01 2月

光 系

No. 4 De c.2 1 01
Elcr nc a d El cr - p ia y tms e to i n e to o tc lS se
基 于 Lnx的 网络 设 备 高效 驱 动 程序 的开 发技 术 iu
徐 沛, 黄 俊
ห้องสมุดไป่ตู้
( e a oa r g a a dIf ma o rcsi , K yL b rt yo S nl n o t nPo es g o fi nr i n C og i nvri P s a dTlcm nctn C ogig4 0 6 , hn ) h nqn U ie t o ot n eeo mu i i , hn q 0 05 C ia g syf ao n
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux网络驱动程序功能分析1.驱动模块的加载和卸载如果网络设备(包括wireless)是PCI规范的,则先是向内核注册该PCI设备(pci_register_driver),然后由pci_driver数据结构中的probe函数指针所指向的侦测函数来初始化该PCI设备,并且同时注册和初始化该网络设备。

如果网络设备(包括wireless)是PCMCIA规范的,则先是向内核注册该PCMCIA设备(register_pccard_driver),然后driver_info_t数据结构中的attach函数指针所指向的侦测函数来初始化该PCMCIA设备,并且同时注册和初始化该网络设备。

static int __init tg3_init(void){//先注册成PCI设备,并初始化,如果是其他的ESIA,PCMCIA,用其他函数return pci_module_init(&amp;tg3_driver);}static void __exit tg3_cleanup(void){pci_unregister_driver(&amp;tg3_driver);//注销PCI设备}module_init(tg3_init); //驱动模块的加载module_exit(tg3_cleanup); //驱动模块的卸载申明为PCI设备:static struct pci_driver tg3_driver = {.name = DRV_MODULE_NAME,.id_table = tg3_pci_tbl, //此驱动所支持的网卡系列,vendor_id, device_id.probe = tg3_init_one, //初始化网络设备的回调函数.remove = __devexit_p(tg3_remove_one), //注销网络设备的回调函数.suspend = tg3_suspend, //设备挂起函数.resume = tg3_resume //设备恢复函数};2.PCI设备探测函数probe,初始化网络设备static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){//初始化设备,使I/O,memory可用,唤醒设备pci_enable_device(pdev);//申请内存空间,配置网卡的I/O,memory资源pci_request_regions(pdev, DRV_MODULE_NAME);pci_set_master(pdev);//设置DMA属性pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff);//网卡 I/O,memory资源的启始地址tg3reg_base = pci_resource_start(pdev, 0);//网卡I/O,memory资源的大小tg3reg_len = pci_resource_len(pdev, 0);//分配并设置网络设备dev = alloc_etherdev(sizeof(*tp));//申明为内核设备模块SET_MODULE_OWNER(dev);//初始化私有结构中的各成员值tp = dev-&gt;priv;tp-&gt;pdev = pdev;tp-&gt;dev = dev;&hellip;&hellip;//锁的初始化spin_lock_init(&amp;tp-&gt;lock);//映射I/O,memory地址到私有域中的寄存器结构tp-&gt;regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len); dev-&gt;irq = pdev-&gt;irq;//网络设备回调函数赋值dev-&gt;open = tg3_open;dev-&gt;stop = tg3_close;dev-&gt;get_stats = tg3_get_stats;dev-&gt;set_multicast_list = tg3_set_rx_mode;dev-&gt;set_mac_aDDRess = tg3_set_mac_addr;dev-&gt;do_ioctl = tg3_ioctl;dev-&gt;tx_timeout = tg3_tx_timeout;dev-&gt;hard_start_xmit= tg3_start_xmit;//网卡的MAC地址赋值dev-&gt;addrtg3_get_device_address(tp);//注册网络设备register_netdev(dev);//把网络设备指针地址放入PCI设备中的设备指针中pci_set_drvdata(pdev, dev);}3.注销网络设备static void __devexit tg3_remove_one(struct pci_dev *pdev){struct net_device *dev = pci_get_drvdata(pdev);//注销网络设备unregister_netdev(dev);//取消地址映射iounmap((void *) ((struct tg3 *)(dev-&gt;priv))-&gt;regs);//释放网络设备kfree(dev);//释放PCI资源pci_release_regions(pdev);//停用PCI设备pci_disable_device(pdev);//PCI设备中的设备指针赋空pci_set_drvdata(pdev, NULL);}4.打开网络设备static int tg3_open(struct net_device *dev){//分配一个中断request_irq(dev-&gt;irq, tg3_interrupt, SA_SHIRQ, dev-&gt;name, dev);/* int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags,const char * devname,void *dev_id);irq是要申请的硬件中断号。

在Intel平台,范围0--15。

handler是向系统登记的中断处理函数。

这是一个回调函数,中断发生时,系统调用这个函数,传入的参数包括硬件中断号,device id,寄存器值。

dev_id就是下面的request_irq时传递给系统的参数dev_id。

irqflags 是中断处理的一些属性。

比较重要的有SA_INTERRUPT,标明中断处理程序是快速处理程序(设置SA_INTERRUPT)还是慢速处理程序(不设置SA_INTERRUPT)。

快速处理程序被调用时屏蔽所有中断。

慢速处理程序不屏蔽。

还有一个SA_SHIRQ属性,设置了以后运行多个设备共享中断。

dev_id在中断共享时会用到。

一般设置为这个设备的device结构本身或者NULL。

中断处理程序可以用dev_id找到相应的控制这个中断的设备,或者用rq2dev_map找到中断对应的设备。

*///初始化硬件tg3_init_hw(tp);//初始化收包和发包的缓冲区tg3_init_rings(tp);//初始化定时器init_timer(&amp;tp-&gt;timer);tp-&gt;timer.expires = jiffies + tp-&gt;timer_offset;tp-&gt;timer.data = (unsigned long) tp;tp-&gt;timer.function = tg3_timer; //超时回调函数add_timer(&amp;tp-&gt;timer);//允许网卡开始传输包netif_start_queue(dev);}5.关闭网络设备static int tg3_close(struct net_device *dev){//停止网卡传输包netif_stop_queue(dev);netif_carrier_off(tp-&gt;dev);//去除定时器del_timer_sync(&amp;tp-&gt;timer);//释放收包和发包的缓冲区tg3_free_rings(tp);//释放中断free_irq(dev-&gt;irq, dev);}[NextPage]6.硬件处理数据包发送static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev){len = (skb-&gt;len - skb-&gt;data_len);//以DMA方式向网卡物理设备传输包。

如果是wireless的话,需要根据802.11协议及硬件的规范从新填充//硬件帧头,然后提交给硬件发送。

mapping = pci_map_single(tp-&gt;pdev, skb-&gt;data, len, PCI_DMA_TODEVICE);tp-&gt;tx_buffers[entry].skb = skb;pci_unmap_addr_set(&amp;tp-&gt;tx_buffers[entry], mapping, mapping);//硬件发送tg3_set_txd(tp, entry, mapping, len, base_flags, mss_and_is_end);//记录发包开始时间dev-&gt;trans_start = jiffies;}7.中断处理收包,发包static void tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs){//如果要收包tg3_rx(tp);//如果要发包tg3_tx(tp);}8.发包static void tg3_tx(struct tg3 *tp){struct tx_ring_info *ri = &amp;tp-&gt;tx_buffers[sw_idx];struct sk_buff *skb = ri-&gt;skb;//以DMA方式向网卡传输包完毕pci_unmap_single(tp-&gt;pdev, pci_unmap_addr(ri, mapping),(skb-&gt;len - skb-&gt;data_len), PCI_DMA_TODEVICE);ri-&gt;skb = NULL;dev_kfree_skb_irq(skb);}9.收包static int tg3_rx(struct tg3 *tp, int budget){struct sk_buff *copy_skb;//分配一个包copy_skb = dev_alloc_skb(len + 2);copy_skb-&gt;dev = tp-&gt;dev;//修改包头空间skb_reserve(copy_skb, 2);//加入数据到包中skb_put(copy_skb, len);//以DMA方式从网卡传输回数据pci_dma_sync_single(tp-&gt;pdev, dma_addr, len, PCI_DMA_FROMDEVICE);memcpy(copy_skb-&gt;data, skb-&gt;data, len);skb = copy_skb;//解析包的协议skb-&gt;protocol = eth_type_trans(skb, tp-&gt;dev);//把包送到协议层netif_rx(skb);//记录收包时间tp-&gt;dev-&gt;last_rx = jiffies;}10.读取包的网卡收发包的状态,统计数据static struct net_device_stats *tg3_get_stats(struct net_device *dev){//从硬件相关的寄存器读取数据,累加//stats-&gt;rx_packets, stats-&gt;tx_packets, stats-&gt;rx_bytes, stats-&gt;tx_bytes等}11.用户的ioctl命令系统调用static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){struct mii_ioctl_data *data = (struct mii_ioctl_data *)&amp;ifr-&gt;ifr_data; switch(cmd) {//ethtool程序命令的调用case SIO*HTOOL:return tg3_ethtool_ioctl(dev, (void *) ifr-&gt;ifr_data);//mii程序命令的调用case SIOCGMIIREG: {err = tg3_readphy(tp, data-&gt;reg_num &amp; 0x1f, &amp;mii_regval)data-&gt;val_out = mii_regval;return err;}&hellip;&hellip;}}12.PCI设备的挂起和恢复函数static int tg3_suspend(struct pci_dev *pdev, u32 state){//停用网卡的中断寄存器tg3_disable_ints(tp);//停止网卡收发包netif_device_detach(dev);//停止网卡某些硬件,fireware的一些功能tg3_halt(tp);//设置网卡的电源状态tg3_set_power_state(tp, state);}static int tg3_resume(struct pci_dev *pdev){//恢复网卡电源tg3_set_power_state(tp, 0);//允许网卡收发包netif_device_attach(dev);//初始化收发包的缓冲区tg3_init_rings(tp);//初始化网卡硬件tg3_init_hw(tp);//打开网卡中断寄存器tg3_enable_ints(tp);}13.参数设置在驱动程序里还提供一些方法供系统对设备的参数进行设置和读取信息。

相关文档
最新文档