您的位置:首页 > 运维架构 > Linux

Linux那些事儿之我是EHCI(4) data structure of ehci driver and device

2008-01-13 20:55 543 查看
阿扁"辞职"了,kde4发布了,更让我激动的是,英雄志过两天又有更新了,这部连载长达8年的小说,终于要进入精彩的大结局。卢云的命运究竟如何?观海云远,四个性格理念完全不同的人,谁是好,谁是坏,谁是对,谁是错?何谓正道?

接着上回说,usb_hcd_pci_probe这个函数在"我是UHCI"中也有讨论,不过我想按照我的思路写下去。




46 /**//**


47 * usb_hcd_pci_probe - initialize PCI-based HCDs


48 * @dev: USB Host Controller being probed


49 * @id: pci hotplug id connecting controller to HCD framework


50 * Context: !in_interrupt()


51 *


52 * Allocates basic PCI resources for this USB host controller, and


53 * then invokes the start() method for the HCD associated with it


54 * through the hotplug entry's driver_data.


55 *


56 * Store this function in the HCD's struct pci_driver as probe().


57 */


58 int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)




59 ...{


60 struct hc_driver *driver;


61 struct usb_hcd *hcd;


62 int retval;


63


64 if (usb_disabled())


65 return -ENODEV;


66


67 if (!id || !(driver = (struct hc_driver *) id->driver_data))


68 return -EINVAL;


69


70 if (pci_enable_device (dev) < 0)


71 return -ENODEV;


72 dev->current_state = PCI_D0;


73 dev->dev.power.power_state = PMSG_ON;


74




75 if (!dev->irq) ...{


76 dev_err (&dev->dev,


77 "Found HC with no IRQ. Check BIOS/PCI %s setup! ",


78 pci_name(dev));


79 retval = -ENODEV;


80 goto err1;


81 }


82


83 hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));




84 if (!hcd) ...{


85 retval = -ENOMEM;


86 goto err1;


87 }


88




89 if (driver->flags & HCD_MEMORY) ...{ // EHCI, OHCI


90 hcd->rsrc_start = pci_resource_start (dev, 0);


91 hcd->rsrc_len = pci_resource_len (dev, 0);


92 if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len,




93 driver->description)) ...{


94 dev_dbg (&dev->dev, "controller already in use ");


95 retval = -EBUSY;


96 goto err2;


97 }


98 hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);




99 if (hcd->regs == NULL) ...{


100 dev_dbg (&dev->dev, "error mapping memory ");


101 retval = -EFAULT;


102 goto err3;


103 }


104




105 } else ...{ // UHCI


106 int region;


107




108 for (region = 0; region < PCI_ROM_RESOURCE; region++) ...{


109 if (!(pci_resource_flags (dev, region) &


110 IORESOURCE_IO))


111 continue;


112


113 hcd->rsrc_start = pci_resource_start (dev, region);


114 hcd->rsrc_len = pci_resource_len (dev, region);


115 if (request_region (hcd->rsrc_start, hcd->rsrc_len,


116 driver->description))


117 break;


118 }




119 if (region == PCI_ROM_RESOURCE) ...{


120 dev_dbg (&dev->dev, "no i/o regions available ");


121 retval = -EBUSY;


122 goto err1;


123 }


124 }


125


126 pci_set_master (dev);


127


128 retval = usb_add_hcd (hcd, dev->irq, IRQF_SHARED);


129 if (retval != 0)


130 goto err4;


131 return retval;


132


133 err4:




134 if (driver->flags & HCD_MEMORY) ...{


135 iounmap (hcd->regs);


136 err3:


137 release_mem_region (hcd->rsrc_start, hcd->rsrc_len);


138 } else


139 release_region (hcd->rsrc_start, hcd->rsrc_len);


140 err2:


141 usb_put_hcd (hcd);


142 err1:


143 pci_disable_device (dev);


144 dev_err (&dev->dev, "init %s fail, %d ", pci_name(dev), retval);


145 return retval;


146 }



64行,usb_disabled()判断内核有没有开启支持usb,要是这都不支持,一切都免谈。

