日期:2014-05-16 浏览次数:20813 次
linux启动过程中pci总线初始化主要包括2部分,pci控制器的注册和pci设备的枚举,pci总线和其他总线一个很重要的区别就是pci总线的枚举,在启动过程中遍历pci总线树上所有可能的dev func,记录下所有存在的设备的vendor id 设备名等,这个是做为后面pci设备驱动初始化中注册pci设备驱动需要匹配的重要依据,类似于platform驱动。
先说pci控制器注册,这个与具体开发板相关,以龙芯1A开发板2.6.33内核为例,在arch/mips/loongson/sb2f/pci.c中部分代码如下:
static struct resource loongson_pci_mem_resource = {
.name = "pci memory space",
.start = 0x14000000UL,
.end = 0x17ffffffUL,
.flags = IORESOURCE_MEM,
};
static struct resource loongson_pci_io_resource = {
.name = "pci io space",
.start = 0x00004000UL,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
static struct pci_controller loongson_pci_controller = {
.pci_ops = &sb2f_pci_pci_ops,
.io_resource = &loongson_pci_io_resource,
.mem_resource = &loongson_pci_mem_resource,
.mem_offset = 0x00000000UL,
.io_offset = 0x00000000UL,
};
static void __init setup_pcimap(void)
{
/*
* local to PCI mapping for CPU accessing PCI space
* CPU address space [256M,448M] is window for accessing pci space
* we set pcimap_lo[0,1,2] to map it to pci space[0M,64M], [320M,448M]
*
* pcimap: PCI_MAP2 PCI_Mem_Lo2 PCI_Mem_Lo1 PCI_Mem_Lo0
* [<2G] [384M,448M] [320M,384M] [0M,64M]
*/
SB2F_PCIMAP = 0x46140;
}
static int __init pcibios_init(void)
{
setup_pcimap();
//loongson_pci_controller.io_map_base = mips_io_port_base;
if(!disablepci)
{
register_pci_conroller(&loongson_pci_controller);
}
return 0;
}
在pcibios_init函数中setup_pcimap中设置pci总线的3个mem space空间的高6位, register_pci_conroller函数是对pci控制器提供的mem和io资源做一下检查 然后将pci控制器添加到内核的pci控制器链表中。
这就完成了对特定pci控制器的初始化。特别要注意控制器结构体中的pci_ops成员,这个成员提供的读写函数就是对pci设备配置寄存器的读写。
接下来来看pci总线的枚举,这是非常重要的一部分。
在arch/mips/pci/pci.c中
在这个pcibios_init函数中,遍历内核pci控制器链表每一个成员,这里我们只有一个控制器,只有一个成员。然后调用pcibus_scanbus来遍历总线,扫描设备。