27.设备的生命线(八)

27.设备的生命线(八)

这个世界上不需要努力就能得到的东西只有一样,那就是年龄。所以要不怕苦不怕累,看完struct usb_bus函数,回到struct usb_hcd函数,继续努力地往下看。

64行,kref,USB主机控制器的引用计数。struct usb_hcd也有自己专用的引用计数函数,在hcd.c文件中。

1526 static void hcd_release (struct kref *kref)
1527 {
1528     struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
1529
1530     kfree(hcd);
1531 }
1532
1533 struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
1534 {
1535     if (hcd)
1536        kref_get (&hcd->kref);
1537     return hcd;
1538 }
1539 EXPORT_SYMBOL (usb_get_hcd);
1540
1541 void usb_put_hcd (struct usb_hcd *hcd)
1542 {
1543     if (hcd)
1544         kref_put (&hcd->kref, hcd_release);
1545 }
1546 EXPORT_SYMBOL (usb_put_hcd);

66行,product_desc,主机控制器的产品描述字符串,对于UHCI,它为“UHCI Host Controller”,对于EHCI,它为“EHCI Host Controller”。

67行,irq_descr[24],这里面保存的是“ehci-hcd:usb1”之类的字符串,也就是驱动的名称再加上总线编号。

71行到73行,电源管理。

78行,driver,每个主机控制器驱动都有一个struct hc_driver结构体。查看它在hcd.h中的定义。

149 struct hc_driver {
150     const char  *description; /* "ehci-hcd" etc */
151     const char  *product_desc; /* product/vendor string */
152     size_t    hcd_priv_size; /* size of private data */
153
154     /* irq handler */
155     irqreturn_t  (*irq) (struct usb_hcd *hcd);
156
157     int     flags;
158 #define HCD_MEMORY  0x0001   /* HC regs use memory (else I/O) */
159 #define HCD_USB11   0x0010    /* USB 1.1 */
160 #define HCD_USB2    0x0020    /* USB 2.0 */
161
162    /* called to init HCD and root hub */
163     int  (*reset) (struct usb_hcd *hcd);
164     int  (*start) (struct usb_hcd *hcd);
165
166     /* NOTE: these suspend/resume calls relate to the HC as
167     * a whole, not just the root hub; they're for PCI bus glue.
168     */
169     /* called after suspending the hub, before entering D3 etc */
170     int  (*suspend) (struct usb_hcd *hcd, pm_message_t message);
171
172    /* called after entering D0 (etc), before resuming the hub */
173     int  (*resume) (struct usb_hcd *hcd);
174
175     /* cleanly make HCD stop writing memory and doing I/O */
176    void  (*stop) (struct usb_hcd *hcd);
177
178     /* shutdown HCD */
179     void  (*shutdown) (struct usb_hcd *hcd);
180
181     /* return current frame number */
182     int  (*get_frame_number) (struct usb_hcd *hcd);
183
184    /* manage i/o requests, device state */
185     int  (*urb_enqueue) (struct usb_hcd *hcd,
186                          struct usb_host_endpoint *ep,
187                          struct urb *urb,
188                          gfp_t mem_flags);
189     int  (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
190
191     /* hw synch, freeing endpoint resources that urb_dequeue can't */
192     void  (*endpoint_disable)(struct usb_hcd *hcd,
193               struct usb_host_endpoint *ep);
194
195     /* root hub support */
196     int       (*hub_status_data) (struct usb_hcd *hcd, char *buf);
197     int       (*hub_control) (struct usb_hcd *hcd,
198                      u16 typeReq, u16 wValue, u16 wIndex,
199                      char *buf, u16 wLength);
200     int       (*bus_suspend)(struct usb_hcd *);
201     int       (*bus_resume)(struct usb_hcd *);
202     int   (*start_port_reset)(struct usb_hcd *, unsigned port_num);
203     void      (*hub_irq_enable)(struct usb_hcd *);
204           /* Needed only if port-change IRQs are level-triggered */
205 };

与usb_driver和pci_driver一样,所有的“xxx_driver”都有一堆函数指针,具体的主机控制器驱动就靠它们,这里只说函数指针之外的东西。

description直白点儿说就是驱动的大名,比如对于UHCI,它是“uhci_hcd”,对于EHCI,它就是“ehci_hcd”。product_desc和struct usb_hcd里的是一样。hcd_priv_size还是有点儿意思的,每个主机控制器驱动都会有一个私有结构体,藏在struct usb_hcd最后的那个变长数组里,这个“变”也是相对的,在创建usb_hcd时也得知道它能变多长,不然谁知道要申请多少内存,这个长度就hcd_priv_size。

81行,flags,属于HCD的一些标志,可用值就在82行和83行。它们什么意思?书到用时方恨少,flags到用时才可知。

69行,70行,85行到91行,这几行都是专为root hub服务的。一个主机控制器对应一个Root Hub,即使在嵌入式系统里,硬件上主机控制器没有集成Root Hub,软件上也需要虚拟一个出来,也就是所谓的Virtual Root Hub。

它位置是特殊的,但需要提供的功能和其他Hub是没有什么差别的,仅仅是在和主机控制器的软硬件接口上有一些特别的规定。Root Hub再怎么特别也始终是一个Hub,是一个USB设备,也不能脱离USB这个大家庭,也要向组织注册,也要有自己的设备生命线。

92行,wireless,无线USB。

94行到97行这几行都是与主机控制器的“娘家”PCI有关的,说到PCI就不得不说到如图1.20.1所示的那张著名的表。

图1.20.1 PCI配置寄存器

在这张表里中断号等很多有用的东西都在里面准备好了。94行的irq就躲在上面表儿里的倒数第四个Byte,HCD可以直接拿来用,根本就不用再去申请。接下来的regs,rsrc_start,rsrc_len就与中间的Base Address0~5脱不开关系了,牵涉到所谓的I/O内存和I/O端口,下面简单介绍一下。

大家都知道CPU是众人瞩目的焦点,但是它也不可能一个人完成工作,计算机运转是一个集体项目,CPU也需要跟各种外设配合交流,它需要访问外设里的寄存器或者内存。

CPU的差别主要表现在空间的差别。一些CPU芯片有两个空间,即I/O空间和内存空间,提供有专门访问外设I/O端口的指令;而另外一些CPU只有一个空间,即内存空间。外设的I/O端口可以映射在I/O空间也可以映射到内存空间,CPU通过访问这两个空间来访问外设,I/O空间有I/O空间访问的接口,内存空间有内存空间访问的接口。当然一些外设不但有寄存器,还有内存,也就是I/O内存,比如EHCI/OHCI,它们需要映射到内存空间。但是不管映射到哪个空间,访问I/O端口还是I/O内存,CPU必须知道它们映射后的地址,不然没有办法配合交流。

在图1.20.1中,中间的那些基地址就是保存PCI设备中I/O内存或I/O端口的首尾位置还有长度。驱动使用时要首先把它们给读出来,如果要映射到I/O空间,则要根据读到的值向系统申请I/O端口资源,如果要映射到内存空间,除了要申请内存资源,还要使用ioremap等进行映射。

96行的rsrc_start和97行的rsrc_len保存的就是从表里读出来的主机控制器的I/O端口或内存的首地址和长度,95行的regs保存的是调用ioremap_nocache映射后的内存地址。

98行,power_budget,能够提供的电流。

101行,*pool [HCD_BUFFER_POOLS],几个dma池。因为HCD_BUFFER_POOLS在100行定义为4,所以这里就表示每个主机控制器可以有4个dma池。

我们知道主机控制器是可以进行DMA传输的,再回到前面讲的struct urb,它有两个成员,transfer_dma和setup_dma,前面只是说可以使用usb_buffer_alloc分配好DMA缓冲区给它们,然后再告诉HCD urb已经有了,HCD就可以不用再进行复杂的DMA映射了。但并没有提到这个获取的DMA缓冲区是从哪里来的。这里所说的DMA池子里来的了。

像创建或销毁线程、数据库连接时比较消耗资源,可以先建一个池子预先创建好一批线程放里面,用时就从里面取出来,不用时就再放里面。

当然,DMA池还有其他的作用。一般来说DMA映射获得的都是以页为单位的内存,urb不需要这么大的,如果需要比较小的DMA缓冲区,就离不开DMA池了。还是查看主机控制器的这几个池子在buffer.c文件中是怎么创建的。

52 int hcd_buffer_create(struct usb_hcd *hcd)
53 {
54     char    name[16];
55     int     i, size;
56
57     if (!hcd->self.controller->dma_mask)
58         return 0;
59
60     for (i = 0; i < HCD_BUFFER_POOLS; i++) {
61         if (!(size = pool_max [i]))
62             continue;
63         snprintf(name, sizeof name, "buffer-%d", size);
64         hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
65             size, size, 0);
66         if (!hcd->pool [i]) {
67             hcd_buffer_destroy(hcd);
68             return -ENOMEM;
69         }
70      }
71      return 0;
72 }

这里首先要判断这个主机控制器支持不支持DAM,如果不支持的话再创建DMA池就是纯粹无稽之谈了。如果主机控制器支持DMA,就逐个使用dma_pool_alloc来创建DMA池,如果创建失败了,就调用同一个文件中的hcd_buffer_destroy来将已经创建成功的池子给销毁掉。

82 void hcd_buffer_destroy(struct usb_hcd *hcd)
83 {
84      int     i;
85
86      for (i = 0; i < HCD_BUFFER_POOLS; i++) {
87          struct dma_pool   *pool = hcd->pool[i];
88          if (pool) {
89             dma_pool_destroy(pool);
90             hcd->pool[i] = NULL;
91         }
92     }
93 }

这里调用的dma_pool_destroy和dma_pool_alloc。每个DMA池子都要找到四个函数,一个用来创建,一个用来销毁,一个用来取内存,一个用来放内存。上面只遇到了创建和销毁的函数,还少两个取内存和放内存的函数,再去同一个文件中找一找。

100 void *hcd_buffer_alloc(
101     struct usb_bus *bus,
102     size_t      size,
103     gfp_t       mem_flags,
104     dma_addr_t     *dma
105 )
106 {
107    struct usb_hcd    *hcd = bus_to_hcd(bus);
108    int       i;
109
110    /* some USB hosts just use PIO */
111    if (!bus->controller->dma_mask) {
112        *dma = ~(dma_addr_t) 0;
113        return kmalloc(size, mem_flags);
114    }
115
116    for (i = 0; i < HCD_BUFFER_POOLS; i++) {
117        if (size <= pool_max [i])
118        return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
119     }
120     return dma_alloc_coherent(hcd->self.controller, size, dma, 0);
121 }
122
123 void hcd_buffer_free(
124     struct usb_bus *bus,
125     size_t        size,
126     void          *addr,
127     dma_addr_t     dma
128 )
129 {
130     struct usb_hcd    *hcd = bus_to_hcd(bus);
131     int             i;
132
133     if (!addr)
134         return;
135
136     if (!bus->controller->dma_mask) {
137         kfree(addr);
138         return;
139     }
140
141     for (i = 0; i < HCD_BUFFER_POOLS; i++) {
142        if (size <= pool_max [i]) {
143            dma_pool_free(hcd->pool [i], addr, dma);
144            return;
145        }
146     }
147     dma_free_coherent(hcd->self.controller, size, addr, dma);
148 }

又可以找到两个函数,即dma_pool_alloc和dma_pool_free函数,现在可以凑齐四个函数了。不过不用管它们四个到底什么长相,只要它们能够干活儿就成了,这里要注意的是以下几个问题。

第一个问题是即使你的主机控制器不支持DMA,这几个函数也是可以用的,只不过创建的不是DMA池子,存取的也不是DMA缓冲区。此时,DMA池子不存在,hcd_buffer_alloc获取的只是适用kmalloc申请的普通内存。当然,你必须在它没有利用价值时使用hcd_buffer_free将它释放掉。

第二个问题是size的问题,它们里面都有一个pool_max,这是个同一个文件中定义的数组。

26 static const size_t  pool_max [HCD_BUFFER_POOLS] = {
27     /* platfor ms without dma-friendly caches might need to
28      * prevent cacheline sharing...
29      */
30      32,
31      128,
32      512,
33      PAGE_SIZE / 2
34      /* bigger --> allocate pages */
35 };

这个数组中定义的就是四个池子中每个池子里保存的DMA缓冲区的size。注意这里虽说只定义了四种size,但是并不说明你使用hcd_buffer_alloc获取DMA缓冲区时不能指定更大的size,如果这几个池子都满足不了要求,那就会使用dma_alloc_coherent建立一个新的DMA映射。还有,每个人的情况都不一样,不可能都会完全恰好和上面定义的四种size一致,那也不用怕,使用这个size获取DMA缓冲区时,池子会选择一个略大一些的回馈过去。

还是回到struct usb_hcd中来。103行,state,主机控制器的状态,紧挨着它的下面那些代码就是相关的可用值和宏定义。