免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Minit

【原】Linux-千兆网卡驱动实现机制浅析 [复制链接]

论坛徽章:
0
发表于 2009-03-25 22:16 |显示全部楼层
原帖由 Minit 于 2009-3-25 20:08 发表
网卡作为一个PCI设备,其必须遵守相应的PCI规范,即必须为网卡定义相应的标识号,每个PCI外设由一个总线编号、一个设备编号及一个功能编号来标识。网卡驱动程序则需要定义相应的pci_device_id结构来表示其支持的PCI外设的标识,通过在驱动程序的pci_device_id中查找设备标识号,将驱动程序与设备联系起来。网卡作为PCI设备,其包括两类空间,一种是配置空间, CPU不能直接访问,访问这个空间,需要借助BIOS功能;另一种是普通的控制寄存器空间,这部分经过映射后,CPU可以直接访问控制 ...


上面的说法有问题。
配置空间访问除了借助BIOS,还可以利用MMIO. 详细的介绍可以看我的blog,PCI规范学习笔记。

实际上,操作系统在枚举完设备后,对e1000配置空间访问是靠MMIO. 最简单的一般也就是读下device id什么的。

当然,中断注册这快,是要访问网卡的配置空间的相关区域的,intx和MSi访问的位置不一样,这看中断注册的实现即可。

至于内存空间,e1000的shared code在Solaris上只提供了两个BAR的定义。Linux的e1000应该和Solaris共享一套shared code,所以,应该差别不大。

论坛徽章:
0
发表于 2009-03-25 22:21 |显示全部楼层
原帖由 Minit 于 2009-3-25 20:08 发表
有关相关寄存器对应的偏移量,一般是通过网卡的相关的datasheet获得。


其实Intel以多种License发布它的驱动的shared code,他们也叫hardware code, 几乎所有的寄存器的偏移量都是在shared code的头文件定义的。

BSD和Solaris和Linux的developer用的shared code是一样的。

论坛徽章:
0
发表于 2009-03-25 22:23 |显示全部楼层
很强大 拜读

论坛徽章:
0
发表于 2009-03-25 22:31 |显示全部楼层
原帖由 Minit 于 2009-3-25 20:08 发表
通过pci_read_config_和pci_write_config_系列函数可以读写网卡的配置空间,如开启网卡设备就是将网卡配置空间的command域置1,从而设备就可以将寄存器映射到内存。如通过函数pci_read_config_byte(pci_dev pdev,PCI_INTERRUPT_LINE,&irq)获得设备所分配的中断号并保存在irq中。pci_read_config_和pci_write_config_系列函数实际上是调用pci_bus_read_config_和pci_bus_write_config_系列函数实现的,这些函数实际操作网卡对应的PCI总线结构。有关PCI寄存器的配置空间可参考《Linux Device Driver 3rd》或《PCI Bus Demystified》。 ...


关于设备配置空间的访问,还有一点就是其实支持MMIO的配置空间其实早就有一个物理内存编址了。

所谓影射,是把物理地址影射到内核虚拟地址空间,以便后续的配置空间访问可以用mov指令来操作。

论坛徽章:
0
发表于 2009-03-25 22:39 |显示全部楼层

回复 #12 Solaris12 的帖子

感谢Solaris12大牛的以上回复,其实在把这个分析贴出来的时候,就猜测到这部分会有较大的问题,一方面尤其是涉及到PCI规范部分,这里一直没有弄得很明白;另一方面就是对intel驱动的shared code部分的掌握,这可能是驱动编写人员会经常涉及到的部分。以上两个部分就跟硬件很相关了,且需要较多的实践经验才会很清楚,对于我自己,可能以前更多的关注的是软件中网络层部分的内容,所以这里的分析绝对是种尝试,也确实比较有难度,也正好借助这个平台大家一起交流学习,
不过相信这个帖子可以给下一步的分析和深入找到比较好的切入点和方向,希望可以把linux下驱动这块有个较全面和准确的了解。
再次谢谢Solaris12兄的指点,希望以后多多指教哈。

有关你上面提出的问题,我会好好研究并再认真分析下,有歧义的地方尽量修改。

论坛徽章:
0
发表于 2009-03-25 22:40 |显示全部楼层
原帖由 Minit 于 2009-3-25 20:10 发表
其将DMA缓冲区与网卡所映射的虚拟地址空间联系起来,使用函数pci_alloc_consistent()实现一致性映射。而虚拟地址空间与网卡的物理地址相对应,故而这三种空间就对应了起来,DMA也就可以在此基础上实现了


这块儿显然是有错误的。

e1000 PCI memory空间有两个寄存器用来标识 ring的位置。ring实际上是一块连续的物理内存,是host memory而不是设备上的memory。

而ring里的descriptor要的是一个host memory buffer的物理地址,而且要求这个buffer的物理页是连续的。任何块物理内存连续的buffer想做DMA buffer用,就必须要知道它的物理地址是什么。

逻辑上, ring里的descriptor指向的也是host memory,且物理地址连续。

论坛徽章:
0
发表于 2009-03-25 22:45 |显示全部楼层
原帖由 Minit 于 2009-3-25 22:39 发表
感谢Solaris12大牛的以上回复,其实在把这个分析贴出来的时候,就猜测到这部分会有较大的问题,一方面尤其是涉及到PCI规范部分,这里一直没有弄得很明白;另一方面就是对intel驱动的shared code部分的掌握,这可 ...


大牛不敢自称。
恰好我在Solaris的Intel的千兆网卡e1000/igb和PCI的底层实现这两部分都有点经验。虽然Linux我不懂,但驱动和PCI这块儿基本是硬件规定死了的,差异并不大。

论坛徽章:
0
发表于 2009-03-25 22:45 |显示全部楼层

回复 #8 Godbach 的帖子

呵呵~ 一起学习哈,我这个分析只是个初步的,有好多问题都还需要搞明白,以后多多交流哦。

这篇分析就是给像Solaris12等这样的大牛来点评和指导的 :wink:

论坛徽章:
0
发表于 2009-03-25 22:54 |显示全部楼层

回复 #16 Solaris12 的帖子

嗯。这个地方也是我一直没搞明白的地方,所以在前面会提出PCI总线地址与物理地址的关系,其实就是对DMA buffer和ring这块没理解清楚,经过您的提示,我大概明白了这个意思,也会再深入的分析下这块。:wink:

论坛徽章:
0
发表于 2009-03-25 22:54 |显示全部楼层
写的很好,其实好多人都看过e1000的网卡驱动,但总结的人还是少啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP