<以下内容来自at91rm9200.pdf文档"USB主机端口(UHP)">
通过接口通信的基本模块为:端点描述符 (ED, 4 个双字 ) 与传输描述符 (TD, 4 或 8 个双字
)。主机控制器对系统中每个端点分配一个端点描述符。传输队列描述符与具体端点的端点描述
符连接。
由于 USB 主机端口逻辑自动检测器件连接,因此 DP 与 DM 上必须有下拉电阻。否则 USB 主
机将一直检测该端口器件连接。
/*
* OHCI Endpoint Descriptor (ED) ... holds TD queue
* See OHCI spec, section 4.2
*
* This is a "Queue Head" for those transfers, which is why
* both EHCI and UHCI call similar structures a "QH".
*/
struct ed;
/*
* OHCI Transfer Descriptor (TD) ... one per transfer segment
* See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
* and 4.3.2 (iso)
*/
struct td
/* get and maybe (re)init an endpoint. init _should_ be done only as part
* of enumeration, usb_set_configuration() or usb_set_interface().
*/
static struct ed *ed_get (
struct ohci_hcd *ohci,
struct usb_host_endpoint *ep,
struct usb_device *udev,
unsigned int pipe,
int interval
) {
struct ed *ed;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
if (!(ed = ep->hcpriv)) {
struct td *td;
int is_out;
u32 info;
ed = ed_alloc (ohci, GFP_ATOMIC); // 从dma内存区申请一个ed
if (!ed) {
/* out of memory */
goto done;
}
/* dummy td; end of td list for ed */
td = td_alloc (ohci, GFP_ATOMIC);
if (!td) {
/* out of memory */
ed_free (ohci, ed);
ed = NULL;
goto done;
}
ed->dummy = td;
ed->hwTailP = cpu_to_hc32 (ohci, td->td_dma);
ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */
ed->state = ED_IDLE;
is_out = !(ep->desc.bEndpointAddress & USB_DIR_IN); // 端点方向
/* FIXME usbcore changes dev->devnum before SET_ADDRESS
* suceeds ... otherwise we wouldn't need "pipe".
*/
info = usb_pipedevice (pipe); // info 获取管道dev->devnum
// #define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
// 创建pipe如下:
// #define usb_sndbulkpipe(dev,endpoint) \
// ((PIPE_BULK << 30) | __create_pipe(dev, endpoint))0
// static inline unsigned int __create_pipe(struct usb_device *dev,
// unsigned int endpoint)
// {
// return (dev->devnum << 8) | (endpoint << 15);
// }
// 其中dev->devnum为Address on USB bus
// choose_address()
// ==> devnum = find_next_zero_bit(bus->devmap.devicemap, 128
// hub_set_address(udev, devnum); 设置devnum为该端口地址
ed->type = usb_pipetype(pipe); // 该type中含有PIPE_ISOCHRONOUS,PIPE_INTERRUPT,
// PIPE_CONTROL和PIPE_BULK等信息
info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << 7; // info 去掉0x80方向位
info |= le16_to_cpu(ep->desc.wMaxPacketSize) << 16; // info 每包最大传输字节数
if (udev->speed == USB_SPEED_LOW)
info |= ED_LOWSPEED;
/* only control transfers store pids in tds */
if (ed->type != PIPE_CONTROL) { // 非control管道,有IN和OUT的标志
info |= is_out ? ED_OUT : ED_IN;
if (ed->type != PIPE_BULK) {
/* periodic transfers... */
if (ed->type == PIPE_ISOCHRONOUS) // 对于usbhid设备ed->type等于PIPE_INTERRUPT
info |= ED_ISO;
else if (interval > 32) /* iso can be bigger */
interval = 32;
ed->interval = interval; // 对于usbhid设备数,interval值为0x0c等毫秒值[luther.gliethttp]
ed->load = usb_calc_bus_time ( // 生成usb总线带宽负载信息
udev->speed, !is_out,
ed->type == PIPE_ISOCHRONOUS,
le16_to_cpu(ep->desc.wMaxPacketSize))
/ 1000;
}
}
ed->hwINFO = cpu_to_hc32(ohci, info); // 将上面生成的info,放入ed物理hwINFO信息中.
ep->hcpriv = ed;
}
done:
spin_unlock_irqrestore (&ohci->lock, flags);
return ed;
}
阅读(1490) | 评论(0) | 转发(0) |