⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtdptd.c

📁 usb isp1761驱动源代码 可编进内核。
💻 C
📖 第 1 页 / 共 3 页
字号:
phci_hcd_submit_async(
        phci_hcd *hcd, 
	struct usb_host_endpoint *ep,
        struct list_head *qtd_list, 
        struct urb *urb,
        int *status)


{
    struct ehci_qtd             *qtd;
    struct hcd_dev             *dev;
    int                         epnum;
    unsigned long               flags;
    struct ehci_qh              *qh = 0;

    urb_priv_t  *urb_priv = urb->hcpriv;


    qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
    dev = (struct hcd_dev *) bus_to_hcd(urb->dev->bus);
    epnum = usb_pipeendpoint (urb->pipe);
    if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe))
        epnum |= 0x10;

    pehci_entry("++ %s, enter\n", __FUNCTION__);    



    /* ehci_hcd->lock guards shared data against other CPUs:
     *   ehci_hcd:      async, reclaim, periodic (and shadow), ...
     *   hcd_dev:       ep[]

     *   ehci_qh:       qh_next, qtd_list

     *   ehci_qtd:      qtd_list
     *
     * Also, hold this lock when talking to HC registers or
     * when updating hw_* fields in shared qh/qtd/... structures.
     */

    spin_lock_irqsave (&hcd->lock, flags);
    spin_lock(&hcd_data_lock);
    qh = phci_hcd_qh_append_tds (hcd, ep, urb, qtd_list, &ep->hcpriv,status);
    if(!qh  || *status < 0)
        goto cleanup;
    /* Control/bulk operations through TTs don't need scheduling,
     * the HC and TT handle it when the TT has a buffer ready.
     */

    /* now the quehead can not be in the unlink state paranoid ??? */

    if(qh->qh_state == QH_STATE_UNLINK){
        pehci_info("%s: free the urb,qh->state %x\n",__FUNCTION__, qh->qh_state);
        phci_hcd_qtd_list_free (hcd, urb, &qh->qtd_list);
        spin_unlock(&hcd_data_lock);
        spin_unlock_irqrestore (&hcd->lock, flags);
        *status = -ENODEV;
        return 0;
    }

    if (likely (qh != 0)) {
        urb_priv->qh = qh;
        if (likely (qh->qh_state == QH_STATE_IDLE))
            phci_hcd_qh_link_async (hcd, qh,status);
    }

cleanup:        
    spin_unlock(&hcd_data_lock);
    /* free it from lock systme can sleep now */
    spin_unlock_irqrestore (&hcd->lock, flags);
    /* could not get the QH terminate and clean. */
    if (unlikely (qh == 0) || *status < 0) {
        phci_hcd_qtd_list_free (hcd, urb, qtd_list);
        return qh;
    }
    return qh;
}

/*
 * initilaize the s-mask c-mask for
 * interrupt transfers.
 */
static int
phci_hcd_qhint_schedule(
        phci_hcd *hcd, 
        struct ehci_qh *qh,
        struct ehci_qtd *qtd,
        struct _isp1761_qhint *qha,
        struct urb *urb)
{
    int i = 0;
    u32 td_info3 = 0;
    u32 td_info5 = 0;
    u32 period = 0;
    u32 usofmask = 1;
    u32  usof = 0;
    u32 ssplit=0,csplit = 0xFF;
    int maxpacket;
    u32 numberofusofs = 0;

    /*and since whol msec frame is empty, i can schedule in any uframe*/
    maxpacket = usb_maxpacket(urb->dev, urb->pipe,!usb_pipein(urb->pipe));
    maxpacket &= 0x7ff;
    /*length of the data per uframe*/
    maxpacket = XFER_PER_UFRAME(qha->td_info1) * maxpacket;

    /*caculate the number of uframes are required*/
    numberofusofs = urb->transfer_buffer_length/maxpacket;
    /*if something left*/
    if(urb->transfer_buffer_length % maxpacket)
        numberofusofs += 1;

    for(i = 0;i<numberofusofs;i++){
        usofmask <<= i;
        usof |= usofmask;

    }

