目的:对USB作深入学习,在此留下笔记。欢迎讨论。
[Linux-3.2][drivers/usb/core/hcd.c]
函数:usb_create_hcd(const struct hc_driver *driver, struct device *dev, const char *bus_name)
其中hc_driver是ehci_atmel_hc_driver,
static const struct hc_driver ehci_atmel_hc_driver = { .description = hcd_name, .product_desc = "Atmel EHCI UHP HS", .hcd_priv_size = sizeof(struct ehci_hcd), /* generic hardware linkage */ .irq = ehci_irq, .flags = HCD_MEMORY | HCD_USB2, /* basic lifecycle operations */ .reset = ehci_atmel_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, /* managing i/o requests and associated device resources */ .urb_enqueue = ehci_urb_enqueue, .urb_dequeue = ehci_urb_dequeue, .endpoint_disable = ehci_endpoint_disable, .endpoint_reset = ehci_endpoint_reset, /* scheduling support */ .get_frame_number = ehci_get_frame, /* root hub support */ .hub_status_data = ehci_hub_status_data, .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, };其中dev是,如下的dev
static struct platform_device at91_usbh_ehci_device = { .name = "atmel-ehci", .id = -1, .dev = { .dma_mask = &ehci_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &usbh_ehci_data, }, .resource = usbh_ehci_resources, .num_resources = ARRAY_SIZE(usbh_ehci_resources), };
/** * usb_create_hcd - create and initialize an HCD structure * @driver: HC driver that will use this hcd * @dev: device for this HC, stored in hcd->self.controller * @bus_name: value to store in hcd->self.bus_name * Context: !in_interrupt() * * Allocate a struct usb_hcd, with extra space at the end for the * HC driver's private data. Initialize the generic members of the * hcd structure. * * If memory is unavailable, returns NULL. */ struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, struct device *dev, const char *bus_name) { return usb_create_shared_hcd(driver, dev, bus_name, NULL); } EXPORT_SYMBOL_GPL(usb_create_hcd);usb_create_hcd的目的:创建并且初始化一个HCD结构体。实际是调用usb_create_shared_hcd来实现。
/** * usb_create_shared_hcd - create and initialize an HCD structure * @driver: HC driver that will use this hcd * @dev: device for this HC, stored in hcd->self.controller * @bus_name: value to store in hcd->self.bus_name * @primary_hcd: a pointer to the usb_hcd structure that is sharing the * PCI device. Only allocate certain resources for the primary HCD * Context: !in_interrupt() * * Allocate a struct usb_hcd, with extra space at the end for the * HC driver's private data. Initialize the generic members of the * hcd structure. * * If memory is unavailable, returns NULL. */ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, struct device *dev, const char *bus_name, struct usb_hcd *primary_hcd) { struct usb_hcd *hcd; hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); if (!hcd) { dev_dbg (dev, "hcd alloc failed\n"); return NULL; } if (primary_hcd == NULL) { hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex), GFP_KERNEL); if (!hcd->bandwidth_mutex) { kfree(hcd); dev_dbg(dev, "hcd bandwidth mutex alloc failed\n"); return NULL; } mutex_init(hcd->bandwidth_mutex); dev_set_drvdata(dev, hcd); } else { hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex; hcd->primary_hcd = primary_hcd; primary_hcd->primary_hcd = primary_hcd; hcd->shared_hcd = primary_hcd; primary_hcd->shared_hcd = hcd; } kref_init(&hcd->kref); usb_bus_init(&hcd->self); hcd->self.controller = dev; hcd->self.bus_name = bus_name; hcd->self.uses_dma = (dev->dma_mask != NULL); init_timer(&hcd->rh_timer); hcd->rh_timer.function = rh_timer_func; hcd->rh_timer.data = (unsigned long) hcd; #ifdef CONFIG_USB_SUSPEND INIT_WORK(&hcd->wakeup_work, hcd_resume_work); #endif hcd->driver = driver; hcd->speed = driver->flags & HCD_MASK; hcd->product_desc = (driver->product_desc) ? driver->product_desc : "USB Host Controller"; return hcd; } EXPORT_SYMBOL_GPL(usb_create_shared_hcd);usb_create_shared_hcd(driver, dev, bus_name, NULL);
2. primary_hcd == NULL,分配一个互斥。并且初始化一个互斥。
3. 引用计数加1;
4. dev_set_drvdata(dev, hcd);
因为dev->p为空,所以调用device_private_init(dev)。
5. usb_bus_init
6. return hcd