Linux那些事儿之我是EHCI(5) 2008年的这一场雪

2008年的这一场雪,比以往时候来的要大一些。以前是买不到票,这次有票也走不了了。
此时此刻,多少兄弟姐妹被困在路上,饥寒交迫,多少城市停电停水,物价飞涨。我真是忍不住破口大骂,好一个和谐盛世!虽说是天灾,但岂无人祸?直接原因是那该死的冻雨。但我认为罪魁乃是三峡工程,以及所谓南水北调。
祝愿那些困在铁路,公路上的人们早日回家团圆,大家过个好年。
还是先看看股市,有消息称,"导致大盘暴跌的原因是因为大面积的降雪, 导致大量的股民滞留车站,机场.无法进入股市抄底, 待在家中人员又因大面积的停电而无法上网操作, 导致了今天的大资金无法介入, 请大家不要恐慌。据不完全统计有60%的基金操盘手被困在机场吃方便面。"
闲话少讲,先补上一张图,Linux那些事儿之我是EHCI(5) 2008年的这一场雪
我们接着usb_hcd_pci_probe()往下走,89 - 108行,是为EHCI申请io内存,92行request_mem_region()申请,98行做一次mapping,在EHCI(1)中曾经提到过,EHCI的接口有3种,第一种是PCI配置寄存器,第二种是io内存,第三种就是普通的内存。这里先把EHCI的io内存登记,再做一次ioremap映射成虚拟地址。
128行进入了 usb_add_hcd()
1548 /**
1549* usb_add_hcd - finish generic HCD structure initialization and register
1550* @hcd: the usb_hcd structure to initialize
1551* @irqnum: Interrupt line to allocate
1552* @irqflags: Interrupt type flags
1553*
1554* Finish the remaining parts of generic HCD initialization: allocate the
1555* buffers of consistent memory, register the bus, request the IRQ line,
1556* and call the driver's reset() and start() routines.
1557*/
1558 int usb_add_hcd(struct usb_hcd *hcd,
1559 unsigned int irqnum, unsigned long irqflags)
1560 {
1561 int retval;
1562 struct usb_device *rhdev;
1563
1564 dev_info(hcd->self.controller, "%s/n", hcd->product_desc);
1565
1566 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
1567
1568 /* HC is in reset state, but accessible.Now do the one-time init,
1569 * bottom up so that hcds can customize the root hubs before khubd
1570 * starts talking to them.(Note, bus id is assigned early too.)
1571 */
1572 if ((retval = hcd_buffer_create(hcd)) != 0) {
1573 dev_dbg(hcd->self.controller, "pool alloc failed/n");
1574 return retval;
1575 }
1576
1577 if ((retval = usb_register_bus(&hcd->self)) < 0)
1578 goto err_register_bus;
1579
1580 if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
1581 dev_err(hcd->self.controller, "unable to allocate root hub/n");
1582 retval = -ENOMEM;
1583 goto err_allocate_root_hub;
1584 }
1585 rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
1586 USB_SPEED_FULL;
1587 hcd->self.root_hub = rhdev;
1588
1589 /* wakeup flag init defaults to "everything works" for root hubs,
1590 * but drivers can override it in reset() if needed, along with
1591 * recording the overall controller's system wakeup capability.
1592 */
1593 device_init_wakeup(&rhdev->dev, 1);
1594
1595 /* "reset" is misnamed; its role is now one-time init. the controller
1596 * should already have been reset (and boot firmware kicked off etc).
1597 */
1598 if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
1599 dev_err(hcd->self.controller, "can't setup/n");
1600 goto err_hcd_driver_setup;
1601 }
1602
1603 /* NOTE: root hub and controller capabilities may not be the same */
1604 if (device_can_wakeup(hcd->self.controller)
1605 && device_can_wakeup(&hcd->self.root_hub->dev))
1606 dev_dbg(hcd->self.controller, "supports USB remote wakeup/n");
1607
1608 /* enable irqs just before we start the controller */
1609 if (hcd->driver->irq) {
1610 snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
1611 hcd->driver->description, hcd->self.busnum);
1612 if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
1613 hcd->irq_descr, hcd)) != 0) {
1614 dev_err(hcd->self.controller,
1615 "request interrupt %d failed/n", irqnum);
1616 goto err_request_irq;
1617 }
1618 hcd->irq = irqnum;
1619 dev_info(hcd->self.controller, "irq %d, %s 0x%08llx/n", irqnum,
1620 (hcd->driver->flags & HCD_MEMORY) ?
1621 "io mem" : "io base",
1622 (unsigned long long)hcd->rsrc_start);
1623 } else {
1624 hcd->irq = -1;
1625 if (hcd->rsrc_start)
1626 dev_info(hcd->self.controller, "%s 0x%08llx/n",1627 (hcd->driver->flags & HCD_MEMORY) ?
1628 "io mem" : "io base",
1629 (unsigned long long)hcd->rsrc_start);
1630 }
1631
1632 if ((retval = hcd->driver->start(hcd)) < 0) {
1633 dev_err(hcd->self.controller, "startup error %d/n", retval);
1634 goto err_hcd_driver_start;
1635 }
1636
1637 /* starting here, usbcore will pay attention to this root hub */
1638 rhdev->bus_mA = min(500u, hcd->power_budget);
1639 if ((retval = register_root_hub(hcd)) != 0)
1640 goto err_register_root_hub;
1641
1642 if (hcd->uses_new_polling && hcd->poll_rh)
1643 usb_hcd_poll_rh_status(hcd);
1644 return retval;
1645
1646 err_register_root_hub:
1647 hcd->driver->stop(hcd);
1648 err_hcd_driver_start:
1649 if (hcd->irq >= 0)
1650 free_irq(irqnum, hcd);
1651 err_request_irq:
1652 err_hcd_driver_setup:
1653 hcd->self.root_hub = NULL;
1654 usb_put_dev(rhdev);
1655 err_allocate_root_hub:
1656 usb_deregister_bus(&hcd->self);
1657 err_register_bus:
1658 hcd_buffer_destroy(hcd);
1659 return retval;
1660 }
1572行hcd_buffer_create()见 UHCI 5 http://blog.csdn.net/fudan_abc/archive/2007/10/10/1818462.aspx。简单总结一下,创建, 摧毁buffur: hcd_buffer_create() / hcd_buffer_destroy(),创建之后,从池子里索取或者把索取的释放回去,usb_buffer_alloc()/usb_buffer_free()。
1577行usb_register_bus见UHCI 6 http://blog.csdn.net/fudan_abc/archive/2007/10/13/1823287.aspx。简单来说,把自己连入到全局变量usb_bus_list中,并调用class_device_create往sysfs新加入一个class。
1598行之前,都和UHCI没有什么分别,hcd->driver->reset指向的是,ehci_pci_hc_driver.ehci_pci_setup()