    /*
       for full/low speed devices, as we 
       have seperate location for all the endpoints
       let the start split goto the first uframe, means 0 uframe
     */
    if(urb->dev->speed != USB_SPEED_HIGH &&
            usb_pipeint(urb->pipe)){
        /*set the complete splits*/
        /*set all the bits and lets see whats happening*/
        /*but this will be set based on the maximum packet size*/
        ssplit = usof;
        /*  need to fix it*/
        csplit = 0x1C;
        qha->td_info6 = csplit;
        period = qh->period;
        if(period >= 32){
            period = qh->period/2;
        }
        td_info3 = period;
        goto done;

    }else{
        if(qh->period >= 8){
            period = qh->period/8;
        }else{
            period = qh->period;
        }
    }
    /*our limitaion is maximum of 32 ie 31, 5 bits*/
    if(period >= 32){
        period  = 32;
        /*devide by 2*/
        period >>= 1;
    }
    if(qh->period >= 8){
        /*millisecond period*/
        td_info3 = (period << 3);
    }else{
        /*usof based tranmsfers*/
        /*minimum 4 usofs*/
        td_info3  = period;
        usof = 0x11;
    }

done:
    td_info5 = usof;
    qha->td_info3 |= td_info3;
    qha->td_info5 |= usof;
    return numberofusofs;
}

/*link interrupts qtds to endpoint*/
struct ehci_qh *
phci_hcd_submit_interrupt(
        phci_hcd *hcd, 
	struct usb_host_endpoint *ep,
        struct list_head *qtd_list, 
        struct urb *urb,
        int *status)
{

    struct ehci_qtd             *qtd;
    struct hcd_dev             *dev;
    int                 epnum;
    unsigned long               flags;
    struct ehci_qh              *qh = 0;
    urb_priv_t  *urb_priv = (urb_priv_t *)urb->hcpriv;


    qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
    dev = (struct hcd_dev *) bus_to_hcd(urb->dev->bus);
    epnum = ep->desc.bEndpointAddress;

    pehci_entry("++ %s, enter\n", __FUNCTION__);    


    /*check for more than one urb queued for this endpoint*/
    qh = ep->hcpriv;

    spin_lock_irqsave (&hcd->lock, flags);
    if(unlikely(qh != 0)){
        if(!list_empty(&qh->qtd_list)){
            *status = -EBUSY;
            goto done;
        } else {
            td_ptd_map_buff_t   *ptd_map_buff;
            td_ptd_map_t                *td_ptd_map;
            ptd_map_buff = &(td_ptd_map_buff[qh->type]);
            td_ptd_map = &ptd_map_buff->map_list[qh->qtd_ptd_index];
            ptd_map_buff->pending_ptd_bitmap |= td_ptd_map->ptd_bitmap; 
            /*NEW*/
            td_ptd_map->qtd = qtd;
            /* maybe reset hardware's data toggle in the qh */
            if (unlikely (!usb_gettoggle (urb->dev, epnum & 0x0f,
                            !(epnum & 0x10)))) {

                /*reset our data toggle*/
                td_ptd_map->datatoggle = 0;
                usb_settoggle (urb->dev, epnum & 0x0f,
                        !(epnum & 0x10), 1);
                qh->datatoggle = 0;
            }
            /* trust the QH was set up as interrupt ... */
            list_splice (qtd_list, &qh->qtd_list);
        }
    }


    if(!qh){
        qh = phci_hcd_make_qh(hcd, urb, qtd_list,status);
        if(likely(qh == 0)){
            *status = -ENOMEM;
            goto done;
        }
        ep->hcpriv = qh;
    }

    if (likely (qh != 0)) {
        urb_priv->qh = qh;
        if (likely (qh->qh_state == QH_STATE_IDLE))
            phci_hcd_qh_link_async (hcd, qh, status);
    }


done:
    /* free it from lock systme can sleep now */
    spin_unlock_irqrestore (&hcd->lock, flags);
    /* could not get the QH terminate and clean. */
    if (unlikely (qh == 0) || *status < 0) {
        phci_hcd_qtd_list_free (hcd, urb, qtd_list);
        return qh;
    }
    return qh;
}




/*
 * converts original EHCI QTD into PTD(philips transfer descriptor)
 * we call PTD as qha also for atl transfers
 * for ATL and INT transfers
 */
void *
phci_hcd_qha_from_qtd(
        phci_hcd        *hcd,
        struct ehci_qtd *qtd,
        struct urb *urb,
        void *ptd,
        u32 ptd_data_addr,
        struct ehci_qh *qh )
{
    u8 toggle = qh->datatoggle;
    u32 token = 0;
    u32         td_info1 = 0;
    u32         td_info3 = 0;
    u32         td_info4 = 0;
    int maxpacket = 0;
    u32 length = 0, temp  = 0;
    /*for non high speed devices*/
    u32     portnum = 0;
    u32     hubnum = 0;
    u32 se = 0,rl = 0xf,nk = 0xf;
    u8 datatoggle = 0;
    struct isp1761_mem_addr *mem_addr = &qtd->mem_addr;
    u32 data_addr = 0;
    u32 multi = 0;
    struct _isp1761_qha *qha = (isp1761_qha*)ptd;
    pehci_entry("++ %s: Entered\n",__FUNCTION__);


