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 + -
显示快捷键?