⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hc_simple_isp116x.c

📁 嵌入式USB主控制器ISP1161的驱动编程
💻 C
📖 第 1 页 / 共 2 页
字号:
	} 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 + -