Linux USB subsystem --- EHCI host controller register

[Linux 3.2] [driver/usb/host/ehci-hcd.c]

函数:ehci_hcd_init()

  1. static int __init ehci_hcd_init(void)  
  2. {  
  3.     int retval = 0;  
  4.   
  5.     if (usb_disabled())  
  6.         return -ENODEV;  
  7.   
  8.     printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);  
  9.     set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);  
  10.     if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||  
  11.             test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))  
  12.         printk(KERN_WARNING "Warning! ehci_hcd should always be loaded"  
  13.                 " before uhci_hcd and ohci_hcd, not after\n");  
  14.   
  15.     pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",  
  16.          hcd_name,  
  17.          sizeof(struct ehci_qh), sizeof(struct ehci_qtd),  
  18.          sizeof(struct ehci_itd), sizeof(struct ehci_sitd));  
  19.   
  20. #ifdef DEBUG  
  21.     ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root);  
  22.     if (!ehci_debug_root) {  
  23.         retval = -ENOENT;  
  24.         goto err_debug;  
  25.     }  
  26. #endif  
  27.   
  28. #ifdef PLATFORM_DRIVER  
  29.     retval = platform_driver_register(&PLATFORM_DRIVER);  
  30.     if (retval < 0)  
  31.         goto clean0;  
  32. #endif  

此函数实现的功能如下:

1. 判断USB是否被禁用了,如果有,直接退出。

2. 打印一条信息:ehci_hcd:    USB 2.0 'Enhanced' Host Controller (EHCI) Driver.

3. 判断UHCI和OHCI是否已经被加载,如果是打印输入warning 信息。

4. pr_debug: 根据编译内核的debug选项,决定是否输出此段信息。

5. 如果定义了DEBUG,则在debugfs下面的usb目录里面创建一个ehci的目录。

6. 注册一个platform驱动。这个platform驱动是根据PLATFORM_DRIVER的定义而决定。platform_driver_register最后还是调用driver_register实现。

(例:对atmel的EHCI来说,如下所示:)

  1. #ifdef CONFIG_ARCH_AT91  
  2. #include "ehci-atmel.c"  
  3. #define PLATFORM_DRIVER     ehci_atmel_driver  
  4. #endif  
其中echi_atmel_driver在ehci-atmel.c文件里面定义。 接下来ehci_atmel_driver里的probe函数(ehci_atmel_drv_probe)就会被调用(为什么呢?本文结尾分析)。

ehci_atmel_drv_proble会调用两个关键函数:usb_create_hcd 与 usb_add_hcd。后篇文章对此进行分析。



备注:内核中的初始化顺序。

start_kernel --> reset_init --> kernel_init --> do_basic_setup --> do_initcalls。do_initcalls的实现如下:

  1. extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];  
  2.   
  3. static void __init do_initcalls(void)  
  4. {  
  5.     initcall_t *fn;  
  6.   
  7.     for (fn = __early_initcall_end; fn < __initcall_end; fn++)  
  8.         do_one_initcall(*fn);  
  9. }  
其中__early_initcall_end, __initcall_end, __early_initcall_end是在vmlinux.lds文件里面定义。 arch_initcall();首先被调用。在arch/arm/kernel/setup.c中有arch_initcall(customize_machine),所以先执行mdes->init_machine(). 这是在board文件中定义。对atmel的at91sam9m10g45ek板子,就会先注册ohci和ehci。在platform_driver_register-->driver_register-->bus_add_driver-->driver_attach --> 最后调用到probe函数。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值