Linux-
Linux-
Linux-
Linux- 千兆网卡驱动实现机制浅析
作者
: Minit,
出处
:
博客
,
责任编辑
:
罗丽艳
,
2009-03-29 00:00
网卡作为一个
PCI
设备 , 其必须遵守相应的
PCI
规范 , 即必须为网卡定义相应的标识号 , 每个
PCI
外设由一个总线编号 、 一个设备
编号及一个功能编号来标识。网卡驱动程序则需要定义相应的
pci_device_id
结构来表示其支持的
PCI
外设的标识
……
1.
1.
1.
1.
引言
本分析主要针对 e1000 网卡,驱动源码为 7.3.20-k2 。本文的目的不是为了讲述如何编写驱动程序,主要是分析网卡驱动内部的
实现机制。通过此分析,希望可以理解驱动程序中的各个部分的关系,对网卡发送和接收数据包有直观的了解,同时也希望对设计网卡
驱动程序有帮助。由于网卡驱动程序与硬件和 操作系统 都有很紧密的联系,故要把某些问题完全弄清楚,需要很多的经验与相关知识,
介于自身的水平有限,且自身经验较少,故肯定存在很多问题,希望本文的读者发现了问题不吝与作者联系。
2.
2.
2.
2. 网卡驱动的体系结构
网卡作为一个
PCI
设备 , 其必须遵守相应的
PCI
规范 , 即必须为网卡定义相应的标识号 , 每个
PCI
外设由一个总线编号 、 一个设备
编号及一个功能编号来标识 。 网卡驱动程序则需要定义相应的
pci_device_id
结构来表示其支持的
PCI
外设的标识 , 通过在驱动程序 的
pci_device_id
中查找设备标识号,将驱动程序与设备联系起来。网卡作为
PCI
设备,其包括两类空间,一种是配置空间,
CPU
不能
直接访问,访问这个空间,需要借助
BIOS
功能
;
另一种是普通的控制寄存器空间,这部分经过映射后,
CPU
可以直接访问控制。
在硬件加电初始化时,
BIOS
统一检查所有的
PCI
设备,并为每个设备分配一个物理地址,该地址通过
BIOS
获得并写到设备的配
置空间内,驱动程序就可以将网卡的普通控制寄存器映射到一段内存空间内, CPU 通过访问映射后的虚拟地址来操控网卡的寄存器。当
操作系统初始化时 , 其为每个
PCI
设备分配一个
pci_dev
结构 , 并将前面分配的物理地址写到
pci_dev
的
resource
字段中 。 在网卡驱
动程序中则可以通过读取 pci_dev 中的 resource 字段获得网卡的寄存器配置空间地址,其由函数 pci_resource_start() 和
pci_resource_end() 获得该空间的起始位置,通过 ioremap() 将该段位置映射到主存中,以便 CPU 访问控制网卡的 I/O 和内存空间
。
如重启网卡设备,则是通过向映射后的网卡的相应寄存器写入命令实现,其通过映射后的首地址及相应的寄存器偏移量找到该寄存器的
位置 , 然后通过函数 writeb() 写该寄存器 。 有关相关寄存器对应的偏移量 , 一般是通过网卡的相关的 datasheet 获得 。 如果要获取网卡
的
MAC
地址,则一般通过函数
readb()
读取首地址开始的前六位内容即可得到。