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

📄 dwc_otg_hcd.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 5 页
字号:
				struct usb_host_endpoint *_ep,				struct urb *_urb,				gfp_t _mem_flags){	int retval = 0;	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);	dwc_otg_qtd_t *qtd;#ifdef DEBUG	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {		dump_urb_info(_urb, "dwc_otg_hcd_urb_enqueue");	}#endif	dbg_otg("\n\n\n\n#############%s()\n\n\n", __FUNCTION__);	if (!dwc_otg_hcd->flags.b.port_connect_status) {		/* No longer connected. */		return -ENODEV;	}	qtd = dwc_otg_hcd_qtd_create(_urb);	if (qtd == NULL) {		DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");		return -ENOMEM;	}	retval = dwc_otg_hcd_qtd_add(qtd, dwc_otg_hcd);	if (retval < 0) {		DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "			  "Error status %d\n", retval);		dwc_otg_hcd_qtd_free(qtd);	}	return retval;}/** Aborts/cancels a USB transfer request. Always returns 0 to indicate * success.  */int dwc_otg_hcd_urb_dequeue(struct usb_hcd *_hcd, struct urb *_urb){	unsigned long flags;	dwc_otg_hcd_t *dwc_otg_hcd;	dwc_otg_qtd_t *urb_qtd;	dwc_otg_qh_t *qh;	struct usb_host_endpoint *_ep = dwc_urb_to_endpoint(_urb);	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");	dbg_otg("DWC OTG HCD URB Dequeue\n");	local_irq_save(flags);	dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);	urb_qtd = (dwc_otg_qtd_t *) _urb->hcpriv;	qh = (dwc_otg_qh_t *) _ep->hcpriv;#ifdef DEBUG	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {		dump_urb_info(_urb, "dwc_otg_hcd_urb_dequeue");		if (urb_qtd == qh->qtd_in_process) {			dump_channel_info(dwc_otg_hcd, qh);		}	}#endif	if (urb_qtd == qh->qtd_in_process) {		/* The QTD is in process (it has been assigned to a channel). */		if (dwc_otg_hcd->flags.b.port_connect_status) {			/*			 * If still connected (i.e. in host mode), halt the			 * channel so it can be used for other transfers. If			 * no longer connected, the host registers can't be			 * written to halt the channel since the core is in			 * device mode.			 */			dwc_otg_hc_halt(dwc_otg_hcd->core_if, qh->channel,					DWC_OTG_HC_XFER_URB_DEQUEUE);		}	}	/*	 * Free the QTD and clean up the associated QH. Leave the QH in the	 * schedule if it has any remaining QTDs.	 */	dwc_otg_hcd_qtd_remove_and_free(urb_qtd);	if (urb_qtd == qh->qtd_in_process) {		dwc_otg_hcd_qh_deactivate(dwc_otg_hcd, qh, 0);		qh->channel = NULL;		qh->qtd_in_process = NULL;	} else if (list_empty(&qh->qtd_list)) {		dwc_otg_hcd_qh_remove(dwc_otg_hcd, qh);	}	local_irq_restore(flags);	_urb->hcpriv = NULL;	/* Higher layer software sets URB status. */	usb_hcd_giveback_urb(_hcd, _urb);	if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {		DWC_PRINT("Called usb_hcd_giveback_urb()\n");		DWC_PRINT("  urb->status = %d\n", _urb->status);	}	return 0;}/** Frees resources in the DWC_otg controller related to a given endpoint. Also * clears state in the HCD related to the endpoint. Any URBs for the endpoint * must already be dequeued. */void dwc_otg_hcd_endpoint_disable(struct usb_hcd *_hcd, struct usb_host_endpoint *_ep){	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);	dwc_otg_qh_t *qh;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)	unsigned long flags;	int retry = 0;#endif	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "		    "endpoint=%d\n", _ep->desc.bEndpointAddress,		    dwc_ep_addr_to_endpoint(_ep->desc.bEndpointAddress));#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)      rescan:	local_irq_save(flags);	qh = (dwc_otg_qh_t *) (_ep->hcpriv);	if (!qh)		goto done;	/** Check that the QTD list is really empty */	if (!list_empty(&qh->qtd_list)) {		if (retry++ < 250) {			local_irq_restore(flags);			schedule_timeout_uninterruptible(1);			goto rescan;		}		DWC_WARN("DWC OTG HCD EP DISABLE:" " QTD List for this endpoint is not empty\n");	}	dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh);	_ep->hcpriv = NULL;      done:	local_irq_restore(flags);#else				// LINUX_VERSION_CODE	qh = (dwc_otg_qh_t *) (_ep->hcpriv);	if (qh != NULL) {#ifdef DEBUG		/** Check that the QTD list is really empty */		if (!list_empty(&qh->qtd_list)) {			DWC_WARN("DWC OTG HCD EP DISABLE:"				 " QTD List for this endpoint is not empty\n");		}#endif		dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh);		_ep->hcpriv = NULL;	}#endif				// LINUX_VERSION_CODE	return;}/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid * interrupt. * * This function is called by the USB core when an interrupt occurs */irqreturn_t dwc_otg_hcd_irq(struct usb_hcd * _hcd){	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);	return IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_otg_hcd));}/** Creates Status Change bitmap for the root hub and root port. The bitmap is * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 * is the status change indicator for the single root port. Returns 1 if either * change indicator is 1, otherwise returns 0. */int dwc_otg_hcd_hub_status_data(struct usb_hcd *_hcd, char *_buf){	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);	_buf[0] = 0;	_buf[0] |= (dwc_otg_hcd->flags.b.port_connect_status_change ||		    dwc_otg_hcd->flags.b.port_reset_change ||		    dwc_otg_hcd->flags.b.port_enable_change ||		    dwc_otg_hcd->flags.b.port_suspend_change ||		    dwc_otg_hcd->flags.b.port_over_current_change) << 1;#ifdef DEBUG	if (_buf[0]) {		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" " Root port status changed\n");		DWC_DEBUGPL(DBG_HCDV, "  port_connect_status_change: %d\n",			    dwc_otg_hcd->flags.b.port_connect_status_change);		DWC_DEBUGPL(DBG_HCDV, "  port_reset_change: %d\n",			    dwc_otg_hcd->flags.b.port_reset_change);		DWC_DEBUGPL(DBG_HCDV, "  port_enable_change: %d\n",			    dwc_otg_hcd->flags.b.port_enable_change);		DWC_DEBUGPL(DBG_HCDV, "  port_suspend_change: %d\n",			    dwc_otg_hcd->flags.b.port_suspend_change);		DWC_DEBUGPL(DBG_HCDV, "  port_over_current_change: %d\n",			    dwc_otg_hcd->flags.b.port_over_current_change);	}#endif	return (_buf[0] != 0);}#ifdef DWC_HS_ELECT_TST/* * Quick and dirty hack to implement the HS Electrical Test * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. * * This code was copied from our userspace app "hset". It sends a * Get Device Descriptor control sequence in two parts, first the * Setup packet by itself, followed some time later by the In and * Ack packets. Rather than trying to figure out how to add this * functionality to the normal driver code, we just hijack the * hardware, using these two function to drive the hardware * directly. */dwc_otg_core_global_regs_t *global_regs;dwc_otg_host_global_regs_t *hc_global_regs;dwc_otg_hc_regs_t *hc_regs;uint32_t *data_fifo;static void do_setup(void){	gintsts_data_t gintsts;	hctsiz_data_t hctsiz;	hcchar_data_t hcchar;	haint_data_t haint;	hcint_data_t hcint;	dbg_otg("%s\n", __FUNCTION__);	/* Enable HAINTs */	dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);	/* Enable HCINTs */	dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);	/* Read GINTSTS */	gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);	/* Read HAINT */	haint.d32 = dwc_read_reg32(&hc_global_regs->haint);	//fprintf(stderr, "HAINT: %08x\n", haint.d32);	/* Read HCINT */	hcint.d32 = dwc_read_reg32(&hc_regs->hcint);	//fprintf(stderr, "HCINT: %08x\n", hcint.d32);	/* Read HCCHAR */	hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);	//fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);	/* Clear HCINT */	dwc_write_reg32(&hc_regs->hcint, hcint.d32);	/* Clear HAINT */	dwc_write_reg32(&hc_global_regs->haint, haint.d32);	/* Clear GINTSTS */	dwc_write_reg32(&global_regs->gintsts, gintsts.d32);	/* Read GINTSTS */	gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);	/*	 * Send Setup packet (Get Device Descriptor)	 */	/* Make sure channel is disabled */	hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);	if (hcchar.b.chen) {		//fprintf(stderr, "Channel already enabled 1, HCCHAR = %08x\n", hcchar.d32);		hcchar.b.chdis = 1;//              hcchar.b.chen = 1;		dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);		//sleep(1);		mdelay(1000);		/* Read GINTSTS */		gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);		//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);		/* Read HAINT */		haint.d32 = dwc_read_reg32(&hc_global_regs->haint);		//fprintf(stderr, "HAINT: %08x\n", haint.d32);		/* Read HCINT */		hcint.d32 = dwc_read_reg32(&hc_regs->hcint);		//fprintf(stderr, "HCINT: %08x\n", hcint.d32);		/* Read HCCHAR */		hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);		//fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);		/* Clear HCINT */		dwc_write_reg32(&hc_regs->hcint, hcint.d32);		/* Clear HAINT */		dwc_write_reg32(&hc_global_regs->haint, haint.d32);		/* Clear GINTSTS */		dwc_write_reg32(&global_regs->gintsts, gintsts.d32);		hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);		//if (hcchar.b.chen) {		//      fprintf(stderr, "** Channel _still_ enabled 1, HCCHAR = %08x **\n", hcchar.d32);		//}	}	/* Set HCTSIZ */	hctsiz.d32 = 0;	hctsiz.b.xfersize = 8;	hctsiz.b.pktcnt = 1;	hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;	dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);	/* Set HCCHAR */	hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);	hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;	hcchar.b.epdir = 0;	hcchar.b.epnum = 0;	hcchar.b.mps = 8;	hcchar.b.chen = 1;	dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);	/* Fill FIFO with Setup data for Get Device Descriptor */	data_fifo = (uint32_t *) ((char *) global_regs + 0x1000);	dwc_write_reg32(data_fifo++, 0x01000680);	dwc_write_reg32(data_fifo++, 0x00080000);	gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	//fprintf(stderr, "Waiting for HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);	/* Wait for host channel interrupt */	do {		gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	} while (gintsts.b.hcintr == 0);	//fprintf(stderr, "Got HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);	/* Disable HCINTs */	dwc_write_reg32(&hc_regs->hcintmsk, 0x0000);	/* Disable HAINTs */	dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000);	/* Read HAINT */	haint.d32 = dwc_read_reg32(&hc_global_regs->haint);	//fprintf(stderr, "HAINT: %08x\n", haint.d32);	/* Read HCINT */	hcint.d32 = dwc_read_reg32(&hc_regs->hcint);	//fprintf(stderr, "HCINT: %08x\n", hcint.d32);	/* Read HCCHAR */	hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);	//fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);	/* Clear HCINT */	dwc_write_reg32(&hc_regs->hcint, hcint.d32);	/* Clear HAINT */	dwc_write_reg32(&hc_global_regs->haint, haint.d32);	/* Clear GINTSTS */	dwc_write_reg32(&global_regs->gintsts, gintsts.d32);	/* Read GINTSTS */	gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);}static void do_in_ack(void){	gintsts_data_t gintsts;	hctsiz_data_t hctsiz;	hcchar_data_t hcchar;	haint_data_t haint;	hcint_data_t hcint;	host_grxsts_data_t grxsts;	dbg_otg("%s\n", __FUNCTION__);	/* Enable HAINTs */	dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001);	/* Enable HCINTs */	dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3);	/* Read GINTSTS */	gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);	/* Read HAINT */	haint.d32 = dwc_read_reg32(&hc_global_regs->haint);	//fprintf(stderr, "HAINT: %08x\n", haint.d32);	/* Read HCINT */	hcint.d32 = dwc_read_reg32(&hc_regs->hcint);	//fprintf(stderr, "HCINT: %08x\n", hcint.d32);	/* Read HCCHAR */	hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);	//fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);	/* Clear HCINT */	dwc_write_reg32(&hc_regs->hcint, hcint.d32);	/* Clear HAINT */	dwc_write_reg32(&hc_global_regs->haint, haint.d32);	/* Clear GINTSTS */	dwc_write_reg32(&global_regs->gintsts, gintsts.d32);	/* Read GINTSTS */	gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);	//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);	/*	 * Receive Control In packet	 */	/* Make sure channel is disabled */	hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);	if (hcchar.b.chen) {		//fprintf(stderr, "Channel already enabled 2, HCCHAR = %08x\n", hcchar.d32);		hcchar.b.chdis = 1;		hcchar.b.chen = 1;		dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);		//sleep(1);		mdelay(1000);		/* Read GINTSTS */		gintsts.d32 = dwc_read_reg32(&global_regs->gintsts);		//fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);		/* Read HAINT */

⌨️ 快捷键说明

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