x86 pci初始化过程

来源:互联网 发布:java有decimal 编辑:程序博客网 时间:2024/04/29 13:24
在《PCI-E体系结构导读》+linux3.15的基础,大致过了下x86 linux pci的初始化过程
=========do_initcalls完成一系列驱动初始化,包括PCI的初始化也在这个过程中=================
kernel_init->kernel_init_freeable->do_basic_setup->do_initcalls
===============================================linux PCI初始化==========================================
Sysmap信息
........
==============
1、drivers/pci/probe.c ---->postcore_initcall(pcibus_class_init); --->.initcall2.init
    class_register(&pcibus_class); //在sys/class/下创建一个pci_bus目录
===============
2、drivers/pci/pci-driver.c ---->postcore_initcall(pci_driver_init); --->.initcall2.init
struct bus_type pci_bus_type = {
   .name = "pci",
   .match = pci_bus_match,/*pci match函数*/
   .uevent = pci_uevent,
   .probe = pci_device_probe,
   .remove = pci_device_remove,
   .shutdown = pci_device_shutdown,
   .dev_groups = pci_dev_groups,
   .bus_groups = pci_bus_groups,
   .drv_groups = pci_drv_groups,
   .pm = PCI_PM_OPS_PTR,
};
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);/*注册pci总线,并在/sys/bus/下创建了一个pci目录*/
}


===================
3、drivers/pci/pci-acpi.c ---->arch_initcall(acpi_pci_init); --->.initcall3.init
===================
4、arch/x86/pci/init.c ---->arch_initcall(pci_arch_init); --->.initcall3.init
//体系架构相关,对于64 bit x86来说使用CONFIG_PCI_DIRECT的方式进行访问PCI配置空间
pci_direct_probe();
pci_direct_init()


//PCI_DIRECT PCI配置空间的读写方式 (PORT IO的读写方式)
struct pci_raw_ops pci_direct_conf1 = {
.read = pci_conf1_read,
.write = pci_conf1_write,
};
/*arch/x86/pci/direct.c*/
pci_conf1_read
pci_conf1_write


//MMIO的PCI配置空间读写方式
arch/x86/pci/mmconfig_32/64.c
=======================
5、driver\pci\slot.cf ---->subsys_initcall(pci_slot_init);    在/sys/bus/pci/下建立一个slots目录
======================
6、drivers/pci/pci-acpi.c subsys_initcall(acpi_init); --->.initcall4.init
=======================
7、arch/x86/pci/legacy.c        ---->subsys_initcall(pci_subsys_init) --->.initcall4.init
=======================
8、arch/x86/pci/i386.c ---->fs_initcall(pcibios_assign_resources); --->.initcall5.init

 
=========================================基于ACPI机制的linux PCI初始化============================================
===========
1、acpi的解析与初始化
start_kernel
-->setup_arch
{
acpi_boot_table_init();-->acpi_table_init/*在内存中找到RSDP、RSDT、XSDT,从而定位ACPI表*/
early_acpi_boot_init();
acpi_boot_init();
}
===========
2、drivers/pci/pci-acpi.c ---->arch_initcall(acpi_pci_init); --->.initcall3.init
===========
3、drivers/pci/pci-acpi.c subsys_initcall(acpi_init); --->.initcall4.init
/*ACPI的方式扫描枚举PCI*/
acpi_init
------>acpi_pci_root_init
--->acpi_pci_root_init();  
--->一系列调用,能最调用到acpi_pci_root_add
--->pci_acpi_scan_root/*遍历pci总线树*/
--->pci_create_root_bus/*创建root总线*/
--->pci_scan_child_bus/*枚举pci树上的设备*/
-->pci_scan_slot
-->pci_scan_single_device
pci_scan_device
pci_device_add
-->pci_scan_bridge
------->acpi_pci_link_init();
===========
4、arch/x86/pci/legacy.c        ---->subsys_initcall(pci_subsys_init) --->.initcall4.init
pci_subsys_init
->x86_init.pci.init /*pci_acpi_init*/
/*
//由于使用acpi pci的方式枚举PCI树上的设备, pci_legacy_init函数将不会被执行了
pci_legacy_init() /*完成对PCI的枚举过程*/
{
pcibios_scan_root(0);/*从PCI 0号总线开始扫描枚举*/
}
*/
->x86_init.pci.init_irq (x86_init_noop)
->pcibios_init();
-->pcibios_resource_survey();/*检查pci设备的bar空间*/
===========
5、arch/x86/pci/i386.c ---->fs_initcall(pcibios_assign_resources); --->.initcall5.init
pcibios_assign_resources /*设备pci设备的BAR空间*/
{
list_for_each_entry(root_bus, &pci_root_buses, node)
pci_assign_unassigned_root_bus_resources(root_bus);
----〉__pci_bus_size_bridges/*修复当前PCI总线树下所有PCI设备的IO空间和存储空间*/
----〉__pci_bus_assign_resources/*配置PCI设备/PCI桥的 PCI配置空间,主要为BAR等关键配置*/
----〉pci_bus_dump_resources/*打印pci设备的系统资源*/

}


参考资料:

《PCIE 体系结构导读》
linux3.15源码















0 0
原创粉丝点击