linux网卡驱动分析之probe函数

本文详细介绍了Linux网卡驱动中的probe函数,主要任务包括:设置DMA寻址能力,分配并映射IO内存,初始化net_device结构,检查硬件特性,并注册网络设备。内容涉及PCI设备配置,IO端口与内存分配,net_device结构成员的初始化,以及设备注册流程。通过对probe函数的分析,读者可以深入理解Linux网卡驱动的工作原理。
摘要由CSDN通过智能技术生成
probe函数中一般完成一下任务:
1、通知内核设备执行DMA的寻址能力,说明设备支持64位还是32位的DMA地址。如果不支持64位的地址,则尝试32位的:
err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64));
	if (!err) {
		err =
		    dma_set_coherent_mask(pci_dev_to_dev(pdev),
					  DMA_BIT_MASK(64));
		if (!err)
			pci_using_dac = 1;
	} else {
		err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32));
		if (err) {
			err = dma_set_coherent_mask(pci_dev_to_dev(pdev),
						    DMA_BIT_MASK(32));
			if (err) {
				dev_err(pci_dev_to_dev(pdev),
					"No usable DMA configuration, aborting\n");
				goto err_dma;
			}
		}
	}
 
2、给设备分配IO内存并映射内存,一般的设备都是通过IO内存映射设备寄存器和设备内存。
        有些设备使用IO端口映射设备寄存器,x86处理器上一共有64KB的IO空间,其中有些IO端口已作为固定的用途,比如80口,作为数码管的显示,比如CF8和CFC用作读取PCI设备配置空间寄存器如果设备需要IO端口,使用如下函数分配IO端口:
request_region(start,n,name)
        IO端口分配后可以直接操作,使用如下函数:
inb(),outb()
inw(),outw()
inl(),outl()
        如果设备需要IO内存,根据设备需要的IO内存大小,分配IO内存:
pci_request_selected_regions(pdev, bars, name);
        在操作IO内存之前,需要映射IO内存,之后可以使用readl或者writel等读写内存的函数操作该块内存
ioremap(mmio_start, mmio_len);
        每个PCI设备最多可以支持6个BAR(Base Address Register),但大部分设备不会使用这么多空间。
        PCI设备复位之后,该寄存器存放PCI设备需要使用的IO空间基地址,这段空间是IO空间还是内存空间,网卡设备一般使用的是内存空间,也可以称为IO内存。该信息是设备出厂时已经设置好的。
        BIOS扫描PCI设备时,会根据系统中的硬件配置为PCI设备分配地址空间,BIOS为所有PCI设备分配的地址空间都不会冲突,之后该信息会传递给操作系统。
       系统软件对PCI总线进行配置时,首先获取BAR空间寄存器中的初始化信息,之后根据处理器的配置,将合理的基地址写入相应的BAR寄存器。系统软件还可以使用该寄存器或者PCI设备使用的BAR空间的长度,其方法是向BAR寄存器写入0xFFFFFFFF,之后读取该寄存器。
        在设备驱动加载之前,设备所需要的地址空间还不会真正的分配,需要在驱动程序中给设备分配IO空间,最后进行ioremap才能访问。
        在系统下,可以通过如下命令查看设备使用的IO内存:
$ lspci | grep "Ethernet controller"
02:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
06:00.0 Ethernet controller: Intel Corporation 82574L Gigabit Network Connection

$ cat /proc/iomem | grep "02:00.0"                                     
  fea00000-fea1ffff : 0000:02:00.0
  fea20000-fea23fff : 0000:02:00.0
       从上面结果可以看出,该设备使用了6个BAR中的2个BAR,即BAR0和BAR1,该设备申请了两块IO内存,BAR0的范围为:fea00000-fea1ffff,大小为128KB,用来映射设备寄存器,BAR1的范围为fea20000-fea23fff,大小为32KB,用来映射flash。设备需要的空间大小是由硬件指定的,但是这两块IO内存的起始地址是在BIOS启动阶段PCI扫描时由BIOS分配的。在e1000e网卡驱动中有如下代码:
      BAR0用来映射设备寄存器,即设备有关寄存器都映射到内存空间,我们可以通过操作内存来操作设备寄存器,pci_resource_start(pdev, 0)就是用来获取BAR0的起始地址:
	mmio_start = pci_resource_start(pdev, 0);
	mmio_len = pci_resource_len(pdev, 0);

	err = -EIO;
	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
       BAR1用来映射flash,pci_resource_start(pdev, 1)用来获取BAR1的起始地址:
   if ((adapter->flags & FLAG_HAS_FLASH) &&
        (pci_resource_flags
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值