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

📄 pehci.c

📁 usb isp1761驱动源代码 可编进内核。
💻 C
📖 第 1 页 / 共 5 页
字号:
#else
    else{
        return;
    }

#endif


    ormask = isp1761_reg_read32(hcd->dev, hcd->regs.int_irq_mask_or, ormask);
    /*process all the endpoints first those are done*/
    donetoclear = donemap;
    while(donetoclear){
        /*index is the number of endpoints open currently*/
        index = donetoclear & mask;
        donetoclear &= ~mask;
        mask <<= 1;
        /*what if we are in the middle of schedule
          where nothing is done*/
        if(!index ){
            location++;
            continue;
        }

        /*read our td_ptd_map*/
        td_ptd_map = &ptd_map_buff->map_list[location];

        /*if this one is already in the removal*/
        if(td_ptd_map->state == TD_PTD_REMOVE ||
                td_ptd_map->state ==  TD_PTD_NEW){
            pehci_check("interrupt td is being removed\n");
            /*this will be handled by urb_remove*/
            /*if this is last urb no need to complete it again*/
            donemap &= ~td_ptd_map->ptd_bitmap;
            /*if there is something pending*/
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;
            continue;
        }


        /*if we found something already in*/
        if(!(skipmap & td_ptd_map->ptd_bitmap)){
            pehci_check("intr td_ptd_map %x,skipnap %x\n",
                    td_ptd_map->ptd_bitmap,skipmap);
            donemap &= ~td_ptd_map->ptd_bitmap;
            /*in case pending*/
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap; ;
            location++;
            continue;
        }


        if(td_ptd_map->state ==  TD_PTD_NEW){
            pehci_check("interrupt not come here, map %x,location %d\n", td_ptd_map->ptd_bitmap,location);
            donemap &= ~td_ptd_map->ptd_bitmap;
            /*in case pending*/
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;
            donemap &= ~td_ptd_map->ptd_bitmap;
            location++;
            continue;
        }

        /*move to the next schedule*/
        location ++;
        /*endpoint, td, urb and memory
         * for current transfer*/
        qh = td_ptd_map->qh;
        qtd = td_ptd_map->qtd;
        if(qtd->state & QTD_STATE_NEW){
            /*we need to schedule it*/
            goto schedule;
        }
        urb = qtd->urb;
        mem_addr = &qtd->mem_addr;

        /*clear the irq mask for this transfer*/
        ormask &= ~td_ptd_map->ptd_bitmap;
        isp1761_reg_write32(hcd->dev, hcd->regs.int_irq_mask_or, ormask);

        ptd_map_buff->active_ptds--;
        memset(qhint, 0, sizeof(struct _isp1761_qhint));

        /*read this ptd from the ram address,address is in the
          td_ptd_map->ptd_header_addr*/
        isp1761_mem_read(hcd->dev, td_ptd_map->ptd_header_addr,0,(u32 *)(qhint),PHCI_QHA_LENGTH,0);

        /*statuc of 8 uframes*/
        for(i=0;i<8;i++){
            /*take care of errors*/
            usofstatus = qhint->td_info5 >> (8 + i * 3);
            switch(usofstatus & 0x7){
                case INT_UNDERRUN:
                    pehci_print("under run , %x\n", usofstatus);
                    break;
                case INT_EXACT:
                    pehci_print("transaction error, %x\n", usofstatus);
                    break;
                case INT_BABBLE:
                    pehci_print("babble error, %x\n", usofstatus);
                    break;
            }
        }

        if(urb->dev->speed != USB_SPEED_HIGH)
            /*length is 1K for full/low speed device*/
            length = PTD_XFERRED_NONHSLENGTH(qhint->td_info4);
        else
            /*length is 32K for high speed device*/
            length = PTD_XFERRED_LENGTH(qhint->td_info4);

        pehci_hcd_update_error_status(qhint->td_info4, urb);
        /*halted, need to finish all the transfer on this endpoint*/
        if(qhint->td_info4 & PTD_STATUS_HALTED){
            //td_ptd_map->lasttd = 1;
            qtd->state |= QTD_STATE_LAST;
            /*in case of halt, next transfer will start with toggle zero,
             *USB speck, 5.8.5*/
            qh->datatoggle = td_ptd_map->datatoggle = 0;
            donemap &= ~td_ptd_map->ptd_bitmap;
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;
            dontschedule = 1;
            goto copylength;
        }


copylength:
        /*preserve the current data toggle*/
        qh->datatoggle = td_ptd_map->datatoggle = PTD_NEXTTOGGLE(qhint->td_info4);
        /*copy data from the host*/
        switch(PTD_PID(qhint->td_info2)){
            case IN_PID:
                if(length && (length <= MAX_PTD_BUFFER_SIZE))
                    /*do read only when there is somedata*/
                    isp1761_mem_read(hcd->dev,(u32)mem_addr->phy_addr,0,(void*)(le32_to_cpu(qtd->hw_buf[0])),length,0);
            case OUT_PID:
                urb->actual_length += length;
                qh->hw_current = qtd->hw_next;
                phci_hcd_mem_free(&qtd->mem_addr);
                qtd->state &= ~QTD_STATE_NEW;
                qtd->state |= QTD_STATE_DONE;
                break;
        }

        if(qtd->state & QTD_STATE_LAST){
            pehci_hcd_urb_complete(hcd,qh,urb,td_ptd_map);
            if(dontschedule){ /*cleanup will start from drivers*/
                dontschedule = 0;
                continue;
            }

            /*take the next if in the queue*/
            if(!list_empty(&qh->qtd_list)){
                struct list_head *head;
                /*last td of previous urb*/
                head = &qh->qtd_list;
                qtd = list_entry(head->next,struct ehci_qtd, qtd_list);
                td_ptd_map->qtd = qtd;
                qh->hw_current = cpu_to_le32(qtd);
                qh->qh_state = QH_STATE_LINKED;

            }else{
                td_ptd_map->qtd = (struct ehci_qtd *) le32_to_cpu(0);
                qh->hw_current = cpu_to_le32(0);
                qh->qh_state = QH_STATE_TAKE_NEXT;
                donemap &= ~td_ptd_map->ptd_bitmap;
                ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;
                continue;
            }

        }

schedule:    
        {
            /*current td comes from qh->hw_current*/    
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;
            ormask |= td_ptd_map->ptd_bitmap;
            ptd_map_buff->active_ptds++;
            pehci_check("inter schedule next qtd %p, active tds %d\n", qtd,ptd_map_buff->active_ptds);
            pehci_hcd_qtd_schedule(hcd,qtd,qh,td_ptd_map);
        }        

    } /*end of while*/


    /*clear all the tds inside this routine*/
    skipmap &= ~donemap;
    isp1761_reg_write32(hcd->dev, hcd->regs.inttdskipmap, skipmap);
    ormask |= donemap;
    isp1761_reg_write32(hcd->dev, hcd->regs.int_irq_mask_or,ormask);
}

