Linux那些事儿之我是USB
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
 26.设备的生命线(七)

26.设备的生命线(七)

在HCD这个片区域里,王中之王就是drivers/usb/core/hcd.h中定义的struct usb_hcd。

58 struct usb_hcd {
59
60      /*
61       * housekeeping
62       */
63      struct usb_bus    self;    /* hcd is-a bus */
64      struct kref       kref;     /* reference counter */
65
66      const char       *product_desc; /* product/vendor string */
67      char            irq_descr[24];  /* driver + bus # */
68
69      struct timer_list   rh_timer;     /* drives root-hub polling */
70      struct urb          *status_urb;  /* the current status urb */
71 #ifdef CONFIG_PM
72      struct work_struct  wakeup_work;  /* for remote wakeup */
73 #endif
74
75       /*
76        * hardware info/state
77        */
78      const struct hc_driver *driver;   /* hw-specific hooks */
79
80      /* Flags that need to be manipulated atomically */
81      unsigned long        flags;
82 #define HCD_FLAG_HW_ACCESSIBLE  0x00000001
83 #define HCD_FLAG_SAW_IRQ      0x00000002
84
85      unsigned             rh_registered:1;/* is root hub registered? */
86
87      /* The next flag is a stopgap, to be removed when all the HCDs
88      * support the new root-hub polling mechanism. */
89      unsigned          uses_new_polling:1;
90      unsigned          poll_rh:1;     /* poll for rh status? */
91      unsigned          poll_pending:1; /* status has changed? */
92      unsigned          wireless:1;    /* Wireless USB HCD */
93
94      int               irq;      /* irq allocated */
95      void __iomem       *regs;      /* device memory/io */
96      u64               rsrc_start;  /* memory/io resource start */
97      u64               rsrc_len;    /* memory/io resource length */
98      unsigned          power_budget; /* in mA, 0 = no limit */
99
100 #define HCD_BUFFER_POOLS   4
101  struct dma_pool   *pool [HCD_BUFFER_POOLS];
102
103      int       state;
104 #define __ACTIVE       0x01
105 #define __SUSPEND      0x04
106 #define __TRANSIENT     0x80
107
108 #define HC_STATE_HALT      0
109 #define HC_STATE_RUNNING    (__ACTIVE)
110 #define HC_STATE_QUIESCING  (__SUSPEND|__TRANSIENT|__ACTIVE)
111 #define HC_STATE_RESUMING   (__SUSPEND|__TRANSIENT)
112 #define HC_STATE_SUSPENDED  (__SUSPEND)
113
114 #define HC_IS_RUNNING(state) ((state) & __ACTIVE)
115 #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
116
117     /* more shared queuing code would be good; it should support
118      * smarter scheduling, handle transaction translators, etc;
119      * input size of periodic table to an interrupt scheduler.
120      * (ohci 32, uhci 1024, ehci 256/512/1024).
121      */
122
123      /* The HC driver's private data is stored at the end of
124       * this structure.
125       */
126      unsigned long hcd_priv[0]
127              __attribute__ ((aligned (sizeof(unsigned long))));
128 };

63行,又一个结构体,struct usb_bus里还有self。

为什么这里会用这么一个戏剧性的词汇——self?我在前面提到过,一个主机控制器就会连出一条USB总线,主机控制器驱动用struct usb_hcd结构表示,一条总线用struct usb_bus结构表示。struct usb_bus在include/linux/usb.h中定义。