    maxpacket = usb_maxpacket(urb->dev,
            urb->pipe,
            usb_pipeout(urb->pipe));

    multi = 1 + ((maxpacket >> 11) & 0x3);

    maxpacket &= 0x7ff;

    /************************first word*********************************/
    length = qtd->length;
    td_info1 = QHA_VALID;
    td_info1 |= (length << 3);
    td_info1 |= (maxpacket << 18);
    td_info1 |= (usb_pipeendpoint(urb->pipe) << 31);
    td_info1 |= MULTI(multi);
    /*set the first dword*/
    qha->td_info1 = td_info1;

    pehci_print("%s: length %d, 1st word 0x%08x\n", __FUNCTION__,length,qha->td_info1);

    /*******************second word***************************************/
    temp = qtd->hw_token;

    /*take the pid, thats of only interest to me from qtd,
     */

    temp = temp & 0x0300;
    temp = temp >> 8;
    /*take the endpoint and its 3 bits*/
    token = (usb_pipeendpoint(urb->pipe) & 0xE) >> 1;
    token |= usb_pipedevice(urb->pipe) << 3;

    if(urb->dev->speed != USB_SPEED_HIGH){
        pehci_print("device is full/low speed, %d\n",urb->dev->speed);
        token |= 1 << 14;
        portnum = urb->dev->ttport;
        /*IMMED*/
        hubnum = urb->dev->tt->hub->devnum;
        token |= portnum << 18;
        token |= hubnum << 25;
        /*for non-high speed transfer
          reload and nak counts are zero
         */  
        rl = 0x0;
        nk = 0x0;

    }

    /*se should be 0x2 for only low speed devices*/
    if(urb->dev->speed == USB_SPEED_LOW)
        se = 0x2;

    if(usb_pipeint(urb->pipe)){
        /*      reload count and nakcount is 
                required for only async transfers
         */
        rl = 0x0;
    }

    /*set the se field, should be zero for all 
      but low speed devices
     */
    token |= se << 16;  
    /*take the pid*/
    token |=  temp << 10;

    if(usb_pipebulk(urb->pipe))
        token  |= EPTYPE_BULK;
    else if(usb_pipeint(urb->pipe))
        token |= EPTYPE_INT;
    else if (usb_pipeisoc(urb->pipe))
        token |= EPTYPE_ISO;


    qha->td_info2 = token;

    pehci_print("%s: second word 0x%08x, qtd token 0x%08x\n",
            __FUNCTION__, qha->td_info2,temp);

    /***********************Third word*************************************/

    /*calculate the data start address from mem_addr for qha*/

    data_addr = ((u32)(mem_addr->phy_addr) & 0xffff) - 0x400;
    data_addr >>= 3;
    pehci_print("data start address %x\n", data_addr);
    /*use this field only if there
     * is something to transfer
     * */
    if(length)  
        td_info3 = data_addr << 8;
    /*RL Count, 16*/
    td_info3 |= (rl << 25);
    qha->td_info3 = td_info3;

    pehci_print("%s: third word 0x%08x, tdinfo 0x%08x\n",
            __FUNCTION__, qha->td_info3,td_info3);


    /**************************fourt word*************************************/

    if(usb_pipecontrol(urb->pipe))
        datatoggle = qtd->hw_token >> 31;
    else
        /*take the data toggle from the previous completed transfer
          or zero in case of fresh*/
        datatoggle = toggle;

    td_info4 = QHA_ACTIVE;
    /*dt*/
    td_info4 |= datatoggle << 25;/*QHA_DATA_TOGGLE; */
    /*3 retry count for setup else forever*/
    if(PTD_PID(qha->td_info2) == SETUP_PID)
        td_info4 |= (3 << 23);
    else
        td_info4 |= (0 << 23);
    /*nak count*/
    td_info4 |= (nk << 19);

    td_info4 |= (qh->ping << 26);
    qha->td_info4 = td_info4;
    pehci_print("%s: fourt word 0x%08x\n",__FUNCTION__, qha->td_info4);
    pehci_entry("-- %s: Exit, qha %p\n",__FUNCTION__, qha);
    return qha;

}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -