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

📄 usb-host.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		urb_t *prev = NULL;		int pos = 0;		for (; u; u = u->next) {			pos++;			if (u == urb) {				if (!prev) {					URB_List[epid] = u->next;				} else {					prev->next = u->next;				}				restore_flags(flags);				if (!prev) {					if (usb_pipetype(u->pipe) == PIPE_CONTROL) {						if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {							/* The EP was enabled, disable it and wait */							TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);							while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid]));						}					} else if (usb_pipetype(u->pipe) == PIPE_BULK) {						if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {							TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);							while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid]));						}					}				}				info("Found urb at epid %d, pos %d", epid, pos);				u->status = -ENOENT;				if (u->complete) {					u->complete(u);				}								hc_priv = (etrax_urb_priv_t *)u->hcpriv;				cleanup_sb(hc_priv->first_sb);				kfree(hc_priv);				DBFEXIT;				return 0;			}			prev = u;		}	}	restore_flags(flags);			DBFEXIT;	return 0;}static int etrax_usb_get_frame_number(struct usb_device *usb_dev){	DBFENTER;	DBFEXIT;	return (*R_USB_FM_NUMBER);}static int etrax_usb_allocate_dev(struct usb_device *usb_dev){  	DBFENTER;	DBFEXIT;	return 0;}static int etrax_usb_deallocate_dev(struct usb_device *usb_dev){	DBFENTER;	DBFEXIT;	return 0;}static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs){	DBFENTER;	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {		info("dma8_sub0_descr (BULK) intr.");		*R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);	}	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {		info("dma8_sub1_descr (CTRL) intr.");		*R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);	}	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {		info("dma8_sub2_descr (INT) intr.");		*R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);	}	if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {		info("dma8_sub3_descr (ISO) intr.");		*R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);	}		DBFEXIT;}static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs){	int epid = 0;	urb_t *urb;	etrax_urb_priv_t *urb_priv;			*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);	while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {		if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {			goto skip_out;		}		if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {						goto skip_out;		}				epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);		urb = URB_List[epid];		if (urb && usb_pipein(urb->pipe)) {			urb_priv = (etrax_urb_priv_t *)urb->hcpriv;			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {				struct in_chunk *in;				dbg_intr("Packet for epid %d in rx buffers", epid);				in = kmalloc(sizeof(struct in_chunk), GFP_ATOMIC);				in->length = myNextRxDesc->hw_len;				in->data = kmalloc(in->length, GFP_ATOMIC);				memcpy(in->data, phys_to_virt(myNextRxDesc->buf), in->length);				list_add_tail(&in->list, &urb_priv->ep_in_list);#ifndef ETRAX_USB_INTR_IRQ				etrax_usb_hc_intr_top_half(irq, vhc, regs);#endif							} else {				if ((urb_priv->rx_offset + myNextRxDesc->hw_len) >				    urb->transfer_buffer_length) {					err("Packet (epid: %d) in RX buffer (%d) was bigger "					    "than the URB has room for (%d)!!!", epid, urb_priv->rx_offset + myNextRxDesc->hw_len, urb->transfer_buffer_length);					goto skip_out;				}								memcpy(urb->transfer_buffer + urb_priv->rx_offset,				       phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len);								urb_priv->rx_offset += myNextRxDesc->hw_len;			}						if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) {				urb_priv->eot = 1;			}					} else {			err("This is almost fatal, inpacket for epid %d which does not exist "			    " or is out!!!\nURB was at 0x%08lX", epid, (unsigned long)urb);						goto skip_out;		}	skip_out:		myPrevRxDesc = myNextRxDesc;		myPrevRxDesc->command |= IO_MASK(USB_IN_command, eol);		myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol);		myLastRxDesc = myPrevRxDesc;		myNextRxDesc->status = 0;		myNextRxDesc = phys_to_virt(myNextRxDesc->next);	}}static void cleanup_sb(USB_SB_Desc_t *sb){	USB_SB_Desc_t *next_sb;		DBFENTER;	if (sb == NULL) {		err("cleanup_sb was given a NULL pointer");		return;	}	while (!(sb->command & IO_MASK(USB_SB_command, eol))) {		next_sb = (USB_SB_Desc_t *)phys_to_virt(sb->next);		kmem_cache_free(usb_desc_cache, sb);		sb = next_sb;	}	kmem_cache_free(usb_desc_cache, sb);	DBFEXIT;}static void handle_control_transfer_attn(int epid, int status){	urb_t *old_urb;	etrax_urb_priv_t *hc_priv;		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)) {		unsigned long flags;		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;			dbg_ctrl("urb_priv->rx_offset: %d in handle_control_attn", urb_priv->rx_offset);		} else {			status = -EPROTO;			old_urb->actual_length = 0;			err("(CTRL) No eot set in IN data!!! rx_offset: %d", urb_priv->rx_offset);		}		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_ctrl_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 void etrax_usb_hc_intr_bottom_half(void *data){	struct usb_reg_context *reg = (struct usb_reg_context *)data;		int error_code;	int epid;	__u32 r_usb_ept_data;	etrax_hc_t *hc = reg->hc; 	__u16 r_usb_rh_port_status_1;	__u16 r_usb_rh_port_status_2;		DBFENTER;	if (reg->r_usb_irq_mask_read & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {		/*		  The Etrax RH does not include a wPortChange register, so this has		  to be handled in software. See section 11.16.2.6.2 in USB 1.1 spec		  for details.		*/				r_usb_rh_port_status_1 = reg->r_usb_rh_port_status_1;		r_usb_rh_port_status_2 = reg->r_usb_rh_port_status_2;				dbg_rh("port_status pending");		dbg_rh("r_usb_rh_port_status_1: 0x%04X", r_usb_rh_port_status_1);		dbg_rh("r_usb_rh_port_status_2: 0x%04X", r_usb_rh_port_status_2);		/* C_PORT_CONNECTION is set on any transition */		hc->rh.wPortChange_1 |=			((r_usb_rh_port_status_1 & (1 << RH_PORT_CONNECTION)) !=			 (hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_CONNECTION))) ?			(1 << RH_PORT_CONNECTION) : 0;				hc->rh.wPortChange_2 |=			((r_usb_rh_port_status_2 & (1 << RH_PORT_CONNECTION)) !=			 (hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_CONNECTION))) ?			(1 << RH_PORT_CONNECTION) : 0;		/* C_PORT_ENABLE is _only_ set on a one to zero transition */		hc->rh.wPortChange_1 |=			((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_ENABLE))			 && !(r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?			(1 << RH_PORT_ENABLE) : 0;				hc->rh.wPortChange_2 |=			((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_ENABLE))			 && !(r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?			(1 << RH_PORT_ENABLE) : 0;				/* C_PORT_SUSPEND seems difficult, lets ignore it.. (for now) */				/* C_PORT_RESET is _only_ set on a transition from the resetting state		   to the enabled state */		hc->rh.wPortChange_1 |=			((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_RESET))			 && (r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ?			(1 << RH_PORT_RESET) : 0;				hc->rh.wPortChange_2 |=			((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_RESET))			 && (r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ?			(1 << RH_PORT_RESET) : 0;				hc->rh.prev_wPortStatus_1 = r_usb_rh_port_status_1;		hc->rh.prev_wPortStatus_2 = r_usb_rh_port_status_2;		}	for (epid = 0; epid < 32; epid++) {		unsigned long flags;		save_flags(flags);		cli();		*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop();		r_usb_ept_data = *R_USB_EPT_DATA;		restore_flags(flags);		if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) {			warn("Was hold for epid %d", epid);			continue;		}		if (!(r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, valid))) {			continue;		}						if (test_bit(epid, (void *)&reg->r_usb_epid_attn)) {			if (URB_List[epid] == NULL) {				err("R_USB_EPT_DATA is 0x%08X", r_usb_ept_data);				err("submit urb has been called %lu times..", submit_urb_count);				err("EPID_ATTN for epid %d, with NULL entry in list", epid);				return;			}						dbg_ep("r_usb_ept_data [%d] == 0x%08X", epid,			       r_usb_ept_data);						error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code,						r_usb_ept_data);						if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {				/* no_error means that this urb was sucessfully sent or that we have				   some undefinde error*/								if (IO_EXTRACT(R_USB_EPT_DATA, error_count_out, r_usb_ept_data) == 3 ||				    IO_EXTRACT(R_USB_EPT_DATA, error_count_in, r_usb_ept_data) == 3) {				/* Actually there were transmission errors */					warn("Undefined error for epid %d", epid);					if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {						handle_control_transfer_attn(epid, -EPROTO);					} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {						handle_bulk_transfer_attn(epid, -EPROTO);					} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {						handle_intr_transfer_attn(epid, -EPROTO);					}							   				} else {					if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {						if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {							etrax_usb_do_intr_recover(epid);						} else {							panic("Epid attention for epid %d (none INTR), with no errors and no "							      "exessive retry r_usb_status is 0x%02X\n",							      epid, reg->r_usb_status);						}											} else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {						panic("Epid attention for epid %d, with no errors and no "						      "exessive retry r_usb_status is 0x%02X\n",						      epid, reg->r_usb_status);											}										warn("Epid attention for epid %d, with no errors and no "					     "exessive retry r_usb_status is 0x%02X",					     epid, reg->r_usb_status);					warn("OUT error count: %d", IO_EXTRACT(R_USB_EPT_DATA, error_count_out,									       r_usb_ept_data));					warn("IN  error count: %d", IO_EXTRACT(R_USB_EPT_DATA, error_count_in,									       r_usb_ept_data));									}							} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, stall)) {				warn("Stall for epid %d", epid);				if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {					handle_control_transfer_attn(epid, -EPIPE);				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {					handle_bulk_transfer_attn(epid, -EPIPE);				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {					handle_intr_transfer_attn(epid, -EPIPE);				}											} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, bus_error)) {				panic("USB bus error for epid %d\n", epid);							} else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) {				warn("Buffer error for epid %d", epid);				if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {					handle_control_transfer_attn(epid, -EPROTO);				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {					handle_bulk_transfer_attn(epid, -EPROTO);				} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {					handle_intr_transfer_attn(epid, -EPROTO);				}			}		} else if (test_bit(epid, (void *)&ep_really_active)) {			/* Should really be else if (testbit(really active)) */			if (usb_pipetype(URB_List[epid]->pipe) == PIPE_CONTROL) {				if (!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))) {					/* Now we have to verify that this CTRL endpoint got disabled					   cause it reached end of list with no error */										if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==					    IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {						/*						  This means that the endpoint has no error, is disabled						  and had inserted traffic,						  i.e. transfer sucessfully completed						*/						dbg_ctrl("Last SB for CTRL %d sent sucessfully", epid);						handle_control_transfer_attn(epid, 0);					}				}							} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_BULK) {				if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable))) {					/* Now we have to verify that this BULK endpoint go disabled					   cause it reached end of list with no error */					if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==					    IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {						/*						  This means that the endpoint has no error, is disabled						  and had inserted traffic,						  i.e. transfer sucessfully completed						*/						dbg_bulk("Last SB for BULK %d sent sucessfully", epid);						handle_bulk_transfer_attn(epid, 0);					}				}			} else if (usb_pipetype(URB_List[epid]->pipe) == PIPE_INTERRUPT) {				handle_intr_transfer_attn(epid, 0);			}		}			}		kfree(reg);	DBFEXIT;}static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs)

⌨️ 快捷键说明

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