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

📄 usb-host.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	USB_SB_Desc_t *sb_desc_1;	etrax_urb_priv_t *urb_priv;	unsigned long flags;	DBFENTER;	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);	if (usb_pipeout(urb->pipe)) {		dbg_bulk("Bulk transfer for epid %d is OUT", epid);		dbg_bulk("transfer_buffer_length == %d", urb->transfer_buffer_length);		dbg_bulk("actual_length == %d", urb->actual_length);			if (urb->transfer_buffer_length > 0xffff) {			panic(__FILE__ __FUNCTION__ ":urb->transfer_buffer_length > 0xffff\n");		}		sb_desc_1->sw_len = urb->transfer_buffer_length;  /* was actual_length */		sb_desc_1->command = IO_FIELD(USB_SB_command, rem, 0) |			IO_STATE(USB_SB_command, tt, out) |#if 0			IO_STATE(USB_SB_command, full, no) |#else			IO_STATE(USB_SB_command, full, yes) |#endif			IO_STATE(USB_SB_command, eot, yes) |			IO_STATE(USB_SB_command, eol, yes);				dbg_bulk("transfer_buffer is at 0x%08X", urb->transfer_buffer);				sb_desc_1->buf = virt_to_phys(urb->transfer_buffer);		sb_desc_1->next = 0;			} else if (usb_pipein(urb->pipe)) {		dbg_bulk("Transfer for epid %d is IN", epid);		dbg_bulk("transfer_buffer_length = %d", urb->transfer_buffer_length);		dbg_bulk("rem is calculated to %d", urb->transfer_buffer_length % maxlen);				sb_desc_1->sw_len = urb->transfer_buffer_length ?			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;		dbg_bulk("sw_len got %d", sb_desc_1->sw_len);		dbg_bulk("transfer_buffer is at 0x%08X", urb->transfer_buffer);				sb_desc_1->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);				sb_desc_1->buf = 0;		sb_desc_1->next = 0;		urb_priv->rx_offset = 0;		urb_priv->eot = 0;	}		urb_priv->first_sb = sb_desc_1;		urb->hcpriv = (void *)urb_priv;		/* Reset toggle bits and reset error count, remeber to di and ei */	/* Warning: it is possible that this locking doesn't work with bottom-halves */	save_flags(flags);	cli();	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();	if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {		panic("Hold was set in %s\n", __FUNCTION__);	}	*R_USB_EPT_DATA &=		~(IO_MASK(R_USB_EPT_DATA, error_count_in) |		  IO_MASK(R_USB_EPT_DATA, error_count_out));		if (usb_pipeout(urb->pipe)) {		char toggle =		usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));		*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out);		*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle);	} else {		char toggle =		usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));		*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in);		*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle);	}			/* Enable the EP descr. */	set_bit(epid, (void *)&ep_really_active);		TxBulkEPList[epid].sub = virt_to_phys(sb_desc_1);	TxBulkEPList[epid].hw_len = 0;	TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);	restore_flags(flags);	if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {		*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);			}	DBFEXIT;}static void handle_bulk_transfer_attn(int epid, int status){	urb_t *old_urb;	etrax_urb_priv_t *hc_priv;	unsigned long flags;	DBFENTER;	clear_bit(epid, (void *)&ep_really_active);		old_urb = URB_List[epid];	URB_List[epid] = old_urb->next;	/* if (status == 0 && IN) find data and copy to urb */	if (status == 0 && usb_pipein(old_urb->pipe)) {		etrax_urb_priv_t *urb_priv;				urb_priv = (etrax_urb_priv_t *)old_urb->hcpriv;		save_flags(flags);		cli();		if (urb_priv->eot == 1) {			old_urb->actual_length = urb_priv->rx_offset;		} else {			if (urb_priv->rx_offset == 0) {				status = 0;			} else {				status = -EPROTO;			}						old_urb->actual_length = 0;			err("(BULK) No eot set in IN data!!! rx_offset is: %d", urb_priv->rx_offset);		}				restore_flags(flags);	}	save_flags(flags);	cli();			*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();	if (usb_pipeout(old_urb->pipe)) {		char toggle =		IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA);		usb_settoggle(old_urb->dev, usb_pipeendpoint(old_urb->pipe),			      usb_pipeout(old_urb->pipe), toggle);	} else {		char toggle =		IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA);		usb_settoggle(old_urb->dev, usb_pipeendpoint(old_urb->pipe),			      usb_pipeout(old_urb->pipe), toggle);	}	restore_flags(flags);	/* If there are any more URB's in the list we'd better start sending */	if (URB_List[epid]) {		etrax_usb_do_bulk_hw_add(URB_List[epid], epid,					 usb_maxpacket(URB_List[epid]->dev, URB_List[epid]->pipe,						       usb_pipeout(URB_List[epid]->pipe)));	}#if 1	else {		/* This means that this EP is now free, deconfigure it */		etrax_usb_free_epid(epid);	}#endif		/* Remember to free the SB's */	hc_priv = (etrax_urb_priv_t *)old_urb->hcpriv;	cleanup_sb(hc_priv->first_sb);	kfree(hc_priv);	old_urb->status = status;	if (old_urb->complete) {		old_urb->complete(old_urb);	}	DBFEXIT;}/* ---------------------------------------------------------------------------- */static int etrax_usb_submit_ctrl_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_ctrl_hw_add(urb, epid, maxlen);	}	DBFEXIT;	return 0;}static void etrax_usb_do_ctrl_hw_add(urb_t *urb, int epid, char maxlen){	USB_SB_Desc_t *sb_desc_1;	USB_SB_Desc_t *sb_desc_2;	USB_SB_Desc_t *sb_desc_3;	etrax_urb_priv_t *urb_priv;	unsigned long flags;	DBFENTER;	urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_KERNEL);	sb_desc_1 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);	sb_desc_2 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);	if (!(sb_desc_1 && sb_desc_2)) {		panic("kmem_cache_alloc in ctrl_hw_add gave NULL pointers !!!\n");	}		sb_desc_1->sw_len = 8;	sb_desc_1->command = IO_FIELD(USB_SB_command, rem, 0) |		IO_STATE(USB_SB_command, tt, setup) |		IO_STATE(USB_SB_command, full, yes) |		IO_STATE(USB_SB_command, eot, yes);		sb_desc_1->buf = virt_to_phys(urb->setup_packet);	sb_desc_1->next = virt_to_phys(sb_desc_2);	dump_sb_desc(sb_desc_1);	if (usb_pipeout(urb->pipe)) {		dbg_ctrl("Transfer for epid %d is OUT", epid);		/* If this Control OUT transfer has an optional data stage we add an OUT token		   before the mandatory IN (status) token, hence the reordered SB list */				if (urb->transfer_buffer) {			dbg_ctrl("This OUT transfer has an extra data stage");			sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);			sb_desc_1->next = virt_to_phys(sb_desc_3);						sb_desc_3->sw_len = urb->transfer_buffer_length;			sb_desc_3->command = IO_STATE(USB_SB_command, tt, out) |				IO_STATE(USB_SB_command, full, yes) |				IO_STATE(USB_SB_command, eot, yes);			sb_desc_3->buf = virt_to_phys(urb->transfer_buffer);			sb_desc_3->next = virt_to_phys(sb_desc_2);		}				sb_desc_2->sw_len = 1;		sb_desc_2->command = IO_FIELD(USB_SB_command, rem, 0) |			IO_STATE(USB_SB_command, tt, in) |			IO_STATE(USB_SB_command, eot, yes) |			IO_STATE(USB_SB_command, eol, yes);		sb_desc_2->buf = 0;		sb_desc_2->next = 0;		dump_sb_desc(sb_desc_2);			} else if (usb_pipein(urb->pipe)) {		dbg_ctrl("Transfer for epid %d is IN", epid);		dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length);		dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen);		sb_desc_3 = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_KERNEL);				sb_desc_2->sw_len = urb->transfer_buffer_length ?			(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;		dbg_ctrl("sw_len got %d", sb_desc_2->sw_len);				sb_desc_2->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);				sb_desc_2->buf = 0;		sb_desc_2->next = virt_to_phys(sb_desc_3);		dump_sb_desc(sb_desc_2);		sb_desc_3->sw_len = 1;		sb_desc_3->command = IO_FIELD(USB_SB_command, rem, 0) |			IO_STATE(USB_SB_command, tt, zout) |			IO_STATE(USB_SB_command, full, yes) |			IO_STATE(USB_SB_command, eot, yes) |			IO_STATE(USB_SB_command, eol, yes);						sb_desc_3->buf = 0;		sb_desc_3->next = 0;		dump_sb_desc(sb_desc_3);		urb_priv->rx_offset = 0;		urb_priv->eot = 0;	}		urb_priv->first_sb = sb_desc_1;		urb->hcpriv = (void *)urb_priv;		/* Reset toggle bits and reset error count, remeber to di and ei */	/* Warning: it is possible that this locking doesn't work with bottom-halves */	save_flags(flags);	cli();	*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();	if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {		panic("Hold was set in %s\n", __FUNCTION__);	}		*R_USB_EPT_DATA &=		~(IO_MASK(R_USB_EPT_DATA, error_count_in) |		  IO_MASK(R_USB_EPT_DATA, error_count_out) |		  IO_MASK(R_USB_EPT_DATA, t_in) |		  IO_MASK(R_USB_EPT_DATA, t_out));	/* Enable the EP descr. */	set_bit(epid, (void *)&ep_really_active);		TxCtrlEPList[epid].sub = virt_to_phys(sb_desc_1);	TxCtrlEPList[epid].hw_len = 0;	TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);	restore_flags(flags);	dump_ep_desc(&TxCtrlEPList[epid]);	if (!(*R_DMA_CH8_SUB1_CMD & IO_MASK(R_DMA_CH8_SUB1_CMD, cmd))) {		*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);			}		DBFEXIT;}static int etrax_usb_submit_urb(urb_t *urb){	etrax_hc_t *hc;	int rval = -EINVAL;		DBFENTER;	urb->next = NULL;	dump_urb(urb);	submit_urb_count++;		hc = (etrax_hc_t*) urb->dev->bus->hcpriv;		if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {		/* This request if for the Virtual Root Hub */		rval = etrax_rh_submit_urb(urb);			} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {		rval = etrax_usb_submit_ctrl_urb(urb);	} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {		rval = etrax_usb_submit_bulk_urb(urb);	} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {		int bustime;		if (urb->bandwidth == 0) {			bustime = usb_check_bandwidth(urb->dev, urb);			if (bustime < 0) {				rval = bustime;			} else {				usb_claim_bandwidth(urb->dev, urb, bustime, 0);				rval = etrax_usb_submit_intr_urb(urb);			}					}	} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {		warn("Isochronous traffic is not supported !!!");		rval = -EINVAL;	}	DBFEXIT;	return rval;}static int etrax_usb_unlink_urb(urb_t *urb){	etrax_hc_t *hc = urb->dev->bus->hcpriv;	int epid;	int devnum, endpoint, slow, maxlen, out_traffic;	etrax_urb_priv_t *hc_priv;	unsigned long flags;		DBFENTER;	dump_urb(urb);	devnum = usb_pipedevice(urb->pipe);	endpoint = usb_pipeendpoint(urb->pipe);	slow = usb_pipeslow(urb->pipe);	maxlen = usb_maxpacket(urb->dev, urb->pipe,			       usb_pipeout(urb->pipe));	out_traffic = usb_pipeout(urb->pipe);	epid = etrax_usb_lookup_epid(devnum, endpoint, slow, maxlen, out_traffic);	if (epid == -1)		return 0;		if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {		int ret;		ret =  etrax_rh_unlink_urb(urb);		DBFEXIT;		return ret;	} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {		int ret;		ret = etrax_usb_unlink_intr_urb(urb);		urb->status = -ENOENT;		if (urb->complete) {			urb->complete(urb);		}		DBFEXIT;		return ret;	}	info("Unlink of BULK or CTRL");	save_flags(flags);	cli();		for (epid = 0; epid < 32; epid++) {		urb_t *u = URB_List[epid];

⌨️ 快捷键说明

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