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

📄 usb_uhci.c

📁 gumstiz u-boot loader in linux
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 ,0,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,0,0,0L);	temp=(unsigned long)&td_int[0];	for(n=1; n<8; n++)		usb_fill_td(&td_int[n],temp,0,0,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;		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;		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(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(td->link) &  UHCI_PTR_QH)))		{			/* check if a device is assigned with this td */			status=swap_32(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=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(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;	/*	 * 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&0x20) && ((in16r(usb_base_addr+USBCMD) && USBCMD_RS)==0)) {			out16r(usb_base_addr + USBCMD, USBCMD_RS | in16r(usb_base_addr + USBCMD));		}	}	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;	int	busdevfunc;/* * HJF - configure IRQ and base from variables optionally. */	char *s;	busdevfunc=pci_find_device(USB_UHCI_VEND_ID,USB_UHCI_DEV_ID,0); /* get PCI Device ID */	if(busdevfunc==-1) {		printf("Error USB UHCI (%04X,%04X) not found\n",USB_UHCI_VEND_ID,USB_UHCI_DEV_ID);		return -1;	}#if 1	s = getenv("usb_irq");	if (s)	{	    temp = atoi(s);	    pci_write_config_byte(busdevfunc, PCI_INTERRUPT_LINE, temp);	}	else#endif	    pci_read_config_byte(busdevfunc,PCI_INTERRUPT_LINE,&temp);	s = getenv("usb_base");	if (s)	{	    unsigned long temp2;	    temp2 = atoi(s);	    pci_write_config_dword(busdevfunc, PCI_BASE_ADDRESS_4, temp2|0x01);	}	irqvec = temp;	irq_free_handler(irqvec);	USB_UHCI_PRINTF("Interrupt Line = %d\n",irqvec);	pci_read_config_byte(busdevfunc,PCI_INTERRUPT_PIN,&temp);	USB_UHCI_PRINTF("Interrupt Pin = %ld\n",temp);	pci_read_config_dword(busdevfunc,PCI_BASE_ADDRESS_4,&usb_base_addr);	USB_UHCI_PRINTF("IO Base Address = 0x%lx\n",usb_base_addr);	usb_base_addr&=0xFFFFFFF0;	usb_base_addr+=CFG_ISA_IO_BASE_ADDRESS;	rh.devnum = 0;	usb_init_skel();	reset_hc();	start_hc();	irq_install_handler(irqvec, (interrupt_handler_t *)handle_usb_interrupt, NULL);	irq_install_handler(0, (interrupt_handler_t *)handle_usb_interrupt, NULL);	return 0;}/* stop uhci */int usb_lowlevel_stop(void){	if(irqvec==-1)		return 1;	irq_free_handler(irqvec);	irq_free_handler(0);	reset_hc();	irqvec=-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 */	'u',			/*  __u8  Unicode */	0,				/*  __u8  Unicode */	'b',			/*  __u8  Unicode */	0,				/*  __u8  Unicode */};/* * Root Hub Control Pipe (interrupt Pipes are not supported) */

⌨️ 快捷键说明

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