Ejemplo n.º 1
0
Archivo: xusbps_hw.c Proyecto: 8l/mxp
/**
* This function perform the reset sequence to the given usbps interface by 
* configuring the appropriate control bits in the usbps specifc registers.
* the usbps reset sequence involves the below steps
* 	Disbale the interrupts
*	Clear the status registers
*	Apply the reset command and wait for reset complete status
*	Update the relevant control registers with reset values
* @param   BaseAddress of the interface
*
* @return   N/A.
*
* @note     None.
*
******************************************************************************/
void XUsbPs_ResetHw(u32 BaseAddress)
{
	u32 RegVal;
	u32 Timeout = 0;
	
	/* Host and device mode */
	/* Disable the interrupts */
	XUsbPs_WriteReg(BaseAddress,XUSBPS_IER_OFFSET,0x0);
	/* Clear the interuupt status */
	RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_ISR_OFFSET);
	XUsbPs_WriteReg(BaseAddress,XUSBPS_ISR_OFFSET,RegVal);

	/* Perform the reset operation using USB CMD register */	
	RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET);
	RegVal = RegVal | XUSBPS_CMD_RST_MASK;
	XUsbPs_WriteReg(BaseAddress,XUSBPS_CMD_OFFSET,RegVal);
	RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET);
	/* Wait till the reset operation returns success */
	/*
	* FIX ME: right now no indication to the caller or user about
	* timeout overflow
	*/
	while ((RegVal & XUSBPS_CMD_RST_MASK) && (Timeout < XUSBPS_RESET_TIMEOUT))
	{
		RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET);	
		Timeout++;
	}
	/* Update periodic list base address register with reset value */		
	XUsbPs_WriteReg(BaseAddress,XUSBPS_LISTBASE_OFFSET,0x0);	
	/* Update async/endpoint list base address register with reset value */		
	XUsbPs_WriteReg(BaseAddress,XUSBPS_ASYNCLISTADDR_OFFSET,0x0);		
	
}
Ejemplo n.º 2
0
/**
 *
 * This function configures the DEVICE side of the controller. The caller needs
 * to pass in the desired configuration (e.g. number of endpoints) and a
 * DMAable buffer that will hold the Queue Head List and the Transfer
 * Descriptors. The required size for this buffer can be obtained by the caller
 * using the: XUsbPs_DeviceMemRequired() macro.
 *
 * @param	InstancePtr is a pointer to the XUsbPs instance of the
 *		controller.
 * @param	CfgPtr is a pointer to the configuration structure that contains
 *		the desired DEVICE side configuration.
 *
 * @return
 *		- XST_SUCCESS: The operation completed successfully.
 *		- XST_FAILURE: An error occured.
 *
 * @note
 * 		The caller may configure the controller for both, DEVICE and
 * 		HOST side.
 *
 ******************************************************************************/
