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

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

2010-08-10 07:13 561 查看
阿扁"辞职"了,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()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: