?? hc_simple_isp116x.c
字號:
} else if ( iso_list_map[1]!=-1 ) { if ( iso_list_map[1]==10 ) { if ( iso_list_map[2]!=-1 ) { if ( iso_list_map[2]==10 ) { return 1; } else { iso_list_p = hci->iso_list.prev->prev->prev; } } else { return 1; } } else { iso_list_p = hci->iso_list.prev->prev; } } else if ( iso_list_map[1]==-1 ) { return 1; } else { printk (KERN_ERR "bug , check iso_list!!, error 2\n"); itl_list_error[2]++; return 1; } urb = list_entry (iso_list_p, struct urb, urb_list); if (frame_number < urb->start_frame) { if ( urb->start_frame > (0xffff-0x10) ) { // do nothing.. } else { return 1; } } itl_add_packet (hci, urb); return 1;}static int itl_add_packet (hci_t *hci, struct urb *urb) { __u8 * data = NULL; int len = 0; int toggle = 0; int type = 0; int maxps; if (usb_pipeisoc(urb->pipe)) { maxps = 1023; } else { 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 ret; int i = 0; int iso = 0; if (maxps == 0) maxps = 8; pid = out ? PID_OUT : PID_IN; iso = 1; if ( iso_list_map[0]<10 && iso_list_map[0]!=-1 ) { i = iso_list_map[0]; } else { i = iso_list_map[1]; } if ( iso_list_map[0]<10 ) { iso_list_map[0]++; } else { iso_list_map[1]++; } data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; len = urb->iso_frame_desc[i].length; type = 1; ret = hc_add_trans (hci, len, data, toggle, maxps, slow, endpoint, address, pid, iso, type); if (ret<0) { printk (KERN_ERR "itl_add_packet error!!\n"); return 1; } return 0;}static int sh_scan_urb_list (hci_t * hci, struct list_head * list_lh){ struct list_head * lh; struct urb * urb; list_for_each (lh, list_lh) { urb = list_entry (lh, struct urb, urb_list); if (!usb_pipeint (urb->pipe) || (((hci->frame_number - urb->start_frame) & 0x7ff) >= urb->interval)) { if (!sh_add_packet (hci, urb)) { return 0; } else { urb->start_frame = hci->frame_number; } } } return 1;}/*-------------------------------------------------------------------------*//* scan lists of active URBs and construct a schedule for a frame * */static int sh_schedule_trans (hci_t * hci){ int units_left; struct list_head * lh; hci->td_array->len = 0; units_left = sh_scan_urb_list (hci, &hci->intr_list); if (units_left) { /* add CTRL transfers */ units_left = sh_scan_urb_list (hci, &hci->ctrl_list); } if (units_left) { /* add BULK transfers */ sh_scan_urb_list (hci, &hci->bulk_list); } /* be fair to each BULK URB (move list head around) */ if (!list_empty (&hci->bulk_list)) { lh = hci->bulk_list.next; list_del (&hci->bulk_list); list_add (&hci->bulk_list, lh); } return 0;}/*-------------------------------------------------------------------------*//* add some parts of the active URB to the schedule * */static int sh_add_packet (hci_t * hci, struct urb * urb){ __u8 * data = NULL; int len = 0; int toggle = 0; int type = 0;// int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); int maxps; if (usb_pipeisoc(urb->pipe)) { maxps = 1023; } else { 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 ret; int i = 0; int iso = 0; if (maxps == 0) maxps = 8; /* calculate len, toggle bit and add the transaction */ switch (usb_pipetype (urb->pipe)) { case PIPE_ISOCHRONOUS: pid = out ? PID_OUT : PID_IN; iso = 1; if (single_itl==0) { i = hci->frame_number - urb->start_frame; } else { i = global_itl; } hci->td_array = &hci->i_td_array [i & 1]; if (i == 1) hci->i_td_array[0].len = 1; data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; len = urb->iso_frame_desc[i].length; type = 1; break; case PIPE_BULK: /* BULK and BULK0 */ case PIPE_INTERRUPT: pid = out ? PID_OUT : PID_IN; len = urb->transfer_buffer_length - urb->actual_length; data = urb->transfer_buffer + urb->actual_length; toggle = usb_gettoggle (urb->dev, endpoint, out); break; case PIPE_CONTROL: switch (qu_urbstate (urb)) { case US_CTRL_SETUP: len = 8; pid = PID_SETUP; data = urb->setup_packet; toggle = 0; break; case US_CTRL_DATA: if (urb->transfer_buffer_length != 0) { pid = out ? PID_OUT : PID_IN; len = urb->transfer_buffer_length - urb->actual_length; data = urb->transfer_buffer + urb->actual_length; toggle = (urb->actual_length & maxps) ? 0 : 1; usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), toggle); break; } else { /* correct state and fall through */ qu_seturbstate (urb, US_CTRL_ACK); } case US_CTRL_ACK: len = 0; /* reply in opposite direction */ pid = !out ? PID_OUT : PID_IN; toggle = 1; usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), toggle); break; } } ret = hc_add_trans (hci, len, data, toggle, maxps, slow, endpoint, address, pid, iso, type); if (ret >= 0) { hci->td_array->td [hci->td_array->len].urb = urb; hci->td_array->td [hci->td_array->len].len = ret; hci->td_array->td [hci->td_array->len].iso_index = i; hci->td_array->len = 1; return 1; } return 0; /* this indicate that we did nothing in hc_add_trans!! */}/***************************************************************************//* parse the hci->itl_list * return the iso urb if it has been done! * *//***************************************************************************/static int itl_done_list (hci_t* hci){ int i = 0; int toggle; int last = 0; int totbytes; int actbytes; int pid; int cc; int active; void * data = NULL; __u8* ptd = NULL; itl_data_t* itl_data_p = NULL; struct list_head* done_list; struct urb* iso_urb; if (!list_empty(&hci->iso_list) ) { iso_urb = list_entry (hci->iso_list.prev, struct urb, urb_list); done_list = hci->itl_list.prev; if ((itl_buffer_die==0 || itl_buffer_die==1) && single_itl==0) { printk (KERN_EMERG "itl_buffer_die happens, start backup\n"); // call this only once immediately while (hci->itl_list.prev!=&hci->itl_list) { // after itl_buffer_die and setup itl_data_p = list_entry (done_list, itl_data_t, list); list_del (done_list); kfree (itl_data_p->data_buf); // we also should delete all itl_list!! kfree (itl_data_p); } single_itl = 1; force_return_flag = 1; force_return_count++; goto force_return; } if (list_empty(&hci->itl_list)) { if (now_sequence > 0) { global_bh_count++; } if (global_bh_count > 10) {// printk (KERN_EMERG "go to force_return!\n"); force_return_flag = 1; force_return_count++; goto force_return; } } while (!list_empty(&hci->itl_list)) { done_list = hci->itl_list.prev; itl_data_p = list_entry (done_list, itl_data_t, list);// i = (itl_data_p->frame_number - iso_urb->start_frame - 2); i = itl_data_p->sequence; now_sequence = itl_data_p->sequence; global_bh_count = 0; if (i<0 || i>=10) { printk (KERN_EMERG "error happen in iso transfer!\n"); printk (KERN_DEBUG "f_n :%d s_f :%d , urb: %p \n",itl_data_p->frame_number, iso_urb->start_frame, iso_urb); list_del (done_list); kfree (itl_data_p->data_buf); kfree (itl_data_p); //FIXME while (1) ; } last_i = i; data = iso_urb->transfer_buffer + iso_urb->iso_frame_desc [i].offset; toggle = 0; ptd = itl_data_p->data_buf; if (ptd<0xc0000000) { kernel_panic_count++; INIT_LIST_HEAD (&hci->itl_list); force_return_flag = 1; force_return_count++; goto force_return; } cc = (ptd [1] >> 4) & 0xf; last = (ptd [3] >> 3) & 0x1; actbytes = ((ptd [1] & 0x3) << 8) | ptd [0]; totbytes = ((ptd [5] & 0x3) << 8) | ptd [4]; pid = (ptd [5] >> 2) & 0x3; if (actbytes > itl_data_p->len) { actbytes = itl_data_p->len; } if (pid == PID_IN && actbytes) memcpy (data, ptd + 8, actbytes); toggle = (ptd [1] >> 2 & 1); if (cc > 0 && cc < 0xE && cc != 9) toggle = !toggle; if (cc) { /* last packet has an error */ if (++iso_urb->error_count > 3 || cc == TD_CC_STALL) { active = 0;// urb_state = 0; /* return */ } else { active = 1; } } else { iso_urb->error_count = 0; } iso_urb->actual_length += actbytes; usb_settoggle (iso_urb->dev, usb_pipeendpoint (iso_urb->pipe), usb_pipeout (iso_urb->pipe), toggle); iso_urb->iso_frame_desc [i].actual_length = actbytes; iso_urb->iso_frame_desc [i].status = cc_to_error [cc]; active = (i < iso_urb->number_of_packets - 1); if (!active ) {force_return: itl_reset = 0; global_bh_count = 0; qu_return_urb (hci, iso_urb, 1); if ( iso_list_map[1]!=-1 ) { iso_list_map[0] = iso_list_map[1]; iso_list_map[1] = iso_list_map[2]; iso_list_map[2] = -1; } else { iso_list_map[0] = -1; // iso_list empty!! } if ( iso_list_map[0]==-1 && ((iso_list_map[1]!=-1)||(iso_list_map[2]!=-1)) ) { itl_list_error[3]++; } if ( iso_list_map[1]==-1 && iso_list_map[2]!=-1 ) { itl_list_error[4]++; } iso_urb = list_entry ( hci->iso_list.prev, struct urb, urb_list); iso_urb->start_frame = ((hci->frame_number + 3)%0x10000); if (force_return_flag==0) { list_del (done_list); kfree (itl_data_p->data_buf); kfree (itl_data_p); } else { force_return_flag = 0; global_bh_count = 0; now_sequence = 0; } goto out; } list_del (done_list); kfree (itl_data_p->data_buf); kfree (itl_data_p); } } else { //just debug information (^V^) if (hci->iso_list.prev==&hci->iso_list && hci->iso_list.next==&hci->iso_list) {// hc_stop_sof_int (hci); } else { if (hci->iso_list.prev!=&hci->iso_list) { printk (KERN_DEBUG "list in prev!!\n"); } else { printk (KERN_DEBUG "list in next!!\n"); } } }out: return 1;} /*-------------------------------------------------------------------------*//* parse the done_list * */static int sh_done_list (hci_t * hci){ int actbytes; int active = 0; void * data = NULL; int cc; int maxps; int toggle; struct urb * urb; int urb_state; int ret = 1; /* -1 parse abbort, 1 parse ok, 0 last element */ int trans = 0; int len; int iso_index = 0; for (trans = 0; ret && trans < hci->td_array->len && trans < MAX_TRANS; trans++) { urb = hci->td_array->td [trans].urb; len = hci->td_array->td [trans].len; if (usb_pipeisoc (urb->pipe)) { iso_index = hci->td_array->td [trans].iso_index; data = urb->transfer_buffer + urb->iso_frame_desc [iso_index].offset; toggle = 0; } else { data = urb->transfer_buffer + urb->actual_length; toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); } urb_state = qu_urbstate (urb); ret = hc_parse_trans (hci, &actbytes, data, &cc, &toggle, len); maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)); if (maxps == 0) maxps = 8; if (cc != TD_NOTACCESSED) { active = (urb_state != US_CTRL_SETUP) && (actbytes && !(actbytes & (maxps - 1)) && (urb->transfer_buffer_length != urb->actual_length + actbytes)); if (!(urb->transfer_flags & USB_DISABLE_SPD) && cc == TD_DATAUNDERRUN) cc = 0; if (cc) { /* last packet has an error */ if (++urb->error_count > 3 || cc == TD_CC_STALL) { active = 0; urb_state = 0; /* return */ } else { active = 1; } } else { urb->error_count = 0; } if (urb_state != US_CTRL_SETUP) { /* no error */ urb->actual_length += actbytes; usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), toggle); } if (usb_pipeisoc (urb->pipe)) { urb->iso_frame_desc [iso_index].actual_length = actbytes; urb->iso_frame_desc [iso_index].status = cc_to_error [cc]; active = (iso_index < urb->number_of_packets - 1); } if (!active) { if (!(urb_state--)) { urb->status = cc_to_error [cc]; qu_return_urb (hci, urb, 1); } else { qu_seturbstate (urb, urb_state); } } } else urb->error_count = 0; } hci->td_array->len = 0; return ret;}/***************************************************************************//* scan the delete list (qu_return_urb removes URB from list) * * *//***************************************************************************/static void sh_del_list (hci_t * hci){ struct list_head * lh = &hci->del_list; struct urb * urb; if (!list_empty (lh)) { do { lh = lh->next; urb = list_entry (lh, struct urb, urb_list); qu_return_urb (hci, urb, 0); } while (!list_empty (lh)); wake_up (&hci->waitq); } return;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -