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

📄 dwc_otg_pcd_intr.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif		dcfg.b.devaddr = ctrl.wValue;		dwc_modify_reg32( &dev_if->dev_global_regs->dcfg,									  0, dcfg.d32);		do_setup_in_status_phase( _pcd );	}}/** *	This function processes SETUP commands.	 In Linux, the USB Command *	processing is done in two places - the first being the PCD and the *	second in the Gadget Driver (for example, the File-Backed Storage *	Gadget Driver). * * <table> * <tr><td>Command	</td><td>Driver </td><td>Description</td></tr> * * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as * defined in chapter 9 of the USB 2.0 Specification chapter 9 * </td></tr> * * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint * requests are the ENDPOINT_HALT feature is procesed, all others the * interface requests are ignored.</td></tr> * * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint * requests are processed by the PCD.  Interface requests are passed * to the Gadget Driver.</td></tr> * * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg, * with device address received </td></tr> * * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the * requested descriptor</td></tr> * * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional - * not implemented by any of the existing Gadget Drivers.</td></tr> * * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable * all EPs and enable EPs for new configuration.</td></tr> * * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return * the current configuration</td></tr> * * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all * EPs and enable EPs for new configuration.</td></tr> * * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the * current interface.</td></tr> * * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug * message.</td></tr> * </table> * * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are * processed by pcd_setup. Calling the Function Driver's setup function from * pcd_setup processes the gadget SETUP commands. */static inline void pcd_setup( dwc_otg_pcd_t *_pcd ){	dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);	dwc_otg_dev_if_t *dev_if = core_if->dev_if;	struct usb_ctrlrequest	ctrl = _pcd->setup_pkt->req;	dwc_otg_pcd_ep_t	*ep0 = &_pcd->ep0;	deptsiz0_data_t doeptsize0 = { .d32 = 0};#ifdef DEBUG_EP0	DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",					ctrl.bRequestType, ctrl.bRequest,					ctrl.wValue, ctrl.wIndex, ctrl.wLength);#endif	doeptsize0.d32 = dwc_read_reg32( &dev_if->out_ep_regs[0]->doeptsiz );	/** @todo handle > 1 setup packet , assert error for now */	if (core_if->dma_enable && core_if->dma_desc_enable == 0 && (doeptsize0.b.supcnt < 2))	{		DWC_ERROR ("\n\n-----------	 CANNOT handle > 1 setup packet in DMA mode\n\n");	}	/* Clean up the request queue */	request_nuke( ep0 );	ep0->stopped = 0;	if (ctrl.bRequestType & USB_DIR_IN)	{		ep0->dwc_ep.is_in = 1;		_pcd->ep0state = EP0_IN_DATA_PHASE;	}	else	{		ep0->dwc_ep.is_in = 0;		_pcd->ep0state = EP0_OUT_DATA_PHASE;	}	if(ctrl.wLength == 0)	{		ep0->dwc_ep.is_in = 1;		_pcd->ep0state = EP0_IN_STATUS_PHASE;	}	if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)	{		/* handle non-standard (class/vendor) requests in the gadget driver */		do_gadget_setup(_pcd, &ctrl );		return;	}	/** @todo NGS: Handle bad setup packet? *//////////////////////////////////////////////// --- Standard Request handling --- ////	switch (ctrl.bRequest)	{		case USB_REQ_GET_STATUS:		do_get_status( _pcd);		break;	case USB_REQ_CLEAR_FEATURE:		do_clear_feature( _pcd );		break;	case USB_REQ_SET_FEATURE:		do_set_feature( _pcd );		break;	case USB_REQ_SET_ADDRESS:		do_set_address( _pcd );		break;	case USB_REQ_SET_INTERFACE:	case USB_REQ_SET_CONFIGURATION://		_pcd->request_config = 1;	/* Configuration changed */		do_gadget_setup(_pcd, &ctrl );		break;	case USB_REQ_SYNCH_FRAME:		do_gadget_setup(_pcd, &ctrl );		break;	default:		/* Call the Gadget Driver's setup functions */		do_gadget_setup(_pcd, &ctrl );		break;	}}/** * This function completes the ep0 control transfer. */static int32_t ep0_complete_request( dwc_otg_pcd_ep_t *_ep ){	dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd);	dwc_otg_dev_if_t *dev_if = core_if->dev_if;	dwc_otg_dev_in_ep_regs_t *in_ep_regs =	dev_if->in_ep_regs[_ep->dwc_ep.num];#ifdef DEBUG_EP0	dwc_otg_dev_out_ep_regs_t *out_ep_regs =			dev_if->out_ep_regs[_ep->dwc_ep.num];#endif	deptsiz0_data_t deptsiz;	desc_sts_data_t desc_sts;	dwc_otg_pcd_request_t *req;	int is_last = 0;	dwc_otg_pcd_t *pcd = _ep->pcd;	//DWC_DEBUGPL(DBG_PCDV, "%s() %s\n", __func__, _ep->ep.name);	if (pcd->ep0_pending && list_empty(&_ep->queue))	{		if (_ep->dwc_ep.is_in)		{#ifdef DEBUG_EP0			DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");#endif			do_setup_out_status_phase(pcd);		}		else		{#ifdef DEBUG_EP0			DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");#endif			do_setup_in_status_phase(pcd);		}		pcd->ep0_pending = 0;		return 1;	}	if (list_empty(&_ep->queue))	{		return 0;	}	req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t, queue);	if (pcd->ep0state == EP0_OUT_STATUS_PHASE || pcd->ep0state == EP0_IN_STATUS_PHASE)	{		is_last = 1;	}	else if (_ep->dwc_ep.is_in)	{		deptsiz.d32 = dwc_read_reg32( &in_ep_regs->dieptsiz);		if(core_if->dma_desc_enable != 0)			desc_sts.d32 = readl(dev_if->in_desc_addr);#ifdef DEBUG_EP0		DWC_DEBUGPL(DBG_PCDV, "%s len=%d  xfersize=%d pktcnt=%d\n",						_ep->ep.name, _ep->dwc_ep.xfer_len,						deptsiz.b.xfersize, deptsiz.b.pktcnt);#endif		if (((core_if->dma_desc_enable == 0) && (deptsiz.b.xfersize == 0)) ||			((core_if->dma_desc_enable != 0) && (desc_sts.b.bytes == 0)))		{			req->req.actual = _ep->dwc_ep.xfer_count;			/* Is a Zero Len Packet needed? */			if (req->req.zero)			{#ifdef DEBUG_EP0				DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");#endif			    req->req.zero = 0;			}			do_setup_out_status_phase(pcd);		}	}	else	{		/* ep0-OUT */#ifdef DEBUG_EP0		deptsiz.d32 = dwc_read_reg32( &out_ep_regs->doeptsiz);		DWC_DEBUGPL(DBG_PCDV, "%s len=%d xsize=%d pktcnt=%d\n",						_ep->ep.name, _ep->dwc_ep.xfer_len,						deptsiz.b.xfersize,						deptsiz.b.pktcnt);#endif		req->req.actual = _ep->dwc_ep.xfer_count;		/* Is a Zero Len Packet needed? */		if (req->req.zero) {#ifdef DEBUG_EP0			DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");#endif    			req->req.zero = 0;		}		if(core_if->dma_desc_enable == 0)			do_setup_in_status_phase(pcd);	}	/* Complete the request */	if (is_last)	{		request_done(_ep, req, 0);		_ep->dwc_ep.start_xfer_buff = 0;		_ep->dwc_ep.xfer_buff = 0;		_ep->dwc_ep.xfer_len = 0;		return 1;	}	return 0;}/** * This function completes the request for the EP.	If there are * additional requests for the EP in the queue they will be started. */static void complete_ep( dwc_otg_pcd_ep_t *_ep ){	dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd);	dwc_otg_dev_if_t *dev_if = core_if->dev_if;	dwc_otg_dev_in_ep_regs_t *in_ep_regs =	dev_if->in_ep_regs[_ep->dwc_ep.num];	deptsiz_data_t deptsiz;	desc_sts_data_t desc_sts;	dwc_otg_pcd_request_t *req = 0;	int is_last = 0;	DWC_DEBUGPL(DBG_PCDV,"%s() %s-%s\n", __func__, _ep->ep.name,					(_ep->dwc_ep.is_in?"IN":"OUT"));	/* Get any pending requests */	if (!list_empty(&_ep->queue))	{		req = list_entry(_ep->queue.next, dwc_otg_pcd_request_t,								 queue);		if (!req)		{			printk("complete_ep 0x%p, req = NULL!\n", _ep);			return;		}	}	else	{		printk("complete_ep 0x%p, ep->queue empty!\n", _ep);		return;	}	DWC_DEBUGPL(DBG_PCD, "Requests %d\n",_ep->pcd->request_pending);	if (_ep->dwc_ep.is_in)	{		deptsiz.d32 = dwc_read_reg32( &in_ep_regs->dieptsiz);		if(core_if->dma_desc_enable != 0)			desc_sts.d32 = readl(_ep->dwc_ep.desc_addr);		if (core_if->dma_enable)		{			if(core_if->dma_desc_enable == 0)			{				if (deptsiz.b.xfersize == 0)					_ep->dwc_ep.xfer_count = _ep->dwc_ep.xfer_len;				DWC_DEBUGPL(DBG_PCDV, "%s len=%d  xfersize=%d pktcnt=%d\n",								_ep->ep.name, _ep->dwc_ep.xfer_len,								deptsiz.b.xfersize, deptsiz.b.pktcnt);				if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0 &&						_ep->dwc_ep.xfer_count == _ep->dwc_ep.xfer_len)				{					is_last = 1;				}				else				{					DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n",							 _ep->ep.name, (_ep->dwc_ep.is_in?"IN":"OUT"),							 deptsiz.b.xfersize, deptsiz.b.pktcnt);				}			}			else			{				if(desc_sts.b.bytes == 0)				{					_ep->dwc_ep.xfer_count = _ep->dwc_ep.xfer_len;					is_last = 1;				}				else				{					DWC_WARN("Incomplete transfer\n");				}			}		}		else		{			DWC_DEBUGPL(DBG_PCDV, "%s len=%d  xfersize=%d pktcnt=%d\n",							_ep->ep.name, _ep->dwc_ep.xfer_len,							deptsiz.b.xfersize, deptsiz.b.pktcnt);			if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0 &&					_ep->dwc_ep.xfer_count == _ep->dwc_ep.xfer_len)			{				is_last = 1;			}			else			{				DWC_WARN("Incomplete transfer (%s-%s [siz=%d pkt=%d])\n",						 _ep->ep.name, (_ep->dwc_ep.is_in?"IN":"OUT"),						 deptsiz.b.xfersize, deptsiz.b.pktcnt);			}		}	}	else	{		dwc_otg_dev_out_ep_regs_t *out_ep_regs =					dev_if->out_ep_regs[_ep->dwc_ep.num];		desc_sts.d32 = 0;		if(core_if->dma_desc_enable != 0)			desc_sts.d32 = readl(_ep->dwc_ep.desc_addr);		deptsiz.d32 = 0;		deptsiz.d32 = dwc_read_reg32( &out_ep_regs->doeptsiz);#ifdef DEBUG		DWC_DEBUGPL(DBG_PCDV, "addr %p,	 %s len=%d cnt=%d xsize=%d pktcnt=%d\n",						&out_ep_regs->doeptsiz, _ep->ep.name, _ep->dwc_ep.xfer_len,						_ep->dwc_ep.xfer_count,						deptsiz.b.xfersize,						deptsiz.b.pktcnt);#endif		is_last = 1;	}	/* Complete the request */	if (is_last)	{		if (core_if->dma_enable)		{			if(core_if->dma_desc_enable == 0)			{				req->req.actual = _ep->dwc_ep.xfer_len - deptsiz.b.xfersize;			}			else			{				req->req.actual = _ep->dwc_ep.xfer_len - desc_sts.b.bytes;			}		}		else		{			req->req.actual = _ep->dwc_ep.xfer_count;		}		request_done(_ep, req, 0);		_ep->dwc_ep.start_xfer_buff = 0;		_ep->dwc_ep.xfer_buff = 0;		_ep->dwc_ep.xfer_len = 0;		/* If there is a request in the queue start it.*/		start_next_request( _ep );	}}#ifdef _EN_ISOC_void make_descriptors_host_ready(dwc_otg_iso_dma_desc_t *dma_desc,int count,int is_in){	int	i;	if(is_in){		iso_in_sts_data_t	sts = {.d32 = 0};		for(i = 0;i < count;++i,++dma_desc){			sts.d32 = readl(&dma_desc->status);			sts.b.bs = BS_HOST_READY;			writel(sts.d32,&dma_desc->status);		}	}else{		iso_out_sts_data_t	sts = {.d32 = 0};		for(i = 0;i < count;++i,++dma_desc){			sts.d32 = readl(&dma_desc->status);			sts.b.bs = BS_HOST_READY;			writel(sts.d32,&dma_desc->status);		}	}}/** * This function is called when Transfer complete interrupt is asserted * for ISO EP. It provides the Gadget driver the data buffer already * processed by PCD and makes some setup for further processing of * periodic transfers */static void process_iso_data_buf( dwc_otg_pcd_ep_t *_ep ){ 	int i, j;	dwc_ep_t *dwc_ep = &_ep->dwc_ep;	dwc_otg_iso_dma_desc_t* dma_desc;	dma_addr_t dma_ad;	volatile uint32_t	*addr;	dwc_otg_pcd_t		*pcd = _ep->pcd;	depctl_data_t		depctl = {.d32 = 0};	dwc_otg_core_if_t	*core_if;	if(_ep->iso_req->status == -ECONNRESET){		DWC_PRINT("Device has already disconnected\n");		/*Device has been disconnected*/		return;	}	if(dwc_ep->is_in == 0){		addr = &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->doepctl;	}else{		addr = &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;	}	/*	 * Core has disabled epena bit.	 * To continue transfers we need to enable it.	 */	depctl.d32 = dwc_read_reg32(addr);	//depctl.b.epena = 1;	//dwc_write_reg32(addr,depctl.d32);	core_if = GET_CORE_IF(pcd);	/** Reinit closed DMA Descriptors*/	if(dwc_ep->is_in == 0) /** ISO OUT EP */	{		iso_out_sts_data_t sts = { .d32 =0 };		iso_out_sts_data_t stsTmp = {.d32 = 0};		uint32_t data_per_desc;		struct usb_gadget_iso_packet_descriptor *iso_packet;		if(dwc_ep->proc_buf_num == 0)		{			/** Buffer 0 descriptors setup */			dma_ad = dwc_ep->dma_addr0;			iso_packet = _ep->iso_req->iso_packet_desc0;		}		else		{			/** Buffer 1 descriptors setup */			dma_ad = dwc_ep->dma_addr1;

⌨️ 快捷键说明

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