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

📄 usb_uhci.c

📁 适合KS8695X
💻 C
📖 第 1 页 / 共 3 页
字号:
		 {
			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 ,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;

	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;
	}
	pci_read_config_byte(busdevfunc,PCI_INTERRUPT_LINE,&temp);
	irqvec = temp;
	irq_free_handler(irqvec);
	USB_UHCI_PRINTF("Interrupt Line = %d, is %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);
	return 0;
}

/* stop uhci
 */
int usb_lowlevel_stop(void)
{
	if(irqvec==-1)
		return 1;
	irq_free_handler(irqvec);
	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) {}
#endif

static 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)
 */


int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len,struct devrequest *cmd)
{

⌨️ 快捷键说明

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