struct usb_hcd {
/*
* housekeeping
*/
struct usb_bus self; /* hcd is-a bus */
struct kref kref; /* reference counter */
const char *product_desc; /* 主机控制器的产品描述字符串,对于UHCI,它为“UHCI Host Controller */
/*这里边儿保存的是“ehci-hcd:usb1”之类的字符串,也就是驱动的大名再加上总线编号。*/
char irq_descr[24];
struct timer_list rh_timer; /* drives root-hub polling */
struct urb *status_urb; /* the current status urb */
#ifdef CONFIG_PM
struct work_struct wakeup_work; /* for remote wakeup */
#endif
/*
* hardware info/state
*/
const struct hc_driver *driver; /* hw-specific hooks */
/* Flags that need to be manipulated atomically */
unsigned long flags;
#define HCD_FLAG_HW_ACCESSIBLE 0x00000001
#define HCD_FLAG_SAW_IRQ 0x00000002
unsigned rh_registered:1;/* is root hub registered? */
/* The next flag is a stopgap, to be removed when all the HCDs
* support the new root-hub polling mechanism. */
unsigned uses_new_polling:1;
unsigned poll_rh:1; /* poll for rh status? */
unsigned poll_pending:1; /* status has changed? */
unsigned wireless:1; /* Wireless USB HCD */
//wireless,是不是无线usb
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
u64 rsrc_start; /* memory/io resource start 是从表里读出来的host controller 的I/O 端口或内存的首地址*/
u64 rsrc_len; /* memory/io resource length 从表里读出来的host controller 的I/O 端口或内存的长度*/
unsigned power_budget; /* in mA, 0 = no limit 能够提供的电流*/
#define HCD_BUFFER_POOLS 4 //表示每个主机控制器可以有4 个dma 池
struct dma_pool *pool [HCD_BUFFER_POOLS];
int state;
# define __ACTIVE 0x01
# define __SUSPEND 0x04
# define __TRANSIENT 0x80
# define HC_STATE_HALT 0
# define HC_STATE_RUNNING (__ACTIVE)
# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT)
# define HC_STATE_SUSPENDED (__SUSPEND)
#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
/* more shared queuing code would be good; it should support
* smarter scheduling, handle transaction translators, etc;
* input size of periodic table to an interrupt scheduler.
* (ohci 32, uhci 1024, ehci 256/512/1024).
*/
/* The HC driver's private data is stored at the end of
* this structure.
*/
unsigned long hcd_priv[0]
__attribute__ ((aligned (sizeof(unsigned long))));
};
int hcd_buffer_create(struct usb_hcd *hcd)
{
char name[16];
int i, size;
if (!hcd->self.controller->dma_mask)
return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (!(size = pool_max [i]))
continue;
snprintf(name, sizeof name, "buffer-%d", size);
hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
size, size, 0);
if (!hcd->pool [i]) {
hcd_buffer_destroy(hcd);
return -ENOMEM;
}
}
return 0;
}
首先要判断下这个主机控制器支持不支持DAM,如果支持DMA,就逐个适用dma_pool_alloc 来创建DMA 池,如果创建失败了,就调用同一个文件里的hcd_buffer_destroy 来将已经创建成功的池子给销毁掉。
void hcd_buffer_destroy(struct usb_hcd *hcd)
{
int i;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
struct dma_pool *pool = hcd->pool[i];
if (pool) {
dma_pool_destroy(pool);
hcd->pool[i] = NULL;
}
}
}
一个用来取内存,一个用来释放内存。
void *hcd_buffer_alloc(struct usb_bus *bus,size_t size,gfp_t mem_flags,dma_addr_t *dma)
{
struct usb_hcd *hcd = bus_to_hcd(bus);
int i;
/* some USB hosts just use PIO */
if (!bus->controller->dma_mask) {
*dma = ~(dma_addr_t) 0;
return kmalloc(size, mem_flags);
}
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (size <= pool_max [i])
return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
}
return dma_alloc_coherent(hcd->self.controller, size, dma, 0);
}
void hcd_buffer_free(struct usb_bus *bus,size_t size,void *addr,dma_addr_t dma)
{
struct usb_hcd *hcd = bus_to_hcd(bus);
int i;
if (!addr)
return;
if (!bus->controller->dma_mask) {
kfree(addr);
return;
}
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (size <= pool_max [i]) {
dma_pool_free(hcd->pool [i], addr, dma);
return;
}
}
dma_free_coherent(hcd->self.controller, size, addr, dma);
}