276 struct usb_bus {
277     struct device *controller;  /* host/master side hardware */
278     int busnum;              /* Bus number (in order of reg) */
279     char *bus_name;            /* stable id (PCI slot_name etc) */
280     u8 uses_dma;            /* Does the host controller use DMA? */
281     u8 otg_port;               /* 0, or number of OTG/HNP port */
282     unsigned is_b_host:1;   /* true during some HNP roleswitches */
283     unsigned b_hnp_enable:1;   /* OTG: did A-Host enable HNP? */
284
285     int devnum_next;           /* Next open device number in
286              * round-robin allocation */
287
288     struct usb_devmap devmap;    /* device address allocation map */
289     struct usb_device *root_hub;  /* Root hub */
290     struct list_head bus_list;    /* list of busses */
291
292     int bandwidth_allocated;    /* on this bus: how much of the time
293                                * reserved for periodic (intr/iso)
294                                * requests is used, on average?
295                                * Units: microseconds/frame.
296                               * Limits: Full/low speed reserve 90%,
297                                * while high speed reserves 80%.
298                                */
299     int bandwidth_int_reqs;    /* number of Interrupt requests */
300     int bandwidth_isoc_reqs;   /* number of Isoc. requests */
301
302 #ifdef CONFIG_USB_DEVICEFS
303  struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
304 #endif
305  struct class_device *class_dev; /* class device for this bus */
306
307 #if defined(CONFIG_USB_MON)
308  struct mon_bus *mon_bus;   /* non-null when associated */
309  int monitored;      /* non-zero when monitored */
310 #endif
311 };

277行,controller,struct usb_hcd包含了一个usb_bus,这里就回应了一个controller。那现在struct usb_hcd里的self和struct usb_bus里的controller这两个词儿,它们到底是什么关系?其实对于写代码的人来说一个主机控制器和一条总线差不多是一码事儿,不用分得那么清楚,可以简单地说它们都是用来描述主机控制器的,那为什么又分成了两个结构?

USB主机控制器是一个设备,而且更多的时候它还是一个PCI设备,那它就应该纳入这个设备模型范畴之内,struct usb_hcd结构中就得嵌入类似struct device或struct pci_dev这样的一个结构体,但是你仔细看一看,能不能在它里面发现这么一个成员?不能。但是再看一看struct usb_bus里第一个成员就是一个struct device结构体。

再以UHCI为例说明,都在host目录下的uhci-族文件中,首先它是一个pci设备,要使用pci_register_driver注册一个struct pci_driver结构体uhci_pci_driver。uhci_pci_driver里又有一个probe,在这个probe里,它调用usb_create_hcd来创建一个usb_hcd,并初始化里面的self,还将这个self里的controller设定为描述主机控制器pci_dev里的struct device结构体,从而将usb_hcd、usb_bus和pci_dev,甚至设备模型都连接起来了。

再接着看uhci-文件中定义的函数。只看它们的参数,你会发现参数中不是struct usb_hcd就是struct uhci_hcd,而且那些函数的前面几行常常会有hcd_to_uhci或者uhci_to_hcd这样的函数在struct usb_hcd和struct uhci_hcd之间转换。struct uhci_hcd是什么?它是uhci自己私有的一个结构体,每个具体的主机控制器都有这么一个类似的结构体。顺便看hcd_to_uhci或者uhci_to_hcd的定义你就会明白,每个主机控制器的这个私有结构体都藏在struct usb_hcd结构最后的hcd_priv变长数组里。

对于具体的主机控制器驱动来说,它们的眼里只有struct usb_hcd,struct usb_hcd结构,至于主机控制器驱动,就如同struct usb_device或struct usb_interface对于USB驱动。没有usb_create_hcd去创建usb_hcd,就不会有usb_bus的存在。

而对于Linux设备模型来说,struct usb_bus无疑要更亲切一些。总之,你可以把struct usb_bus当做只是嵌入到struct usb_hcd里面的一个结构体,它将struct usb_hcd要完成的一部分工作进行了封装,因为要描述一个主机控制器太复杂太难,于是就开了struct usb_bus去专门面对设备模型、sysfs等。这也就是在前面说struct usb_hcd才是“王中之王”的原因。

你知道Greg他们是怎么描述这种奇妙的关系吗?他们把这个叫做HCD bus-glue layer,并致力于“flatten out it”。这个关系早先是比较混沌的,现在要清晰一些,以后只会更清晰,struct usb_hcd越来越走上台前,struct usb_bus越来越走向幕后。

278行,busnum,总线编号,你的计算机里总可以有多个主机控制器吧,自然也就可以有多条USB总线了,既然可以有多条USB总线,就要编号方便确认了。有关总线编号,可以看一看定义在drivesr/usb/core/hcd.c里的这几行。

88 /* used when allocating bus numbers */
89 #define USB_MAXBUS     64
90 struct usb_busmap {
91     unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];
92 };
93 static struct usb_busmap busmap;

在讲struct usb_device函数中的devnum时候,说到过一个devicemap,这里又有一个busmap。当时分析说devicemap一共有128位,同理可知,这里的busmap一共有64位,也就是说最多可以有64条USB总线。

279行,bus_name。bus,总线;name,名字;bus_name即总线的名字。什么样的名字?要知道大多数情况下主机控制器都是一个PCI设备,那么bus_name应该就是用来在PCI总线上标识USB主机控制器的名字,PCI总线使用标准的PCI ID来标识PCI设备,所以bus_name里保存的应该就是主机控制器对应的PCI ID。UHCI等调用usb_create_hcd创建usb_hcd时确实是将它们对应PCI ID赋给了bus_name。

现在简单介绍PCI ID。PCI spec允许单个系统可以最多有256条PCI总线,对我们来说当然是太多了,但是对于一些特殊的系统,它可能还觉得这满足不了要求,于是所有的PCI总线又被划分为domain,每个PCI domain又可以最多拥有256条总线,而且每条总线上又可以支持32个设备。这些设备中还都可以是多功能板,它们还都可以最多支持8种功能。那系统怎么来区分每种功能的呢?总要知道它在哪个domain,哪条总线,哪个设备板上吧。这么说还是太笼统了,你可以用lspci命令看。

00:00.0 Host bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (rev 01)
00:01.0 PCI bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (rev 01)
00:07.0 ISA bridge: Intel Corporation 82371AB/EB/MB PIIX4 ISA (rev 08)
00:07.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)
00:07.2 USB Controller: Intel Corporation 82371AB/EB/MB PIIX4 USB
00:07.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
00:0f.0 VGA compatible controller: VMware Inc [VMware SVGA II] PCI Display Adapter
00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)
00:11.0 Ethernet controller: Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE] (rev 10)
00:12.0 Multimedia audio controller: Ensoniq ES1371 [AudioPCI-97] (rev 02)

每行前面的数字就是所谓的“PCI ID”,每个PCI ID由domain号(16位),总线编号(8位),设备号(5位),功能号(3位)组成,不过这里lspci没有标明domain号,但对于一台普通计算机而言,一般也就只有一个domain,0x0000。

280行,uses_dma,表明这个主机控制器是否支持DMA。主机控制器的一项重要工作就是在内存和USB总线之间传输数据,这个过程可以使用DMA或者不使用DMA。不使用DMA的方式即所谓的PIO方式。DMA代表着Direct Memory Access,即直接内存访问,不需要CPU去干预。具体去看一看PCI DMA吧,因为一般来说主机控制器都是PCI设备,uses_dma都在它们自己的probe函数中设置了。

281行到283行,有关otg的代码。

285行,devnum_next;288行,devmap,早就说过devmap这张表了,devnum_next中记录的就是这张表里下一个为0的位,里面为1的位都是已经被这条总线上的USB设备占据了的。

289行,root_hub,Root Hub在所有的Hub里面是那么特殊,还记得USB的那棵树吗?它就是那棵树的根,和USB主机控制器绑定在一起,其他的hub和设备都必须从它这儿延伸出去。正是因为这种特殊的关系,写代码的人就直接将它放在了struct usb_bus结构中。USB主机控制器︰USB总线︰Root Hub为1︰1︰1。

290行,bus_list,在drivers/usb/core/hcd.c中定义有一个全局队列usb_bus_list。

84 /* host controllers we manage */
85 LIST_HEAD (usb_bus_list);
86 EXPORT_SYMBOL_GPL (usb_bus_list);

它就是所有USB总线的组织。每次一条总线新添加进来,都要向这个组织靠拢,都要使用bus_list字段链接在这个队列上。

292行,bandwidth_allocated,表明总线为中断传输和等时传输预留了多少带宽,协议中规定了,对于高速传输来说,最多可以有80%的带宽,对于低速传输和全速传输要多一点,可以达到90%的带宽。它的单位是ms,表示一帧或微帧内有多少ms可以留给中断/等时传输用。

299行,bandwidth_int_reqs;300行,bandwidth_isoc_reqs,分别表示当前中断传输和等时传输的数量。

302行到304行,是usbfs的,每条总线都对应于/proc/bus/usb下的一个目录。

305行,class_dev,这里又牵涉设备模型中的一个概念——设备的class,即设备的类。像前面提到的设备模型中的总线、设备、驱动三个核心概念,纯粹是从写驱动的角度看的,而这里的类则是面向于Linux的广大用户,它不管你是用什么接口,怎么去连接,它只管对用户来说提供了什么功能。一个SCSI硬盘和一个ATA硬盘对驱动来说是不相关的两个东西,但是对于用户来说,它们都是硬盘,都是用来备份文件。

设备模型与sysfs是分不开的,class在sysfs里的体现就在/sys/class下面,可以去看一看。

atm   dma graphics hwmon    i2c-adapter input
mem   misc net pci_bus     scsi_device scsi_disk
scsi_host   sound     spi_host spi_master spi_transport tty
usb_device  usb_endpoint usb_host   vc    vtconsole

看到里面的usb_host了吧,它就是所有USB主机控制器的类,这些目录都是怎么来的呢?咱们还要追溯USB子系统的初始化函数usb_init,它里面有下面这一段:

877  retval = usb_host_init();
878  if (retval)
879      goto host_init_failed;

当时只是简单说这是用来初始化主机控制器的,在hcd.c里:

671 static struct class *usb_host_class;
672
673 int usb_host_init(void)
674 {
675     int retval = 0;
676
677     usb_host_class = class_create(THIS_MODULE, "usb_host");
678     if (IS_ERR(usb_host_class))
679         retval = PTR_ERR(usb_host_class);
680     return retval;
681 }

usb_host_init所作的一切就是调用class_create创建了一个usb_host这样的类,你只要加载了usbcore模块就能在/sys/class下面看到有usb_host目录出现。既然usb_host目录表示USB主机控制器的类,那么它下面应该就对应各个具体的主机控制器了,你用ls命令就能看到usb_host1、usb_host2等这样的目录,它们每个都对应一个在你系统里实际存在的主机控制器,实际上在hcd.c里的usb_register_bus函数有以下这几行。

735 bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
736         bus->controller, "usb_host%d", busnum);

这两行就是使用class_device_create在/sys/class/usb_host下面为每条总线创建了一个目录,目录名里的数字代表的就是每条总线的编号,usb_register_bus函数是每个主机控制器驱动在probe里调用的,向USB Core注册一条总线,也可以说是注册一个主机控制器。

在struct usb_bus的最后,307行到310行,CONFIG_USB_MON是干什么用的?这要查看drivers/usb/mon目录下的Kconfig。

5 config USB_MON
6       bool "USB Monitor"
7       depends on USB!=n
8       default y
9       help
10        If you say Y here, a component which captures the USB traffic
11        between peripheral-specific drivers and HC drivers will be built.
12        For more information, see <file:Documentation/usb/usbmon.txt>.
13
14        This is somewhat experimental at this time, but it should be safe.
15
16        If unsure, say Y.

文件中就这么多内容,从里面咱们可以知道,如果定义了CONFIG_USB_MON,一个所谓的USB Monitor,也就是USB监视器就会编进内核。这个Monitor是用来监视USB总线上的底层通信流的,相关的文件都在drivers/usb/mon下面。