zoukankan      html  css  js  c++  java
  • Linux USB Host-Controller的初始化代码框架分析【转】

    转自:http://blog.csdn.net/zkami/article/details/2496770

    usb_hcd_omap_probe (const struct hc_driver *driver) (dev/ohci/ohci-omap.c)
    在模块初始化时被platform_driver_register()调用,用来初始化与ohci_hcd_omap_driver
    相匹配的usb主控制器.
    ->usb_create_hcd(driver);   创建一个代表host-controller的数据结构(struct usb_hcd)并初始化 core/hcd.h 
            ->hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); 为struct usb_hcd分配一块内存  
            ->usb_bus_init (struct usb_bus *bus); (hcd.c) 初始化代表usb bus的数据结构(struct usb_bus)
            ->初始化struct usb_hcd的定时器,工作队列
    ->填充struct usb_hcd的rsrc_start字段:host-controller memory/io的起始物理地址
        rsrc_len字段:host-controller memory/io的长度
        regs字段:host-controller memory/io映射的内核虚拟地址。
    ->ohci_hcd_init(struct ohci_hcd *ohci);    (dev/ohci/ohci-mem.c)
    ->usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags)    (/core/hcd.h)
        完成struct usb_hcd剩余的初始化工作
            ->hcd_buffer_create(hcd):创建dmapool
            ->usb_register_bus(usb_bus):注册usb bus
            ->usb_alloc_dev(NULL, &hcd->self, 0): (core/usb.c)
                处理主控制器hcd上的根Hub(hcd->self.root_hub),这里做的就是为Root Hub申请了一个struct                usb_device结构体,并且初始化, 将返回值赋给指针rhdev. Root Hub的parent指针指向了Controller本身.
            ->ohci_omap_init:完成omap硬件的init工作  
                ->otg_get_transceiver();
                ->otg_set_host(ohci->transceiver, &ohci_to_hcd(ohci)->self);    
                    针对OTG特性进行的初始化,后面分析
                ->ohci_init(struct ohci_hcd *ohci); (host/ohci-hcd.c)
                        ->为ohci->hcca分配空间
                        ->ohci_mem_init() 创建ohci->td_cache和ohci->ed_cache的dma_pool
            ->request_irq(irqnum, &usb_hcd_irq, irqflags,hcd->irq_descr, hcd)
               注册中断处理函数.其中中断号是irqnum, 中断服务程序是usb_hcd_irq(struct usb_hcd *hcd) (ohci-hcd.c).
               根据usb2.0 spec定义的中断类型有:usb_hcd_irq()根据具体类型执行相应操作,后面分析.
               #define OHCI_INTR_SO    (1 << 0)    /* scheduling overrun */
               #define OHCI_INTR_WDH    (1 << 1)    /* writeback of done_head */
               #define OHCI_INTR_SF    (1 << 2)    /* start frame */
               #define OHCI_INTR_RD    (1 << 3)    /* resume detect */
               #define OHCI_INTR_UE    (1 << 4)    /* unrecoverable error */
               #define OHCI_INTR_FNO    (1 << 5)    /* frame number overflow */
               #define OHCI_INTR_RHSC    (1 << 6)    /* root hub status change */
               #define OHCI_INTR_OC    (1 << 30)    /* ownership change */
               #define OHCI_INTR_MIE    (1 << 31)    /* master interrupt enable */
            ->ohci_omap_start(struct usb_hcd *hcd):启动OHCI
                  ->ohci_run(struct ohci_hcd *ohci) (ohci-hcd.c)
                      Start an OHCI controller, set the BUS operational resets USB and controller
                      enable interrupts 根据spec写相应寄存器来启动OHCI HC
                  ->ohci_stop(struct usb_hcd *hcd)
                      ohci_run失败的话,释放一些资源和已申请的中断, 释放ohci的ed/td cache以及ohci-hcca
            ->register_root_hub(struct usb_hcd) (core/hcd.c)
                  ->usb_set_device_state(usb_device, usb_device_state)
                     是roothub的话仅将new_state赋给udev->state,否则根据usb_device_state作不同处理
                  ->usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE) 获取roothub的设备描述符
                          ->usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);返回设备描述符,后面分析
                  ->usb_new_device(usb_dev)       配置并注册usb设备 (hub.c)
                          ->usb_configure_device(udev); (hub.c)    读取设备的配置信息
                              ->usb_get_configuration(udev);
                              ->usb_cache_string() 读取设备以下三个信息(字符描述符):product, manufacturer, serial
                              ->usb_configure_device_otg(udev);
                          ->usb_autoresume_device(udev->parent);  建立usb设备的父子关系
                          ->device_add(&udev->dev);   
                             注册usb设备: 将设备加载到总线上(添加到总线的设备队列中),并为该设备搜索与之匹配的驱动
                          ->usb_set_device_state(udev, USB_STATE_NOTATTACHED);
                  ->usb_hc_died (hcd);
            ->usb_hcd_poll_rh_status(usb_hcd)    hcd.c
                获取“根Hub状态变化”的具体信息,并将该信息递交给usb_hcd->status_urb
                    ->ohci_hub_status_data(usb_hcd, buf)
                        首先: 读取根Hub"状态变化信息",并将其存放于buffer中
                          ->ohci_root_hub_state_changes(ohci, changed, any_connected);
                          根据主控制器在设备接入前的状态(如SUSPEND),将主控制器状态设置为中断发生后的下一状态(如OPERATION), 并判断根Hub是否需要继续轮询(poll_rh等于表示需要继续轮询)
                              ->ohci_rh_suspend(ohci, 1);  pm方面以后分析
                              ->ohci_rh_resume(ohci);      pm方面以后分析
                              ->usb_hcd_resume_root_hub(ohci_to_hcd(ohci));    pm方面以后分析
                        然后: 将保存于buffer中的root hub"状态变化信息"传递给usb_hcd->status_urb并将该urb提交给root hub驱动层
                    -> usb_hcd_unlink_urb_from_ep()
                    -> usb_hcd_giveback_urb()
                    -> mod_timer() 调整roothub定时器使其再次进入定时器队列

  • 相关阅读:
    保持页面上滚动条原来位置
    ASP.NET页面刷新的实现方法
    绝对定位下的控件动态添加操作
    实现页面打开后滚动到最底端的效果
    获得页面下所有的控件
    获得sql列名
    PropertyUtils.getProperty和PropertyUtils.setProperty的用法详解
    Javascript 第三章
    Javascript 第五章
    Javascript 第六章
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/4992204.html
Copyright © 2011-2022 走看看