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

📄 usb-ohci.c

📁 周立功2410开发板USB键盘与鼠标应用开发源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
**-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static char *hcfs2string (int state){	switch (state) {		case OHCI_USB_RESET:	return "reset";		case OHCI_USB_RESUME:	return "resume";		case OHCI_USB_OPER:	return "operational";		case OHCI_USB_SUSPEND:	return "suspend";	}	return "?";}/*********************************************************************************************************** Function name: ** Descriptions: ** Input:** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/// dump control and status registersstatic void ohci_dump_status (ohci_t *controller){	struct ohci_regs	*regs = controller->regs;	__u32			temp;	temp = readl (&regs->revision) & 0xff;//	if (temp != 0x10)		printk ("spec %d.%d\n", (temp >> 4), (temp & 0x0f));	temp = readl (&regs->control);	printk ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp,		(temp & OHCI_CTRL_RWE) ? " RWE" : "",		(temp & OHCI_CTRL_RWC) ? " RWC" : "",		(temp & OHCI_CTRL_IR) ? " IR" : "",		hcfs2string (temp & OHCI_CTRL_HCFS),		(temp & OHCI_CTRL_BLE) ? " BLE" : "",		(temp & OHCI_CTRL_CLE) ? " CLE" : "",		(temp & OHCI_CTRL_IE) ? " IE" : "",		(temp & OHCI_CTRL_PLE) ? " PLE" : "",		temp & OHCI_CTRL_CBSR		);	temp = readl (&regs->cmdstatus);	printk ("cmdstatus: 0x%08x SOC=%d%s%s%s%s\n", temp,		(temp & OHCI_SOC) >> 16,		(temp & OHCI_OCR) ? " OCR" : "",		(temp & OHCI_BLF) ? " BLF" : "",		(temp & OHCI_CLF) ? " CLF" : "",		(temp & OHCI_HCR) ? " HCR" : ""		);	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));	// intrdisable always same as intrenable	// ohci_dump_intr_mask ("intrdisable", readl (&regs->intrdisable));	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));	maybe_print_eds ("donehead", readl (&regs->donehead));}static void ohci_dump_roothub (ohci_t *controller, int verbose){	__u32			temp, ndp, i;	temp = roothub_a (controller);	ndp = (temp & RH_A_NDP);//	if (verbose) {		printk ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,			((temp & RH_A_POTPGT) >> 24) & 0xff,			(temp & RH_A_NOCP) ? " NOCP" : "",			(temp & RH_A_OCPM) ? " OCPM" : "",			(temp & RH_A_DT) ? " DT" : "",			(temp & RH_A_NPS) ? " NPS" : "",			(temp & RH_A_PSM) ? " PSM" : "",			ndp			);		temp = roothub_b (controller);		printk ("roothub.b: %08x PPCM=%04x DR=%04x\n",			temp,			(temp & RH_B_PPCM) >> 16,			(temp & RH_B_DR)			);		temp = roothub_status (controller);		printk ("roothub.status: %08x%s%s%s%s%s%s\n",			temp,			(temp & RH_HS_CRWE) ? " CRWE" : "",			(temp & RH_HS_OCIC) ? " OCIC" : "",			(temp & RH_HS_LPSC) ? " LPSC" : "",			(temp & RH_HS_DRWE) ? " DRWE" : "",			(temp & RH_HS_OCI) ? " OCI" : "",			(temp & RH_HS_LPS) ? " LPS" : ""			);//	}		for (i = 0; i < ndp; i++) {		temp = roothub_portstatus (controller, i);		printk ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n",			i,			temp,			(temp & RH_PS_PRSC) ? " PRSC" : "",			(temp & RH_PS_OCIC) ? " OCIC" : "",			(temp & RH_PS_PSSC) ? " PSSC" : "",			(temp & RH_PS_PESC) ? " PESC" : "",			(temp & RH_PS_CSC) ? " CSC" : "",			(temp & RH_PS_LSDA) ? " LSDA" : "",			(temp & RH_PS_PPS) ? " PPS" : "",			(temp & RH_PS_PRS) ? " PRS" : "",			(temp & RH_PS_POCI) ? " POCI" : "",			(temp & RH_PS_PSS) ? " PSS" : "",			(temp & RH_PS_PES) ? " PES" : "",			(temp & RH_PS_CCS) ? " CCS" : ""			);	}}/*********************************************************************************************************** Function name: ** Descriptions: ** Input:** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void ohci_dump (ohci_t *controller, int verbose){	printk ("OHCI controller usb-%s state\n", controller->slot_name);	// dumps some of the state we know about	ohci_dump_status (controller);	if (verbose)		ep_print_int_eds (controller, "hcca");	printk ("hcca frame #%04x\n", controller->hcca->frame_no);	ohci_dump_roothub (controller, 1);}#endif/*-------------------------------------------------------------------------* * Interface functions (URB) *-------------------------------------------------------------------------*//* return a request to the completion handler */ /*********************************************************************************************************** Function name: ** Descriptions: ** Input:** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static int sohci_return_urb (struct ohci *hc, urb_t * urb){	urb_priv_t * urb_priv = urb->hcpriv;	urb_t * urbt;	unsigned long flags;	int i;		if (!urb_priv)		return -1; /* urb already unlinked */	/* just to be sure */	if (!urb->complete) {		urb_rm_priv (urb);		return -1;	}	#ifdef DEBUG	urb_print (urb, "RET", usb_pipeout (urb->pipe));#endif	switch (usb_pipetype (urb->pipe)) {  		case PIPE_INTERRUPT:			pci_unmap_single (hc->ohci_dev,				urb_priv->td [0]->data_dma,				urb->transfer_buffer_length,				usb_pipeout (urb->pipe)					? PCI_DMA_TODEVICE					: PCI_DMA_FROMDEVICE);#if 1			urb->complete (urb);			/* implicitly requeued */  			urb->actual_length = 0;  			urb->status = USB_ST_URB_PENDING;  			if (urb_priv->state != URB_DEL)  				td_submit_urb (urb);#else			if (urb->interval) {				urb->complete (urb);							/* implicitly requeued */				urb->actual_length = 0;				urb->status = USB_ST_URB_PENDING;				if (urb_priv->state != URB_DEL)					td_submit_urb (urb);			} else {				urb_rm_priv(urb);				urb->complete (urb);			}#endif  			break;  					case PIPE_ISOCHRONOUS:			for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);			if (urbt) { /* send the reply and requeue URB */					pci_unmap_single (hc->ohci_dev,					urb_priv->td [0]->data_dma,					urb->transfer_buffer_length,					usb_pipeout (urb->pipe)						? PCI_DMA_TODEVICE						: PCI_DMA_FROMDEVICE);				urb->complete (urb);				spin_lock_irqsave (&usb_ed_lock, flags);				urb->actual_length = 0;  				urb->status = USB_ST_URB_PENDING;  				urb->start_frame = urb_priv->ed->last_iso + 1;  				if (urb_priv->state != URB_DEL) {  					for (i = 0; i < urb->number_of_packets; i++) {  						urb->iso_frame_desc[i].actual_length = 0;  						urb->iso_frame_desc[i].status = -EXDEV;  					}  					td_submit_urb (urb);  				}  				spin_unlock_irqrestore (&usb_ed_lock, flags);  				  			} else { /* unlink URB, call complete */				urb_rm_priv (urb);				urb->complete (urb); 				}					break;  						case PIPE_BULK:		case PIPE_CONTROL: /* unlink URB, call complete */			urb_rm_priv (urb);			urb->complete (urb);				break;	}	return 0;}/*-------------------------------------------------------------------------*//* get a transfer request *//*********************************************************************************************************** Function name: sohci_submit_urb** Descriptions: USB设备类驱动程序通过调用该函数可将相应的URB传递给HCD层来进行相应的数据传输。** Input:A:**       B:**       C:** Output : 返回值为小于或等于零的数,其中零表示提交URB操作成功,其它为错误代码。**        0						操作成功**        -ENOMEN     函数内部内存分配失败**        -ENXIO      相应的端点已经存在一个控制传输、中断传输或批量传输URB**        -EINVAL     在下面几种情况下都回返回该错误代码**                        无效的数据传输类型**                        无效的中断间隔**                        多个被请求的中断数据包**                        等时传输的数据包数目小于0**        -EAGAIN     在下面几种情况下都回返回该错误代码**                        被指定等时传输中的起始帧过早**                        在使用ISO-ASAP时,太长的时间调度和数据重传**        -EFBIG      太多的等时数据帧(仅仅针对UHCI主控制器驱动)**        -EPIPE      相应的管道已经被中止(STALLED)**        -ENOSPC     USB总线没有足够的带宽用于该URB传输**        -ESHUTDOWN	主控制器已被终止** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/ static int sohci_submit_urb (urb_t * urb){	ohci_t * ohci;	ed_t * ed;	urb_priv_t * urb_priv;	unsigned int pipe = urb->pipe;	int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));	int i, size = 0;	unsigned long flags;	int bustime = 0;	int mem_flags = ALLOC_FLAGS;	if (!urb->dev || !urb->dev->bus)		return -ENODEV;		if (urb->hcpriv)			/* urb already in use */		return -EINVAL;//	if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) //		return -EPIPE;		usb_inc_dev_use (urb->dev);	ohci = (ohci_t *) urb->dev->bus->hcpriv;	#ifdef DEBUG	urb_print (urb, "SUB", usb_pipein (pipe));#endif		/* handle a request to the virtual root hub */	if (usb_pipedevice (pipe) == ohci->rh.devnum)  {	// 如果与根集线器地址一至,即为操作根集线器,调用根集线器处理		return rh_submit_urb (urb);	}		/* when controller's hung, permit only roothub cleanup attempts	 * such as powering down ports */	if (ohci->disabled) {								//主控制器已被终止		usb_dec_dev_use (urb->dev);			return -ESHUTDOWN;	}	/* every endpoint has a ed, locate and fill it */	if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {		usb_dec_dev_use (urb->dev);			return -ENOMEM;	}	/* for the private part of the URB we need the number of TDs (size) */	// 根据各传输类型,确定需要的传输描述符个数	switch (usb_pipetype (pipe)) {		case PIPE_BULK:	/* one TD for every 4096 Byte */			size = (urb->transfer_buffer_length - 1) / 4096 + 1;			/* If the transfer size is multiple of the pipe mtu,			 * we may need an extra TD to create a empty frame			 * Jean II */			 // 如果传输刚好是满包,则需要多一个空包			if ((urb->transfer_flags & USB_ZERO_PACKET) &&			    usb_pipeout (pipe) &&			    (urb->transfer_buffer_length != 0) && 			    ((urb->transfer_buffer_length % maxps) == 0))				size++;			break;		case PIPE_ISOCHRONOUS: /* number of packets from URB */			size = urb->number_of_packets;			if (size <= 0) {				usb_dec_dev_use (urb->dev);					return -EINVAL;			}			for (i = 0; i < urb->number_of_packets; i++) {  				urb->iso_frame_desc[i].actual_length = 0;  				urb->iso_frame_desc[i].status = -EXDEV;  			}			break;		case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */			size = (urb->transfer_buffer_length == 0)? 2: 						(urb->transfer_buffer_length - 1) / 4096 + 3;			break;		case PIPE_INTERRUPT: /* one TD */			size = 1;			// 中断传输只有一个TD(传输描述符)			break;	}	/* allocate the private part of the URB */	// 分配URB的私有数据RAM	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), 							in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);	if (!urb_priv) {		usb_dec_dev_use (urb->dev);			return -ENOMEM;	}	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *));		/* fill the private part of the URB */	urb_priv->length = size;		// 传输描述符的个数	urb_priv->ed = ed;					// 	/* allocate the TDs (updating hash chains) */	spin_lock_irqsave (&usb_ed_lock, flags);	for (i = 0; i < size; i++) { 		urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);// 分配传输描述符		if (!urb_priv->td[i]) {			urb_priv->length = i;			urb_free_priv (ohci, urb_priv);								// 释放URB私有数据			spin_unlock_irqrestore (&usb_ed_lock, flags);			usb_dec_dev_use (urb->dev);				return -ENOMEM;		}	}		if (ed->state == ED_NEW || (ed->state & ED_DEL)) {		// 检查端点状态

⌨️ 快捷键说明

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