+++ /dev/null
-/******************************************************************************
-*
-* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* Use of the Software is limited solely to applications:
-* (a) running on a Xilinx device, or
-* (b) that interact with a Xilinx device through a bus or interconnect.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* Except as contained in this notice, the name of the Xilinx shall not be used
-* in advertising or otherwise to promote the sale, use or other dealings in
-* this Software without prior written authorization from Xilinx.
-*
-******************************************************************************/
-/******************************************************************************/
-/**
- * @file xusbps_endpoint.c
-* @addtogroup usbps_v2_1
-* @{
- *
- * Endpoint specific function implementations.
- *
- * @note None.
- *
- * <pre>
- * MODIFICATION HISTORY:
- *
- * Ver Who Date Changes
- * ----- ---- -------- --------------------------------------------------------
- * 1.00a jz 10/10/10 First release
- * 1.03a nm 09/21/12 Fixed CR#678977. Added proper sequence for setup packet
- * handling.
- * 1.04a nm 11/02/12 Fixed CR#683931. Mult bits are set properly in dQH.
- * 2.00a kpc 04/03/14 Fixed CR#777763. Updated the macro names
- * 2.1 kpc 04/28/14 Added XUsbPs_EpBufferSendWithZLT api and merged common
- * code to XUsbPs_EpQueueRequest.
- * </pre>
- ******************************************************************************/
-
-/***************************** Include Files **********************************/
-
-#include <string.h> /* for bzero() */
-#include <stdio.h>
-
-#include "xusbps.h"
-#include "xusbps_endpoint.h"
-
-/************************** Constant Definitions ******************************/
-
-/**************************** Type Definitions ********************************/
-
-/************************** Variable Definitions ******************************/
-
-/************************** Function Prototypes ******************************/
-
-static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr);
-static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr);
-static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr);
-static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
- const u8 *BufferPtr, u32 BufferLen);
-
-static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len);
-
-/* Functions to reconfigure endpoint upon host's set alternate interface
- * request.
- */
-static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
- int EpNum, unsigned short NewDirection);
-static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
- int EpNum, unsigned short NewDirection);
-static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
- const u8 *BufferPtr, u32 BufferLen, u8 ReqZero);
-
-/******************************* Functions ************************************/
-
-/*****************************************************************************/
-/**
- *
- * 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;
-}
-
-/*****************************************************************************/
-/**
-* 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)
-{
- Xil_AssertNonvoid(InstancePtr != NULL);
- Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
-
- return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
- BufferLen, FALSE);
-}
-
-/*****************************************************************************/
-/**
-* This function sends a given data buffer and also zero length packet if the
-* Bufferlen is in multiples of endpoint max packet size.
-*
-* @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_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum,
- const u8 *BufferPtr, u32 BufferLen)
-{
- u8 ReqZero = FALSE;
- XUsbPs_EpSetup *Ep;
-
- Xil_AssertNonvoid(InstancePtr != NULL);
- Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
-
- Ep = &InstancePtr->DeviceConfig.EpCfg[EpNum].In;
-
- if ((BufferLen >= Ep->MaxPacketSize) &&
- (BufferLen % Ep->MaxPacketSize == 0)) {
- ReqZero = TRUE;
- }
-
- return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
- BufferLen, ReqZero);
-}
-
-/*****************************************************************************/
-/**
-* This function sends a given data buffer and also sends ZLT packet if it is
-* requested.
-*
-* @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.
-* @param ReqZero is the
-*
-* @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.
-*
-******************************************************************************/
-static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
- const u8 *BufferPtr, u32 BufferLen, u8 ReqZero)
-{
- 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;
- u32 exit = 1;
-
-
- /* 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 && (ReqZero == FALSE)) {
- XUsbPs_dTDSetIOC(Ep->dTDHead);
- exit = 0;
- }
- 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;
- }
-
- if (ReqZero && BufferLen == 0) {
- ReqZero = FALSE;
- }
-
- } while(BufferLen || exit);
-
- 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;
-}
-
-/*****************************************************************************/
-/**
- * This function receives a data buffer from the endpoint of the given endpoint
- * number.
- *
- * @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 BufferPtr (OUT param) is a pointer to the buffer pointer to hold
- * the reference of the data buffer.
- * @param BufferLenPtr (OUT param) is a pointer to the integer that will
- * hold the buffer length.
- * @param Handle is the opaque handle to be used when the buffer is
- * released.
- *
- * @return
- * - XST_SUCCESS: The operation completed successfully.
- * - XST_FAILURE: An error occured.
- * - XST_USB_NO_BUF: No buffer available.
- *
- * @note
- * After handling the data in the buffer, the user MUST release
- * the buffer using the Handle by calling the
- * XUsbPs_EpBufferRelease() function.
- *
- ******************************************************************************/
-int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum,
- u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle)
-{
- XUsbPs_EpOut *Ep;
- XUsbPs_EpSetup *EpSetup;
- u32 length = 0;
-
- Xil_AssertNonvoid(InstancePtr != NULL);
- Xil_AssertNonvoid(BufferPtr != NULL);
- Xil_AssertNonvoid(BufferLenPtr != NULL);
- Xil_AssertNonvoid(Handle != 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].Out;
-
- XUsbPs_dTDInvalidateCache(Ep->dTDCurr);
-
- if (XUsbPs_dTDIsActive(Ep->dTDCurr)) {
- return XST_USB_NO_BUF;
- }
-
- /* The buffer is not active which means that it has been processed by
- * the DMA engine and contains valid data.
- */
- EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out;
-
-
- /* Use the buffer pointer stored in the "user data" field of the
- * Transfer Descriptor.
- */
- *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr,
- XUSBPS_dTDUSERDATA);
-
- length = EpSetup->BufSize -
- XUsbPs_dTDGetTransferLen(Ep->dTDCurr);
-
- if(length > 0) {
- *BufferLenPtr = length;
- }else {
- *BufferLenPtr = 0;
- }
-
- *Handle = (u32) Ep->dTDCurr;
-
-
- /* Reset the descriptor's BufferPointer0 and Transfer Length fields to
- * their original value. Note that we can not yet re-activate the
- * descriptor as the caller will be using the attached buffer. Once the
- * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we
- * can re-activate the descriptor.
- */
- XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr);
- XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize);
-
- XUsbPs_dTDFlushCache(Ep->dTDCurr);
-
- return XST_SUCCESS;
-}
-
-
-/*****************************************************************************/
-/**
-* This function returns a previously received data buffer to the driver.
-*
-* @param Handle is a pointer to the buffer that is returned.
-*
-* @return None.
-*
-******************************************************************************/
-void XUsbPs_EpBufferRelease(u32 Handle)
-{
- XUsbPs_dTD *dTDPtr;
-
- /* Perform sanity check on Handle.*/
- Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN)));
-
- /* Activate the descriptor and clear the Terminate bit. Make sure to do
- * the proper cache handling.
- */
- dTDPtr = (XUsbPs_dTD *) Handle;
-
- XUsbPs_dTDInvalidateCache(dTDPtr);
-
- XUsbPs_dTDClrTerminate(dTDPtr);
- XUsbPs_dTDSetActive(dTDPtr);
- XUsbPs_dTDSetIOC(dTDPtr);
-
- XUsbPs_dTDFlushCache(dTDPtr);
-
-}
-
-
-/*****************************************************************************/
-/**
- * This function sets the handler for endpoint events.
- *
- * @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 Direction is the direction of the endpoint (bitfield):
- * - XUSBPS_EP_DIRECTION_OUT
- * - XUSBPS_EP_DIRECTION_IN
- * @param CallBackFunc is the Handler callback function.
- * Can be NULL if the user wants to disable the handler entry.
- * @param CallBackRef is the user definable data pointer that will be
- * passed back if the handler is called. May be NULL.
- *
- * @return
- * - XST_SUCCESS: The operation completed successfully.
- * - XST_FAILURE: An error occured.
- * - XST_INVALID_PARAM: Invalid parameter passed.
- *
- * @note
- * The user can disable a handler by setting the callback function
- * pointer to NULL.
- *
- ******************************************************************************/
-int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction,
- XUsbPs_EpHandlerFunc CallBackFunc,
- void *CallBackRef)
-{
- XUsbPs_Endpoint *Ep;
-
- Xil_AssertNonvoid(InstancePtr != NULL);
- Xil_AssertNonvoid(CallBackFunc != NULL);
- Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
-
- Ep = &InstancePtr->DeviceConfig.Ep[EpNum];
-
- if(Direction & XUSBPS_EP_DIRECTION_OUT) {
- Ep->Out.HandlerFunc = CallBackFunc;
- Ep->Out.HandlerRef = CallBackRef;
- }
-
- if(Direction & XUSBPS_EP_DIRECTION_IN) {
- Ep->In.HandlerFunc = CallBackFunc;
- Ep->In.HandlerRef = CallBackRef;
- }
-
- return XST_SUCCESS;
-}
-
-
-/*****************************************************************************/
-/**
-* 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;
-}
-
-
-/*****************************************************************************/
-/**
-* 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_SetSetupTripwire(InstancePtr);
-
- XUsbPs_dQHInvalidateCache(Ep->dQH);
-
- Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0);
- Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1);
- } while (FALSE == XUsbPs_SetupTripwireIsSet(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_ClrSetupTripwire(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;
-}
-
-
-/*****************************************************************************/
-/**
-*
-* This function initializes the endpoint pointer data structure.
-*
-* The function sets up the local data structure with the aligned addresses for
-* the Queue Head and Transfer Descriptors.
-*
-* @param DevCfgPtr is pointer to the XUsbPs DEVICE configuration
-* structure.
-*
-* @return none
-*
-* @note
-* Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the
-* system. Therefore no memory is reserved for them.
-*
-******************************************************************************/
-static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr)
-{
- int EpNum;
- u8 *p;
-
- XUsbPs_Endpoint *Ep;
- XUsbPs_EpConfig *EpCfg;
-
- /* Set up the XUsbPs_Endpoint array. This array is used to define the
- * location of the Queue Head list and the Transfer Descriptors in the
- * block of DMA memory that has been passed into the driver.
- *
- * 'p' is used to set the pointers in the local data structure.
- * Initially 'p' is pointed to the beginning of the DMAable memory
- * block. As pointers are assigned, 'p' is incremented by the size of
- * the respective object.
- */
- Ep = DevCfgPtr->Ep;
- EpCfg = DevCfgPtr->EpCfg;
-
- /* Start off with 'p' pointing to the (aligned) beginning of the DMA
- * buffer.
- */
- p = (u8 *) DevCfgPtr->PhysAligned;
-
-
- /* Initialize the Queue Head pointer list.
- *
- * Each endpoint has two Queue Heads. One for the OUT direction and one
- * for the IN direction. An OUT Queue Head is always followed by an IN
- * Queue Head.
- *
- * Queue Head alignment is XUSBPS_dQH_ALIGN.
- *
- * Note that we have to reserve space here for unused endpoints.
- */
- for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
- /* OUT Queue Head */
- Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p;
- p += XUSBPS_dQH_ALIGN;
-
- /* IN Queue Head */
- Ep[EpNum].In.dQH = (XUsbPs_dQH *) p;
- p += XUSBPS_dQH_ALIGN;
- }
-
-
- /* 'p' now points to the first address after the Queue Head list. The
- * Transfer Descriptors start here.
- *
- * Each endpoint has a variable number of Transfer Descriptors
- * depending on user configuration.
- *
- * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN.
- */
- for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
- /* OUT Descriptors.
- */
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
- Ep[EpNum].Out.dTDs = (XUsbPs_dTD *) p;
- Ep[EpNum].Out.dTDCurr = (XUsbPs_dTD *) p;
- p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs;
- }
-
- /* IN Descriptors.
- */
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
- Ep[EpNum].In.dTDs = (XUsbPs_dTD *) p;
- Ep[EpNum].In.dTDHead = (XUsbPs_dTD *) p;
- Ep[EpNum].In.dTDTail = (XUsbPs_dTD *) p;
- p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].In.NumBufs;
- }
- }
-
-
- /* 'p' now points to the first address after the Transfer Descriptors.
- * The data buffers for the OUT Transfer Desciptors start here.
- *
- * Note that IN (TX) Transfer Descriptors are not assigned buffers at
- * this point. Buffers will be assigned when the user calls the send()
- * function.
- */
- for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
-
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
- /* If BufSize for this endpoint is set to 0 it means
- * that we do not need to attach a buffer to this
- * descriptor. We also initialize it's buffer pointer
- * to NULL.
- */
- if (0 == EpCfg[EpNum].Out.BufSize) {
- Ep[EpNum].Out.dTDBufs = NULL;
- continue;
- }
-
- Ep[EpNum].Out.dTDBufs = p;
- p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs;
- }
- }
-
-
- /* Initialize the endpoint event handlers to NULL.
- */
- for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
- Ep[EpNum].Out.HandlerFunc = NULL;
- Ep[EpNum].In.HandlerFunc = NULL;
- }
-}
-
-
-/*****************************************************************************/
-/**
-*
-* This function initializes the Queue Head List in memory.
-*
-* @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
-* structure.
-*
-* @return None
-*
-* @note None.
-*
-******************************************************************************/
-static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr)
-{
- int EpNum;
-
- XUsbPs_Endpoint *Ep;
- XUsbPs_EpConfig *EpCfg;
-
- /* Setup pointers for simpler access. */
- Ep = DevCfgPtr->Ep;
- EpCfg = DevCfgPtr->EpCfg;
-
-
- /* Go through the list of Queue Head entries and:
- *
- * - Set Transfer Descriptor addresses
- * - Set Maximum Packet Size
- * - Disable Zero Length Termination (ZLT) for non-isochronous transfers
- * - Enable Interrupt On Setup (IOS)
- *
- */
- for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
-
- /* OUT Queue Heads.*/
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
- XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
- XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
-
- /* For isochronous, ep max packet size translates to different
- * values in queue head than other types.
- * Also enable ZLT for isochronous.
- */
- if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {
- XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,
- EpCfg[EpNum].Out.MaxPacketSize);
- XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);
- }else {
- XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
- EpCfg[EpNum].Out.MaxPacketSize);
- XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
- }
-
- /* Only control OUT needs this */
- if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) {
- XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
- }
-
- /* Set up the overlay next dTD pointer. */
- XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
- XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
-
- XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
- }
-
-
- /* IN Queue Heads. */
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
- XUsbPs_WritedQH(Ep[EpNum].In.dQH,
- XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
-
-
- /* Isochronous ep packet size can be larger than 1024.*/
- if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {
- XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,
- EpCfg[EpNum].In.MaxPacketSize);
- XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);
- }else {
- XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
- EpCfg[EpNum].In.MaxPacketSize);
- XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
- }
-
- XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
- }
- }
-}
-
-
-/*****************************************************************************/
-/**
- *
- * This function initializes the Transfer Descriptors lists in memory.
- *
- * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
- * structure.
- *
- * @return
- * - XST_SUCCESS: The operation completed successfully.
- * - XST_FAILURE: An error occured.
- *
- ******************************************************************************/
-static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr)
-{
- int EpNum;
-
- XUsbPs_Endpoint *Ep;
- XUsbPs_EpConfig *EpCfg;
-
- /* Setup pointers for simpler access. */
- Ep = DevCfgPtr->Ep;
- EpCfg = DevCfgPtr->EpCfg;
-
-
- /* Walk through the list of endpoints and initialize their Transfer
- * Descriptors.
- */
- for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
- int Td;
- int NumdTD;
-
- XUsbPs_EpOut *Out = &Ep[EpNum].Out;
- XUsbPs_EpIn *In = &Ep[EpNum].In;
-
-
- /* OUT Descriptors
- * ===============
- *
- * + Set the next link pointer
- * + Set the interrupt complete and the active bit
- * + Attach the buffer to the dTD
- */
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
- NumdTD = EpCfg[EpNum].Out.NumBufs;
- }
- else {
- NumdTD = 0;
- }
-
- for (Td = 0; Td < NumdTD; ++Td) {
- int Status;
-
- int NextTd = (Td + 1) % NumdTD;
-
- XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
-
- /* Set NEXT link pointer. */
- XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
- &Out->dTDs[NextTd]);
-
- /* Set the OUT descriptor ACTIVE and enable the
- * interrupt on complete.
- */
- XUsbPs_dTDSetActive(&Out->dTDs[Td]);
- XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
-
-
- /* Set up the data buffer with the descriptor. If the
- * buffer pointer is NULL it means that we do not need
- * to attach a buffer to this descriptor.
- */
- if (NULL == Out->dTDBufs) {
- XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
- continue;
- }
-
- Status = XUsbPs_dTDAttachBuffer(
- &Out->dTDs[Td],
- Out->dTDBufs +
- (Td * EpCfg[EpNum].Out.BufSize),
- EpCfg[EpNum].Out.BufSize);
- if (XST_SUCCESS != Status) {
- return XST_FAILURE;
- }
-
- XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
- }
-
-
- /* IN Descriptors
- * ==============
- *
- * + Set the next link pointer
- * + Set the Terminate bit to mark it available
- */
- if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
- NumdTD = EpCfg[EpNum].In.NumBufs;
- }
- else {
- NumdTD = 0;
- }
-
- for (Td = 0; Td < NumdTD; ++Td) {
- int NextTd = (Td + 1) % NumdTD;
-
- XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
-
- /* Set NEXT link pointer. */
- XUsbPs_WritedTD(In->dTDs[Td], XUSBPS_dTDNLP,
- In->dTDs[NextTd]);
-
- /* Set the IN descriptor's TERMINATE bits. */
- XUsbPs_dTDSetTerminate(In->dTDs[Td]);
-
- XUsbPs_dTDFlushCache(&In->dTDs[Td]);
- }
- }
-
- return XST_SUCCESS;
-}
-
-
-/*****************************************************************************/
-/**
- *
- * This function associates a buffer with a Transfer Descriptor. The function
- * will take care of splitting the buffer into multiple 4kB aligned segments if
- * the buffer happens to span one or more 4kB pages.
- *
- * @param dTDIndex is a pointer to the Transfer Descriptor
- * @param BufferPtr is pointer to the buffer to link to the descriptor.
- * @param BufferLen is the length of the buffer.
- *
- * @return
- * - XST_SUCCESS: The operation completed successfully.
- * - XST_FAILURE: An error occured.
- * - XST_USB_BUF_TOO_BIG: The provided buffer is bigger than tha
- * maximum allowed buffer size (16k).
- *
- * @note
- * Cache invalidation and flushing needs to be handler by the
- * caller of this function.
- *
- ******************************************************************************/
-static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
- const u8 *BufferPtr, u32 BufferLen)
-{
- u32 BufAddr;
- u32 BufEnd;
- u32 PtrNum;
-
- Xil_AssertNonvoid(dTDPtr != NULL);
-
- /* Check if the buffer is smaller than 16kB. */
- if (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) {
- return XST_USB_BUF_TOO_BIG;
- }
-
- /* Get a u32 of the buffer pointer to avoid casting in the following
- * logic operations.
- */
- BufAddr = (u32) BufferPtr;
-
-
- /* Set the buffer pointer 0. Buffer pointer 0 can point to any location
- * in memory. It does not need to be 4kB aligned. However, if the
- * provided buffer spans one or more 4kB boundaries, we need to set up
- * the subsequent buffer pointers which must be 4kB aligned.
- */
- XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(0), BufAddr);
-
- /* Check if the buffer spans a 4kB boundary.
- *
- * Only do this check, if we are not sending a 0-length buffer.
- */
- if (BufferLen > 0) {
- BufEnd = BufAddr + BufferLen -1;
- PtrNum = 1;
-
- while ((BufAddr & 0xFFFFF000) != (BufEnd & 0xFFFFF000)) {
- /* The buffer spans at least one boundary, let's set
- * the next buffer pointer and repeat the procedure
- * until the end of the buffer and the pointer written
- * are in the same 4kB page.
- */
- BufAddr = (BufAddr + 0x1000) & 0xFFFFF000;
- XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(PtrNum),
- BufAddr);
- PtrNum++;
- }
- }
-
- /* Set the length of the buffer. */
- XUsbPs_dTDSetTransferLen(dTDPtr, BufferLen);
-
-
- /* We remember the buffer pointer in the user data field (reserved
- * field in the dTD). This makes it easier to reset the buffer pointer
- * after a buffer has been received on the endpoint. The buffer pointer
- * needs to be reset because the DMA engine modifies the buffer pointer
- * while receiving.
- */
- XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDUSERDATA, BufferPtr);
-
- return XST_SUCCESS;
-}
-
-
-/*****************************************************************************/
-/**
- * This function set the Max PacketLen for the queue head for isochronous EP.
- *
- * If the max packet length is greater than XUSBPS_MAX_PACKET_SIZE, then
- * Mult bits are set to reflect that.
- *
- * @param dQHPtr is a pointer to the dQH element.
- * @param Len is the Length to be set.
- *
- ******************************************************************************/
-static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len)
-{
- u32 Mult = (Len & ENDPOINT_MAXP_MULT_MASK) >> ENDPOINT_MAXP_MULT_SHIFT;
- u32 MaxPktSize = (Mult > 1) ? ENDPOINT_MAXP_LENGTH : Len;
-
- if (MaxPktSize > XUSBPS_MAX_PACKET_SIZE) {
- return;
- }
-
- if (Mult > 3) {
- return;
- }
-
- /* Set Max packet size */
- XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG,
- (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) &
- ~XUSBPS_dQHCFG_MPL_MASK) |
- (MaxPktSize << XUSBPS_dQHCFG_MPL_SHIFT));
-
- /* Set Mult to tell hardware how many transactions in each microframe */
- XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG,
- (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) &
- ~XUSBPS_dQHCFG_MULT_MASK) |
- (Mult << XUSBPS_dQHCFG_MULT_SHIFT));
-
-}
-
-/*****************************************************************************/
-/**
-* This function reconfigures one Ep corresponding to host's request of setting
-* alternate interface. The endpoint has been disabled before this call.
-*
-* Both QH and dTDs are updated for the new configuration.
-*
-* @param InstancePtr is a pointer to the XUsbPs instance of the
-* controller.
-* @param CfgPtr
-* Pointer to the updated XUsbPs DEVICE configuration structure.
-*
-* @param EpNum
-* The endpoint to be reconfigured.
-*
-* @param NewDirection
-* The new transfer direction the endpoint.
-*
-* @param DirectionChanged
-* A boolean value indicate whether the transfer direction has changed.
-*
-* @return
-* XST_SUCCESS upon success, XST_FAILURE otherwise.
-*
-******************************************************************************/
-int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr,
- int EpNum, unsigned short NewDirection,
- int DirectionChanged) {
-
- int Status = XST_SUCCESS;
- XUsbPs_Endpoint *Ep;
- XUsbPs_EpConfig *EpCfg;
-
- Xil_AssertNonvoid(InstancePtr != NULL);
- Xil_AssertNonvoid(CfgPtr != NULL);
-
- Ep = CfgPtr->Ep;
- EpCfg = CfgPtr->EpCfg;
-
- /* If transfer direction changes, dTDs has to be reset
- * Number of buffers are preset and should not to be changed.
- */
- if(DirectionChanged) {
- if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
- u8 *p;
-
- /* Swap the pointer to the dTDs.
- */
- Ep[EpNum].Out.dTDs = Ep[EpNum].In.dTDs;
- p = (u8 *)(Ep[EpNum].Out.dTDs + XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs);
-
- /* Set the OUT buffer if buffer size is not zero
- */
- if(EpCfg[EpNum].Out.BufSize > 0) {
- Ep[EpNum].Out.dTDBufs = p;
- }
- } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
- Ep[EpNum].In.dTDs = Ep[EpNum].Out.dTDs;
- }
- }
-
- /* Reset dTD progress tracking pointers
- */
- if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
- Ep[EpNum].In.dTDHead = Ep[EpNum].In.dTDTail = Ep[EpNum].In.dTDs;
- } else if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
- Ep[EpNum].Out.dTDCurr = Ep[EpNum].Out.dTDs;
- }
-
- /* Reinitialize information in QH
- */
- XUsbPs_dQHReinitEp(CfgPtr, EpNum, NewDirection);
-
- /* Reinitialize the dTD linked list, and flush the cache
- */
- Status = XUsbPs_dTDReinitEp(CfgPtr, EpNum, NewDirection);
- if(Status != XST_SUCCESS) {
- return Status;
- }
-
- return XST_SUCCESS;
-}
-
-
-/*****************************************************************************/
-/**
- * This function re-initializes the Queue Head List in memory.
- * The endpoint 1 has been disabled before this call.
- *
- * @param DevCfgPtr
- * Pointer to the updated XUsbPs DEVICE configuration structure.
- *
- * @param EpNum
- * The endpoint to be reconfigured.
- *
- * @param NewDirection
- * The new transfer direction of endpoint 1
- *
- * @return none
- *
- ******************************************************************************/
-static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
-int EpNum, unsigned short NewDirection)
-{
- XUsbPs_Endpoint *Ep;
- XUsbPs_EpConfig *EpCfg;
-
- /* Setup pointers for simpler access.
- */
- Ep = DevCfgPtr->Ep;
- EpCfg = DevCfgPtr->EpCfg;
-
-
- /* Go through the list of Queue Head entries and:
- *
- * - Set Transfer Descriptor addresses
- * - Set Maximum Packet Size
- * - Disable Zero Length Termination (ZLT) for non-isochronous transfers
- * - Enable Interrupt On Setup (IOS)
- *
- */
- if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
- /* OUT Queue Heads.
- */
- XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
- XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
-
- /* For isochronous, ep max packet size translates to different
- * values in queue head than other types.
- * Also enable ZLT for isochronous.
- */
- if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {
- XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,
- EpCfg[EpNum].Out.MaxPacketSize);
- XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);
- }else {
- XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
- EpCfg[EpNum].Out.MaxPacketSize);
- XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
- }
-
- XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
-
- /* Set up the overlay next dTD pointer.
- */
- XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
- XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
-
- XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
-
- } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
-
- /* IN Queue Heads.
- */
- XUsbPs_WritedQH(Ep[EpNum].In.dQH,
- XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
-
- /* Isochronous ep packet size can be larger than 1024. */
- if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {
- XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,
- EpCfg[EpNum].In.MaxPacketSize);
- XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);
- }else {
- XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
- EpCfg[EpNum].In.MaxPacketSize);
- XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
- }
-
- XUsbPs_dQHSetIOS(Ep[EpNum].In.dQH);
-
- XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
- }
-
-}
-
-/*****************************************************************************/
-/**
- *
- * This function re-initializes the Transfer Descriptors lists in memory.
- * The endpoint has been disabled before the call. The transfer descriptors
- * list pointer has been initialized too.
- *
- * @param DevCfgPtr
- * Pointer to the XUsbPs DEVICE configuration structure.
- *
- * @param EpNum
- * The endpoint to be reconfigured.
- *
- * @param NewDirection
- * The new transfer direction of endpoint 1
- *
- * @return
- * - XST_SUCCESS: The operation completed successfully.
- * - XST_FAILURE: An error occured.
- *
- ******************************************************************************/
-static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
-int EpNum, unsigned short NewDirection)
-{
- XUsbPs_Endpoint *Ep;
- XUsbPs_EpConfig *EpCfg;
- int Td;
- int NumdTD;
-
-
- /* Setup pointers for simpler access.
- */
- Ep = DevCfgPtr->Ep;
- EpCfg = DevCfgPtr->EpCfg;
-
-
- if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
- XUsbPs_EpOut *Out = &Ep[EpNum].Out;
-
- /* OUT Descriptors
- * ===============
- *
- * + Set the next link pointer
- * + Set the interrupt complete and the active bit
- * + Attach the buffer to the dTD
- */
- NumdTD = EpCfg[EpNum].Out.NumBufs;
-
- for (Td = 0; Td < NumdTD; ++Td) {
- int Status;
-
- int NextTd = (Td + 1) % NumdTD;
-
- XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
-
- /* Set NEXT link pointer.
- */
- XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
- &Out->dTDs[NextTd]);
-
- /* Set the OUT descriptor ACTIVE and enable the
- * interrupt on complete.
- */
- XUsbPs_dTDSetActive(&Out->dTDs[Td]);
- XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
-
- /* Set up the data buffer with the descriptor. If the
- * buffer pointer is NULL it means that we do not need
- * to attach a buffer to this descriptor.
- */
- if (Out->dTDBufs != NULL) {
-
- Status = XUsbPs_dTDAttachBuffer(
- &Out->dTDs[Td],
- Out->dTDBufs +
- (Td * EpCfg[EpNum].Out.BufSize),
- EpCfg[EpNum].Out.BufSize);
- if (Status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- }
- XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
- }
- } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
- XUsbPs_EpIn *In = &Ep[EpNum].In;
-
- /* IN Descriptors
- * ==============
- *
- * + Set the next link pointer
- * + Set the Terminate bit to mark it available
- */
- NumdTD = EpCfg[EpNum].In.NumBufs;
-
- for (Td = 0; Td < NumdTD; ++Td) {
- int NextTd = (Td + 1) % NumdTD;
-
- XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
-
- /* Set NEXT link pointer.
- */
- XUsbPs_WritedTD(&In->dTDs[Td], XUSBPS_dTDNLP,
- &In->dTDs[NextTd]);
-
- /* Set the IN descriptor's TERMINATE bits.
- */
- XUsbPs_dTDSetTerminate(&In->dTDs[Td]);
-
- XUsbPs_dTDFlushCache(&In->dTDs[Td]);
- }
- }
-
- return XST_SUCCESS;
-}
-
-/** @} */