那接下来是要了解PCI相关的初始化,及其他。 要了解PCI是因为在弄网卡设备。
可惜的是作者没写完。
不管他是否写完了,我还是得要看这部分的代码。
1:从何看起
这个是从那位前辈学来的,要从入口函数看起,但怎么知道do_initcalls中调用的入口函数哪些与PCI有关呢?
根据include/linux/init.h中的定义可知,入口函数使用xxxx_initcall宏来定义的,
因此我们在PCI相应的目录中使用grep命令来查看需要读的入口函数。
- [zxg@zxg-pc linux-2.6.35]$ grep "initcall" arch/x86/pci/* -R
- arch/x86/pci/amd_bus.c:postcore_initcall(amd_postcore_init);
- arch/x86/pci/i386.c: * called in fs_initcall (one below subsys_initcall),
- arch/x86/pci/i386.c:fs_initcall(pcibios_assign_resources);
- arch/x86/pci/init.c:/* arch_initcall has too random ordering, so call the initializers
- arch/x86/pci/init.c:arch_initcall(pci_arch_init);
- arch/x86/pci/legacy.c:subsys_initcall(pci_subsys_init);
- arch/x86/pci/mmconfig-shared.c:late_initcall(pci_mmcfg_late_insert_resources);
- [zxg@zxg-pc linux-2.6.35]$ grep "initcall" drivers/pci/* -R
- drivers/pci/pci-acpi.c:arch_initcall(acpi_pci_init);
- drivers/pci/pci.c:late_initcall(pci_resource_alignment_sysfs_init);
- drivers/pci/pci-driver.c:postcore_initcall(pci_driver_init);
- drivers/pci/pci-sysfs.c:late_initcall(pci_sysfs_init);
- drivers/pci/probe.c:postcore_initcall(pcibus_class_init);
- drivers/pci/proc.c:device_initcall(pci_proc_init);
- drivers/pci/quirks.c:fs_initcall_sync(pci_apply_final_quirks);
- drivers/pci/slot.c:subsys_initcall(pci_slot_init);
-
- 按顺序列下来就是
- postcore_initcall: pci_driver_init, pcibus_class_init, amd_postcore_init
- arch_initcall: acpi_pci_init, pci_arch_init
- subsys_initcall: pci_subsys_init, pci_slot_init
- fs_initcall: pcibios_assign_resources, pci_apply_final_quirks.
- device_initcall: pci_proc_init,
- late_initcall: pci_sysfs_init, pci_mmcfg_late_insert_resources
2:postcore_initcall系列函数
postcore_initcall中有三个函数,那它们的顺序又是怎样的?
对于pci_driver_init和pcibus_class_init函数,它们都处于drivers/pci目录下,
按前辈的说法,它们的执行顺序要看Makefile。
在drivers/pci目录的Makefile中有一句
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o pci-driver.o search.o pci-sysfs.o rom.o setup-res.o irq.o
由于 probe.o在pci-driver.o的前面,因此pcibus_class_init要比pci_driver_init先执行。
看来obj-y后面的.o文件的顺序也是很重要的,不能乱。
但amd_postcore_init是在arch/x86/pci下的,和另外的两个函数不是同一个目录,这个顺序是怎样的?
根据上面的经验知道摆放顺序很重要,因此关键在于arch/x86/pci目录下的Makefile和drivers/pci目录下的Makefile,哪个文件先执行。 这个又由根目录的Makefile来决定了。
我想还是不要蛋疼的去看根目录的Makefile,这样可能需要把Make的manual再看一遍,很有可能看完后还是不懂。
既然amd_postcore_init是在arch目录下,而arch目录中的东西是和体系结构有关的,那么猜测amd_postcore_init要比其他两个函数先执行。要是体系结构没弄清,编译其他代码可能也没多大用处。
在amd_postcore_init函数中有一句:
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return 0;
我猜意思是:如果cpu不是AMD就不管下面的了。 既然我是Intel cpu,那我就不看这个函数。貌似这个函数挺复杂的。
pcibus_class_init
- static struct class pcibus_class = {
- .name = "pci_bus",
- .dev_release = &release_pcibus_dev,
- };
- static int __init pcibus_class_init(void)
- {
- return class_register(&pcibus_class);
- }
既然我还没看class相关的东西,那我猜测这个函数是在/sys/class目录下创建了pci_bus目录。
pci_driver_init
- struct bus_type pci_bus_type = {
- .name = "pci",
- .match = pci_bus_match,
- .uevent = pci_uevent,
- .probe = pci_device_probe,
- .remove = pci_device_remove,
- .shutdown = pci_device_shutdown,
- .dev_attrs = pci_dev_attrs,
- .bus_attrs = pci_bus_attrs,
- .pm = PCI_PM_OPS_PTR,
- };
- static int __init pci_driver_init(void)
- {
- return bus_register(&pci_bus_type);
- }
在学bus_type时,已看过该函数了,不多说。
2:arch_initcall
按上面的想法,则pci_arch_init要比acpi_pci_init先执行
pci_arch_init: MD,目前完全不知道这个函数是什么意思。 我先看看PCI标准有说什么没。
- static __init int pci_arch_init(void)
- {
- #ifdef CONFIG_PCI_DIRECT
- int type = 0;
- type = pci_direct_probe();
- #endif
- if (!(pci_probe & PCI_PROBE_NOEARLY))
- pci_mmcfg_early_init();
- #ifdef CONFIG_PCI_OLPC
- if (!pci_olpc_init())
- return 0; /* skip additional checks if it's an XO */
- #endif
- #ifdef CONFIG_PCI_BIOS
- pci_pcbios_init();
- #endif
- /*
- * don't check for raw_pci_ops here because we want pcbios as last
- * fallback, yet it's needed to run first to set pcibios_last_bus
- * in case legacy PCI probing is used. otherwise detecting peer busses
- * fails.
- */
- #ifdef CONFIG_PCI_DIRECT
- pci_direct_init(type);
- #endif
- if (!raw_pci_ops && !raw_pci_ext_ops)
- printk(KERN_ERR
- "PCI: Fatal: No config space access function found\n");
- dmi_check_pciprobe();
- dmi_check_skip_isa_align();
- return 0;
- }
阅读(820) | 评论(0) | 转发(0) |