Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531242
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-07-19 10:53:47

<以下内容来自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) |
给主人留下些什么吧!~~