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

📄 usb_uhci.c

📁 最新版的u-boot,2008-10-18发布
💻 C
📖 第 1 页 / 共 3 页
字号:
 */uhci_td_t *uhci_alloc_int_td(void){	int i;	for (i = 0; i < USB_MAX_TEMP_INT_TD; i++) {		if (tmp_int_td[i].dev_ptr == 0)	/* no device assigned -> free TD */			return &tmp_int_td[i];	}	return NULL;}/*------------------------------------------------------------------- * submits USB interrupt (ie. polling ;-) */int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,		   int transfer_len, int interval){	int nint, n;	unsigned long status, destination;	unsigned long info, tmp;	uhci_td_t *mytd;	if (interval < 0 || interval >= 256)		return -1;	if (interval == 0)		nint = 0;	else {		for (nint = 0, n = 1; nint <= 8; nint++, n += n) {	/* round interval down to 2^n */			if (interval < n) {				interval = n / 2;				break;			}		}		nint--;	}	USB_UHCI_PRINTF("Rounded interval to %i, chain  %i\n", interval, nint);	mytd = uhci_alloc_int_td();	if (mytd == NULL) {		printf("No free INT TDs found\n");		return -1;	}	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27);/*		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);*/	destination =	    (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe) |	    (((transfer_len - 1) & 0x7ff) << 21);	info =	    destination |	    (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) <<	     TD_TOKEN_TOGGLE);	tmp = swap_32(td_int[nint].link);	usb_fill_td(mytd, tmp, status, info, (unsigned long)buffer,		    (unsigned long)dev);	/* Link it */	tmp = swap_32((unsigned long)mytd);	td_int[nint].link = tmp;	usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));	return 0;}/********************************************************************** * Low Level functions */void reset_hc(void){	/* Global reset for 100ms */	out16r(usb_base_addr + USBPORTSC1, 0x0204);	out16r(usb_base_addr + USBPORTSC2, 0x0204);	out16r(usb_base_addr + USBCMD, USBCMD_GRESET | USBCMD_RS);	/* Turn off all interrupts */	out16r(usb_base_addr + USBINTR, 0);	wait_ms(50);	out16r(usb_base_addr + USBCMD, 0);	wait_ms(10);}void start_hc(void){	int timeout = 1000;	while (in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) {		if (!--timeout) {			printf("USBCMD_HCRESET timed out!\n");			break;		}	}	/* Turn on all interrupts */	out16r(usb_base_addr + USBINTR,	       USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);	/* Start at frame 0 */	out16r(usb_base_addr + USBFRNUM, 0);	/* set Framebuffer base address */	out32r(usb_base_addr + USBFLBASEADD, (unsigned long)&framelist);	/* Run and mark it configured with a 64-byte max packet */	out16r(usb_base_addr + USBCMD, USBCMD_RS | USBCMD_CF | USBCMD_MAXP);}/* Initialize the skeleton */void usb_init_skel(void){	unsigned long temp;	int n;	for (n = 0; n < USB_MAX_TEMP_INT_TD; n++)		tmp_int_td[n].dev_ptr = 0L;	/* no devices connected */	/* last td */	usb_fill_td(&td_last, UHCI_PTR_TERM, TD_CTRL_IOC, USB_PID_OUT, 0, 0L);	/* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */	/* End Queue Header */	usb_fill_qh(&qh_end, UHCI_PTR_TERM, (unsigned long)&td_last);	/* Bulk Queue Header */	temp = (unsigned long)&qh_end;	usb_fill_qh(&qh_bulk, temp | UHCI_PTR_QH, UHCI_PTR_TERM);	/* Control Queue Header */	temp = (unsigned long)&qh_bulk;	usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH, UHCI_PTR_TERM);	/* 1ms Interrupt td */	temp = (unsigned long)&qh_cntrl;	usb_fill_td(&td_int[0], temp | UHCI_PTR_QH, 0, USB_PID_OUT, 0, 0L);	temp = (unsigned long)&td_int[0];	for (n = 1; n < 8; n++)		usb_fill_td(&td_int[n], temp, 0, USB_PID_OUT, 0, 0L);	for (n = 0; n < 1024; n++) {		/* link all framelist pointers to one of the interrupts */		int m, o;		if ((n & 127) == 127)			framelist[n] = swap_32((unsigned long)&td_int[0]);		else			for (o = 1, m = 2; m <= 128; o++, m += m)				if ((n & (m - 1)) == ((m - 1) / 2))					framelist[n] =					    swap_32((unsigned long)&td_int[o]);	}}/* check the common skeleton for completed transfers, and update the status * of the "connected" device. Called from the IRQ routine. */void usb_check_skel(void){	struct usb_device *dev;	/* start with the control qh */	if (qh_cntrl.dev_ptr != 0) {	/* it's a device assigned check if this caused IRQ */		dev = (struct usb_device *)qh_cntrl.dev_ptr;		/* Flush cache now that hardware updated DATA and TDs/QHs */		if (!leon3_snooping_avail)			sparc_dcache_flush_all();		usb_get_td_status(&tmp_td[0], dev);	/* update status */		if (!(dev->status & USB_ST_NOT_PROC)) {	/* is not active anymore, disconnect devices */			qh_cntrl.dev_ptr = 0;		}	}	/* now process the bulk */	if (qh_bulk.dev_ptr != 0) {	/* it's a device assigned check if this caused IRQ */		dev = (struct usb_device *)qh_bulk.dev_ptr;		/* Flush cache now that hardware updated DATA and TDs/QHs */		if (!leon3_snooping_avail)			sparc_dcache_flush_all();		usb_get_td_status(&tmp_td[0], dev);	/* update status */		if (!(dev->status & USB_ST_NOT_PROC)) {	/* is not active anymore, disconnect devices */			qh_bulk.dev_ptr = 0;		}	}}/* check the interrupt chain, ubdate the status of the appropriate device, * call the appropriate irqhandler and reactivate the TD if the irqhandler * returns with 1 */void usb_check_int_chain(void){	int i, res;	unsigned long link, status;	struct usb_device *dev;	uhci_td_t *td, *prevtd;	for (i = 0; i < 8; i++) {		prevtd = &td_int[i];	/* the first previous td is the skeleton td */		link = swap_32(READ32(&td_int[i].link)) & 0xfffffff0;	/* next in chain */		td = (uhci_td_t *) link;	/* assign it */		/* all interrupt TDs are finally linked to the td_int[0].		 * so we process all until we find the td_int[0].		 * if int0 chain points to a QH, we're also done		 */		while (((i > 0) && (link != (unsigned long)&td_int[0])) ||		       ((i == 0)			&& !(swap_32(READ32(&td->link)) & UHCI_PTR_QH))) {			/* check if a device is assigned with this td */			status = swap_32(READ32(&td->status));			if ((td->dev_ptr != 0L) && !(status & TD_CTRL_ACTIVE)) {				/* td is not active and a device is assigned -> call irqhandler */				dev = (struct usb_device *)td->dev_ptr;				dev->irq_act_len = ((status & 0x7FF) == 0x7FF) ? 0 : (status & 0x7FF) + 1;	/* transfered length */				dev->irq_status = usb_uhci_td_stat(status);	/* get status */				res = dev->irq_handle(dev);	/* call irqhandler */				if (res == 1) {					/* reactivate */					status |= TD_CTRL_ACTIVE;					td->status = swap_32(status);					prevtd = td;	/* previous td = this td */				} else {					prevtd->link = READ32(&td->link);	/* link previous td directly to the nex td -> unlinked */					/* remove device pointer */					td->dev_ptr = 0L;				}			}	/* if we call the irq handler */			link = swap_32(READ32(&td->link)) & 0xfffffff0;	/* next in chain */			td = (uhci_td_t *) link;	/* assign it */		}		/* process all td in this int chain */	}			/* next interrupt chain */}/* usb interrupt service routine. */void handle_usb_interrupt(void){	unsigned short status;	static int error = 0;	/*	 * Read the interrupt status, and write it back to clear the	 * interrupt cause	 */	status = in16r(usb_base_addr + USBSTS);	if (!status)		/* shared interrupt, not mine */		return;	if (status != 1) {		/* remove host controller halted state */		if ((status & (USBSTS_HCPE | USBSTS_HCH)) ==		    (USBSTS_HCPE | USBSTS_HCH)) {			/* Stop due to bug in driver, or hardware */			out16r(usb_base_addr + USBSTS, status);			out16r(usb_base_addr + USBCMD,			       USBCMD_HCRESET | USBCMD_GRESET);			printf			    ("GRUSB: HW detected error(s) in USB Descriptors (STS: 0x%x)\n",			     status);			usb_show_td(8);			return;		} else if ((status & 0x20)			   && ((in16r(usb_base_addr + USBCMD) & USBCMD_RS) ==			       0)) {			if (error < 10) {				out16r(usb_base_addr + USBCMD,				       USBCMD_RS | in16r(usb_base_addr +							 USBCMD));				error++;			}		} else			error = 0;	}	usb_check_int_chain();	/* call interrupt handlers for int tds */	usb_check_skel();	/* call completion handler for common transfer routines */	out16r(usb_base_addr + USBSTS, status);}/* init uhci */int usb_lowlevel_init(void){	unsigned char temp;	ambapp_ahbdev ahbdev;	/* Find GRUSB core using AMBA Plug&Play information */	if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_UHCI, &ahbdev) != 1) {		printf("USB UHCI: Failed to find GRUSB controller\n");		return -1;	}	usb_base_addr = ahbdev.address[0];	grusb_irq = ahbdev.irq;	/*	   usb_base_addr = 0xfffa0000;	   grusb_irq = 10;	 */#ifdef USB_UHCI_DEBUG	grusb_show_regs();#endif	memset(td_int, 0, sizeof(td_int));	memset(tmp_td, 0, sizeof(tmp_td));	memset(tmp_int_td, 0, sizeof(tmp_int_td));	memset(&qh_cntrl, 0, sizeof(qh_cntrl));	memset(&qh_end, 0, sizeof(qh_end));	memset(&td_last, 0, sizeof(td_last));	irq_free_handler(grusb_irq);	USB_UHCI_PRINTF("GRUSB: at 0x%lx irq %d\n", usb_base_addr, grusb_irq);	rh.devnum = 0;	usb_init_skel();	reset_hc();	start_hc();	irq_install_handler(grusb_irq,			    (interrupt_handler_t *) handle_usb_interrupt, NULL);	return 0;}/* stop uhci */int usb_lowlevel_stop(void){	if (grusb_irq == -1)		return 1;	irq_free_handler(grusb_irq);	reset_hc();	grusb_irq = -1;	return 0;}/******************************************************************************************* * Virtual Root Hub * Since the uhci does not have a real HUB, we simulate one ;-) */#undef	USB_RH_DEBUG#ifdef	USB_RH_DEBUG#define	USB_RH_PRINTF(fmt,args...)	printf (fmt ,##args)static void usb_display_wValue(unsigned short wValue, unsigned short wIndex);static void usb_display_Req(unsigned short req);#else#define USB_RH_PRINTF(fmt,args...)static void usb_display_wValue(unsigned short wValue, unsigned short wIndex){}static void usb_display_Req(unsigned short req){}#endifstatic unsigned char root_hub_dev_des[] = {	0x12,			/*  __u8  bLength; */	0x01,			/*  __u8  bDescriptorType; Device */	0x00,			/*  __u16 bcdUSB; v1.0 */	0x01,	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */	0x00,			/*  __u8  bDeviceSubClass; */	0x00,			/*  __u8  bDeviceProtocol; */	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */	0x00,			/*  __u16 idVendor; */	0x00,	0x00,			/*  __u16 idProduct; */	0x00,	0x00,			/*  __u16 bcdDevice; */	0x00,	0x01,			/*  __u8  iManufacturer; */	0x00,			/*  __u8  iProduct; */	0x00,			/*  __u8  iSerialNumber; */	0x01			/*  __u8  bNumConfigurations; */};/* Configuration descriptor */static unsigned char root_hub_config_des[] = {	0x09,			/*  __u8  bLength; */	0x02,			/*  __u8  bDescriptorType; Configuration */	0x19,			/*  __u16 wTotalLength; */	0x00,	0x01,			/*  __u8  bNumInterfaces; */	0x01,			/*  __u8  bConfigurationValue; */	0x00,			/*  __u8  iConfiguration; */	0x40,			/*  __u8  bmAttributes;				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */	0x00,			/*  __u8  MaxPower; */	/* interface */	0x09,			/*  __u8  if_bLength; */	0x04,			/*  __u8  if_bDescriptorType; Interface */	0x00,			/*  __u8  if_bInterfaceNumber; */	0x00,			/*  __u8  if_bAlternateSetting; */	0x01,			/*  __u8  if_bNumEndpoints; */	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */	0x00,			/*  __u8  if_bInterfaceSubClass; */	0x00,			/*  __u8  if_bInterfaceProtocol; */	0x00,			/*  __u8  if_iInterface; */	/* endpoint */	0x07,			/*  __u8  ep_bLength; */	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */	0x03,			/*  __u8  ep_bmAttributes; Interrupt */	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */	0x00,	0xff			/*  __u8  ep_bInterval; 255 ms */};static unsigned char root_hub_hub_des[] = {	0x09,			/*  __u8  bLength; */	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */	0x02,			/*  __u8  bNbrPorts; */	0x00,			/* __u16  wHubCharacteristics; */	0x00,	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */	0x00,			/*  __u8  bHubContrCurrent; 0 mA */	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */};static unsigned char root_hub_str_index0[] = {	0x04,			/*  __u8  bLength; */	0x03,			/*  __u8  bDescriptorType; String-descriptor */	0x09,			/*  __u8  lang ID */	0x04,			/*  __u8  lang ID */};static unsigned char root_hub_str_index1[] = {	28,			/*  __u8  bLength; */	0x03,			/*  __u8  bDescriptorType; String-descriptor */	'U',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'H',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'C',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'I',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	' ',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'R',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'o',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'o',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	't',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	' ',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */	'H',			/*  __u8  Unicode */	0,			/*  __u8  Unicode */

⌨️ 快捷键说明

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