70行,pci_enable_device()这是对ehci三类接口中的pci configuration space进行操作,设置其中某个寄存器的值,使设备处于工作状态。调用pci_read_config_word()和pci_write_config_word来读写pci配置空间的寄存器。pci_enable_device -> pci_enable_device_bars -> do_pci_enable_device ... 原理不难,只要对照spec可以看懂。

72,73是电源管理的内容。75判断设备的中断号是否为空。
83,usb_create_hcd() 创建一个usb_hcd机构体。





1480 /**//**


1481 * usb_create_hcd - create and initialize an HCD structure


1482 * @driver: HC driver that will use this hcd


1483 * @dev: device for this HC, stored in hcd->self.controller


1484 * @bus_name: value to store in hcd->self.bus_name


1485 * Context: !in_interrupt()


1486 *


1487 * Allocate a struct usb_hcd, with extra space at the end for the


1488 * HC driver's private data. Initialize the generic members of the


1489 * hcd structure.


1490 *


1491 * If memory is unavailable, returns NULL.


1492 */


1493 struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,


1494 struct device *dev, char *bus_name)




1495 ...{


1496 struct usb_hcd *hcd;


1497


1498 hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);




1499 if (!hcd) ...{


1500 dev_dbg (dev, "hcd alloc failed ");


1501 return NULL;


1502 }


1503 dev_set_drvdata(dev, hcd);


1504 kref_init(&hcd->kref);


1505


1506 usb_bus_init(&hcd->self);


1507 hcd->self.controller = dev;


1508 hcd->self.bus_name = bus_name;


1509 hcd->self.uses_dma = (dev->dma_mask != NULL);


1510


1511 init_timer(&hcd->rh_timer);


1512 hcd->rh_timer.function = rh_timer_func;


1513 hcd->rh_timer.data = (unsigned long) hcd;


1514 #ifdef CONFIG_PM


1515 INIT_WORK(&hcd->wakeup_work, hcd_resume_work);


1516 #endif


1517


1518 hcd->driver = driver;


1519 hcd->product_desc = (driver->product_desc) ? driver->product_desc :


1520 "USB Host Controller";


1521


1522 return hcd;


1523 }




一下子出现了很多数据结构,现在有必要捋一捋它们之间的关系。
(1)描述驱动的数据结构

ehci主控器的驱动程序需要包括些什么东西?站在pci总线的角度来说,ehci是一个pci的设备,驱动程序里面必须提供操作ehci设备,比如开启(start),关闭(stop),重启(reset),中断的函数。另外,站在usb控制器的角度来说,驱动程序里面还要与底层usb系统交互的函数,如插入/删除urb(rb_enqueue, urb_dequeue)。


pci_driver ehci_pci_driver{
.........
.id_table = pci_ids, ------------>driver_data = (unsigned long) &ehci_pci_hc_driver,
.probe = usb_hcd_pci_probe

}
hc_driver ehci_pci_hc_driver{
........
.hcd_priv_size = sizeof(struct ehci_hcd),

.irq = ehci_irq,
.reset = ehci_pci_setup,
.start = ehci_run,
.stop = ehci_stop,
.shutdown = ehci_shutdown,

.urb_enqueue = ehci_urb_enqueue,
.urb_dequeue = ehci_urb_dequeue,
}

(2)描述设备的数据结构

usb_hcd{
........
usb_bus .self
.hcd_priv = ehci_hcd
}


usb_hcd交大人甲有过论述:linux那些事儿 之 戏说USB(28)设备的生命线 (七) http://blog.csdn.net/fudan_abc/archive/2007/10/18/1831459.aspx

usb_hcd注释上说USB Host Controller Driver,但我更愿意认为它是一个描述一个usb主控制器设备的数据结构。usb_hcd描述了usb主控制器共有的属性,usb_hcd.hcd_priv指向了特定的主控制器数据结构,它描述各自特有的属性。对ehci,是ehci_hcd,对uhci,是uhci_hcd。usb_hcd的成员usb_bus self 是HCD bus-glue layer,usb主控器与总线之间粘合剂。

这样,1498就好理解了。1506行usb_bus_init初始化usb_hcd.self。 1511-1513初始化 root harbor 计时器。然后就有返回到usb_hcd_pci_probe()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: