Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3523478
  • 博文数量: 1805
  • 博客积分: 135
  • 博客等级: 入伍新兵
  • 技术积分: 3345
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-19 20:01
文章分类

全部博文(1805)

文章存档

2017年(19)

2016年(80)

2015年(341)

2014年(438)

2013年(349)

2012年(332)

2011年(248)

分类: LINUX

2013-03-16 14:03:39

原文地址:linux 设备:PCI设备 (1) 作者:zengxg14


linux 设备:初始化中,讲述了设备的初始化,最后调用的是do_initcalls函数,
linux 内核:do_initcalls中,也了解了do_initcalls函数的执行情况。

那接下来是要了解PCI相关的初始化,及其他。 要了解PCI是因为在弄网卡设备。
关于PCI有个系列的文章可以参考:http://blog.csdn.net/fudan_abc/article/category/345294
可惜的是作者没写完。

不管他是否写完了,我还是得要看这部分的代码。

1:从何看起

这个是从那位前辈学来的,要从入口函数看起,但怎么知道do_initcalls中调用的入口函数哪些与PCI有关呢?
根据include/linux/init.h中的定义可知,入口函数使用xxxx_initcall宏来定义的,
因此我们在PCI相应的目录中使用grep命令来查看需要读的入口函数。

  1. [zxg@zxg-pc linux-2.6.35]$ grep "initcall" arch/x86/pci/* -R
  2. arch/x86/pci/amd_bus.c:postcore_initcall(amd_postcore_init);
  3. arch/x86/pci/i386.c: * called in fs_initcall (one below subsys_initcall),
  4. arch/x86/pci/i386.c:fs_initcall(pcibios_assign_resources);
  5. arch/x86/pci/init.c:/* arch_initcall has too random ordering, so call the initializers
  6. arch/x86/pci/init.c:arch_initcall(pci_arch_init);
  7. arch/x86/pci/legacy.c:subsys_initcall(pci_subsys_init);
  8. arch/x86/pci/mmconfig-shared.c:late_initcall(pci_mmcfg_late_insert_resources);
  9. [zxg@zxg-pc linux-2.6.35]$ grep "initcall" drivers/pci/* -R
  10. drivers/pci/pci-acpi.c:arch_initcall(acpi_pci_init);
  11. drivers/pci/pci.c:late_initcall(pci_resource_alignment_sysfs_init);
  12. drivers/pci/pci-driver.c:postcore_initcall(pci_driver_init);
  13. drivers/pci/pci-sysfs.c:late_initcall(pci_sysfs_init);
  14. drivers/pci/probe.c:postcore_initcall(pcibus_class_init);
  15. drivers/pci/proc.c:device_initcall(pci_proc_init);
  16. drivers/pci/quirks.c:fs_initcall_sync(pci_apply_final_quirks);
  17. drivers/pci/slot.c:subsys_initcall(pci_slot_init);
  18.  
  19. 按顺序列下来就是
  20. postcore_initcall:    pci_driver_init, pcibus_class_init, amd_postcore_init
  21. arch_initcall:        acpi_pci_init, pci_arch_init
  22. subsys_initcall:      pci_subsys_init, pci_slot_init
  23. fs_initcall:          pcibios_assign_resources, pci_apply_final_quirks.
  24. device_initcall:      pci_proc_init, 
  25. 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

  1. static struct class pcibus_class = {
  2.     .name        = "pci_bus",
  3.     .dev_release    = &release_pcibus_dev,
  4. };

  5. static int __init pcibus_class_init(void)
  6. {
  7.     return class_register(&pcibus_class);
  8. }
既然我还没看class相关的东西,那我猜测这个函数是在/sys/class目录下创建了pci_bus目录。

pci_driver_init

  1. struct bus_type pci_bus_type = {
  2.     .name        = "pci",
  3.     .match        = pci_bus_match,
  4.     .uevent        = pci_uevent,
  5.     .probe        = pci_device_probe,
  6.     .remove        = pci_device_remove,
  7.     .shutdown    = pci_device_shutdown,
  8.     .dev_attrs    = pci_dev_attrs,
  9.     .bus_attrs    = pci_bus_attrs,
  10.     .pm        = PCI_PM_OPS_PTR,
  11. };

  12. static int __init pci_driver_init(void)
  13. {
  14.     return bus_register(&pci_bus_type);
  15. }
在学bus_type时,已看过该函数了,不多说。

2:arch_initcall
按上面的想法,则pci_arch_init要比acpi_pci_init先执行

pci_arch_init:   MD,目前完全不知道这个函数是什么意思。   我先看看PCI标准有说什么没。

  1. static __init int pci_arch_init(void)
  2. {
  3. #ifdef CONFIG_PCI_DIRECT
  4.     int type = 0;

  5.     type = pci_direct_probe();
  6. #endif

  7.     if (!(pci_probe & PCI_PROBE_NOEARLY))
  8.         pci_mmcfg_early_init();

  9. #ifdef CONFIG_PCI_OLPC
  10.     if (!pci_olpc_init())
  11.         return 0;    /* skip additional checks if it's an XO */
  12. #endif
  13. #ifdef CONFIG_PCI_BIOS
  14.     pci_pcbios_init();
  15. #endif
  16.     /*
  17.      * don't check for raw_pci_ops here because we want pcbios as last
  18.      * fallback, yet it's needed to run first to set pcibios_last_bus
  19.      * in case legacy PCI probing is used. otherwise detecting peer busses
  20.      * fails.
  21.      */
  22. #ifdef CONFIG_PCI_DIRECT
  23.     pci_direct_init(type);
  24. #endif
  25.     if (!raw_pci_ops && !raw_pci_ext_ops)
  26.         printk(KERN_ERR
  27.         "PCI: Fatal: No config space access function found\n");

  28.     dmi_check_pciprobe();

  29.     dmi_check_skip_isa_align();

  30.     return 0;
  31. }









阅读(820) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~