int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr,
			    const XUsbPs_DeviceConfig *CfgPtr)
{
	int	Status;
	u32 ModeValue = 0x0;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(CfgPtr      != NULL);

	/* Copy the configuration data over into the local instance structure */
	InstancePtr->DeviceConfig = *CfgPtr;


	/* Align the buffer to a 2048 byte (XUSBPS_dQH_BASE_ALIGN) boundary.*/
	InstancePtr->DeviceConfig.PhysAligned =
		(InstancePtr->DeviceConfig.DMAMemPhys +
					 XUSBPS_dQH_BASE_ALIGN) &
						~(XUSBPS_dQH_BASE_ALIGN -1);

	/* Initialize the endpoint pointer list data structure. */
	XUsbPs_EpListInit(&InstancePtr->DeviceConfig);


	/* Initialize the Queue Head structures in DMA memory. */
	XUsbPs_dQHInit(&InstancePtr->DeviceConfig);


	/* Initialize the Transfer Descriptors in DMA memory.*/
	Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig);
	if (XST_SUCCESS != Status) {
		return XST_FAILURE;
	}

	/* Changing the DEVICE mode requires a controller RESET. */
	if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) {
		return XST_FAILURE;
	}

	/* Set the Queue Head List address. */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPLISTADDR_OFFSET,
				InstancePtr->DeviceConfig.PhysAligned);

	/* Set the USB mode register to configure DEVICE mode.
	 *
	 * XUSBPS_MODE_SLOM_MASK note:
	 *   Disable Setup Lockout. Setup Lockout is not required as we
	 *   will be using the tripwire mechanism when handling setup
	 *   packets.
	 */
	ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK;

	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_MODE_OFFSET, ModeValue);

	XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET,
				XUSBPS_OTGSC_OT_MASK);

	return XST_SUCCESS;
}
Ejemplo n.º 3
0
/**
*
* This function performs device reset, device is stopped at the end.
*
* @param	InstancePtr is a pointer to XUsbPs instance of the controller.
*
* @return	None.
*
* @note 	None.
*
******************************************************************************/
void XUsbPs_DeviceReset(XUsbPs *InstancePtr)
{
	int Timeout;

	/* Clear all setup token semaphores by reading the
	 * XUSBPS_EPSTAT_OFFSET register and writing its value back to
	 * itself.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET,
		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
			XUSBPS_EPSTAT_OFFSET));

	/* Clear all the endpoint complete status bits by reading the
	 * XUSBPS_EPCOMPL_OFFSET register and writings its value back
	 * to itself.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET,
		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
			XUSBPS_EPCOMPL_OFFSET));

	/* Cancel all endpoint prime status by waiting until all bits
	 * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF
	 * to XUSBPS_EPFLUSH_OFFSET.
	 *
	 * Avoid hanging here by using a Timeout counter...
	 */
	Timeout = XUSBPS_TIMEOUT_COUNTER;
	while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPPRIME_OFFSET) &
				XUSBPS_EP_ALL_MASK) && --Timeout) {
		/* NOP */
	}
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF);

	XUsbPs_Stop(InstancePtr);

	/* Write to CR register for controller reset */
 	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_CMD_OFFSET) | XUSBPS_CMD_RST_MASK);

	/* Wait for reset to finish, hardware clears the reset bit once done  */
	Timeout = 1000000;
	while((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_CMD_OFFSET) &
				XUSBPS_CMD_RST_MASK) && --Timeout) {
		/* NOP */
	}
}
Ejemplo n.º 4
0
/**
* This function primes an endpoint.
*
* @param	InstancePtr is pointer to the XUsbPs instance.
* @param	EpNum is the number of the endpoint to receive data from.
* @param	Direction is the direction of the endpoint (bitfield):
* 			- XUSBPS_EP_DIRECTION_OUT
* 			- XUSBPS_EP_DIRECTION_IN
*
* @return
*		- XST_SUCCESS: The operation completed successfully.
*		- XST_FAILURE: An error occured.
*		- XST_INVALID_PARAM: Invalid parameter passed.
*
* @note		None.
*
******************************************************************************/
int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction)
{
	u32	Mask;

	Xil_AssertNonvoid(InstancePtr  != NULL);
	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);

	/* Get the right bit mask for the endpoint direction. */
	switch (Direction) {

	case XUSBPS_EP_DIRECTION_OUT:
		Mask = 0x00000001;
		break;

	case XUSBPS_EP_DIRECTION_IN:
		Mask = 0x00010000;
		break;

	default:
		return XST_INVALID_PARAM;
	}

	/* Write the endpoint prime register. */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPPRIME_OFFSET, Mask << EpNum);

	return XST_SUCCESS;
}
Ejemplo n.º 5
0
/**
* This functions sets the controller's DEVICE address. It also sets the
* advance bit so the controller will wait for the next IN-ACK before the new
* address takes effect.
*
* @param	InstancePtr is a pointer to XUsbPs instance of the controller.
* @param	Address is the Address of the device.
*
* @return
*		- XST_SUCCESS: Address set successfully.
*		- XST_FAILURE: An error occured.
*		- XST_INVALID_PARAM: Invalid parameter passed, e.g. address
*		value too big.
*
* @note 	None.
*
*****************************************************************************/
int XUsbPs_SetDeviceAddress(XUsbPs *InstancePtr, u8 Address)
{
	Xil_AssertNonvoid(InstancePtr != NULL);

	/* Check address range validity. */
	if (Address > XUSBPS_DEVICEADDR_MAX) {
		return XST_INVALID_PARAM;
	}

	/* Set the address register with the Address value provided. Also set
	 * the Address Advance Bit. This will cause the address to be set only
	 * after an IN occured and has been ACKed on the endpoint.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_DEVICEADDR_OFFSET,
			 	(Address << XUSBPS_DEVICEADDR_ADDR_SHIFT) |
			 	XUSBPS_DEVICEADDR_DEVICEAADV_MASK);

	return XST_SUCCESS;
}
Ejemplo n.º 6
0
/**
*
* This function resets the USB device. All the configuration registers are
* reset to their default values. The function waits until the reset operation
* is complete or for a certain duration within which the reset operation is
* expected to be completed.
*
* @param	InstancePtr is a pointer to XUsbPs instance of the controller.
*
* @return
*		- XST_SUCCESS Reset operation completed successfully.
*		- XST_FAILURE Reset operation timed out.
*
* @note 	None.
*
******************************************************************************/
int XUsbPs_Reset(XUsbPs *InstancePtr)
{
	int Timeout;

	Xil_AssertNonvoid(InstancePtr != NULL);

	/* Write a 1 to the RESET bit. The RESET bit is cleared by HW once the
	 * RESET is complete.
	 *
	 * We are going to wait for the RESET bit to clear before we return
	 * from this function. Unfortunately we do not have timers available at
	 * this point to determine when we should report a Timeout.
	 *
	 * However, by using a large number for the poll loop we can assume
	 * that the polling operation will take longer than the expected time
	 * the HW needs to RESET. If the poll loop expires we can assume a
	 * Timeout. The drawback is that on a slow system (and even on a fast
	 * system) this can lead to _very_ long Timeout periods.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_CMD_OFFSET, XUSBPS_CMD_RST_MASK);


	/* Wait for the RESET bit to be cleared by HW. */
	Timeout = XUSBPS_TIMEOUT_COUNTER;
	while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_CMD_OFFSET) &
				XUSBPS_CMD_RST_MASK) && --Timeout) {
		/* NOP */
	}

	if (0 == Timeout) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Ejemplo n.º 7
0
/**
* This function is the first-level interrupt handler for the USB core. All USB
* interrupts will be handled here. Depending on the type of the interrupt,
* second level interrupt handler may be called. Second level interrupt
* handlers will be registered by the user using the:
*    XUsbPs_IntrSetHandler()
* and/or
*    XUsbPs_EpSetHandler()
* functions.
*
*
* @param	HandlerRef is a Reference passed to the interrupt register
*		function. In our case this will be a pointer to the XUsbPs
*		instance.
*
* @return	None
*
* @note		None
*
******************************************************************************/
void XUsbPs_IntrHandler(void *HandlerRef)
{
	XUsbPs	*InstancePtr;

	u32	IrqSts;

	Xil_AssertVoid(HandlerRef != NULL);

	InstancePtr = (XUsbPs *) HandlerRef;

	/* Handle controller (non-endpoint) related interrupts. */
	IrqSts = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_ISR_OFFSET);

	/* Clear the interrupt status register. */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_ISR_OFFSET, IrqSts);

	/* Nak interrupt, used to respond to host's IN request */
	if(IrqSts & XUSBPS_IXR_NAK_MASK) {
		/* Ack the hardware	 */
		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
					XUSBPS_EPNAKISR_OFFSET,
			XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
						XUSBPS_EPNAKISR_OFFSET));
	}


	/***************************************************************
	 *
	 * Handle general interrupts. Endpoint interrupts will be handler
	 * later.
	 *
	 */

	/* RESET interrupt.*/
	if (IrqSts & XUSBPS_IXR_UR_MASK) {
		XUsbPs_IntrHandleReset(InstancePtr, IrqSts);
		return;
	}

	/* Check if we have a user handler that needs to be called. Note that
	 * this is the handler for general interrupts. Endpoint interrupts will
	 * be handled below.
	 */
	if ((IrqSts & InstancePtr->HandlerMask) && InstancePtr->HandlerFunc) {
		(InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts);
	}


	/***************************************************************
	 *
	 * Handle Endpoint interrupts.
	 *
	 */
	if (IrqSts & XUSBPS_IXR_UI_MASK) {
		u32	EpStat;
		u32	EpCompl;

		/* ENDPOINT 0 SETUP PACKET HANDLING
		 *
		 * Check if we got a setup packet on endpoint 0. Currently we
		 * only check for setup packets on endpoint 0 as we would not
		 * expect setup packets on any other endpoint (even though it
		 * is possible to send setup packets on other endpoints).
		 */
		EpStat = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
						XUSBPS_EPSTAT_OFFSET);
		if (EpStat & 0x0001) {
			/* Handle the setup packet */
			XUsbPs_IntrHandleEp0Setup(InstancePtr);

			/* Re-Prime the endpoint.
			 * Endpoint is de-primed if a setup packet comes in.
	 		 */
			XUsbPs_EpPrime(InstancePtr, 0, XUSBPS_EP_DIRECTION_OUT);
		}

		/* Check for RX and TX complete interrupts. */
		EpCompl = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
						XUSBPS_EPCOMPL_OFFSET);


		/* ACK the complete interrupts. */
		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
					XUSBPS_EPCOMPL_OFFSET, EpCompl);

		/* Check OUT (RX) endpoints. */
		if (EpCompl & XUSBPS_EP_OUT_MASK) {
			XUsbPs_IntrHandleRX(InstancePtr, EpCompl);
		}

		/* Check IN (TX) endpoints. */
		if (EpCompl & XUSBPS_EP_IN_MASK) {
			XUsbPs_IntrHandleTX(InstancePtr, EpCompl);
		}
	}
}
Ejemplo n.º 8
0
/**
* This function handles a RESET interrupt. It will notify the interrupt
* handler callback of the RESET condition.
*
* @param	InstancePtr is pointer to the XUsbPs instance of the controller
* @param	IrqSts is the Interrupt status register content.
*		To be passed on to the user.
*
* @return	None
*
* @Note		None.
*
******************************************************************************/
static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts)
{
	int Timeout;

	/* Clear all setup token semaphores by reading the
	 * XUSBPS_EPSTAT_OFFSET register and writing its value back to
	 * itself.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET,
		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPSTAT_OFFSET));

	/* Clear all the endpoint complete status bits by reading the
	 * XUSBPS_EPCOMPL_OFFSET register and writings its value back
	 * to itself.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
			XUSBPS_EPCOMPL_OFFSET,
		XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPCOMPL_OFFSET));

	/* Cancel all endpoint prime status by waiting until all bits
	 * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF
	 * to XUSBPS_EPFLUSH_OFFSET.
	 *
	 * Avoid hanging here by using a Timeout counter...
	 */
	Timeout = XUSBPS_TIMEOUT_COUNTER;
	while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
					XUSBPS_EPPRIME_OFFSET) &
					XUSBPS_EP_ALL_MASK) && --Timeout) {
		/* NOP */
	}
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF);

	/* Make sure that the reset bit in XUSBPS_PORTSCR1_OFFSET is
	 * still set at this point. If the code gets to this point and
	 * the reset bit has already been cleared we are in trouble and
	 * hardware reset is necessary.
	 */
	if (!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_PORTSCR1_OFFSET) &
				XUSBPS_PORTSCR_PR_MASK)) {
		/* Send a notification to the user that a hardware
		 * RESET is required. At this point we can only hope
		 * that the user registered an interrupt handler and
		 * will issue a hardware RESET.
		 */
		if (InstancePtr->HandlerFunc) {
			(InstancePtr->HandlerFunc)(InstancePtr->HandlerRef,
						   IrqSts);
		}
		else {
			for (;;);
		}

		/* If we get here there is nothing more to do. The user
		 * should have reset the core.
		 */
		return;
	}

	/* Check if we have a user handler that needs to be called.
	 */
	if (InstancePtr->HandlerFunc) {
		(InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts);
	}

	/* We are done. After RESET we don't proceed in the interrupt
	 * handler.
	 */
}
Ejemplo n.º 9
0
/**
* This function extracts the Setup Data from a given endpoint.
*
* @param	InstancePtr is a pointer to the XUsbPs instance of the
*		controller.
* @param	EpNum is the number of the endpoint to receive data from.
* @param	SetupDataPtr is a pointer to the setup data structure to be
*		filled.
*
* @return
*		- XST_SUCCESS: The operation completed successfully.
*		- XST_FAILURE: An error occured.
*
* @note		None.
******************************************************************************/
int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum,
				XUsbPs_SetupData *SetupDataPtr)
{
	XUsbPs_EpOut	*Ep;

	u32	Data[2];
	u8	*p;

	int Timeout;

	Xil_AssertNonvoid(InstancePtr  != NULL);
	Xil_AssertNonvoid(SetupDataPtr != NULL);
	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);

	Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;


	/* Get the data from the Queue Heads Setup buffer into local variables
	 * so we can extract the setup data values.
	 */
	do {
		/* Arm the tripwire. The tripwire will tell us if a new setup
		 * packet arrived (in which case the tripwire bit will be
		 * cleared) while we were reading the buffer. If a new setup
		 * packet arrived the buffer is corrupted and we continue
		 * reading.
		 */
		XUsbPs_SetTripwire(InstancePtr);

		XUsbPs_dQHInvalidateCache(Ep->dQH);

		Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0);
		Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1);
	} while (FALSE == XUsbPs_TripwireIsSet(InstancePtr));

	/* Clear the pending endpoint setup stat bit.
	 */
	XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPSTAT_OFFSET, 1 << EpNum);

	/* Clear the Tripwire bit and continue.
	 */
	XUsbPs_ClrTripwire(InstancePtr);


	/* Data in the setup buffer is being converted by the core to big
	 * endian format. We have to take care of proper byte swapping when
	 * reading the setup data values.
	 *
	 * Need to check if there is a smarter way to do this and take the
	 * processor/memory-controller endianess into account?
	 */
	p = (u8 *) Data;

	SetupDataPtr->bmRequestType	= p[0];
	SetupDataPtr->bRequest		= p[1];
	SetupDataPtr->wValue		= (p[3] << 8) | p[2];
	SetupDataPtr->wIndex		= (p[5] << 8) | p[4];
	SetupDataPtr->wLength		= (p[7] << 8) | p[6];

	/* Before we leave we need to make sure that the endpoint setup bit has
	 * cleared. It needs to be 0 before the endpoint can be re-primed.
	 *
	 * Note: According to the documentation this endpoint setup bit should
	 * clear within 1-2us after it has been written above. This means that
	 * we should never catch it being 1 here. However, we still need to
	 * poll it to make sure. Just in case, we use a counter 'Timeout' so we
	 * won't hang here if the bit is stuck for some reason.
	 */
	Timeout = XUSBPS_TIMEOUT_COUNTER;
	while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
				XUSBPS_EPSTAT_OFFSET) &
				(1 << EpNum)) && --Timeout) {
		/* NOP */
	}
	if (0 == Timeout) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Ejemplo n.º 10