/*atl(bulk/control) transfer handler*/
/*1. read done map
  2. read the ptd to see any errors
  3. copy the payload to and from
  4. update ehci td
  5. make new ptd if transfer there and earlier done
  6. schedule
 */
    static void
pehci_hcd_atl_worker(phci_hcd *hcd)
{
    u32 donemap = 0, donetoclear=0;
    u32 pendingmap = 0;
    u32 rl = 0; 
    u32 mask = 0x1,index = 0;
    u32 location = 0;
    u32 nakcount = 0;
    u32 active = 0;
    u32 length = 0;
    u32 skipmap = 0;
    u32 tempskipmap = 0;        
    u32 ormask=0;
    struct urb *urb;
    struct ehci_qtd *qtd = 0;
    struct ehci_qh *qh;
    struct _isp1761_qha   atlqha;
    struct _isp1761_qha *qha;
    td_ptd_map_t       *td_ptd_map;
    td_ptd_map_buff_t   *ptd_map_buff;
    urb_priv_t          *urbpriv = 0;   
    struct isp1761_mem_addr *mem_addr = 0;
    u32 dontschedule = 0;       

    ptd_map_buff = &(td_ptd_map_buff[TD_PTD_BUFF_TYPE_ATL]);
    pendingmap = ptd_map_buff->pending_ptd_bitmap;

#ifdef MSEC_INT_BASED
    /*running on skipmap rather donemap,
      some cases donemap may not be set 
      for complete transfer
     */                 
    skipmap = isp1761_reg_read32(hcd->dev, hcd->regs.atltdskipmap, skipmap);
    tempskipmap = ~skipmap;
    if(tempskipmap){
        donemap = isp1761_reg_read32(hcd->dev, hcd->regs.atltddonemap,donemap);
        skipmap |= donemap;
        isp1761_reg_write32(hcd->dev, hcd->regs.atltdskipmap, skipmap);
        qha = &atlqha;
        donemap |= pendingmap;
        tempskipmap &= ~donemap;
    }

    /*if sof interrupt enabled*/
    else{
        /*if there is something pending , put this transfer in*/
        if(pendingmap){
            pehci_hcd_schedule_pending_ptds(hcd,pendingmap,(u8)TD_PTD_BUFF_TYPE_ATL,1);
        }
        return;
    }
#else

    donemap = isp1761_reg_read32(hcd->dev, hcd->regs.atltddonemap,donemap);
    if(donemap){
        skipmap = isp1761_reg_read32(hcd->dev, hcd->regs.atltdskipmap, skipmap);
        skipmap |= donemap;
        isp1761_reg_write32(hcd->dev, hcd->regs.atltdskipmap, skipmap);
        qha = &atlqha;
    }
    else{
        return;

    }
#endif

    /*read the interrupt mask registers*/
    ormask = isp1761_reg_read32(hcd->dev, hcd->regs.atl_irq_mask_or, ormask);


    /*this map is used only to update and
     * scheduling for the tds who are not
     * complete. the tds those are complete
     * new schedule will happen from
     * td_ptd_submit_urb routine
     * */
    donetoclear = donemap;
    /*we will be processing skipped tds also*/
    donetoclear |= tempskipmap; 
    /*process all the endpoints first those are done*/
    while(donetoclear){
        /*index is the number of endpoint open currently*/
        index = donetoclear & mask;
        donetoclear &= ~mask;
        mask <<= 1;
        /*what if we are in the middle of schedule
          where nothing is done
         */
        if(!index ){
            location++;
            continue;
        }

        /*read our td_ptd_map*/
        td_ptd_map = &ptd_map_buff->map_list[location];

        /*urb is in remove*/
        if(td_ptd_map->state == TD_PTD_NEW ||
                td_ptd_map->state ==  TD_PTD_REMOVE){
            pehci_check("atl td is being removed,map %x, skipmap %x\n", td_ptd_map->ptd_bitmap, skipmap);
            pehci_check("temp skipmap %x, pendign map %x,done %x\n",tempskipmap, pendingmap,donemap);

            /*unlink urb will take care of this*/
            donemap &= ~td_ptd_map->ptd_bitmap;
            /*in case pending*/
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;
            location++;
            continue;
        }


        /*move to the next endpoint*/
        location ++;
        /*endpoint, td, urb and memory
         * for current endpoint*/
        qh = td_ptd_map->qh;
        qtd = td_ptd_map->qtd;
        if(!qh || !qtd)
        {
            err("Never Error:QH and QTD must not be zero\n");
            donemap &= ~td_ptd_map->ptd_bitmap;
            /*in case pending*/
            ptd_map_buff->pending_ptd_bitmap &= ~td_ptd_map->ptd_bitmap;            
            continue;
        } 
#ifdef MSEC_INT_BASED           
        /*new td must be scheduled*/
        if((qtd->state & QTD_STATE_NEW) /*&&
                                          (pendingmap & td_ptd_map->ptd_bitmap)*/){
            /*this td will come here first time from
             *pending tds, so its qh->hw_current needs to
             * adjusted
             */
            qh->hw_current = QTD_NEXT (qtd->qtd_dma);
            goto schedule;
        }
#endif                  

        urb = qtd->urb;
        urbpriv = (urb_priv_t *)urb->hcpriv;
        mem_addr = &qtd->mem_addr;

#ifdef MSEC_INT_BASED
        /*check here for the td if its done*/
        if(donemap & td_ptd_map->ptd_bitmap){
            /*nothing to do*/
            ;
        }else{
       

⌨️ 快捷键说明

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