cy7c67200_300_hcd_simple.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 2,186 行 · 第 1/5 页

C
2,186
字号
    cy_dbg("Enter qu_queue_urb\n");    HWTrace (0x20);    /* for ISOC transfers calculate start frame index */            if (usb_pipeisoc (urb->pipe) && urb->transfer_flags & USB_ISO_ASAP)     {         if (ed->pipe_head)         {            HWTrace (0x21);            urb->start_frame = ed->last_iso;             ed->last_iso = (ed->last_iso + urb->number_of_packets) % 2048;        }        else        {            HWTrace (0x22);            urb->start_frame = cy67x00_get_next_frame_number(cy_priv, port_num);            ed->last_iso = (urb->start_frame + urb->number_of_packets) % 2048;        }    }        if (ed->pipe_head)     {        HWTrace (0x23);        HWData(&urb->urb_list);        HWData(&ed->urb_queue);        list_add_tail(&urb->urb_list, &ed->urb_queue);    }     else     {        HWTrace (0x24);        ed->pipe_head = urb;        qu_queue_active_urb (cy_priv, urb, ed, port_num);        /* kick start the transfer *///        sh_schedule_trans (cy_priv, port_num / 2);    }    return 0;}/*************************************************************************** * Function Name : qu_next_urb * * This function removes the URB from the queue and add the next URB to  * active list.  *  * Input: hci = data structure for the host controller  *        urb = USB request block data structure  *        resub_ok = resubmit flag * * Return: pointer to the next urb   **************************************************************************/static urb_t * qu_next_urb (cy_priv_t * cy_priv, urb_t * urb, int port_num, int resub_ok) {       hci_t * hci = cy_priv->hci;    struct hci_device * hci_dev = usb_to_hci (urb->dev);    epd_t * ed = &hci_dev->ed [qu_pipeindex (urb->pipe)];    urb_t * tmp_urb;    struct list_head * list_lh;    struct list_head * lh;    HWTrace (0x7777);       cy_dbg("enter qu_next_urb\n");    list_del (&urb->urb_list);    if (ed->pipe_head == urb)     {#ifdef HC_URB_TIMEOUT        if (urb->timeout)            del_timer (&ed->timeout);#endif        HWTrace (0x7778);           HWData(hci->port[port_num].active_urbs);        HWTrace (0x7779);           if (!list_empty (&ed->urb_queue))         {            HWTrace (0x8000);               HWData(&ed->urb_queue);            list_lh = &ed->urb_queue;            lh = list_lh->next;            tmp_urb = list_entry (lh, urb_t, urb_list);            HWTrace (0x8001);               HWData(&tmp_urb->urb_list);            HWTrace (0x8002);               list_del (&tmp_urb->urb_list);            HWTrace (0x8003);               ed->pipe_head = tmp_urb;            HWTrace (0x8004);               qu_queue_active_urb (cy_priv, tmp_urb, ed, port_num);            HWTrace (0x8005);               cy_dbg("qu_next_urb: queue next active urb, iso = %c\n", usb_pipeisoc(tmp_urb->pipe)?'Y':'N' );        }         else         {            HWTrace (0x8007);               ed->pipe_head = NULL;            tmp_urb = NULL;            cy_dbg("qu_next_urb: queue is empty!\n");        }    }    HWTrace (0x8008);    return tmp_urb;}/*************************************************************************** * Function Name : qu_return_urb * * This function is part of the return path.    *  * Input: hci = data structure for the host controller  *        urb = USB request block data structure  *        resub_ok = resubmit flag * * Return: pointer to the next urb   **************************************************************************/static urb_t * qu_return_urb (cy_priv_t * cy_priv, urb_t * urb, int port_num, int resub_ok) {        urb_t * next_urb;    cy_dbg("enter qu_return_rub\n");    next_urb = qu_next_urb (cy_priv, urb, port_num, resub_ok);    hcs_return_urb (cy_priv, urb, port_num, resub_ok);    return next_urb;    }int sh_calc_urb_bitTime(urb_t * urb){    int bitTime = 0;    bitTime = 8 * (urb->transfer_buffer_length - urb->actual_length);        if (bitTime > MAX_FRAME_BW)    {       bitTime = MAX_FRAME_BW;    }    return (bitTime);}/*************************************************************************** * Function Name : sh_add_urb_to_frame * * This function adds the urb to the current USB frame.  There can be  * multiple USB transactions associated with the URB.  Providing that  * the transfer_buffer_length - actual_length can be big.  Therefore we * have to include all USB transaction associated with the URB in this frame * Therefore, the URB  will add to the frame list if the  * max packet size + current frame BW < EOT  *  * Input: hci = data structure for the host controller  *        urb = USB request block data structure  * * Return: 1 = successful; bandwidth still available to add more urb  *         0 = unsuccessful; no more bandwidth   **************************************************************************/int sh_add_urb_to_frame(hci_t * hci, urb_t * urb, int port_num){    int sie_num = port_num / 2;    int bitTime;    HWTrace(0xE0);        if (urb == NULL)    {        HWTrace(0xE2);        return 0;    }        bitTime = 8 * usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));    /* CHECK total BANDWIDTH */    if ((bitTime + hci->sie[sie_num].bandwidth_allocated) > MAX_FRAME_BW)    {        /* no bandwidth left in the frame, don't schedule it */        return -1;    }        switch (usb_pipetype (urb->pipe))     {        case PIPE_ISOCHRONOUS:          case PIPE_INTERRUPT:                /* Check for periodic bandwidth */                if ((hci->sie[sie_num].periodic_bw_allocated + bitTime) > MAX_PERIODIC_BW)        {            return -1;        }        else        {            hci->sie[sie_num].periodic_bw_allocated += sh_calc_urb_bitTime(urb);        }    }    hci->sie[sie_num].bandwidth_allocated += sh_calc_urb_bitTime(urb);     /* Break the urb from the urb chain */    list_del(&urb->urb_list);             /* Add the urb to the frame list */        list_add_tail(&urb->urb_list, &hci->port[port_num].frame_urb_list);     HWTrace(0xE1);    return bitTime;}boolean  sh_check_frame_bw(hci_t * hci, int sie_num, int len){    int bitTime = len * 8;    int alloc_bw =  hci->sie[sie_num].bandwidth_allocated;    if ((alloc_bw + bitTime ) >= MAX_FRAME_BW) {        HWTrace(0x900);//      cy_dbg("sh_check_fram_bw: alloc_bw = 0x%X, bitTime = 0x%X\n",alloc_bw, bitTime);    }    return((alloc_bw + bitTime) < MAX_FRAME_BW); }void sh_claim_frame_bw(hci_t * hci, int sie_num, int len){    int bitTime = len * 8;    hci->sie[sie_num].bandwidth_allocated += bitTime;}void sh_release_frame_bw (hci_t * hci, int sie_num, int len){    int bitTime = len * 8;    hci->sie[sie_num].bandwidth_allocated -= bitTime;}void sh_init_frame_bw (hci_t * hci, int sie_num){    hci->sie[sie_num].bandwidth_allocated = 0;    hci->sie[sie_num].periodic_bw_allocated = 0;}/* This function will convert the URB into the list of TD's and * copies the TD and its data into the CY7C67200/300 memory  */int sh_add_urb_to_TD(cy_priv_t * cy_priv,  urb_t *urb, int port_num){    hci_t * hci = cy_priv->hci;    td_t * td;    int sie_num = port_num / 2;    int len = 0;    int current_len = 0;    int toggle = 0;    int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));    int endpoint = usb_pipeendpoint (urb->pipe);    int address = usb_pipedevice (urb->pipe);    int slow = usb_pipeslow (urb->pipe);    int out = usb_pipeout (urb->pipe);    int pid = 0;    int iso = 0;    int tt = 0;  /* transfer type */    int i;    int frame_num;    HWTrace(0xE00);        if (maxps == 0)         maxps = 8;    /* calculate len, toggle bit and add the transaction */    switch (usb_pipetype (urb->pipe))     {    case PIPE_ISOCHRONOUS:        HWTrace(0xE01);        pid = out ? PID_OUT : PID_IN;        iso = 1;//      frame_num = (hci->port[port_num].frame_number + 1);        frame_num = cy67x00_get_next_frame_number (cy_priv, port_num);        if (frame_num >= urb->start_frame)            i = frame_num - urb->start_frame;        else            i = (frame_num + 2048) - urb->start_frame;                len = urb->iso_frame_desc[i].length > maxps ? maxps :               urb->iso_frame_desc[i].length;        tt = TT_ISOCHRONOUS;        HWData((unsigned short) i);        HWData((unsigned short) urb->start_frame);        HWData((unsigned short) len);        /* Check for bandwidth */        if( sh_check_frame_bw(hci, sie_num, len) &&           (hci->sie[sie_num].last_td_addr + CY_TD_SIZE <             hci->sie[sie_num].tdBaseAddr + SIE_TD_SIZE) &&           (hci->sie[sie_num].last_buf_addr + len <            hci->sie[sie_num].bufBaseAddr + SIE_TD_BUF_SIZE) )        {            /* claim SIE bandwidth */            sh_claim_frame_bw(hci, sie_num, len);            /* allocate the TD */            HWTrace(0xBEF1);            td = (td_t *) kmalloc(sizeof (td_t), GFP_KERNEL);            if (td == NULL)            {                HWTrace(0xEEEE);                cy_err("sh_add_urb_to_TD: unable to allocate TD\n");                return 0;            }            td->last_td_flag = 0;            /* set the external processor data pointer */            td->sa_data_ptr = urb->transfer_buffer + urb->iso_frame_desc[i].offset;                        /* Fill the TD */            fillTd(hci, td, &hci->sie[sie_num].last_td_addr,                    &hci->sie[sie_num].last_buf_addr, address, endpoint, pid,                    len, toggle, slow, tt, port_num);            td->urb = urb;                        /* add the TD to the TD list */            list_add_tail(&td->td_list, &hci->sie[sie_num].td_list_head);               /* update the last_td_addr and last_buf_addr */            hci->sie[sie_num].last_td_addr += CY_TD_SIZE;            hci->sie[sie_num].last_buf_addr += len;        }        break;                case PIPE_CONTROL:        /* Three different types of TDs need to be created each phase of control pipe:         * SETUP, DATA, STATUS          */                 HWTrace(0xE02);        tt = TT_CONTROL;        HWData(urb->interval);        /* Check for Setup Stage */        if ((urb->interval == 0) || (urb->interval == SETUP_STAGE)) {            /* Check for bandwidth */            if( sh_check_frame_bw(hci, sie_num, 8) &&	           (hci->sie[sie_num].last_td_addr + CY_TD_SIZE < 	            hci->sie[sie_num].tdBaseAddr + SIE_TD_SIZE) &&	           (hci->sie[sie_num].last_buf_addr + len <	            hci->sie[sie_num].bufBaseAddr + SIE_TD_BUF_SIZE) )	       	{                sh_claim_frame_bw(hci, sie_num, 8);                /* allocate the TD */                HWTrace(0xBEF2);                td = (td_t *) kmalloc(sizeof (td_t), GFP_KERNEL);                if (td == NULL)                {                    HWTrace(0xEEEE);                    cy_err("sh_add_urb_to_TD: unable to allocate TD\n");                    return 0;                }                td->last_td_flag = 0;                /* Setup packets are 8 bytes in length */                len = 8;                pid = PID_SETUP;                td->sa_data_ptr = (char *) urb->setup_packet;                toggle = 0;                                /* Fill the TD */                fillTd(hci, td, &hci->sie[sie_num].last_td_addr,                        &hci->sie[sie_num].last_buf_addr, address, endpoint, pid,                        len, toggle, slow, tt, port_num);                td->urb = urb;                                td->last_td_flag = SETUP_STAGE;                urb->interval = SETUP_STAGE;                /* add the TD to the TD list */                list_add_tail(&td->td_list, &hci->sie[sie_num].td_list_head);                                   /* update the last_td_addr */                hci->sie[sie_num].last_td_addr += CY_TD_SIZE;                hci->sie[sie_num].last_buf_addr += len;            }            else            {                /* Free the td */                HWTrace(0xE05);            }        }        else if (urb->interval == DATA_STAGE) {            if (urb->transfer_buffer_length != urb->actual_length)            {                current_len = urb->actual_length;                toggle = (current_len & maxps) ? 0 : 1;                while (urb->transfer_buffer_length - current_len)                {                    len = (urb->transfer_buffer_length - current_len) > maxps                           ? maxps : urb->transfer_buffer_length - current_len;                    /* Check for bandwidth */                    if( sh_check_frame_bw(hci, sie_num, len) &&			           (hci->sie[sie_num].last_td_addr + CY_TD_SIZE < 			            hci->sie[sie_num].tdBaseAddr + SIE_TD_SIZE) &&			           (hci->sie[sie_num].last_buf_addr + len <			            hci->sie[sie_num].bufBaseAddr + SIE_TD_BUF_SIZE) )			       	{                        sh_claim_frame_bw(hci, sie_num, len);                        /* allocate the TD */                        HWTrace(0xBEF3);                        td = (td_t *) kmalloc(sizeof (td_t), GFP_KERNEL);                        if (td == NULL)                        {                            HWTrace(0xEEEE);                            cy_err("sh_add_urb_to_TD: unable to allocate TD\n");                            return 0;                        }                        td->last_td_flag = 0;                        pid = out ? PID_OUT : PID_IN;                                                   /* set the external processor data pointer */                        td->sa_data_ptr = urb->transfer_buffer + current_len;

⌨️ 快捷键说明

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