0
/**
* This function sends a given data buffer.
*
* @param	InstancePtr is a pointer to XUsbPs instance of the controller.
* @param	EpNum is the number of the endpoint to receive data from.
* @param	BufferPtr is a pointer to the buffer to send.
* @param	BufferLen is the Buffer length.
*
* @return
*		- XST_SUCCESS: The operation completed successfully.
*		- XST_FAILURE: An error occured.
*		- XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
*		- XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
*
******************************************************************************/
int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum,
				const u8 *BufferPtr, u32 BufferLen)
{
	int		Status;
	u32		Token;
	XUsbPs_EpIn	*Ep;
	XUsbPs_dTD	*DescPtr;
	u32 		Length;
	u32		PipeEmpty = 1;
	u32		Mask = 0x00010000;
	u32		BitMask = Mask << EpNum;
	u32		RegValue;
	u32		Temp;

	Xil_AssertNonvoid(InstancePtr  != NULL);
	Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);

	/* Locate the next available buffer in the ring. A buffer is available
	 * if its descriptor is not active.
	 */
	Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In;

	Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen);

	if(Ep->dTDTail != Ep->dTDHead) {
		PipeEmpty = 0;
	}
	XUsbPs_dTDInvalidateCache(Ep->dTDHead);

	/* Tell the caller if we do not have any descriptors available. */
	if (XUsbPs_dTDIsActive(Ep->dTDHead)) {
		return XST_USB_NO_DESC_AVAILABLE;
	}

	/* Remember the current head. */
	DescPtr = Ep->dTDHead;

	do {
		Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen;
		/* Attach the provided buffer to the current descriptor.*/
		Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length);
		if (XST_SUCCESS != Status) {
			return XST_FAILURE;
		}
		BufferLen -= Length;
		BufferPtr += Length;

		XUsbPs_dTDSetActive(Ep->dTDHead);
		if(BufferLen == 0)
			XUsbPs_dTDSetIOC(Ep->dTDHead);
		XUsbPs_dTDClrTerminate(Ep->dTDHead);
		XUsbPs_dTDFlushCache(Ep->dTDHead);

		/* Advance the head descriptor pointer to the next descriptor. */
		Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead);
		/* Terminate the next descriptor and flush the cache.*/
		XUsbPs_dTDInvalidateCache(Ep->dTDHead);
		/* Tell the caller if we do not have any descriptors available. */
		if (XUsbPs_dTDIsActive(Ep->dTDHead)) {
			return XST_USB_NO_DESC_AVAILABLE;
		}
	} while(BufferLen);

	XUsbPs_dTDSetTerminate(Ep->dTDHead);
	XUsbPs_dTDFlushCache(Ep->dTDHead);

	if(!PipeEmpty) {
		/* Read the endpoint prime register. */
		RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET);
		if(RegValue & BitMask) {
			return XST_SUCCESS;
		}

		do {
			RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);
			XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
						RegValue | XUSBPS_CMD_ATDTW_MASK);
			Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET)
						& BitMask;
		} while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) &
				XUSBPS_CMD_ATDTW_MASK));

		RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);
		XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
					RegValue & ~XUSBPS_CMD_ATDTW_MASK);

		if(Temp) {
			return XST_SUCCESS;
		}
	}

	/* Check, if the DMA engine is still running. If it is running, we do
	 * not clear Queue Head fields.
	 *
	 * Same cache rule as for the Transfer Descriptor applies for the Queue
	 * Head.
	 */
	XUsbPs_dQHInvalidateCache(Ep->dQH);
	/* Add the dTD to the dQH */
	XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr);
	Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN);
	Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK);
	XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token);

	XUsbPs_dQHFlushCache(Ep->dQH);

	Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN);

	return Status;
}