慢慢欣赏linux PCI-PCIE定制化

PCI/PCIE协议还是很完美的,所以目前很是流行。所以linux内核主线代码是严格按照协议来的,例如pci_read_bases(dev, 6, PCI_ROM_ADDRESS);轮流获取6个MEM空间大小。

但是由于开发是存在BUG,或者开发者没有彻底理解PCI/PCIE或是别的原因,很多设备并没有严格按照PCI/PCIE协议来实现。

例如,有的设备实际上只有一个有效的BASE_ADDRESS地址,但是实际探测有N个地址,部分无效的地址空间还特别大,导致地址空间不够,后面别的PCI设备无法获取地址。

针对这种情况,linux内核做了妥协,允许驱动初始化流程在某个阶段可以修改前面阶段的一些资源,也就是数据结构。

enum pci_fixup_pass {
	pci_fixup_early,	/* Before probing BARs */
	pci_fixup_header,	/* After reading configuration header */
	pci_fixup_final,	/* Final phase of device fixups */
	pci_fixup_enable,	/* pci_enable_device() time */
	pci_fixup_resume,	/* pci_device_resume() */
	pci_fixup_suspend,	/* pci_device_suspend */
	pci_fixup_resume_early, /* pci_device_resume_early() */
};

刚才讲的那种情况,可以在pci_fixup_header阶段修正,方法如下:

DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_XXX,	PCI_DEVICE_ID_IBM_XXX,	fixup_xxx_pci_bar);

//只保留BASE_ADDRESS0的资源信息,其它5个BAR的资源信息全部清除
static void fixup_xxx_pci_bar(struct pci_dev *dev)
	for (i = 1; i < DEVICE_COUNT_RESOURCE; i++) {
		dev->resource[i].start = dev->resource[i].end = 0;
		dev->resource[i].flags = 0;
	}

生效的位置:获取BASE_ADDREESS大小之后,分配PCI/PCIE域到BASE_ADDREESS里面之前

void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
	/* Fix up broken headers */
	pci_fixup_device(pci_fixup_header, dev);

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值