参考资料:
1) 《Linux内核源代码情景分析》
2) Linux内核源代码(2.6.32)。
本文只讨论比较简单的软硬件配置场景。
系统中的第一条PCI总线(即主PCI总线),挂在“宿主—PCI桥”上。
CPU通过“宿主——PCI桥”就可以访问主PCI总线了。
PC机中通常只有一个“宿主—PCI桥”。但是,通过引入其他类型的PCI桥,可以将更多的总线(可以是PCI总线,也可以是ISA总线)连接到主PCI总线上来。这样一来,系统中就可以有多条总线存在了。
下层PCI总线也可以进一步通过PCI桥,将更下一层的PCI总线连接进来。
在上层总线看来,PCI桥也是连接到本总线上的一个设备。
主PCI总线的编号是0,其他的pci总线编号则从1开始依次递增。PCI总线上的一个设备,可以包含1~8个功能,编号是0~7。每个功能称为一个逻辑设备。
有些设备可能只包含一个逻辑设备。例如,一块网卡,上面可能就一个逻辑设备。
在Linux内核角度来看,这些逻辑设备才是最终的设备。
这样的话,每条PCI总线,最大支持32*8个逻辑设备,即256个逻辑设备。
int __init pci_subsys_init(void) { #ifdef CONFIG_X86_NUMAQ pci_numaq_init(); #endif #ifdef CONFIG_ACPI pci_acpi_init(); #endif #ifdef CONFIG_X86_VISWS pci_visws_init(); #endif pci_legacy_init(); pcibios_fixup_peer_bridges(); pcibios_irq_init(); pcibios_init(); return 0; } subsys_initcall(pci_subsys_init);
static int __init pci_legacy_init(void) { if (!raw_pci_ops) { printk("PCI: System does not support PCI\n"); return 0; } if (pcibios_scanned++) return 0; printk("PCI: Probing PCI hardware\n"); pci_root_bus = pcibios_scan_root(0); if (pci_root_bus) pci_bus_add_devices(pci_root_bus); return 0; }
因此,最终进入 pci_scan_bus_parented,进而进入pci_scan_child_bus去扫描总线上的设备(这里只关注核心部分,因此跳得有点快^_^)。
struct pci_bus * __devinit pcibios_scan_root(int busnum) { struct pci_bus *bus = NULL; struct pci_sysdata *sd; while ((bus = pci_find_next_bus(bus)) != NULL) { if (bus->number == busnum) { /* Already scanned */ return bus; } } /* Allocate per-root-bus (not per bus) arch-specific data. * TODO: leak; this memory is never freed. * It's arguable whether it's worth the trouble to care. */ sd = kzalloc(sizeof(*sd), GFP_KERNEL); if (!sd) { printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); return NULL; } sd->node = get_mp_bus_to_node(busnum); printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); if (!bus) kfree(sd); return bus; }
pci_scan_child_bus的核心代码如下:
for (devfn = 0; devfn < 0x100; devfn += 8) pci_scan_slot(bus, devfn);
这里的devfn,是devicefunction的缩写,即“设备功能”的意思。
相当于是设备号与功能号的组合,高位是设备号,低3-bit是功能号。
int pci_scan_slot(struct pci_bus *bus, int devfn) { int fn, nr = 0; struct pci_dev *dev; dev = pci_scan_single_device(bus, devfn); if (dev && !dev->is_added)/* new device? */ nr++; if (dev && dev->multifunction) { for (fn = 1; fn < 8; fn++) { dev = pci_scan_single_device(bus, devfn + fn); if (dev) { if (!dev->is_added) nr++; dev->multifunction = 1; } } } /* only one slot has pcie device */ if (bus->self && nr) pcie_aspm_init_link_state(bus->self); return nr; }
原文地址:http://blog.csdn.net/crazycoder8848/article/details/46536861