Linux那些事儿之我是UHCI(15)Root Hub的注册

回到usb_add_hcd之后,1638,得出rhdevbus_mA,这个咱们在Hub驱动中已经讲过.有些主机控制器是需要设置power_budget,咱们没有设置过,就是默认值0,所以这里得到的是bus_mA就是0,0表示没有限制,hub驱动中我们看到了对于没有限制的情况我们是给每个端口设置为最多500mA,因为通常来讲计算机的usb端口能提供的最多就是500mA.

1639,register_root_hub,来自drivers/usb/core/hcd.c.

783 /**

784 * register_root_hub - called by usb_add_hcd() to register a root hub

785 * @hcd: host controller for this root hub

786 *

787 * This function registers the root hub with the USB subsystem. It sets up

788 * the device properly in the device tree and then calls usb_new_device()

789 * to register the usb device. It also assigns the root hub's USB address

790 * (always 1).

791 */

792 static int register_root_hub(struct usb_hcd *hcd)

793 {

794 struct device *parent_dev = hcd->self.controller;

795 struct usb_device *usb_dev = hcd->self.root_hub;

796 const int devnum = 1;

797 int retval;

798

799 usb_dev->devnum = devnum;

800 usb_dev->bus->devnum_next = devnum + 1;

801 memset (&usb_dev->bus->devmap.devicemap, 0,

802 sizeof usb_dev->bus->devmap.devicemap);

803 set_bit (devnum, usb_dev->bus->devmap.devicemap);

804 usb_set_device_state(usb_dev, USB_STATE_ADDRESS);

805

806 mutex_lock(&usb_bus_list_lock);

807

808 usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);

809 retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);

810 if (retval != sizeof usb_dev->descriptor) {

811 mutex_unlock(&usb_bus_list_lock);

812 dev_dbg (parent_dev, "can't read %s device descriptor %d/n",

813 usb_dev->dev.bus_id, retval);

814 return (retval < 0) ? retval : -EMSGSIZE;

815 }

816

817 retval = usb_new_device (usb_dev);

818 if (retval) {

819 dev_err (parent_dev, "can't register root hub for %s, %d/n",

820 usb_dev->dev.bus_id, retval);

821 }

822 mutex_unlock(&usb_bus_list_lock);

823

824 if (retval == 0) {

825 spin_lock_irq (&hcd_root_hub_lock);

826 hcd->rh_registered = 1;

827 spin_unlock_irq (&hcd_root_hub_lock);

828

829 /* Did the HC die before the root hub was registered? */

830 if (hcd->state == HC_STATE_HALT)

831 usb_hc_died (hcd); /* This time clean up */

832 }

833

834 return retval;

835 }

这个函数的意图很明显,我们说过,Host Controller通常是带有一个Root Hub,常言说得好,不想吃天鹅肉的癞蛤蟆不是好癞蛤蟆,同样,不集成Root Hub的主机控制器也不是好主机控制器,常言又说了,吃了天鹅肉的癞蛤蟆还是癞蛤蟆,同样,集成了Root Hub的主机控制器也还是主机控制器.实际上,当我们的uhci_start执行完了之后,主机控制器已经可以开始工作了,至少它已经可以开始处理urb.我们不妨就从这个函数开始展开.不过在展开这个函数之前,我们先了断一下usb_add_hcd这个函数,我们注意到在register_root_hub之后,也就只剩下一个函数了,它就是usb_hcd_poll_rh_status,这个函数将是整个故事中出现次数最多的一个函数.但是在这里我们看到,调用完usb_hcd_poll_rh_status之后,usb_add_hcd这个浩浩荡荡的函数也就这么华丽丽的结束了它的使命,我们和usb_add_hcd这个函数的恩恩怨怨也就此结束.但其实更令我们激动不已的是,usb_add_hcd结束之后,实际上当我们返回usb_hcd_pci_probe的时候我们惊奇的发现,其实这时候usb_hcd_pci_probe函数也结束了,这一切简直充满戏剧性,因为我们知道,probe函数总是每个driver的最复杂的函数之一,而我们却几乎是在不知不觉中就走完了这段漫漫长路,怎能不让人感受无限惊喜!

,那么现在等待我们的就是两个函数,一个是register_root_hub,我们已经贴出来了,另一个是usb_hcd_poll_rh_status,这一个的代码我们等会儿再贴出来.先来看前者.

