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

📄 itdptd.c

📁 usb isp1761驱动源代码 可编进内核。
💻 C
📖 第 1 页 / 共 3 页
字号:

        /* 
         * Inidicate that we can send a complete split starting from
         * the third uFrame to how much complete split is needed to
         * retrieve all data. 
         *
         * Of course, the first uFrame is reserved for the start split, the
         * second is reserved for the TT to send the request and get some
         * data.
         */      
        qhead->csplit = (usof << 2);
    } /* if(ep_in) */
    else
    {
        /* 
         * For ISO OUT we don't need to send out a complete split 
         * since we do not require and data coming in to us (since ISO
         * do not have integrity checking/handshake).
         *
         * For start split we indicate that we send a start split from the 
         * first uFrame up to the the last uFrame needed to retrieve all
         * data
         */
        qhead->ssplit = usof;
        qhead->csplit = 0;
    } /* else for if(ep_in) */          
    return 0;
}/* phcd_iso_scheduling_info */

/*
 * phcd_iso_itd_fill - Allocate memory from the PAYLOAD memory region
 *
 * phci_hcd *pHcd_st
 *  - Main host controller driver structure
 * struct ehci_itd *itd
 *  - Isochronous Transfer Descriptor, contains elements as defined by the
 *        EHCI standard plus a few more Philips specific elements.
 * struct urb *urb
 *  - USB Request Block, contains information regarding the type and how much data
 *    is requested to be transferred.
 * unsigned long packets
 *  - Total number of packets to completely transfer this ISO transfer request.
 *
 * API Description
 * This is mainly responsible for:
 * - Initialize the following elements of the ITS structure
 *       > itd->length = length;        -- the size of the request
 *       > itd->multi = multi;          -- the number of transactions for 
 *                                         this EP per micro frame
 *       > itd->hw_bufp[0] = buf_dma;   -- The base address of the buffer where 
 *                                         to put the data (this base address was
 *                                         the buffer provided plus the offset)
 * - Allocating memory from the PAYLOAD memory area, where the data coming from
 *   the requesting party will be placed or data requested by the requesting party will
 *   be retrieved when it is available.
 */
unsigned long phcd_iso_itd_fill ( phci_hcd *hcd,
        struct ehci_itd *itd,
        struct urb *urb,
        unsigned long packets
        )
{
    unsigned long length, offset, pipe;
    unsigned long max_pkt, mult;
    dma_addr_t buff_dma;
    struct isp1761_mem_addr *mem_addr;

    iso_dbg(ISO_DBG_ENTRY, "phcd_iso_itd_fill entry\n");
    /* 
     * The value for both these variables are supplied by the one
     * who submitted the URB.
     */
    length = urb->iso_frame_desc[packets].length;
    offset = urb->iso_frame_desc[packets].offset;

    /* Initialize the status and actual length of this packet*/
    urb->iso_frame_desc[packets].actual_length = 0;
    urb->iso_frame_desc[packets].status = -EXDEV;

    /* Buffer for this packet*/
    buff_dma = cpu_to_le32((unsigned char *)urb->transfer_buffer + offset);

    /* Memory for this packet*/
    mem_addr = &itd->mem_addr;

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

    mult = 1 + ((max_pkt >> 11) & 0x3); 
    max_pkt = max_pkt & 0x7FF;  
    max_pkt *= mult;

    if( (length < 0) || (max_pkt < length) )
    {
        iso_dbg(ISO_DBG_ERR,"[phcd_iso_itd_fill Error]: No available memory.\n");
        return -ENOSPC;
    }
    itd->buf_dma = buff_dma;

    /* 
     * Allocate memory in the PAYLOAD memory region for the 
     * data buffer for this ITD
     */
    phci_hcd_mem_alloc(length, mem_addr, 0);
    if( length && ( (mem_addr->phy_addr == 0 ) || 
                (mem_addr->virt_addr == 0) ) )
    {   
        mem_addr = 0;
        iso_dbg(ISO_DBG_ERR, "[phcd_iso_itd_fill Error]: No payload memory available\n");
        return -ENOMEM;
    }

    /* Length of this packet */
    itd->length = length;

    /* Number of transaction per uframe */
    itd->multi = mult;

    /* Buffer address, one ptd per packet */
    itd->hw_bufp[0] = buff_dma;

    iso_dbg(ISO_DBG_EXIT, "phcd_iso_itd_fill exit\n");  
    return 0;
} /* phcd_iso_itd_fill */

/*
 * phcd_iso_get_itd_ptd_index - Allocate an ISO PTD from the ISO PTD map list
 *
 * phci_hcd *hcd
 *      - Main host controller driver structure
 * struct ehci_itd *itd
 *  - Isochronous Transfer Descriptor, contains elements as defined by the
 *        EHCI standard plus a few more Philips specific elements.
 *
 * API Description
 * This is mainly responsible for:
 * - Allocating an ISO PTD from the ISO PTD map list
 * - Set the equivalent bit of the allocated PTD to active
 *   in the bitmap so that this PTD will be included into
 *   the periodic schedule
 */
void phcd_iso_get_itd_ptd_index( phci_hcd *hcd, struct ehci_itd *itd )
{
    td_ptd_map_buff_t *ptd_map_buff;    
    unsigned long buff_type, max_ptds;
    unsigned char itd_index, bitmap;

    /* Local variable initialization */
    bitmap = 0x1;
    buff_type = td_ptd_pipe_x_buff_type[TD_PTD_BUFF_TYPE_ISTL];
    ptd_map_buff = (td_ptd_map_buff_t *) &(td_ptd_map_buff[buff_type]); 
    max_ptds = ptd_map_buff->max_ptds;

    for(itd_index = 0; itd_index < max_ptds; itd_index++) 
    {   
        /* 
         * ISO have 32 PTDs, the first thing to do is look for a free PTD.
         */
        if(ptd_map_buff->map_list[itd_index].state == TD_PTD_NEW) 
        {
            /* 
             * Determine if this is a newly allocated ITD by checking the
             * itd_index, since it was set to TD_PTD_INV_PTD_INDEX during
             * initialization
             */
            if( itd->itd_index == TD_PTD_INV_PTD_INDEX ) 
            {
                itd->itd_index = itd_index;
            }

            /* Once there is a free slot, indicate that it is already taken */
            ptd_map_buff->map_list[itd_index].datatoggle = 0;
            ptd_map_buff->map_list[itd_index].state = TD_PTD_ACTIVE;
            ptd_map_buff->map_list[itd_index].qtd = NULL;

            /* Put a connection to the ITD with the PTD maplist */
            ptd_map_buff->map_list[itd_index].itd  = itd;
            ptd_map_buff->map_list[itd_index].qh = NULL;

            /* ptd_bitmap just holds the bit assigned to this PTD. */            
            ptd_map_buff->map_list[itd_index].ptd_bitmap = bitmap << itd_index;

            phci_hcd_fill_ptd_addresses(&ptd_map_buff->map_list[itd_index], 
                    itd->itd_index, buff_type); 

            /* 
             * Indicate that this ITD is the last in the list and update 
             * the number of active PTDs
             */
            ptd_map_buff->map_list[itd_index].lasttd = 0;
            ptd_map_buff->total_ptds ++;

            /* TO DO: This variable is not used from what I have seen. */                       
            ptd_map_buff->active_ptd_bitmap |= (bitmap << itd_index);
            break;
        }/* if(ptd_map_buff->map_list[itd_index].state == TD_PTD_NEW) */
    }/* for(itd_index = 0; itd_index < max_ptds; itd_index++) */
    return;
}/* phcd_iso_get_itd_ptd_index */

/*
 * phcd_iso_itd_free_list - Free memory used by ITDs in ITD list
 *
 * phci_hcd *hcd
 *      - Main host controller driver structure
 * struct urb *urb
 *  - USB Request Block, contains information regarding the type and how much data
 *    is requested to be transferred.
 * unsigned long status
 *  - Variable provided by the calling routine that contain the status of the 
 *        ITD list.
 *
 * API Description
 * This is mainly responsible for:
 *  - Cleaning up memory used by each ITD in the ITD list
 */
void phcd_iso_itd_free_list( phci_hcd *hcd,
        struct urb *urb,
        unsigned long status
        )
{
    td_ptd_map_buff_t *ptd_map_buff;
    struct ehci_itd *first_itd, *next_itd, *itd;
    td_ptd_map_t *td_ptd_map;

    /* Local variable initialization */
    ptd_map_buff = &(td_ptd_map_buff[TD_PTD_BUFF_TYPE_ISTL]);
    first_itd = (struct ehci_itd *) urb->hcpriv;        
    itd = first_itd;

    /* 
     * Check if there is only one ITD, if so immediately 
     * go and clean it up.
     */
    if(itd->hw_next == EHCI_LIST_END)
    {           
        if(itd->itd_index != TD_PTD_INV_PTD_INDEX)
        {
            td_ptd_map = &ptd_map_buff->map_list[itd->itd_index];
            td_ptd_map->state = TD_PTD_NEW;
        }

        if(status != -ENOMEM)
            phci_hcd_mem_free(&itd->mem_addr);

        list_del (&itd->itd_list);
        qha_free(qha_cache, itd);

        urb->hcpriv = 0;
        return;
    } /* if(itd->hw_next == EHCI_LIST_END) */

    while(1)
    {
        /* Get the ITD following the head ITD */
        next_itd = (struct ehci_itd *) le32_to_cpu(itd->hw_next);
        if(next_itd->hw_next == EHCI_LIST_END)
        {               
            /* 
             * If the next ITD is the end of the list, check if space have 
             * already been allocated in the PTD array.
             */
            if(next_itd->itd_index != TD_PTD_INV_PTD_INDEX)
            {
                /* Free up its allocation */
                td_ptd_map = &ptd_map_buff->map_list[next_itd->itd_index];
                td_ptd_map->state = TD_PTD_NEW;
            }

            /* 
             * If the error is not about memory allocation problems, then
             * free up the memory used.
             */
            if(status != -ENOMEM)       
            {
                iso_dbg(ISO_DBG_ERR,"[phcd_iso_itd_free_list Error]: Memory not available\n");
                phci_hcd_mem_free(&next_itd->mem_addr);
            }

            /* Remove from the ITD list and free up space allocated for ITD structure */
            list_del (&next_itd->itd_list);
            qha_free(qha_cache, next_itd);
            break;
        } /* if(next_itd->hw_next == EHCI_LIST_END)*/ 

        /* 
         * If ITD is not the end of the list, it only means that it already have everything allocated
         * and there is no need to check which procedure failed. So just free all resourcs immediately
         */
        itd->hw_next = next_itd->hw_next;

        td_ptd_map = &ptd_map_buff->map_list[next_itd->itd_index];
        td_ptd_map->state = TD_PTD_NEW;
        phci_hcd_mem_free(&next_itd->mem_addr);
        list_del (&next_itd->itd_list);
        qha_free(qha_cache, next_itd);
    } /*  while(1) */

    /* Now work on the head ITD, it is the last one processed. */
    if(first_itd->itd_index != TD_PTD_INV_PTD_INDEX)
    {
        td_ptd_map = &ptd_map_buff->map_list[first_itd->itd_index];
        td_ptd_map->state = TD_PTD_NEW;
    }

    if(status != -ENOMEM)
    {
        iso_dbg(ISO_DBG_ERR,"[phcd_iso_itd_free_list Error]: No memory\n");
        phci_hcd_mem_free(&first_itd->mem_addr);
    }

    list_del (&first_itd->itd_list);

⌨️ 快捷键说明

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