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

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

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

46 /**/ /**
47*usb_hcd_pci_probe-initializePCI-basedHCDs
48*@dev:USBHostControllerbeingprobed
49*@id:pcihotplugidconnectingcontrollertoHCDframework
50*Context:!in_interrupt()
51*
52*AllocatesbasicPCIresourcesforthisUSBhostcontroller,and
53*theninvokesthestart()methodfortheHCDassociatedwithit
54*throughthehotplugentry'sdriver_data.
55*
56*StorethisfunctionintheHCD'sstructpci_driverasprobe().
57
*/

58 int usb_hcd_pci_probe( struct pci_dev * dev, const struct pci_device_id * id)
59 ... {
60structhc_driver*driver;
61structusb_hcd*hcd;
62intretval;
63
64if(usb_disabled())
65return-ENODEV;
66
67if(!id||!(driver=(structhc_driver*)id->driver_data))
68return-EINVAL;
69
70if(pci_enable_device(dev)<0)
71return-ENODEV;
72dev->current_state=PCI_D0;
73dev->dev.power.power_state=PMSG_ON;
74
75if(!dev->irq)...{
76dev_err(&dev->dev,
77"FoundHCwithnoIRQ.CheckBIOS/PCI%ssetup! ",
78pci_name(dev));
79retval=-ENODEV;
80gotoerr1;
81}

82
83hcd=usb_create_hcd(driver,&dev->dev,pci_name(dev));
84if(!hcd)...{
85retval=-ENOMEM;
86gotoerr1;
87}

88
89if(driver->flags&HCD_MEMORY)...{//EHCI,OHCI
90hcd->rsrc_start=pci_resource_start(dev,0);
91hcd->rsrc_len=pci_resource_len(dev,0);
92if(!request_mem_region(hcd->rsrc_start,hcd->rsrc_len,
93driver->description))...{
94dev_dbg(&dev->dev,"controlleralreadyinuse ");
95retval=-EBUSY;
96gotoerr2;
97}

98hcd->regs=ioremap_nocache(hcd->rsrc_start,hcd->rsrc_len);
99if(hcd->regs==NULL)...{
100dev_dbg(&dev->dev,"errormappingmemory ");
101retval=-EFAULT;
102gotoerr3;
103}

104
105}
else...{//UHCI
106intregion;
107
108for(region=0;region<PCI_ROM_RESOURCE;region++)...{
109if(!(pci_resource_flags(dev,region)&
110IORESOURCE_IO))
111continue;
112
113hcd->rsrc_start=pci_resource_start(dev,region);
114hcd->rsrc_len=pci_resource_len(dev,region);
115if(request_region(hcd->rsrc_start,hcd->rsrc_len,
116driver->description))
117break;
118}

119if(region==PCI_ROM_RESOURCE)...{
120dev_dbg(&dev->dev,"noi/oregionsavailable ");
121retval=-EBUSY;
122gotoerr1;
123}

124}

125
126pci_set_master(dev);
127
128retval=usb_add_hcd(hcd,dev->irq,IRQF_SHARED);
129if(retval!=0)
130gotoerr4;
131returnretval;
132
133err4:
134if(driver->flags&HCD_MEMORY)...{
135iounmap(hcd->regs);
136err3:
137release_mem_region(hcd->rsrc_start,hcd->rsrc_len);
138}
else
139release_region(hcd->rsrc_start,hcd->rsrc_len);
140err2:
141usb_put_hcd(hcd);
142err1:
143pci_disable_device(dev);
144dev_err(&dev->dev,"init%sfail,%d ",pci_name(dev),retval);
145returnretval;
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-createandinitializeanHCDstructure
1482*@driver:HCdriverthatwillusethishcd
1483*@dev:deviceforthisHC,storedinhcd->self.controller
1484*@bus_name:valuetostoreinhcd->self.bus_name
1485*Context:!in_interrupt()
1486*
1487*Allocateastructusb_hcd,withextraspaceattheendforthe
1488*HCdriver'sprivatedata.Initializethegenericmembersofthe
1489*hcdstructure.
1490*
1491*Ifmemoryisunavailable,returnsNULL.
1492
*/

1493 struct usb_hcd * usb_create_hcd( const struct hc_driver * driver,
1494 struct device * dev, char * bus_name)
1495 ... {
1496structusb_hcd*hcd;
1497
1498hcd=kzalloc(sizeof(*hcd)+driver->hcd_priv_size,GFP_KERNEL);
1499if(!hcd)...{
1500dev_dbg(dev,"hcdallocfailed ");
1501returnNULL;
1502}

1503dev_set_drvdata(dev,hcd);
1504kref_init(&hcd->kref);
1505
1506usb_bus_init(&hcd->self);
1507hcd->self.controller=dev;
1508hcd->self.bus_name=bus_name;
1509hcd->self.uses_dma=(dev->dma_mask!=NULL);
1510
1511init_timer(&hcd->rh_timer);
1512hcd->rh_timer.function=rh_timer_func;
1513hcd->rh_timer.data=(unsignedlong)hcd;
1514#ifdefCONFIG_PM
1515INIT_WORK(&hcd->wakeup_work,hcd_resume_work);
1516#endif
1517
1518hcd->driver=driver;
1519hcd->product_desc=(driver->product_desc)?driver->product_desc:
1520"USBHostController";
1521
1522returnhcd;
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()

你可能感兴趣的:(struct)