X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FDemo%2FCORTEX_R5_UltraScale_MPSoC%2FRTOSDemo_R5_bsp%2Fpsu_cortexr5_0%2Flibsrc%2Fusbpsu_v1_4%2Fsrc%2Fxusbpsu_controltransfers.c;fp=FreeRTOS%2FDemo%2FCORTEX_R5_UltraScale_MPSoC%2FRTOSDemo_R5_bsp%2Fpsu_cortexr5_0%2Flibsrc%2Fusbpsu_v1_4%2Fsrc%2Fxusbpsu_controltransfers.c;h=19be417fbf570baa3dc986c13b1870b8652475ad;hb=2f3240cae4193f5662f4b8f24c4decdb2bc7778b;hp=0000000000000000000000000000000000000000;hpb=6e33f3d844560120d8110ec9d6a50f912b594b87;p=freertos diff --git a/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/usbpsu_v1_4/src/xusbpsu_controltransfers.c b/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/usbpsu_v1_4/src/xusbpsu_controltransfers.c new file mode 100644 index 000000000..19be417fb --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/usbpsu_v1_4/src/xusbpsu_controltransfers.c @@ -0,0 +1,694 @@ +/****************************************************************************** +* +* Copyright (C) 2016 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 xusbpsu_controltransfers.c +* @addtogroup usbpsu_v1_0 +* @{ +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.0   sg  06/06/16 First release
+* 1.3	vak 04/03/17 Added CCI support for USB
+* 1.4	bk  12/01/18 Modify USBPSU driver code to fit USB common example code
+*		     for all USB IPs.
+*
+* 
+* +*****************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xusbpsu_endpoint.h" +#include "sleep.h" +#include "xusb_wrapper.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/****************************************************************************/ +/** +* Initiates DMA on Control Endpoint 0 to receive Setup packet. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* +* @return XST_SUCCESS else XST_FAILURE. +* +* @note None. +* +*****************************************************************************/ +s32 XUsbPsu_RecvSetup(struct XUsbPsu *InstancePtr) +{ + struct XUsbPsu_EpParams *Params; + struct XUsbPsu_Trb *TrbPtr; + struct XUsbPsu_Ep *Ept; + s32 Ret; + + Xil_AssertNonvoid(InstancePtr != NULL); + + Params = XUsbPsu_GetEpParams(InstancePtr); + Xil_AssertNonvoid(Params != NULL); + + /* Setup packet always on EP0 */ + Ept = &InstancePtr->eps[0]; + if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) { + return (s32)XST_FAILURE; + } + + TrbPtr = &InstancePtr->Ep0_Trb; + + TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData; + TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16; + TrbPtr->Size = 8U; + TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_SETUP; + + TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO + | XUSBPSU_TRB_CTRL_LST + | XUSBPSU_TRB_CTRL_IOC + | XUSBPSU_TRB_CTRL_ISP_IMI); + + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) { + Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb)); + Xil_DCacheFlushRange((UINTPTR)&InstancePtr->SetupData, sizeof(SetupPacket)); + } + + Params->Param0 = 0U; + Params->Param1 = (UINTPTR)TrbPtr; + + InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE; + + Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT, + XUSBPSU_DEPCMD_STARTTRANSFER, Params); + if (Ret != XST_SUCCESS) { + return (s32)XST_FAILURE; + } + + Ept->EpStatus |= XUSBPSU_EP_BUSY; + Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr, + Ept->UsbEpNum, Ept->Direction); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* Stalls Control Endpoint and restarts to receive Setup packet. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0StallRestart(struct XUsbPsu *InstancePtr) +{ + struct XUsbPsu_Ep *Ept; + + Xil_AssertVoid(InstancePtr != NULL); + + /* reinitialize physical ep1 */ + Ept = &InstancePtr->eps[1]; + Ept->EpStatus = XUSBPSU_EP_ENABLED; + + /* stall is always issued on EP0 */ + XUsbPsu_EpSetStall(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT); + + Ept = &InstancePtr->eps[0]; + Ept->EpStatus = XUSBPSU_EP_ENABLED; + InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE; + (void)XUsbPsu_RecvSetup(InstancePtr); +} + +/****************************************************************************/ +/** +* Checks the Data Phase and calls user Endpoint handler. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Event is a pointer to the Endpoint event occured in core. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0DataDone(struct XUsbPsu *InstancePtr, + const struct XUsbPsu_Event_Epevt *Event) +{ + struct XUsbPsu_Ep *Ept; + struct XUsbPsu_Trb *TrbPtr; + u32 Status; + u32 Length; + u32 Epnum; + u8 Dir; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Event != NULL); + + Epnum = Event->Epnumber; + Dir = (u8)(!!Epnum); + Ept = &InstancePtr->eps[Epnum]; + TrbPtr = &InstancePtr->Ep0_Trb; + + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) + Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb)); + + Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size); + if (Status == XUSBPSU_TRBSTS_SETUP_PENDING) { + return; + } + + Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK; + + if (Length == 0U) { + Ept->BytesTxed = Ept->RequestedBytes; + } else { + if (Dir == XUSBPSU_EP_DIR_IN) { + Ept->BytesTxed = Ept->RequestedBytes - Length; + } else { + if ((Dir == XUSBPSU_EP_DIR_OUT) && (Ept->UnalignedTx == 1U)) { + Ept->BytesTxed = Ept->RequestedBytes; + Ept->UnalignedTx = 0U; + } + } + } + + if (Dir == XUSBPSU_EP_DIR_OUT) { + /* Invalidate Cache */ + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) + Xil_DCacheInvalidateRange((INTPTR)Ept->BufferPtr, Ept->BytesTxed); + } + + if (Ept->Handler != NULL) { + Ept->Handler(InstancePtr->AppData, Ept->RequestedBytes, Ept->BytesTxed); + } +} + +/****************************************************************************/ +/** +* Checks the Status Phase and starts next Control transfer. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Event is a pointer to the Endpoint event occured in core. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0StatusDone(struct XUsbPsu *InstancePtr, + const struct XUsbPsu_Event_Epevt *Event) +{ + struct XUsbPsu_Trb *TrbPtr; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Event != NULL); + + TrbPtr = &InstancePtr->Ep0_Trb; + + if (InstancePtr->IsInTestMode != 0U) { + s32 Ret; + + Ret = XUsbPsu_SetTestMode(InstancePtr, + InstancePtr->TestMode); + if (Ret < 0) { + XUsbPsu_Ep0StallRestart(InstancePtr); + return; + } + } + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) + Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb)); + + (void)XUsbPsu_RecvSetup(InstancePtr); +} + +/****************************************************************************/ +/** +* Handles Transfer complete event of Control Endpoints EP0 OUT and EP0 IN. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Event is a pointer to the Endpoint event occured in core. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0XferComplete(struct XUsbPsu *InstancePtr, + const struct XUsbPsu_Event_Epevt *Event) +{ + struct XUsbPsu_Ep *Ept; + SetupPacket *Ctrl; + u16 Length; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Event != NULL); + + Ept = &InstancePtr->eps[Event->Epnumber]; + Ctrl = &InstancePtr->SetupData; + + Ept->EpStatus &= ~XUSBPSU_EP_BUSY; + Ept->ResourceIndex = 0U; + + switch (InstancePtr->Ep0State) { + case XUSBPSU_EP0_SETUP_PHASE: + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) { + Xil_DCacheInvalidateRange((INTPTR)&InstancePtr->SetupData, + sizeof(InstancePtr->SetupData)); + } + Length = Ctrl->wLength; + if (Length == 0U) { + InstancePtr->IsThreeStage = 0U; + InstancePtr->ControlDir = XUSBPSU_EP_DIR_OUT; + } else { + InstancePtr->IsThreeStage = 1U; + InstancePtr->ControlDir = !!(Ctrl->bRequestType & + USB_DIR_IN); + } + + Xil_AssertVoid(InstancePtr->Chapter9 != NULL); + + InstancePtr->Chapter9(InstancePtr->AppData, + &InstancePtr->SetupData); + break; + + case XUSBPSU_EP0_DATA_PHASE: + XUsbPsu_Ep0DataDone(InstancePtr, Event); + break; + + case XUSBPSU_EP0_STATUS_PHASE: + XUsbPsu_Ep0StatusDone(InstancePtr, Event); + break; + + default: + /* Default case is a required MISRA-C guideline. */ + break; + } +} + +/****************************************************************************/ +/** +* Starts Status Phase of Control Transfer +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Event is a pointer to the Endpoint event occured in core. +* +* @return XST_SUCCESS else XST_FAILURE +* +* @note None. +* +*****************************************************************************/ +s32 XUsbPsu_Ep0StartStatus(struct XUsbPsu *InstancePtr, + const struct XUsbPsu_Event_Epevt *Event) +{ + struct XUsbPsu_Ep *Ept; + struct XUsbPsu_EpParams *Params; + struct XUsbPsu_Trb *TrbPtr; + u32 Type; + s32 Ret; + u8 Dir; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Event != NULL); + + Ept = &InstancePtr->eps[Event->Epnumber]; + Params = XUsbPsu_GetEpParams(InstancePtr); + Xil_AssertNonvoid(Params != NULL); + if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) { + return (s32)XST_FAILURE; + } + + Type = (InstancePtr->IsThreeStage != 0U) ? XUSBPSU_TRBCTL_CONTROL_STATUS3 + : XUSBPSU_TRBCTL_CONTROL_STATUS2; + TrbPtr = &InstancePtr->Ep0_Trb; + /* we use same TrbPtr for setup packet */ + TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData; + TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16; + TrbPtr->Size = 0U; + TrbPtr->Ctrl = Type; + + TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO + | XUSBPSU_TRB_CTRL_LST + | XUSBPSU_TRB_CTRL_IOC + | XUSBPSU_TRB_CTRL_ISP_IMI); + + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) { + Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb)); + } + + Params->Param0 = 0U; + Params->Param1 = (UINTPTR)TrbPtr; + + InstancePtr->Ep0State = XUSBPSU_EP0_STATUS_PHASE; + + /* + * Control OUT transfer - Status stage happens on EP0 IN - EP1 + * Control IN transfer - Status stage happens on EP0 OUT - EP0 + */ + Dir = !InstancePtr->ControlDir; + + Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, Dir, + XUSBPSU_DEPCMD_STARTTRANSFER, Params); + if (Ret != XST_SUCCESS) { + return (s32)XST_FAILURE; + } + + Ept->EpStatus |= XUSBPSU_EP_BUSY; + Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr, + Ept->UsbEpNum, Ept->Direction); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* Ends Data Phase - used incase of error. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Dep is a pointer to the Endpoint structure. +* +* @return None +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0_EndControlData(struct XUsbPsu *InstancePtr, + struct XUsbPsu_Ep *Ept) +{ + struct XUsbPsu_EpParams *Params; + u32 Cmd; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Ept != NULL); + + if (Ept->ResourceIndex == 0U) { + return; + } + + Params = XUsbPsu_GetEpParams(InstancePtr); + Xil_AssertVoid(Params != NULL); + + Cmd = XUSBPSU_DEPCMD_ENDTRANSFER; + Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex); + (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction, + Cmd, Params); + Ept->ResourceIndex = 0U; + XUsbSleep(200U); +} + +/****************************************************************************/ +/** +* Handles Transfer Not Ready event of Control Endpoints EP0 OUT and EP0 IN. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Event is a pointer to the Endpoint event occured in core. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0XferNotReady(struct XUsbPsu *InstancePtr, + const struct XUsbPsu_Event_Epevt *Event) +{ + struct XUsbPsu_Ep *Ept; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Event != NULL); + + Ept = &InstancePtr->eps[Event->Epnumber]; + + switch (Event->Status) { + case DEPEVT_STATUS_CONTROL_DATA: + /* + * We already have a DATA transfer in the controller's cache, + * if we receive a XferNotReady(DATA) we will ignore it, unless + * it's for the wrong direction. + * + * In that case, we must issue END_TRANSFER command to the Data + * Phase we already have started and issue SetStall on the + * control endpoint. + */ + if (Event->Epnumber != InstancePtr->ControlDir) { + XUsbPsu_Ep0_EndControlData(InstancePtr, Ept); + XUsbPsu_Ep0StallRestart(InstancePtr); + } + break; + + case DEPEVT_STATUS_CONTROL_STATUS: + (void)XUsbPsu_Ep0StartStatus(InstancePtr, Event); + break; + + default: + /* Default case is a required MIRSA-C guideline. */ + break; + } +} + +/****************************************************************************/ +/** +* Handles Interrupts of Control Endpoints EP0 OUT and EP0 IN. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param Event is a pointer to the Endpoint event occured in core. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void XUsbPsu_Ep0Intr(struct XUsbPsu *InstancePtr, + const struct XUsbPsu_Event_Epevt *Event) +{ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Event != NULL); + + switch (Event->Endpoint_Event) { + case XUSBPSU_DEPEVT_XFERCOMPLETE: + XUsbPsu_Ep0XferComplete(InstancePtr, Event); + break; + + case XUSBPSU_DEPEVT_XFERNOTREADY: + XUsbPsu_Ep0XferNotReady(InstancePtr, Event); + break; + + case XUSBPSU_DEPEVT_XFERINPROGRESS: + case XUSBPSU_DEPEVT_STREAMEVT: + case XUSBPSU_DEPEVT_EPCMDCMPLT: + break; + + default: + /* Default case is a required MIRSA-C guideline. */ + break; + } +} + +/****************************************************************************/ +/** +* Initiates DMA to send data on Control Endpoint EP0 IN to Host. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param BufferPtr is pointer to data. +* @param BufferLen is Length of data buffer. +* +* @return XST_SUCCESS else XST_FAILURE +* +* @note None. +* +*****************************************************************************/ +s32 XUsbPsu_Ep0Send(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 BufferLen) +{ + /* Control IN - EP1 */ + struct XUsbPsu_EpParams *Params; + struct XUsbPsu_Ep *Ept; + struct XUsbPsu_Trb *TrbPtr; + s32 Ret; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + + Ept = &InstancePtr->eps[1]; + Params = XUsbPsu_GetEpParams(InstancePtr); + Xil_AssertNonvoid(Params != NULL); + + if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) { + return (s32)XST_FAILURE; + } + + Ept->RequestedBytes = BufferLen; + Ept->BytesTxed = 0U; + Ept->BufferPtr = BufferPtr; + + TrbPtr = &InstancePtr->Ep0_Trb; + + TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr; + TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16; + TrbPtr->Size = BufferLen; + TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA; + + TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO + | XUSBPSU_TRB_CTRL_LST + | XUSBPSU_TRB_CTRL_IOC + | XUSBPSU_TRB_CTRL_ISP_IMI); + + Params->Param0 = 0U; + Params->Param1 = (UINTPTR)TrbPtr; + + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) { + Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb)); + Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen); + } + + InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE; + + Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_IN, + XUSBPSU_DEPCMD_STARTTRANSFER, Params); + if (Ret != XST_SUCCESS) { + return (s32)XST_FAILURE; + } + + Ept->EpStatus |= XUSBPSU_EP_BUSY; + Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr, + Ept->UsbEpNum, Ept->Direction); + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* Initiates DMA to receive data on Control Endpoint EP0 OUT from Host. +* +* @param InstancePtr is a pointer to the XUsbPsu instance. +* @param BufferPtr is pointer to data. +* @param Length is Length of data to be received. +* +* @return XST_SUCCESS else XST_FAILURE +* +* @note None. +* +*****************************************************************************/ +s32 XUsbPsu_Ep0Recv(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 Length) +{ + struct XUsbPsu_EpParams *Params; + struct XUsbPsu_Ep *Ept; + struct XUsbPsu_Trb *TrbPtr; + u32 Size; + s32 Ret; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + + Ept = &InstancePtr->eps[0]; + Params = XUsbPsu_GetEpParams(InstancePtr); + Xil_AssertNonvoid(Params != NULL); + + if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) { + return (s32)XST_FAILURE; + } + + Ept->RequestedBytes = Length; + Size = Length; + Ept->BytesTxed = 0U; + Ept->BufferPtr = BufferPtr; + + /* + * 8.2.5 - An OUT transfer size (Total TRB buffer allocation) + * must be a multiple of MaxPacketSize even if software is expecting a + * fixed non-multiple of MaxPacketSize transfer from the Host. + */ + if (!IS_ALIGNED(Length, Ept->MaxSize)) { + Size = (u32)roundup(Length, Ept->MaxSize); + Ept->UnalignedTx = 1U; + } + + TrbPtr = &InstancePtr->Ep0_Trb; + + TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr; + TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16; + TrbPtr->Size = Size; + TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA; + + TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO + | XUSBPSU_TRB_CTRL_LST + | XUSBPSU_TRB_CTRL_IOC + | XUSBPSU_TRB_CTRL_ISP_IMI); + + if (InstancePtr->ConfigPtr->IsCacheCoherent == 0) { + Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb)); + Xil_DCacheInvalidateRange((INTPTR)BufferPtr, Length); + } + + Params->Param0 = 0U; + Params->Param1 = (UINTPTR)TrbPtr; + + InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE; + + Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT, + XUSBPSU_DEPCMD_STARTTRANSFER, Params); + if (Ret != XST_SUCCESS) { + return (s32)XST_FAILURE; + } + + Ept->EpStatus |= XUSBPSU_EP_BUSY; + Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr, + Ept->UsbEpNum, Ept->Direction); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* API for Sleep routine. +* +* @param USeconds is time in MicroSeconds. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUsbSleep(u32 USeconds) { + (void)usleep(USeconds); +} +/** @} */