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

📄 usb-host.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct usb_reg_context *reg;	DBFENTER;	reg = (struct usb_reg_context *)kmalloc(sizeof(struct usb_reg_context), GFP_ATOMIC);	if (!(reg)) {		panic("kmalloc failed in top_half\n");	}	reg->hc = (etrax_hc_t *)vhc;	reg->r_usb_irq_mask_read    = *R_USB_IRQ_MASK_READ;	reg->r_usb_status           = *R_USB_STATUS;#if 0	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) {		panic("r_usb_status said perror\n");	}	if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) {		panic("r_usb_status said ourun !!!\n");	}#endif		reg->r_usb_epid_attn        = *R_USB_EPID_ATTN;	reg->r_usb_rh_port_status_1 = *R_USB_RH_PORT_STATUS_1;	reg->r_usb_rh_port_status_2 = *R_USB_RH_PORT_STATUS_2;	reg->usb_bh.sync = 0;	reg->usb_bh.routine = etrax_usb_hc_intr_bottom_half;	reg->usb_bh.data = reg;	queue_task(&reg->usb_bh, &tq_immediate);	mark_bh(IMMEDIATE_BH);	DBFEXIT;}static int etrax_rh_submit_urb(urb_t *urb){	struct usb_device *usb_dev = urb->dev;	etrax_hc_t *hc = usb_dev->bus->hcpriv;	unsigned int pipe = urb->pipe;	devrequest *cmd = (devrequest *) urb->setup_packet;	void *data = urb->transfer_buffer;	int leni = urb->transfer_buffer_length;	int len = 0;	int stat = 0;	__u16 bmRType_bReq;	__u16 wValue;	__u16 wIndex;	__u16 wLength;	DBFENTER;	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {		dbg_rh("Root-Hub submit IRQ: every %d ms", urb->interval);		hc->rh.urb = urb;		hc->rh.send = 1;		hc->rh.interval = urb->interval;		etrax_rh_init_int_timer(urb);		DBFEXIT;				return 0;	}	bmRType_bReq = cmd->requesttype | cmd->request << 8;	wValue = le16_to_cpu(cmd->value);	wIndex = le16_to_cpu(cmd->index);	wLength = le16_to_cpu(cmd->length);	dbg_rh("bmRType_bReq : 0x%04X (%d)", bmRType_bReq, bmRType_bReq);	dbg_rh("wValue       : 0x%04X (%d)", wValue, wValue);	dbg_rh("wIndex       : 0x%04X (%d)", wIndex, wIndex);	dbg_rh("wLength      : 0x%04X (%d)", wLength, wLength);		switch (bmRType_bReq) {				/* Request Destination:		   without flags: Device, 		   RH_INTERFACE: interface, 		   RH_ENDPOINT: endpoint,		   RH_CLASS means HUB here, 		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 		 */	case RH_GET_STATUS:		*(__u16 *) data = cpu_to_le16 (1);		OK (2);			case RH_GET_STATUS | RH_INTERFACE:		*(__u16 *) data = cpu_to_le16 (0);		OK (2);			case RH_GET_STATUS | RH_ENDPOINT:		*(__u16 *) data = cpu_to_le16 (0);		OK (2);			case RH_GET_STATUS | RH_CLASS:		*(__u32 *) data = cpu_to_le32 (0);		OK (4);		/* hub power ** */			case RH_GET_STATUS | RH_OTHER | RH_CLASS:		if (wIndex == 1) {			*((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_1);			*((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_1);		}		else if (wIndex == 2) {			*((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_2);			*((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_2);		}		else {			dbg_rh("RH_GET_STATUS whith invalid wIndex !!");			OK(0);		}				OK(4);	case RH_CLEAR_FEATURE | RH_ENDPOINT:		switch (wValue) {		case (RH_ENDPOINT_STALL):			OK (0);		}		break;	case RH_CLEAR_FEATURE | RH_CLASS:		switch (wValue) {		case (RH_C_HUB_OVER_CURRENT):			OK (0);	/* hub power over current ** */		}		break;	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:		switch (wValue) {		case (RH_PORT_ENABLE):			if (wIndex == 1) {				dbg_rh("trying to do disable of port 1");				*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes);				while (hc->rh.prev_wPortStatus_1 &				       IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes));				*R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no);				dbg_rh("Port 1 is disabled");			} else if (wIndex == 2) {				dbg_rh("trying to do disable of port 2");								*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes);				while (hc->rh.prev_wPortStatus_2 &				       IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes));				*R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no);				dbg_rh("Port 2 is disabled");			} else {				dbg_rh("RH_CLEAR_FEATURE->RH_PORT_ENABLE "				       "with invalid wIndex == %d!!", wIndex);			}										OK (0);		case (RH_PORT_SUSPEND):			/* Opposite to suspend should be resume, so well do a resume */			if (wIndex == 1) {				*R_USB_COMMAND =					IO_STATE(R_USB_COMMAND, port_sel, port1) |					IO_STATE(R_USB_COMMAND, port_cmd, resume)|					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);			} else if (wIndex == 2) {				*R_USB_COMMAND =					IO_STATE(R_USB_COMMAND, port_sel, port2) |					IO_STATE(R_USB_COMMAND, port_cmd, resume)|					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);			} else {				dbg_rh("RH_CLEAR_FEATURE->RH_PORT_SUSPEND "				       "with invalid wIndex == %d!!", wIndex);			}						OK (0);		case (RH_PORT_POWER):			OK (0);	/* port power ** */		case (RH_C_PORT_CONNECTION):						if (wIndex == 1) {				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_CONNECTION);			}			else if (wIndex == 2) {				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_CONNECTION);			}			else {				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_CONNECTION "				       "with invalid wIndex == %d!!", wIndex);			}			OK (0);		case (RH_C_PORT_ENABLE):			if (wIndex == 1) {				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_ENABLE);			}			else if (wIndex == 2) {				hc->rh.wPortChange_2 &= ~(1 << RH_PORT_ENABLE);			}			else {				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_ENABLE "				       "with invalid wIndex == %d!!", wIndex);			}			OK (0);		case (RH_C_PORT_SUSPEND):/*** WR_RH_PORTSTAT(RH_PS_PSSC); */			OK (0);		case (RH_C_PORT_OVER_CURRENT):			OK (0);	/* port power over current ** */		case (RH_C_PORT_RESET):			if (wIndex == 1) {				hc->rh.wPortChange_1 &= ~(1 << RH_PORT_RESET);			}			else if (wIndex == 2) {				dbg_rh("This is wPortChange before clear: 0x%04X", hc->rh.wPortChange_2);								hc->rh.wPortChange_2 &= ~(1 << RH_PORT_RESET);				dbg_rh("This is wPortChange after clear: 0x%04X", hc->rh.wPortChange_2);			} else {				dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_RESET "				       "with invalid index == %d!!", wIndex);			}			OK (0);				}		break;			case RH_SET_FEATURE | RH_OTHER | RH_CLASS:		switch (wValue) {		case (RH_PORT_SUSPEND):			if (wIndex == 1) {				*R_USB_COMMAND =					IO_STATE(R_USB_COMMAND, port_sel, port1) |					IO_STATE(R_USB_COMMAND, port_cmd, suspend) |					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);			} else if (wIndex == 2) {				*R_USB_COMMAND =					IO_STATE(R_USB_COMMAND, port_sel, port2) |					IO_STATE(R_USB_COMMAND, port_cmd, suspend) |					IO_STATE(R_USB_COMMAND, ctrl_cmd, nop);			} else {				dbg_rh("RH_SET_FEATURE->RH_C_PORT_SUSPEND "				       "with invalid wIndex == %d!!", wIndex);			}						OK (0);		case (RH_PORT_RESET):			if (wIndex == 1) {				int port1_retry;							port1_redo:				dbg_rh("Doing reset of port 1");				*R_USB_COMMAND =					IO_STATE(R_USB_COMMAND, port_cmd, reset) |					IO_STATE(R_USB_COMMAND, port_sel, port1);				/* We must once again wait at least 10ms for the device to recover */				port1_retry = 0;				while (!((*((volatile __u16 *)&hc->rh.prev_wPortStatus_1)) &					 IO_STATE(R_USB_RH_PORT_STATUS_1,						  enabled, yes))) {					printk(""); if (port1_retry++ >= 10000) {goto port1_redo;}				}								/* This only seems to work if we use printk,				   not even schedule() works !!! WHY ?? */				udelay(15000);			}			else if (wIndex == 2) {				int port2_retry;							port2_redo:				dbg_rh("Doing reset of port 2");								*R_USB_COMMAND =					IO_STATE(R_USB_COMMAND, port_cmd, reset) |					IO_STATE(R_USB_COMMAND, port_sel, port2);				/* We must once again wait at least 10ms for the device to recover */				port2_retry = 0;				while (!((*((volatile __u16 *)&hc->rh.prev_wPortStatus_2)) &					 IO_STATE(R_USB_RH_PORT_STATUS_2,						  enabled, yes))) {					printk(""); if (port2_retry++ >= 10000) {goto port2_redo;}				}								/* This only seems to work if we use printk,				   not even schedule() works !!! WHY ?? */				udelay(15000);			}			/* Try to bring the HC into running state */			*R_USB_COMMAND =				IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run);						nop(); while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy));						dbg_rh("...Done");			OK(0);		case (RH_PORT_POWER):			OK (0);	/* port power ** */		case (RH_PORT_ENABLE):			/* There is no rh port enable command in the Etrax USB interface!!!! */			OK (0);		}		break;			case RH_SET_ADDRESS:		hc->rh.devnum = wValue;		dbg_rh("RH address set to: %d", hc->rh.devnum);		OK (0);			case RH_GET_DESCRIPTOR:		switch ((wValue & 0xff00) >> 8) {		case (0x01):	/* device descriptor */			len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_dev_des), wLength));			memcpy (data, root_hub_dev_des, len);			OK (len);		case (0x02):	/* configuration descriptor */			len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength));			memcpy (data, root_hub_config_des, len);			OK (len);		case (0x03):	/* string descriptors */			len = usb_root_hub_string (wValue & 0xff,						   0xff, "ETRAX 100LX",						   data, wLength);			if (len > 0) {				OK(min(leni, len));			} else 				stat = -EPIPE;		}		break;			case RH_GET_DESCRIPTOR | RH_CLASS:		root_hub_hub_des[2] = hc->rh.numports;		len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_hub_des), wLength));		memcpy (data, root_hub_hub_des, len);		OK (len);			case RH_GET_CONFIGURATION:		*(__u8 *) data = 0x01;		OK (1);			case RH_SET_CONFIGURATION:		OK (0);			default:		stat = -EPIPE;	}	urb->actual_length = len;	urb->status = stat;	urb->dev = NULL;	if (urb->complete) {		urb->complete (urb);	}	DBFEXIT;		return 0;}static int __init etrax_usb_hc_init(void){	static etrax_hc_t *hc;	struct usb_bus *bus;	struct usb_device *usb_rh;		DBFENTER;	info("ETRAX 100LX USB-HCD %s (c) 2001 Axis Communications AB\n", usb_hcd_version);		hc = kmalloc(sizeof(etrax_hc_t), GFP_KERNEL);	/* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */	usb_desc_cache = kmem_cache_create("usb_desc_cache", sizeof(USB_EP_Desc_t), 0, 0, 0, 0);	if (!usb_desc_cache) {		panic("USB Desc Cache allocation failed !!!\n");	}		etrax_usb_bus = bus = usb_alloc_bus(&etrax_usb_device_operations);	hc->bus = bus;	bus->hcpriv = hc;	/* Initalize RH to the default address.	   And make sure that we have no status change indication */	hc->rh.numports = 2;  /* The RH has two ports */	hc->rh.devnum = 0;	hc->rh.wPortChange_1 = 0;	hc->rh.wPortChange_2 = 0;	/* Also initate the previous values to zero */	hc->rh.prev_wPortStatus_1 = 0;	hc->rh.prev_wPortStatus_2 = 0;	/* Initialize the intr-traffic flags */	hc->intr.sleeping = 0;	hc->intr.wq = NULL;	/* Initially all ep's are free except ep 0 */	ep_usage_bitmask = 0;	set_bit(0, (void *)&ep_usage_bitmask);	ep_really_active = 0;	ep_out_traffic = 0;	memset(URB_List, 0, sizeof(URB_List));	/* This code should really be moved */	if (request_dma(USB_TX_DMA_NBR, "ETRAX 100LX built-in USB (Tx)")) {		err("Could not allocate DMA ch 8 for USB");		etrax_usb_hc_cleanup();		DBFEXIT;		return -1;	}		if (request_dma(USB_RX_DMA_NBR, "ETRAX 100LX built-in USB (Rx)")) {		err("Could not allocate DMA ch 9 for USB");		etrax_usb_hc_cleanup();		DBFEXIT;		return -1;	}	#if 0  /* Moved to head.S */	*R_GEN_CONFIG = genconfig_shadow =		(genconfig_shadow & ~(IO_MASK(R_GEN_CONFIG, usb1) |				      IO_MASK(R_GEN_CONFIG, usb2) |				      IO_MASK(R_GEN_CONFIG, dma8) |				      IO_MASK(R_GEN_CONFIG, dma9))) |		IO_STATE(R_GEN_CONFIG, dma8, usb) |		IO_STATE(R_GEN_CONFIG, dma9, usb)#ifdef CONFIG_ETRAX_USB_HOST_PORT1		| IO_STATE(R_GEN_CONFIG, usb1, select)#endif#ifdef CONFIG_ETRAX_USB_HOST_PORT2		| IO_STATE(R_GEN_CONFIG, usb2, select)#endif	;#endif		usb_register_bus(hc->bus);	/* We may have to set more bits, but these are the obvious ones */	*R_IRQ_MASK2_SET =		IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) |		IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) |		IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) |		IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set);	*R_IRQ_MASK2_SET =		IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) |		IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);	*R_USB_IRQ_MASK_SET = 		IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set) |		IO_STATE(R_USB_IRQ_MASK_SET, ctl_eot, set) |		IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) |#ifdef ETRAX_USB_INTR_IRQ		IO_STATE(R_USB_IRQ_MASK_SET, intr_eot, set) |#endif		IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) |		IO_STATE(R_USB_IRQ_MASK_SET, port_status, set);		if (request_irq(ETRAX_USB_HC_IRQ, etrax_usb_hc_intr_top_half, 0,			"ETRAX 100LX built-in USB (HC)", hc)) {		err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ);		etrax_usb_hc_cleanup();		DBFEXIT;		return -1;	}		if (request_irq(ETRAX_USB_RX_IRQ, etrax_usb_rx_interrupt, 0,			"ETRAX 100LX bu

⌨️ 快捷键说明

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