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