看过这么的函数之后,我们不得不说,register_root_hub这个函数是所有函数中最直接,最赤裸裸的.因为这个函数从函数名到函数内部代码的每一行都是那么明了,即便是用下半身思考的男青年们也能一目了然的看懂每一行究竟在干嘛.

799,root hubdevnum设置为1,毫无疑问.因为整棵设备树就是起源于Root Hub,如果把usb设备树比做水泊梁山一百单八好汉,那么Root Hub就相当于及时雨宋江,他不做老大谁做老大.

800,从现在开始记录busdevnum_next,2开始.

801,802,803,初始化busdevmap,并且把root hub的那把交椅先给占了.

804,usb_set_device_state(),不用多说了吧,hub driver中那个八大函数中的第二个.Root Hub:我准备好了!于是为它把状态设置为USB_STATE_ADDRESS.

紧接着,808809,设置Root HubwMaxPacketSize64,然后获取Root Hub的设备描述符.

817,usb_new_device,我们更加不会陌生,hub driver中八大函数的第七个.这个函数结束之后,咱们的Root Hub就算从软件的角度来说彻底融入了整个usb世界,或者说这一步就算是真正的注册了.一切顺利的话返回0.

824,设置rh_registered1.顾名思义,告诉全世界,咱们这个HCDRoot Hub现在算是有户口的人了.

830行这个if就是为变态们准备的,你这里正在注册呢,也不知哪位哥们儿缺德,帮你把主机控制器的驱动给卸载了,比如他卸载了uhci-hcd,那么usb_remove_hcd会被执行,于是hcd->state会被设置为HC_STATE_HALT,真遇上这么一件倒霉事那咱也没办法,没啥好说的,执行usb_hc_died.这个函数是用来汇报说主机控制器不正常的shutdown.这个函数并不复杂,但是有好几处调用了它,咱们稍微看一下,来自drivers/usb/core/hcd.c:

1451 /**

1452 * usb_hc_died - report abnormal shutdown of a host controller (bus glue)

1453 * @hcd: pointer to the HCD representing the controller

1454 *

1455 * This is called by bus glue to report a USB host controller that died

1456 * while operations may still have been pending. It's called automatically

1457 * by the PCI glue, so only glue for non-PCI busses should need to call it.

1458 */

1459 void usb_hc_died (struct usb_hcd *hcd)

1460 {

1461 unsigned long flags;

1462

1463 dev_err (hcd->self.controller, "HC died; cleaning up/n");

1464

1465 spin_lock_irqsave (&hcd_root_hub_lock, flags);

1466 if (hcd->rh_registered) {

1467 hcd->poll_rh = 0;

1468

1469 /* make khubd clean up old urbs and devices */

1470 usb_set_device_state (hcd->self.root_hub,

1471 USB_STATE_NOTATTACHED);

1472 usb_kick_khubd (hcd->self.root_hub);

1473 }

1474 spin_unlock_irqrestore (&hcd_root_hub_lock, flags);

1475 }

正如我们所说的那样,确实不复杂,在这个道德沦丧的社会里,能看到这么简单这么单纯的一个函数真的很不容易,也许是写代码的人良心发现吧,如果每个函数都设计得像西直门立交桥一样复杂,如果每次函数跳转都像地铁十三号线转二号线那么曲折蜿蜒,非要给乘客一种犹太人走在集中营里的感觉,那么也许这代码就没人愿意看了.1466,注意到我们刚才把rh_register设置成了1,所以这里这段if的代码要被执行,设置poll_rh0.再次调用usb_set_device_state函数,Root Hub的状态给设置成USB_STATE_NOTATTACHED这种原始状态.最后调用usb_kick_khubd函数.后者其实就是披了马甲的kick_khubd()函数.不信你就看,来自drivers/usb/core/hub.c:

331 void usb_kick_khubd(struct usb_device *hdev)

332 {

333 kick_khubd(hdev_to_hub(hdev));

334 }

关于kick_khubd我想就不用多说了吧,hub driver中最重要的函数之一.我们知道这个函数会触发hub_events(),hub_events中判断出hub处于了USB_STATE_NOTATTACHED的状态,就会调用hub_pre_reset去处理那些后事.当然,这种情况对咱们大多数人来说是不会发生的,除非您吃了,非得显摆一下自己的能耐.

假如您没吃,那么咱们这里这个register_root_hub也就走到尽头了.看透了人间聚散的你我,也许并不会介意这种离别.心若知道灵犀的方向,哪怕不能够朝夕相伴.

你可能感兴趣的:(linux)