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

📄 usb-host.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	clear_bit(epid, (void *)&ep_really_active);	URB_List[epid] = NULL;	etrax_usb_free_epid(epid);		DBFEXIT;	return 0;}void etrax_usb_do_intr_recover(int epid){	USB_EP_Desc_t *first_ep, *tmp_ep;		first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);	tmp_ep = first_ep;	do {		if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid &&		    !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) {			tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes);		}				tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep);			} while (tmp_ep != first_ep);}static int etrax_usb_submit_intr_urb(urb_t *urb){	USB_EP_Desc_t *tmp_ep;	USB_EP_Desc_t *first_ep;		int epid;	char devnum;	char endpoint;	char maxlen;	char out_traffic;	char slow;	int interval;	int i;		etrax_urb_priv_t *urb_priv;		DBFENTER;	devnum = usb_pipedevice(urb->pipe);	endpoint = usb_pipeendpoint(urb->pipe);	maxlen = usb_maxpacket(urb->dev, urb->pipe,			       usb_pipeout(urb->pipe));	out_traffic = usb_pipeout(urb->pipe);	slow = usb_pipeslow(urb->pipe);	interval = urb->interval;	dbg_intr("Intr traffic for dev %d, endpoint %d, maxlen %d, slow %d",		 devnum, endpoint, maxlen, slow);		epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen, out_traffic);	if (epid == -1) {		epid = etrax_usb_allocate_epid();		if (epid == -1) {			/* We're out of endpoints, return some error */			err("We're out of endpoints");			return -ENOMEM;		}		/* Now we have to fill in this ep */		etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow, out_traffic);	}	/* Ok, now we got valid endpoint, lets insert some traffic */	urb_priv = (etrax_urb_priv_t *)kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);	urb_priv->first_sb = 0;	urb_priv->rx_offset = 0;	urb_priv->eot = 0;	INIT_LIST_HEAD(&urb_priv->ep_in_list);	urb->hcpriv = urb_priv;	/* This is safe since there cannot be any other URB's for this epid */	URB_List[epid] = urb;#if 0	first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);#else	first_ep = &TxIntrEPList[0];#endif	/* Round of the interval to 2^n, it is obvious that this code favours	   smaller numbers, but that is actually a good thing */	for (i = 0; interval; i++) {		interval = interval >> 1;	}	urb->interval = interval = 1 << (i - 1);	dbg_intr("Interval rounded to %d", interval);	tmp_ep = first_ep;	i = 0;	do {		if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) {			if ((i % interval) == 0) {				/* Insert the traffic ep after tmp_ep */				USB_EP_Desc_t *traffic_ep;				USB_SB_Desc_t *traffic_sb;				traffic_ep = (USB_EP_Desc_t *)					kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);				traffic_sb = (USB_SB_Desc_t *)					kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);				traffic_ep->hw_len = 0;				traffic_ep->command = IO_FIELD(USB_EP_command, epid, epid) |					IO_STATE(USB_EP_command, enable, yes);				traffic_ep->sub = virt_to_phys(traffic_sb);				if (usb_pipein(urb->pipe)) {					traffic_sb->sw_len = urb->transfer_buffer_length ?						(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;					traffic_sb->next = 0;					traffic_sb->buf = 0;					traffic_sb->command = IO_FIELD(USB_SB_command, rem,								       urb->transfer_buffer_length % maxlen) |						IO_STATE(USB_SB_command, tt, in) |						IO_STATE(USB_SB_command, eot, yes) |						IO_STATE(USB_SB_command, eol, yes);									} else if (usb_pipeout(urb->pipe)) {					traffic_sb->sw_len = urb->transfer_buffer_length;					traffic_sb->next = 0;					traffic_sb->buf = virt_to_phys(urb->transfer_buffer);					traffic_sb->command = IO_FIELD(USB_SB_command, rem, 0) |						IO_STATE(USB_SB_command, tt, out) |						IO_STATE(USB_SB_command, eot, yes) |						IO_STATE(USB_SB_command, eol, yes) |						IO_STATE(USB_SB_command, full, yes);				}				traffic_ep->nep = tmp_ep->nep;				tmp_ep->nep = virt_to_phys(traffic_ep);				dbg_intr("One ep sucessfully inserted");			}			i++;		}		tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->nep);	} while (tmp_ep != first_ep);	set_bit(epid, (void *)&ep_really_active);		*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);	DBFEXIT;		return 0;}static void handle_intr_transfer_attn(int epid, int status){	urb_t *old_urb;	DBFENTER;	old_urb = URB_List[epid];		/* if (status == 0 && IN) find data and copy to urb */	if (status == 0 && usb_pipein(old_urb->pipe)) {		unsigned long flags;		etrax_urb_priv_t *urb_priv;		struct list_head *entry;		struct in_chunk *in;		urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;				save_flags(flags);		cli();		list_for_each(entry, &urb_priv->ep_in_list) {			in = list_entry(entry, struct in_chunk, list);			memcpy(old_urb->transfer_buffer, in->data, in->length);			old_urb->actual_length = in->length;			old_urb->status = status;						if (old_urb->complete) {				old_urb->complete(old_urb);			}						list_del(entry);			kfree(in->data);			kfree(in);		}						restore_flags(flags);	} else if (status != 0) {		warn("Some sort of error for INTR EP !!!!");#ifdef ETRAX_USB_INTR_ERROR_FATAL		/* This means that an INTR error is fatal for that endpoint */		etrax_usb_unlink_intr_urb(old_urb);		old_urb->status = status;		if (old_urb->complete) {			old_urb->complete(old_urb);		}#else		/* In this case we reenable the disabled endpoint(s) */		etrax_usb_do_intr_recover(epid);#endif		}		DBFEXIT;}static int etrax_rh_unlink_urb (urb_t *urb){	etrax_hc_t *hc;		DBFENTER;		hc = urb->dev->bus->hcpriv;		if (hc->rh.urb == urb) {		hc->rh.send = 0;		del_timer(&hc->rh.rh_int_timer);	}		DBFEXIT;	return 0;}static void etrax_rh_send_irq(urb_t *urb){	__u16 data = 0;	etrax_hc_t *hc = urb->dev->bus->hcpriv;//	static prev_wPortStatus_1 = 0;//	static prev_wPortStatus_2 = 0;	/*	DBFENTER; */		/*  dbg_rh("R_USB_FM_NUMBER   : 0x%08X", *R_USB_FM_NUMBER);  dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING);*/		data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0;	data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0;	*((__u16 *)urb->transfer_buffer) = cpu_to_le16(data);	urb->actual_length = 1;	urb->status = 0;		if (data && hc->rh.send && urb->complete) {		dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1); 		dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2);		urb->complete(urb);	}  /*	DBFEXIT; */}static void etrax_rh_init_int_timer(urb_t *urb){	etrax_hc_t *hc;	/*	DBFENTER; */		hc = urb->dev->bus->hcpriv;	hc->rh.interval = urb->interval;	init_timer(&hc->rh.rh_int_timer);	hc->rh.rh_int_timer.function = etrax_rh_int_timer_do;	hc->rh.rh_int_timer.data = (unsigned long)urb;	hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000);	add_timer(&hc->rh.rh_int_timer);	/*	DBFEXIT; */}static void etrax_rh_int_timer_do(unsigned long ptr){	urb_t *urb;	etrax_hc_t *hc;	/*	DBFENTER; */		urb = (urb_t*)ptr;	hc = urb->dev->bus->hcpriv;		if (hc->rh.send) {		etrax_rh_send_irq(urb);	}		etrax_rh_init_int_timer(urb);	/*	DBFEXIT; */}static void etrax_usb_setup_epid(int epid, char devnum, char endpoint, char packsize, char slow, char out_traffic){	unsigned long flags;		DBFENTER;	save_flags(flags);	cli();		if (test_bit(epid, (void *)&ep_usage_bitmask)) {		restore_flags(flags);		warn("Trying to setup used epid %d", epid);		DBFEXIT;		return;	}		set_bit(epid, (void *)&ep_usage_bitmask);		*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);	nop();	*R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) |		IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |		IO_FIELD(R_USB_EPT_DATA, dev, devnum) |		IO_FIELD(R_USB_EPT_DATA, max_len, packsize) |		IO_FIELD(R_USB_EPT_DATA, low_speed, slow);	if (out_traffic)		set_bit(epid, (void *)&ep_out_traffic);	else		clear_bit(epid, (void *)&ep_out_traffic);	restore_flags(flags);	dbg_ep("Setting up ep_id %d with devnum %d, endpoint %d and max_len %d (%s)",	       epid, devnum, endpoint, packsize, out_traffic ? "OUT" : "IN");	DBFEXIT;}static void etrax_usb_free_epid(int epid){	unsigned long flags;		DBFENTER;	if (!test_bit(epid, (void *)&ep_usage_bitmask)) {		warn("Trying to free unused epid %d", epid);		DBFEXIT;		return;	}	save_flags(flags);	cli();	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);	nop();	while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold))		printk("+");	*R_USB_EPT_DATA = 0;	clear_bit(epid, (void *)&ep_usage_bitmask);	restore_flags(flags);	dbg_ep("epid: %d freed", epid);		DBFEXIT;}static int etrax_usb_lookup_epid(unsigned char devnum, char endpoint, char slow, int maxp, char out_traffic){	int i;	unsigned long flags;	__u32 data;		DBFENTER;	save_flags(flags);	cli();	/* Skip first ep_id since it is reserved when intr. or iso traffic is used */	for (i = 0; i < NBR_OF_EP_DESC; i++) {		if (test_bit(i, (void *)&ep_usage_bitmask) &&		    test_bit(i, (void *)&ep_out_traffic) == out_traffic) {			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i);			nop();			data = *R_USB_EPT_DATA;			if ((IO_MASK(R_USB_EPT_DATA, valid) & data) &&			    (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) &&			    (IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) &&			    (IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) &&			    (IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxp)) {				restore_flags(flags);					dbg_ep("Found ep_id %d for devnum %d, endpoint %d (%s)",				       i, devnum, endpoint, out_traffic ? "OUT" : "IN");				DBFEXIT;				return i;			}		}	}	restore_flags(flags);		dbg_ep("Found no ep_id for devnum %d, endpoint %d (%s)",	       devnum, endpoint, out_traffic ? "OUT" : "IN");	DBFEXIT;	return -1;}static int etrax_usb_allocate_epid(void){	int i;		DBFENTER;	for (i = 0; i < NBR_OF_EP_DESC; i++) {		if (!test_bit(i, (void *)&ep_usage_bitmask)) {			dbg_ep("Found free ep_id at %d", i);			DBFEXIT;			return i;		}	}	dbg_ep("Found no free ep_id's");	DBFEXIT;	return -1;}static int etrax_usb_submit_bulk_urb(urb_t *urb){	int epid;	char devnum;	char endpoint;	char maxlen;	char out_traffic;	char slow;	urb_t *tmp_urb;		unsigned long flags;		DBFENTER;	devnum = usb_pipedevice(urb->pipe);	endpoint = usb_pipeendpoint(urb->pipe);	maxlen = usb_maxpacket(urb->dev, urb->pipe,			       usb_pipeout(urb->pipe));	out_traffic = usb_pipeout(urb->pipe);	slow = usb_pipeslow(urb->pipe);		epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen, out_traffic);	if (epid == -1) {		epid = etrax_usb_allocate_epid();		if (epid == -1) {			/* We're out of endpoints, return some error */			err("We're out of endpoints");			return -ENOMEM;		}		/* Now we have to fill in this ep */		etrax_usb_setup_epid(epid, devnum, endpoint, maxlen, slow, out_traffic);	}	/* Ok, now we got valid endpoint, lets insert some traffic */	urb->status = -EINPROGRESS;	save_flags(flags);	cli();		if (URB_List[epid]) {		/* Find end of list and add */		for (tmp_urb = URB_List[epid]; tmp_urb->next; tmp_urb = tmp_urb->next)			dump_urb(tmp_urb);		tmp_urb->next = urb;		restore_flags(flags);	} else {		/* If this is the first URB, add the URB and do HW add */		URB_List[epid] = urb;		restore_flags(flags);		etrax_usb_do_bulk_hw_add(urb, epid, maxlen);	}	DBFEXIT;	return 0;}static void etrax_usb_do_bulk_hw_add(urb_t *urb, int epid, char maxlen)

⌨️ 快捷键说明

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