cy7c67200_300_hcd_simple.c

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

C
2,186
字号
                        /* 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 = DATA_STAGE;                                                /* add the TD to the TD list */                        list_add_tail(&td->td_list, &hci->sie[sie_num].td_list_head);                           /* Clear td pointer */                        td = NULL;                        /* update the last_td_addr */                        hci->sie[sie_num].last_td_addr += CY_TD_SIZE;                        hci->sie[sie_num].last_buf_addr += len;                        current_len += len;                        toggle = !toggle;                    }                    else                    {                        HWTrace(0xE07);                        break;                    }                }            }            else            {                HWTrace(0xE77);            }        }        else if (urb->interval == STATUS_STAGE) {            /* Check for bandwidth */            if( sh_check_frame_bw(hci, sie_num, 1) &&	           (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, 1);                /* allocate the TD */                HWTrace(0xBEF4);                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;                len = 0;                pid = !out ? PID_OUT : PID_IN;                 toggle = 1;                usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),                 usb_pipeout (urb->pipe), toggle);                /* set the external processor data pointer: arbitrary pick it */                td->sa_data_ptr = urb->setup_packet;                /* 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 = STATUS_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            {                HWTrace(0xE10);            }        }        else        {            /* Assume error */            HWTrace(0xE11);        }        break;    case PIPE_BULK: /* BULK and BULK0 */        HWTrace(0xE12);		/* Intentional fall through */    case PIPE_INTERRUPT:        HWTrace(0xE13);        current_len = urb->actual_length;        toggle = usb_gettoggle (urb->dev, endpoint, out);        pid = out ? PID_OUT : PID_IN;        if (usb_pipetype(urb->pipe) == PIPE_BULK)        {            tt = TT_BULK;        }           else        {            tt = TT_INTERRUPT;        }        while ((urb->transfer_buffer_length - current_len) > 0)        {            len = ((urb->transfer_buffer_length - current_len) > maxps) ?                 maxps : (urb->transfer_buffer_length - current_len);            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(0xBEF5);                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 + current_len;                                /* 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);                   /* Clear td pointer */                td = NULL;                /* update the last_td_addr */                hci->sie[sie_num].last_td_addr += CY_TD_SIZE;                hci->sie[sie_num].last_buf_addr += len;                current_len+= len;                toggle = !toggle;            }            else             {                HWTrace(0xE14);                break;            }        }    }     HWTrace(0xE15);    return 1;}/*************************************************************************** * Function Name : sh_execute_td * * This function copies the TD and its associated data into cy7c67200/300.    *  * Input: cy_priv = data structure for the host controller  *        td  = pointer to a TD * * Return: 1 = successful; bandwidth still available to add more urb  *         0 = unsuccessful; no more bandwidth   **************************************************************************/int sh_execute_td(cy_priv_t * cy_priv, td_t * td, int td_addr, int sie_num){    char * pdata = td->sa_data_ptr;    int len = td->port_length & TD_PORTLENMASK_DL;    /* copy the data to cy7c67200/300 */	/* Note:  Do not write data for a read */	if ((td->pid_ep & TD_PIDEPMASK_PID) != TD_PID_IN)	{	    lcd_write_memory(td->ly_base_addr, len, pdata, cy_priv);	}    /* copy the TD to cy7c67200/300 */    lcd_write_memory(td_addr, CY_TD_SIZE, (char *) td, cy_priv);    return 0;}int sh_process_frame(cy_priv_t * cy_priv, int sie_num){    hci_t * hci = cy_priv->hci;    td_t * td;    int td_addr = 0;    struct list_head * lh = &hci->sie[sie_num].td_list_head;    unsigned short int_enbl = 0;        HWTrace(0xD0);        lh = lh->next;    if (list_empty(lh))    {        hci->sie[sie_num].td_active = FALSE;        /* Empty List: nothing to do, exit */        HWTrace(0xD1);        return 0;    }    td_addr = hci->sie[sie_num].tdBaseAddr;    /* Check for wrap around condition of the doubly linked list */    while (lh != &hci->sie[sie_num].td_list_head)    {        td = list_entry(lh, td_t, td_list);        if (td== NULL)        {            HWTrace(0xD2);            return 0;        }                if (lh->next == &hci->sie[sie_num].td_list_head)        {            /* This is the last TD in the TD list */            /* so put the td.next_td_addr to be null to indicate the last td */            td->next_td_addr = 0;        }                /* copy data and TD to Lyberty */        sh_execute_td(cy_priv, td, td_addr, sie_num);                        /* get the next td address */        td_addr = td->next_td_addr;                      /* get the next TD */        lh = lh->next;    }    hci->sie[sie_num].td_active = TRUE;    /* set the TD pointer in Lyberty */    if (sie_num == SIE0)    {        lcd_write_reg(HUSB_SIE1_pCurrentTDPtr, hci->sie[sie_num].tdBaseAddr, cy_priv);    }    else    {        lcd_write_reg(HUSB_SIE2_pCurrentTDPtr, hci->sie[sie_num].tdBaseAddr, cy_priv);    }    HWTrace(0xD4);       return (1);}/*************************************************************************** * Function Name : sh_scan_urb_list * * This function goes through the urb list and schedule the  * the transaction.    *  * Input: hci = data structure for the host controller  *        list_lh = pointer to the isochronous list  * * Return: 0 = unsuccessful; 1 = successful   **************************************************************************/static int sh_scan_urb_list (cy_priv_t * cy_priv, struct list_head * list_lh, int port_num) {    hci_t * hci = cy_priv->hci;    struct list_head * lh = list_lh->next;    urb_t * urb;    int frame_num = 0;    int index = 0;    HWTrace(0xF0);    HWData(port_num);    HWData((unsigned short) list_lh);    if (list_lh == NULL)    {        HWTrace(0xF1);        cy_err("sh_scan_urb_list: error, list_lh == NULL\n");        return 1;    }    while (lh != list_lh)    {        HWTrace(0xF00);        HWData((unsigned short) lh);        if (lh == NULL)        {            HWTrace(0xF11);            cy_err("sh_scan_urb_list: error, lh == NULL\n");            return 1;        }        urb = list_entry (lh, urb_t, urb_list);		if (lh == lh->next)		{            HWTrace(0xFEEE);            cy_err("sh_scan_urb_list: error, loop found!\n");            return 1;		}        lh = lh->next;         if (urb == NULL)        {            HWTrace(0xF2);            return 1;        }        HWTrace(0xF22);//      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)        {                                                                  index = frame_num - urb->start_frame;        }        else        {            index = (frame_num + 2048) - urb->start_frame;        }          switch (usb_pipetype (urb->pipe))         {        case PIPE_ISOCHRONOUS:              HWTrace(0xF05);/* Debug */            HWData((unsigned short) index);            HWData((unsigned short) urb->number_of_packets);            HWData((unsigned short) urb->start_frame);            HWData((unsigned short) frame_num);/* Debug */            if (index < urb->number_of_packets)            {                /* add the urb to to the frame list */                if (!sh_add_urb_to_TD (cy_priv, urb, port_num))                {                    HWTrace(0xF4);                    return 0;                }                else                 {                    /* Successful added to the TD,                      * now update the urb->start_frame *///                  urb->start_frame = hci->port[port_num].frame_number;                    HWTrace(0xF5);                }             }            break;        case PIPE_INTERRUPT:            HWTrace(0xF06);/* Debug */            HWData((unsigned short) index);            HWData((unsigned short) urb->interval);            HWData((unsigned short) urb->start_frame);            HWData((unsigned short) frame_num);/* Debug */            if (index >= urb->interval)            {                /* add the urb to to the frame list */                if (!sh_add_urb_to_TD (cy_priv, urb, port_num))                {                    HWTrace(0xF6);                    return 0;                }                else                 {                    /* Successful added to the TD,                      * now update the urb->start_frame *///                  urb->start_frame = hci->port[port_num].frame_number;                    urb->start_frame = cy67x00_get_current_frame_number(cy_priv, port_num);                    HWTrace(0xF7);                }             }            break;        case PIPE_CONTROL:        case PIPE_BULK:                        /* add the urb to to the frame list */            if (!sh_add_urb_to_TD (cy_priv, urb, port_num))            {                HWTrace(0xF8);                return 0;            }            break;        default:            cy_err("sh_scan_urb_list: unknown pipe %d\n", usb_pipetype(urb->pipe)); 			return 0;        }    }                      HWTrace(0xF9);    return 1;}/* intialize the active TD list */static void sh_init_active_td(cy_priv_t * cy_priv, int sie_num){    hci_t * hci = cy_priv->hci;    struct list_head * td_lh = &hci->sie[sie_num].td_list_head;    td_t * td;    /* Initialize the TD bandwitdh */        sh_init_frame_bw (hci, sie_num);    /* initialize the link list */        if (!list_empty(&hci->sie[sie_num].td_list_head))    {        HWTrace(0xeee2);//      cy_err("sh_init_active: the TD List Head in not empty!!\n");        /* Remove any remaining td's */        td_lh = td_lh->next;        while (td_lh != &hci->sie[sie_num].td_list_head)        {            td = list_entry(td_lh, td_t, td_list);

⌨️ 快捷键说明

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