]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC/RTOSDemo_A53_bsp/psu_cortexa53_0/libsrc/usbpsu_v1_1/src/xusbpsu_controltransfers.c
Update Zynq MPSoC hardware definition and BSP files to be those shipped with the...
[freertos] / FreeRTOS / Demo / CORTEX_A53_64-bit_UltraScale_MPSoC / RTOSDemo_A53_bsp / psu_cortexa53_0 / libsrc / usbpsu_v1_1 / src / xusbpsu_controltransfers.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2016 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /****************************************************************************/
33 /**
34 *
35 * @file xusbpsu_controltransfers.c
36 * @addtogroup usbpsu_v1_0
37 * @{
38 *
39 * <pre>
40 * MODIFICATION HISTORY:
41 *
42 * Ver   Who  Date     Changes
43 * ----- ---- -------- -------------------------------------------------------
44 * 1.0   sg  06/06/16 First release
45 *
46 * </pre>
47 *
48 *****************************************************************************/
49
50 /***************************** Include Files *********************************/
51
52 #include "xusbpsu.h"
53 #include "xusbpsu_endpoint.h"
54 /************************** Constant Definitions *****************************/
55
56 #define USB_DIR_OUT                             0U              /* to device */
57 #define USB_DIR_IN                              0x80U   /* to host */
58
59 /**************************** Type Definitions *******************************/
60
61 /***************** Macros (Inline Functions) Definitions *********************/
62
63 /************************** Function Prototypes ******************************/
64
65
66 /************************** Variable Definitions *****************************/
67
68
69 /****************************************************************************/
70 /**
71 * Initiates DMA on Control Endpoint 0 to receive Setup packet.
72 *
73 * @param        InstancePtr is a pointer to the XUsbPsu instance.
74 *
75 * @return       XST_SUCCESS else XST_FAILURE.
76 *
77 * @note         None.
78 *
79 *****************************************************************************/
80 s32 XUsbPsu_RecvSetup(struct XUsbPsu *InstancePtr)
81 {
82         struct XUsbPsu_EpParams *Params;
83         struct XUsbPsu_Trb      *TrbPtr;
84         struct XUsbPsu_Ep       *Ept;
85         s32     Ret;
86
87         Xil_AssertNonvoid(InstancePtr != NULL);
88
89         Params = XUsbPsu_GetEpParams(InstancePtr);
90         Xil_AssertNonvoid(Params != NULL);
91
92         /* Setup packet always on EP0 */
93         Ept = &InstancePtr->eps[0];
94         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
95                 return XST_FAILURE;
96         }
97
98         TrbPtr = &InstancePtr->Ep0_Trb;
99
100         TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
101         TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
102         TrbPtr->Size = 8U;
103         TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_SETUP;
104
105         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
106                         | XUSBPSU_TRB_CTRL_LST
107                         | XUSBPSU_TRB_CTRL_IOC
108                         | XUSBPSU_TRB_CTRL_ISP_IMI);
109
110         Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
111
112         Params->Param0 = 0U;
113         Params->Param1 = (UINTPTR)TrbPtr;
114
115         InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
116
117         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
118                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
119         if (Ret != XST_SUCCESS) {
120                 return XST_FAILURE;
121         }
122
123         Ept->EpStatus |= XUSBPSU_EP_BUSY;
124         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
125                                                 Ept->UsbEpNum, Ept->Direction);
126
127         return XST_SUCCESS;
128 }
129
130 /****************************************************************************/
131 /**
132 * Stalls Control Endpoint and restarts to receive Setup packet.
133 *
134 * @param        InstancePtr is a pointer to the XUsbPsu instance.
135 *
136 * @return       None
137 *
138 * @note         None.
139 *
140 *****************************************************************************/
141 void XUsbPsu_Ep0StallRestart(struct XUsbPsu *InstancePtr)
142 {
143         struct XUsbPsu_Ep               *Ept;
144
145         Xil_AssertVoid(InstancePtr != NULL);
146
147         /* reinitialize physical ep1 */
148         Ept = &InstancePtr->eps[1];
149         Ept->EpStatus = XUSBPSU_EP_ENABLED;
150
151         /* stall is always issued on EP0 */
152         XUsbPsu_EpSetStall(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT);
153
154         Ept = &InstancePtr->eps[0];
155         Ept->EpStatus = XUSBPSU_EP_ENABLED;
156         InstancePtr->Ep0State = XUSBPSU_EP0_SETUP_PHASE;
157         (void)XUsbPsu_RecvSetup(InstancePtr);
158 }
159
160 /****************************************************************************/
161 /**
162 * Checks the Data Phase and calls user Endpoint handler.
163 *
164 * @param        InstancePtr is a pointer to the XUsbPsu instance.
165 * @param        Event is a pointer to the Endpoint event occured in core.
166 *
167 * @return       None.
168 *
169 * @note         None.
170 *
171 *****************************************************************************/
172 void XUsbPsu_Ep0DataDone(struct XUsbPsu *InstancePtr,
173                                                  const struct XUsbPsu_Event_Epevt *Event)
174 {
175         struct XUsbPsu_Ep       *Ept;
176         struct XUsbPsu_Trb      *TrbPtr;
177         u32     Status;
178         u32     Length;
179         u32     Epnum;
180         u8      Dir;
181
182         Xil_AssertVoid(InstancePtr != NULL);
183         Xil_AssertVoid(Event != NULL);
184
185         Epnum = Event->Epnumber;
186         Dir = (u8)(!!Epnum);
187         Ept = &InstancePtr->eps[Epnum];
188         TrbPtr = &InstancePtr->Ep0_Trb;
189
190         Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
191
192         Status = XUSBPSU_TRB_SIZE_TRBSTS(TrbPtr->Size);
193         if (Status == XUSBPSU_TRBSTS_SETUP_PENDING) {
194                 return;
195         }
196
197         Length = TrbPtr->Size & XUSBPSU_TRB_SIZE_MASK;
198
199         if (Length == 0U) {
200                 Ept->BytesTxed = Ept->RequestedBytes;
201         } else {
202                 if (Dir == XUSBPSU_EP_DIR_IN) {
203                         Ept->BytesTxed = Ept->RequestedBytes - Length;
204                 } else if (Dir == XUSBPSU_EP_DIR_OUT) {
205                         if (Ept->UnalignedTx == 1U) {
206                                 Ept->BytesTxed = Ept->RequestedBytes;
207                                 Ept->UnalignedTx = 0U;
208                         }
209                 }
210         }
211
212         if (Dir == XUSBPSU_EP_DIR_OUT) {
213                 /* Invalidate Cache */
214                 Xil_DCacheInvalidateRange((INTPTR)Ept->BufferPtr, Ept->BytesTxed);
215         }
216
217         if (Ept->Handler != NULL) {
218                 Ept->Handler(InstancePtr, Ept->RequestedBytes, Ept->BytesTxed);
219         }
220 }
221
222 /****************************************************************************/
223 /**
224 * Checks the Status Phase and starts next Control transfer.
225 *
226 * @param        InstancePtr is a pointer to the XUsbPsu instance.
227 * @param        Event is a pointer to the Endpoint event occured in core.
228 *
229 * @return       None.
230 *
231 * @note         None.
232 *
233 *****************************************************************************/
234 void XUsbPsu_Ep0StatusDone(struct XUsbPsu *InstancePtr,
235                 const struct XUsbPsu_Event_Epevt *Event)
236 {
237         struct XUsbPsu_Trb      *TrbPtr;
238
239         Xil_AssertVoid(InstancePtr != NULL);
240         Xil_AssertVoid(Event != NULL);
241
242         TrbPtr = &InstancePtr->Ep0_Trb;
243
244         if (InstancePtr->IsInTestMode != 0U) {
245                 s32 Ret;
246
247                 Ret = XUsbPsu_SetTestMode(InstancePtr,
248                                         InstancePtr->TestMode);
249                 if (Ret < 0) {
250                         XUsbPsu_Ep0StallRestart(InstancePtr);
251                         return;
252                 }
253         }
254         Xil_DCacheInvalidateRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
255
256         (void)XUsbPsu_RecvSetup(InstancePtr);
257 }
258
259 /****************************************************************************/
260 /**
261 * Handles Transfer complete event of Control Endpoints EP0 OUT and EP0 IN.
262 *
263 * @param        InstancePtr is a pointer to the XUsbPsu instance.
264 * @param        Event is a pointer to the Endpoint event occured in core.
265 *
266 * @return       None.
267 *
268 * @note         None.
269 *
270 *****************************************************************************/
271 void XUsbPsu_Ep0XferComplete(struct XUsbPsu *InstancePtr,
272                                                          const struct XUsbPsu_Event_Epevt *Event)
273 {
274         struct XUsbPsu_Ep *Ept;
275         SetupPacket *Ctrl;
276         u16 Length;
277
278         Xil_AssertVoid(InstancePtr != NULL);
279         Xil_AssertVoid(Event != NULL);
280
281         Ept = &InstancePtr->eps[Event->Epnumber];
282         Ctrl = &InstancePtr->SetupData;
283
284         Ept->EpStatus &= ~XUSBPSU_EP_BUSY;
285         Ept->ResourceIndex = 0U;
286
287         switch (InstancePtr->Ep0State) {
288         case XUSBPSU_EP0_SETUP_PHASE:
289                 Xil_DCacheInvalidateRange((INTPTR)&InstancePtr->SetupData,
290                                         sizeof(InstancePtr->SetupData));
291                 Length = Ctrl->wLength;
292                 if (Length == 0U) {
293                         InstancePtr->IsThreeStage = 0U;
294                         InstancePtr->ControlDir = XUSBPSU_EP_DIR_OUT;
295                 } else {
296                         InstancePtr->IsThreeStage = 1U;
297                         InstancePtr->ControlDir = !!(Ctrl->bRequestType &
298                                                         USB_DIR_IN);
299                 }
300
301                 Xil_AssertVoid(InstancePtr->Chapter9 != NULL);
302
303                 InstancePtr->Chapter9(InstancePtr,
304                                                                         &InstancePtr->SetupData);
305                 break;
306
307         case XUSBPSU_EP0_DATA_PHASE:
308                 XUsbPsu_Ep0DataDone(InstancePtr, Event);
309                 break;
310
311         case XUSBPSU_EP0_STATUS_PHASE:
312                 XUsbPsu_Ep0StatusDone(InstancePtr, Event);
313                 break;
314
315         default:
316                 /* Default case is a required MISRA-C guideline. */
317                 break;
318         }
319 }
320
321 /****************************************************************************/
322 /**
323 * Starts Status Phase of Control Transfer
324 *
325 * @param        InstancePtr is a pointer to the XUsbPsu instance.
326 * @param        Event is a pointer to the Endpoint event occured in core.
327 *
328 * @return       XST_SUCCESS else XST_FAILURE
329 *
330 * @note         None.
331 *
332 *****************************************************************************/
333 s32 XUsbPsu_Ep0StartStatus(struct XUsbPsu *InstancePtr,
334                                 const struct XUsbPsu_Event_Epevt *Event)
335 {
336         struct XUsbPsu_Ep  *Ept;
337         struct XUsbPsu_EpParams *Params;
338         struct XUsbPsu_Trb *TrbPtr;
339         u32 Type;
340         s32 Ret;
341         u8 Dir;
342
343         Xil_AssertNonvoid(InstancePtr != NULL);
344         Xil_AssertNonvoid(Event != NULL);
345
346         Ept = &InstancePtr->eps[Event->Epnumber];
347         Params = XUsbPsu_GetEpParams(InstancePtr);
348         Xil_AssertNonvoid(Params != NULL);
349         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
350                 return XST_FAILURE;
351         }
352
353         Type = (InstancePtr->IsThreeStage != 0U) ? XUSBPSU_TRBCTL_CONTROL_STATUS3
354                                         : XUSBPSU_TRBCTL_CONTROL_STATUS2;
355         TrbPtr = &InstancePtr->Ep0_Trb;
356         /* we use same TrbPtr for setup packet */
357         TrbPtr->BufferPtrLow = (UINTPTR)&InstancePtr->SetupData;
358         TrbPtr->BufferPtrHigh = ((UINTPTR)&InstancePtr->SetupData >> 16) >> 16;
359         TrbPtr->Size = 0U;
360         TrbPtr->Ctrl = Type;
361
362         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
363                         | XUSBPSU_TRB_CTRL_LST
364                         | XUSBPSU_TRB_CTRL_IOC
365                         | XUSBPSU_TRB_CTRL_ISP_IMI);
366
367         Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
368
369         Params->Param0 = 0U;
370         Params->Param1 = (UINTPTR)TrbPtr;
371
372         InstancePtr->Ep0State = XUSBPSU_EP0_STATUS_PHASE;
373
374         /*
375          * Control OUT transfer - Status stage happens on EP0 IN - EP1
376          * Control IN transfer - Status stage happens on EP0 OUT - EP0
377          */
378         Dir = !InstancePtr->ControlDir;
379
380         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, Dir,
381                                                         XUSBPSU_DEPCMD_STARTTRANSFER, Params);
382         if (Ret != XST_SUCCESS) {
383                 return XST_FAILURE;
384         }
385
386         Ept->EpStatus |= XUSBPSU_EP_BUSY;
387         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
388                                                         Ept->UsbEpNum, Ept->Direction);
389
390         return XST_SUCCESS;
391 }
392
393 /****************************************************************************/
394 /**
395 * Ends Data Phase - used incase of error.
396 *
397 * @param        InstancePtr is a pointer to the XUsbPsu instance.
398 * @param        Dep is a pointer to the Endpoint structure.
399 *
400 * @return       None
401 *
402 * @note         None.
403 *
404 *****************************************************************************/
405 void XUsbPsu_Ep0_EndControlData(struct XUsbPsu *InstancePtr,
406                                                                 struct XUsbPsu_Ep *Ept)
407 {
408         struct XUsbPsu_EpParams *Params;
409         u32     Cmd;
410
411         Xil_AssertVoid(InstancePtr != NULL);
412         Xil_AssertVoid(Ept != NULL);
413
414         if (Ept->ResourceIndex == 0U) {
415                 return;
416         }
417
418         Params = XUsbPsu_GetEpParams(InstancePtr);
419         Xil_AssertVoid(Params != NULL);
420
421         Cmd = XUSBPSU_DEPCMD_ENDTRANSFER;
422         Cmd |= XUSBPSU_DEPCMD_PARAM(Ept->ResourceIndex);
423         (void)XUsbPsu_SendEpCmd(InstancePtr, Ept->UsbEpNum, Ept->Direction,
424                                                 Cmd, Params);
425         Ept->ResourceIndex = 0U;
426         XUsbSleep(200U);
427 }
428
429 /****************************************************************************/
430 /**
431 * Handles Transfer Not Ready event of Control Endpoints EP0 OUT and EP0 IN.
432 *
433 * @param        InstancePtr is a pointer to the XUsbPsu instance.
434 * @param        Event is a pointer to the Endpoint event occured in core.
435 *
436 * @return       None.
437 *
438 * @note         None.
439 *
440 *****************************************************************************/
441 void XUsbPsu_Ep0XferNotReady(struct XUsbPsu *InstancePtr,
442                                                          const struct XUsbPsu_Event_Epevt *Event)
443 {
444         struct XUsbPsu_Ep *Ept;
445
446         Xil_AssertVoid(InstancePtr != NULL);
447         Xil_AssertVoid(Event != NULL);
448
449         Ept = &InstancePtr->eps[Event->Epnumber];
450
451         switch (Event->Status) {
452         case DEPEVT_STATUS_CONTROL_DATA:
453                 /*
454                  * We already have a DATA transfer in the controller's cache,
455                  * if we receive a XferNotReady(DATA) we will ignore it, unless
456                  * it's for the wrong direction.
457                  *
458                  * In that case, we must issue END_TRANSFER command to the Data
459                  * Phase we already have started and issue SetStall on the
460                  * control endpoint.
461                  */
462                 if (Event->Epnumber != InstancePtr->ControlDir) {
463                         XUsbPsu_Ep0_EndControlData(InstancePtr, Ept);
464                         XUsbPsu_Ep0StallRestart(InstancePtr);
465                 }
466                 break;
467
468         case DEPEVT_STATUS_CONTROL_STATUS:
469                 (void)XUsbPsu_Ep0StartStatus(InstancePtr, Event);
470                 break;
471
472         default:
473                 /* Default case is a required MIRSA-C guideline. */
474                 break;
475         }
476 }
477
478 /****************************************************************************/
479 /**
480 * Handles Interrupts of Control Endpoints EP0 OUT and EP0 IN.
481 *
482 * @param        InstancePtr is a pointer to the XUsbPsu instance.
483 * @param        Event is a pointer to the Endpoint event occured in core.
484 *
485 * @return       None.
486 *
487 * @note         None.
488 *
489 *****************************************************************************/
490 void XUsbPsu_Ep0Intr(struct XUsbPsu *InstancePtr,
491                 const struct XUsbPsu_Event_Epevt *Event)
492 {
493
494         Xil_AssertVoid(InstancePtr != NULL);
495         Xil_AssertVoid(Event != NULL);
496
497         switch (Event->Endpoint_Event) {
498         case XUSBPSU_DEPEVT_XFERCOMPLETE:
499                 XUsbPsu_Ep0XferComplete(InstancePtr, Event);
500                 break;
501
502         case XUSBPSU_DEPEVT_XFERNOTREADY:
503                 XUsbPsu_Ep0XferNotReady(InstancePtr, Event);
504                 break;
505
506         case XUSBPSU_DEPEVT_XFERINPROGRESS:
507         case XUSBPSU_DEPEVT_STREAMEVT:
508         case XUSBPSU_DEPEVT_EPCMDCMPLT:
509                 break;
510
511         default:
512                 /* Default case is a required MIRSA-C guideline. */
513                 break;
514         }
515 }
516
517 /****************************************************************************/
518 /**
519 * Initiates DMA to send data on Control Endpoint EP0 IN to Host.
520 *
521 * @param        InstancePtr is a pointer to the XUsbPsu instance.
522 * @param        BufferPtr is pointer to data.
523 * @param        BufferLen is Length of data buffer.
524 *
525 * @return       XST_SUCCESS else XST_FAILURE
526 *
527 * @note         None.
528 *
529 *****************************************************************************/
530 s32 XUsbPsu_Ep0Send(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 BufferLen)
531 {
532         /* Control IN - EP1 */
533         struct XUsbPsu_EpParams *Params;
534         struct XUsbPsu_Ep       *Ept;
535         struct XUsbPsu_Trb      *TrbPtr;
536         s32 Ret;
537
538         Xil_AssertNonvoid(InstancePtr != NULL);
539         Xil_AssertNonvoid(BufferPtr != NULL);
540
541         Ept = &InstancePtr->eps[1];
542         Params = XUsbPsu_GetEpParams(InstancePtr);
543         Xil_AssertNonvoid(Params != NULL);
544
545         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
546                 return XST_FAILURE;
547         }
548
549         Ept->RequestedBytes = BufferLen;
550         Ept->BytesTxed = 0U;
551         Ept->BufferPtr = BufferPtr;
552
553         TrbPtr = &InstancePtr->Ep0_Trb;
554
555         TrbPtr->BufferPtrLow  = (UINTPTR)BufferPtr;
556         TrbPtr->BufferPtrHigh  = ((UINTPTR)BufferPtr >> 16) >> 16;
557         TrbPtr->Size = BufferLen;
558         TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
559
560         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
561                         | XUSBPSU_TRB_CTRL_LST
562                         | XUSBPSU_TRB_CTRL_IOC
563                         | XUSBPSU_TRB_CTRL_ISP_IMI);
564
565         Params->Param0 = 0U;
566         Params->Param1 = (UINTPTR)TrbPtr;
567
568         Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
569         Xil_DCacheFlushRange((INTPTR)BufferPtr, BufferLen);
570
571         InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
572
573         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_IN,
574                                                         XUSBPSU_DEPCMD_STARTTRANSFER, Params);
575         if (Ret != XST_SUCCESS) {
576                 return XST_FAILURE;
577         }
578
579         Ept->EpStatus |= XUSBPSU_EP_BUSY;
580         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
581                                                 Ept->UsbEpNum, Ept->Direction);
582
583         return XST_SUCCESS;
584 }
585
586 /****************************************************************************/
587 /**
588 * Initiates DMA to receive data on Control Endpoint EP0 OUT from Host.
589 *
590 * @param        InstancePtr is a pointer to the XUsbPsu instance.
591 * @param        BufferPtr is pointer to data.
592 * @param        Length is Length of data to be received.
593 *
594 * @return       XST_SUCCESS else XST_FAILURE
595 *
596 * @note         None.
597 *
598 *****************************************************************************/
599 s32 XUsbPsu_Ep0Recv(struct XUsbPsu *InstancePtr, u8 *BufferPtr, u32 Length)
600 {
601         struct XUsbPsu_EpParams *Params;
602         struct XUsbPsu_Ep       *Ept;
603         struct XUsbPsu_Trb      *TrbPtr;
604         u32 Size;
605         s32 Ret;
606
607         Xil_AssertNonvoid(InstancePtr != NULL);
608         Xil_AssertNonvoid(BufferPtr != NULL);
609
610         Ept = &InstancePtr->eps[0];
611         Params = XUsbPsu_GetEpParams(InstancePtr);
612         Xil_AssertNonvoid(Params != NULL);
613
614         if ((Ept->EpStatus & XUSBPSU_EP_BUSY) != 0U) {
615                 return XST_FAILURE;
616         }
617
618         Ept->RequestedBytes = Length;
619         Size = Length;
620         Ept->BytesTxed = 0U;
621         Ept->BufferPtr = BufferPtr;
622
623         /*
624          * 8.2.5 - An OUT transfer size (Total TRB buffer allocation)
625          * must be a multiple of MaxPacketSize even if software is expecting a
626          * fixed non-multiple of MaxPacketSize transfer from the Host.
627          */
628         if (!IS_ALIGNED(Length, Ept->MaxSize)) {
629                 Size = (u32)roundup(Length, Ept->MaxSize);
630                 InstancePtr->UnalignedTx = 1U;
631         }
632
633         TrbPtr = &InstancePtr->Ep0_Trb;
634
635         TrbPtr->BufferPtrLow = (UINTPTR)BufferPtr;
636         TrbPtr->BufferPtrHigh = ((UINTPTR)BufferPtr >> 16) >> 16;
637         TrbPtr->Size = Size;
638         TrbPtr->Ctrl = XUSBPSU_TRBCTL_CONTROL_DATA;
639
640         TrbPtr->Ctrl |= (XUSBPSU_TRB_CTRL_HWO
641                         | XUSBPSU_TRB_CTRL_LST
642                         | XUSBPSU_TRB_CTRL_IOC
643                         | XUSBPSU_TRB_CTRL_ISP_IMI);
644
645         Xil_DCacheFlushRange((INTPTR)TrbPtr, sizeof(struct XUsbPsu_Trb));
646         Xil_DCacheInvalidateRange((INTPTR)BufferPtr, Length);
647
648         Params->Param0 = 0U;
649         Params->Param1 = (UINTPTR)TrbPtr;
650
651         InstancePtr->Ep0State = XUSBPSU_EP0_DATA_PHASE;
652
653         Ret = XUsbPsu_SendEpCmd(InstancePtr, 0U, XUSBPSU_EP_DIR_OUT,
654                                 XUSBPSU_DEPCMD_STARTTRANSFER, Params);
655         if (Ret != XST_SUCCESS) {
656                 return XST_FAILURE;
657         }
658
659         Ept->EpStatus |= XUSBPSU_EP_BUSY;
660         Ept->ResourceIndex = (u8)XUsbPsu_EpGetTransferIndex(InstancePtr,
661                                                         Ept->UsbEpNum, Ept->Direction);
662
663         return XST_SUCCESS;
664 }
665
666 /*****************************************************************************/
667 /**
668 *
669 * API for Sleep routine.
670 *
671 * @param        USeconds is time in MicroSeconds.
672 *
673 * @return       None.
674 *
675 * @note         None.
676 *
677 ******************************************************************************/
678 void XUsbSleep(u32 USeconds) {
679         (void)usleep(USeconds);
680 }
681 /** @} */