]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/usbps_v2_1/src/xusbps_endpoint.c
24bd89b5dffc980c3ccbf1f19bd665ba3d05d564
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / usbps_v2_1 / src / xusbps_endpoint.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2014 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  * @file xusbps_endpoint.c
35  *
36  * Endpoint specific function implementations.
37  *
38  * @note     None.
39  *
40  * <pre>
41  * MODIFICATION HISTORY:
42  *
43  * Ver   Who  Date     Changes
44  * ----- ---- -------- --------------------------------------------------------
45  * 1.00a jz  10/10/10 First release
46  * 1.03a nm  09/21/12 Fixed CR#678977. Added proper sequence for setup packet
47  *                    handling.
48  * 1.04a nm  11/02/12 Fixed CR#683931. Mult bits are set properly in dQH.
49  * 2.00a kpc 04/03/14 Fixed CR#777763. Updated the macro names 
50  * 2.1   kpc 04/28/14 Added XUsbPs_EpBufferSendWithZLT api and merged common
51  *                    code to XUsbPs_EpQueueRequest.
52  * </pre>
53  ******************************************************************************/
54
55 /***************************** Include Files **********************************/
56
57 #include <string.h> /* for bzero() */
58 #include <stdio.h>
59
60 #include "xusbps.h"
61 #include "xusbps_endpoint.h"
62
63 /************************** Constant Definitions ******************************/
64
65 /**************************** Type Definitions ********************************/
66
67 /************************** Variable Definitions ******************************/
68
69 /************************** Function Prototypes ******************************/
70
71 static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr);
72 static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr);
73 static int  XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr);
74 static int  XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
75                                         const u8 *BufferPtr, u32 BufferLen);
76
77 static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len);
78
79 /* Functions to reconfigure endpoint upon host's set alternate interface
80  * request.
81  */
82 static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
83                                         int EpNum, unsigned short NewDirection);
84 static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
85                                         int EpNum, unsigned short NewDirection);
86 static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
87                                 const u8 *BufferPtr, u32 BufferLen, u8 ReqZero);
88
89 /******************************* Functions ************************************/
90
91 /*****************************************************************************/
92 /**
93  *
94  * This function configures the DEVICE side of the controller. The caller needs
95  * to pass in the desired configuration (e.g. number of endpoints) and a
96  * DMAable buffer that will hold the Queue Head List and the Transfer
97  * Descriptors. The required size for this buffer can be obtained by the caller
98  * using the: XUsbPs_DeviceMemRequired() macro.
99  *
100  * @param       InstancePtr is a pointer to the XUsbPs instance of the
101  *              controller.
102  * @param       CfgPtr is a pointer to the configuration structure that contains
103  *              the desired DEVICE side configuration.
104  *
105  * @return
106  *              - XST_SUCCESS: The operation completed successfully.
107  *              - XST_FAILURE: An error occured.
108  *
109  * @note
110  *              The caller may configure the controller for both, DEVICE and
111  *              HOST side.
112  *
113  ******************************************************************************/
114 int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr,
115                             const XUsbPs_DeviceConfig *CfgPtr)
116 {
117         int     Status;
118         u32 ModeValue = 0x0;
119
120         Xil_AssertNonvoid(InstancePtr != NULL);
121         Xil_AssertNonvoid(CfgPtr      != NULL);
122
123         /* Copy the configuration data over into the local instance structure */
124         InstancePtr->DeviceConfig = *CfgPtr;
125
126
127         /* Align the buffer to a 2048 byte (XUSBPS_dQH_BASE_ALIGN) boundary.*/
128         InstancePtr->DeviceConfig.PhysAligned =
129                 (InstancePtr->DeviceConfig.DMAMemPhys +
130                                          XUSBPS_dQH_BASE_ALIGN) &
131                                                 ~(XUSBPS_dQH_BASE_ALIGN -1);
132
133         /* Initialize the endpoint pointer list data structure. */
134         XUsbPs_EpListInit(&InstancePtr->DeviceConfig);
135
136
137         /* Initialize the Queue Head structures in DMA memory. */
138         XUsbPs_dQHInit(&InstancePtr->DeviceConfig);
139
140
141         /* Initialize the Transfer Descriptors in DMA memory.*/
142         Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig);
143         if (XST_SUCCESS != Status) {
144                 return XST_FAILURE;
145         }
146
147         /* Changing the DEVICE mode requires a controller RESET. */
148         if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) {
149                 return XST_FAILURE;
150         }
151
152         /* Set the Queue Head List address. */
153         XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
154                                 XUSBPS_EPLISTADDR_OFFSET,
155                                 InstancePtr->DeviceConfig.PhysAligned);
156
157         /* Set the USB mode register to configure DEVICE mode.
158          *
159          * XUSBPS_MODE_SLOM_MASK note:
160          *   Disable Setup Lockout. Setup Lockout is not required as we
161          *   will be using the tripwire mechanism when handling setup
162          *   packets.
163          */
164         ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK;
165
166         XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
167                                 XUSBPS_MODE_OFFSET, ModeValue);
168
169         XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET,
170                                 XUSBPS_OTGSC_OT_MASK);
171
172         return XST_SUCCESS;
173 }
174
175 /*****************************************************************************/
176 /**
177 * This function sends a given data buffer.
178 *
179 * @param        InstancePtr is a pointer to XUsbPs instance of the controller.
180 * @param        EpNum is the number of the endpoint to receive data from.
181 * @param        BufferPtr is a pointer to the buffer to send.
182 * @param        BufferLen is the Buffer length.
183 *
184 * @return
185 *               - XST_SUCCESS: The operation completed successfully.
186 *               - XST_FAILURE: An error occured.
187 *               - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
188 *               - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
189 *
190 ******************************************************************************/
191 int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum,
192                                 const u8 *BufferPtr, u32 BufferLen)
193 {
194         Xil_AssertNonvoid(InstancePtr  != NULL);
195         Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
196
197         return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
198                                         BufferLen, FALSE);
199 }
200
201 /*****************************************************************************/
202 /**
203 * This function sends a given data buffer and also zero length packet if the
204 * Bufferlen is in multiples of endpoint max packet size.
205 *
206 * @param        InstancePtr is a pointer to XUsbPs instance of the controller.
207 * @param        EpNum is the number of the endpoint to receive data from.
208 * @param        BufferPtr is a pointer to the buffer to send.
209 * @param        BufferLen is the Buffer length.
210 *
211 * @return
212 *               - XST_SUCCESS: The operation completed successfully.
213 *               - XST_FAILURE: An error occured.
214 *               - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
215 *               - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
216 *
217 ******************************************************************************/
218 int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum,
219                                 const u8 *BufferPtr, u32 BufferLen)
220 {
221         u8 ReqZero = FALSE;
222         XUsbPs_EpSetup *Ep;
223
224         Xil_AssertNonvoid(InstancePtr  != NULL);
225         Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
226
227         Ep = &InstancePtr->DeviceConfig.EpCfg[EpNum].In;
228
229         if ((BufferLen >= Ep->MaxPacketSize) &&
230                 (BufferLen % Ep->MaxPacketSize == 0)) {
231                 ReqZero = TRUE;
232         }
233
234         return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
235                                                 BufferLen, ReqZero);
236 }
237
238 /*****************************************************************************/
239 /**
240 * This function sends a given data buffer and also sends ZLT packet if it is
241 * requested.
242 *
243 * @param        InstancePtr is a pointer to XUsbPs instance of the controller.
244 * @param        EpNum is the number of the endpoint to receive data from.
245 * @param        BufferPtr is a pointer to the buffer to send.
246 * @param        BufferLen is the Buffer length.
247 * @param        ReqZero is the
248 *
249 * @return
250 *               - XST_SUCCESS: The operation completed successfully.
251 *               - XST_FAILURE: An error occured.
252 *               - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
253 *               - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
254 *
255 ******************************************************************************/
256 static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
257                                 const u8 *BufferPtr, u32 BufferLen, u8 ReqZero)
258 {
259         int             Status;
260         u32             Token;
261         XUsbPs_EpIn     *Ep;
262         XUsbPs_dTD      *DescPtr;
263         u32             Length;
264         u32             PipeEmpty = 1;
265         u32             Mask = 0x00010000;
266         u32             BitMask = Mask << EpNum;
267         u32             RegValue;
268         u32             Temp;
269         u32 exit = 1;
270
271
272         /* Locate the next available buffer in the ring. A buffer is available
273          * if its descriptor is not active.
274          */
275         Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In;
276
277         Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen);
278
279         if(Ep->dTDTail != Ep->dTDHead) {
280                 PipeEmpty = 0;
281         }
282         XUsbPs_dTDInvalidateCache(Ep->dTDHead);
283
284         /* Tell the caller if we do not have any descriptors available. */
285         if (XUsbPs_dTDIsActive(Ep->dTDHead)) {
286                 return XST_USB_NO_DESC_AVAILABLE;
287         }
288
289         /* Remember the current head. */
290         DescPtr = Ep->dTDHead;
291
292         do {
293                 Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen;
294                 /* Attach the provided buffer to the current descriptor.*/
295                 Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length);
296                 if (XST_SUCCESS != Status) {
297                         return XST_FAILURE;
298                 }
299                 BufferLen -= Length;
300                 BufferPtr += Length;
301
302                 XUsbPs_dTDSetActive(Ep->dTDHead);
303                 if (BufferLen == 0 && (ReqZero == FALSE)) {
304                         XUsbPs_dTDSetIOC(Ep->dTDHead);
305                         exit = 0;
306                 }
307                 XUsbPs_dTDClrTerminate(Ep->dTDHead);
308                 XUsbPs_dTDFlushCache(Ep->dTDHead);
309
310                 /* Advance the head descriptor pointer to the next descriptor. */
311                 Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead);
312                 /* Terminate the next descriptor and flush the cache.*/
313                 XUsbPs_dTDInvalidateCache(Ep->dTDHead);
314                 /* Tell the caller if we do not have any descriptors available. */
315                 if (XUsbPs_dTDIsActive(Ep->dTDHead)) {
316                         return XST_USB_NO_DESC_AVAILABLE;
317                 }
318
319                 if (ReqZero && BufferLen == 0) {
320                         ReqZero = FALSE;
321                 }
322
323         } while(BufferLen || exit);
324
325         XUsbPs_dTDSetTerminate(Ep->dTDHead);
326         XUsbPs_dTDFlushCache(Ep->dTDHead);
327
328         if(!PipeEmpty) {
329                 /* Read the endpoint prime register. */
330                 RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET);
331                 if(RegValue & BitMask) {
332                         return XST_SUCCESS;
333                 }
334
335                 do {
336                         RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);
337                         XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
338                                                 RegValue | XUSBPS_CMD_ATDTW_MASK);
339                         Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET)
340                                                 & BitMask;
341                 } while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) &
342                                 XUSBPS_CMD_ATDTW_MASK));
343
344                 RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);
345                 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
346                                         RegValue & ~XUSBPS_CMD_ATDTW_MASK);
347
348                 if(Temp) {
349                         return XST_SUCCESS;
350                 }
351         }
352
353         /* Check, if the DMA engine is still running. If it is running, we do
354          * not clear Queue Head fields.
355          *
356          * Same cache rule as for the Transfer Descriptor applies for the Queue
357          * Head.
358          */
359         XUsbPs_dQHInvalidateCache(Ep->dQH);
360         /* Add the dTD to the dQH */
361         XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr);
362         Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN);
363         Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK);
364         XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token);
365
366         XUsbPs_dQHFlushCache(Ep->dQH);
367
368         Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN);
369
370         return Status;
371 }
372
373 /*****************************************************************************/
374 /**
375  * This function receives a data buffer from the endpoint of the given endpoint
376  * number.
377  *
378  * @param       InstancePtr is a pointer to the XUsbPs instance of the
379  *              controller.
380  * @param       EpNum is the number of the endpoint to receive data from.
381  * @param       BufferPtr (OUT param) is a pointer to the buffer pointer to hold
382  *              the reference of the data buffer.
383  * @param       BufferLenPtr (OUT param) is a pointer to the integer that will
384  *              hold the buffer length.
385  * @param       Handle is the opaque handle to be used when the buffer is
386  *              released.
387  *
388  * @return
389  *              - XST_SUCCESS: The operation completed successfully.
390  *              - XST_FAILURE: An error occured.
391  *              - XST_USB_NO_BUF: No buffer available.
392  *
393  * @note
394  *              After handling the data in the buffer, the user MUST release
395  *              the buffer using the Handle by calling the
396  *              XUsbPs_EpBufferRelease() function.
397  *
398  ******************************************************************************/
399 int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum,
400                                 u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle)
401 {
402         XUsbPs_EpOut    *Ep;
403         XUsbPs_EpSetup  *EpSetup;
404         u32 length = 0;
405
406         Xil_AssertNonvoid(InstancePtr  != NULL);
407         Xil_AssertNonvoid(BufferPtr    != NULL);
408         Xil_AssertNonvoid(BufferLenPtr != NULL);
409         Xil_AssertNonvoid(Handle       != NULL);
410         Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
411
412         /* Locate the next available buffer in the ring. A buffer is available
413          * if its descriptor is not active.
414          */
415         Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;
416
417         XUsbPs_dTDInvalidateCache(Ep->dTDCurr);
418
419         if (XUsbPs_dTDIsActive(Ep->dTDCurr)) {
420                 return XST_USB_NO_BUF;
421         }
422
423         /* The buffer is not active which means that it has been processed by
424          * the DMA engine and contains valid data.
425          */
426         EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out;
427
428
429         /* Use the buffer pointer stored in the "user data" field of the
430          * Transfer Descriptor.
431          */
432         *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr,
433                                                 XUSBPS_dTDUSERDATA);
434
435         length = EpSetup->BufSize -
436                         XUsbPs_dTDGetTransferLen(Ep->dTDCurr);
437
438         if(length > 0) {
439                 *BufferLenPtr = length;
440         }else {
441                 *BufferLenPtr = 0;
442         }
443
444         *Handle = (u32) Ep->dTDCurr;
445
446
447         /* Reset the descriptor's BufferPointer0 and Transfer Length fields to
448          * their original value. Note that we can not yet re-activate the
449          * descriptor as the caller will be using the attached buffer. Once the
450          * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we
451          * can re-activate the descriptor.
452          */
453         XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr);
454         XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize);
455
456         XUsbPs_dTDFlushCache(Ep->dTDCurr);
457
458         return XST_SUCCESS;
459 }
460
461
462 /*****************************************************************************/
463 /**
464 * This function returns a previously received data buffer to the driver.
465 *
466 * @param        Handle is a pointer to the buffer that is returned.
467 *
468 * @return       None.
469 *
470 ******************************************************************************/
471 void XUsbPs_EpBufferRelease(u32 Handle)
472 {
473         XUsbPs_dTD              *dTDPtr;
474
475         /* Perform sanity check on Handle.*/
476         Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN)));
477
478         /* Activate the descriptor and clear the Terminate bit. Make sure to do
479          * the proper cache handling.
480          */
481         dTDPtr = (XUsbPs_dTD *) Handle;
482
483         XUsbPs_dTDInvalidateCache(dTDPtr);
484
485         XUsbPs_dTDClrTerminate(dTDPtr);
486         XUsbPs_dTDSetActive(dTDPtr);
487         XUsbPs_dTDSetIOC(dTDPtr);
488
489         XUsbPs_dTDFlushCache(dTDPtr);
490
491 }
492
493
494 /*****************************************************************************/
495 /**
496  * This function sets the handler for endpoint events.
497  *
498  * @param       InstancePtr is a pointer to the XUsbPs instance of the
499  *              controller.
500  * @param       EpNum is the number of the endpoint to receive data from.
501  * @param       Direction is the direction of the endpoint (bitfield):
502  *                      - XUSBPS_EP_DIRECTION_OUT
503  *                      - XUSBPS_EP_DIRECTION_IN
504  * @param       CallBackFunc is the Handler callback function.
505  *              Can be NULL if the user wants to disable the handler entry.
506  * @param       CallBackRef is the user definable data pointer that will be
507  *              passed back if the handler is called. May be NULL.
508  *
509  * @return
510  *              - XST_SUCCESS: The operation completed successfully.
511  *              - XST_FAILURE: An error occured.
512  *              - XST_INVALID_PARAM: Invalid parameter passed.
513  *
514  * @note
515  *              The user can disable a handler by setting the callback function
516  *              pointer to NULL.
517  *
518  ******************************************************************************/
519 int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction,
520                          XUsbPs_EpHandlerFunc CallBackFunc,
521                          void *CallBackRef)
522 {
523         XUsbPs_Endpoint *Ep;
524
525         Xil_AssertNonvoid(InstancePtr  != NULL);
526         Xil_AssertNonvoid(CallBackFunc != NULL);
527         Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
528
529         Ep = &InstancePtr->DeviceConfig.Ep[EpNum];
530
531         if(Direction & XUSBPS_EP_DIRECTION_OUT) {
532                 Ep->Out.HandlerFunc     = CallBackFunc;
533                 Ep->Out.HandlerRef      = CallBackRef;
534         }
535
536         if(Direction & XUSBPS_EP_DIRECTION_IN) {
537                 Ep->In.HandlerFunc      = CallBackFunc;
538                 Ep->In.HandlerRef       = CallBackRef;
539         }
540
541         return XST_SUCCESS;
542 }
543
544
545 /*****************************************************************************/
546 /**
547 * This function primes an endpoint.
548 *
549 * @param        InstancePtr is pointer to the XUsbPs instance.
550 * @param        EpNum is the number of the endpoint to receive data from.
551 * @param        Direction is the direction of the endpoint (bitfield):
552 *                       - XUSBPS_EP_DIRECTION_OUT
553 *                       - XUSBPS_EP_DIRECTION_IN
554 *
555 * @return
556 *               - XST_SUCCESS: The operation completed successfully.
557 *               - XST_FAILURE: An error occured.
558 *               - XST_INVALID_PARAM: Invalid parameter passed.
559 *
560 * @note         None.
561 *
562 ******************************************************************************/
563 int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction)
564 {
565         u32     Mask;
566
567         Xil_AssertNonvoid(InstancePtr  != NULL);
568         Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
569
570         /* Get the right bit mask for the endpoint direction. */
571         switch (Direction) {
572
573         case XUSBPS_EP_DIRECTION_OUT:
574                 Mask = 0x00000001;
575                 break;
576
577         case XUSBPS_EP_DIRECTION_IN:
578                 Mask = 0x00010000;
579                 break;
580
581         default:
582                 return XST_INVALID_PARAM;
583         }
584
585         /* Write the endpoint prime register. */
586         XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
587                                 XUSBPS_EPPRIME_OFFSET, Mask << EpNum);
588
589         return XST_SUCCESS;
590 }
591
592
593 /*****************************************************************************/
594 /**
595 * This function extracts the Setup Data from a given endpoint.
596 *
597 * @param        InstancePtr is a pointer to the XUsbPs instance of the
598 *               controller.
599 * @param        EpNum is the number of the endpoint to receive data from.
600 * @param        SetupDataPtr is a pointer to the setup data structure to be
601 *               filled.
602 *
603 * @return
604 *               - XST_SUCCESS: The operation completed successfully.
605 *               - XST_FAILURE: An error occured.
606 *
607 * @note         None.
608 ******************************************************************************/
609 int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum,
610                                 XUsbPs_SetupData *SetupDataPtr)
611 {
612         XUsbPs_EpOut    *Ep;
613
614         u32     Data[2];
615         u8      *p;
616
617         int Timeout;
618
619         Xil_AssertNonvoid(InstancePtr  != NULL);
620         Xil_AssertNonvoid(SetupDataPtr != NULL);
621         Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
622
623         Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;
624
625
626         /* Get the data from the Queue Heads Setup buffer into local variables
627          * so we can extract the setup data values.
628          */
629         do {
630                 /* Arm the tripwire. The tripwire will tell us if a new setup
631                  * packet arrived (in which case the tripwire bit will be
632                  * cleared) while we were reading the buffer. If a new setup
633                  * packet arrived the buffer is corrupted and we continue
634                  * reading.
635                  */
636                 XUsbPs_SetSetupTripwire(InstancePtr);
637
638                 XUsbPs_dQHInvalidateCache(Ep->dQH);
639
640                 Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0);
641                 Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1);
642         } while (FALSE == XUsbPs_SetupTripwireIsSet(InstancePtr));
643
644         /* Clear the pending endpoint setup stat bit.
645          */
646         XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
647                                 XUSBPS_EPSTAT_OFFSET, 1 << EpNum);
648
649         /* Clear the Tripwire bit and continue.
650          */
651         XUsbPs_ClrSetupTripwire(InstancePtr);
652
653
654         /* Data in the setup buffer is being converted by the core to big
655          * endian format. We have to take care of proper byte swapping when
656          * reading the setup data values.
657          *
658          * Need to check if there is a smarter way to do this and take the
659          * processor/memory-controller endianess into account?
660          */
661         p = (u8 *) Data;
662
663         SetupDataPtr->bmRequestType     = p[0];
664         SetupDataPtr->bRequest          = p[1];
665         SetupDataPtr->wValue            = (p[3] << 8) | p[2];
666         SetupDataPtr->wIndex            = (p[5] << 8) | p[4];
667         SetupDataPtr->wLength           = (p[7] << 8) | p[6];
668
669         /* Before we leave we need to make sure that the endpoint setup bit has
670          * cleared. It needs to be 0 before the endpoint can be re-primed.
671          *
672          * Note: According to the documentation this endpoint setup bit should
673          * clear within 1-2us after it has been written above. This means that
674          * we should never catch it being 1 here. However, we still need to
675          * poll it to make sure. Just in case, we use a counter 'Timeout' so we
676          * won't hang here if the bit is stuck for some reason.
677          */
678         Timeout = XUSBPS_TIMEOUT_COUNTER;
679         while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
680                                 XUSBPS_EPSTAT_OFFSET) &
681                                 (1 << EpNum)) && --Timeout) {
682                 /* NOP */
683         }
684         if (0 == Timeout) {
685                 return XST_FAILURE;
686         }
687
688         return XST_SUCCESS;
689 }
690
691
692 /*****************************************************************************/
693 /**
694 *
695 * This function initializes the endpoint pointer data structure.
696 *
697 * The function sets up the local data structure with the aligned addresses for
698 * the Queue Head and Transfer Descriptors.
699 *
700 * @param        DevCfgPtr is pointer to the XUsbPs DEVICE configuration
701 *               structure.
702 *
703 * @return       none
704 *
705 * @note
706 *               Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the
707 *               system. Therefore no memory is reserved for them.
708 *
709 ******************************************************************************/
710 static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr)
711 {
712         int     EpNum;
713         u8      *p;
714
715         XUsbPs_Endpoint *Ep;
716         XUsbPs_EpConfig *EpCfg;
717
718         /* Set up the XUsbPs_Endpoint array. This array is used to define the
719          * location of the Queue Head list and the Transfer Descriptors in the
720          * block of DMA memory that has been passed into the driver.
721          *
722          * 'p' is used to set the pointers in the local data structure.
723          * Initially 'p' is pointed to the beginning of the DMAable memory
724          * block. As pointers are assigned, 'p' is incremented by the size of
725          * the respective object.
726          */
727         Ep      = DevCfgPtr->Ep;
728         EpCfg   = DevCfgPtr->EpCfg;
729
730         /* Start off with 'p' pointing to the (aligned) beginning of the DMA
731          * buffer.
732          */
733         p = (u8 *) DevCfgPtr->PhysAligned;
734
735
736         /* Initialize the Queue Head pointer list.
737          *
738          * Each endpoint has two Queue Heads. One for the OUT direction and one
739          * for the IN direction. An OUT Queue Head is always followed by an IN
740          * Queue Head.
741          *
742          * Queue Head alignment is XUSBPS_dQH_ALIGN.
743          *
744          * Note that we have to reserve space here for unused endpoints.
745          */
746         for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
747                 /* OUT Queue Head */
748                 Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p;
749                 p += XUSBPS_dQH_ALIGN;
750
751                 /* IN Queue Head */
752                 Ep[EpNum].In.dQH = (XUsbPs_dQH *) p;
753                 p += XUSBPS_dQH_ALIGN;
754         }
755
756
757         /* 'p' now points to the first address after the Queue Head list. The
758          * Transfer Descriptors start here.
759          *
760          * Each endpoint has a variable number of Transfer Descriptors
761          * depending on user configuration.
762          *
763          * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN.
764          */
765         for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
766                 /* OUT Descriptors.
767                  */
768                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
769                         Ep[EpNum].Out.dTDs              = (XUsbPs_dTD *) p;
770                         Ep[EpNum].Out.dTDCurr   = (XUsbPs_dTD *) p;
771                         p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs;
772                 }
773
774                 /* IN Descriptors.
775                  */
776                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
777                         Ep[EpNum].In.dTDs               = (XUsbPs_dTD *) p;
778                         Ep[EpNum].In.dTDHead    = (XUsbPs_dTD *) p;
779                         Ep[EpNum].In.dTDTail    = (XUsbPs_dTD *) p;
780                         p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].In.NumBufs;
781                 }
782         }
783
784
785         /* 'p' now points to the first address after the Transfer Descriptors.
786          * The data buffers for the OUT Transfer Desciptors start here.
787          *
788          * Note that IN (TX) Transfer Descriptors are not assigned buffers at
789          * this point. Buffers will be assigned when the user calls the send()
790          * function.
791          */
792         for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
793
794                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
795                         /* If BufSize for this endpoint is set to 0 it means
796                          * that we do not need to attach a buffer to this
797                          * descriptor. We also initialize it's buffer pointer
798                          * to NULL.
799                          */
800                         if (0 == EpCfg[EpNum].Out.BufSize) {
801                                 Ep[EpNum].Out.dTDBufs = NULL;
802                                 continue;
803                         }
804
805                         Ep[EpNum].Out.dTDBufs = p;
806                         p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs;
807                 }
808         }
809
810
811         /* Initialize the endpoint event handlers to NULL.
812          */
813         for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
814                 Ep[EpNum].Out.HandlerFunc = NULL;
815                 Ep[EpNum].In.HandlerFunc  = NULL;
816         }
817 }
818
819
820 /*****************************************************************************/
821 /**
822 *
823 * This function initializes the Queue Head List in memory.
824 *
825 * @param        DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
826 *               structure.
827 *
828 * @return       None
829 *
830 * @note         None.
831 *
832 ******************************************************************************/
833 static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr)
834 {
835         int     EpNum;
836
837         XUsbPs_Endpoint *Ep;
838         XUsbPs_EpConfig *EpCfg;
839
840         /* Setup pointers for simpler access. */
841         Ep      = DevCfgPtr->Ep;
842         EpCfg   = DevCfgPtr->EpCfg;
843
844
845         /* Go through the list of Queue Head entries and:
846          *
847          * - Set Transfer Descriptor addresses
848          * - Set Maximum Packet Size
849          * - Disable Zero Length Termination (ZLT) for non-isochronous transfers
850          * - Enable Interrupt On Setup (IOS)
851          *
852          */
853         for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
854
855                 /* OUT Queue Heads.*/
856                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
857                         XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
858                                         XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
859
860                         /* For isochronous, ep max packet size translates to different
861                          * values in queue head than other types.
862                          * Also enable ZLT for isochronous.
863                          */
864                         if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {
865                                 XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,
866                         EpCfg[EpNum].Out.MaxPacketSize);
867                                 XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);
868                         }else {
869                                 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
870                                             EpCfg[EpNum].Out.MaxPacketSize);
871                                 XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
872                         }
873
874                         /* Only control OUT needs this */
875                         if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) {
876                                 XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
877                         }
878
879                         /* Set up the overlay next dTD pointer. */
880                         XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
881                                         XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
882
883                         XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
884                 }
885
886
887                 /* IN Queue Heads. */
888                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
889                         XUsbPs_WritedQH(Ep[EpNum].In.dQH,
890                                   XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
891
892
893                         /* Isochronous ep packet size can be larger than 1024.*/
894                         if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {
895                                 XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,
896                                                 EpCfg[EpNum].In.MaxPacketSize);
897                                 XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);
898                         }else {
899                                 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
900                                             EpCfg[EpNum].In.MaxPacketSize);
901                                 XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
902                         }
903
904                         XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
905                 }
906         }
907 }
908
909
910 /*****************************************************************************/
911 /**
912  *
913  * This function initializes the Transfer Descriptors lists in memory.
914  *
915  * @param       DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
916  *              structure.
917  *
918  * @return
919  *              - XST_SUCCESS: The operation completed successfully.
920  *              - XST_FAILURE: An error occured.
921  *
922  ******************************************************************************/
923 static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr)
924 {
925         int     EpNum;
926
927         XUsbPs_Endpoint *Ep;
928         XUsbPs_EpConfig *EpCfg;
929
930         /* Setup pointers for simpler access. */
931         Ep      = DevCfgPtr->Ep;
932         EpCfg   = DevCfgPtr->EpCfg;
933
934
935         /* Walk through the list of endpoints and initialize their Transfer
936          * Descriptors.
937          */
938         for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
939                 int     Td;
940                 int     NumdTD;
941
942                 XUsbPs_EpOut    *Out = &Ep[EpNum].Out;
943                 XUsbPs_EpIn     *In  = &Ep[EpNum].In;
944
945
946                 /* OUT Descriptors
947                  * ===============
948                  *
949                  * + Set the next link pointer
950                  * + Set the interrupt complete and the active bit
951                  * + Attach the buffer to the dTD
952                  */
953                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
954                         NumdTD = EpCfg[EpNum].Out.NumBufs;
955                 }
956                 else {
957                         NumdTD = 0;
958                 }
959
960                 for (Td = 0; Td < NumdTD; ++Td) {
961                         int     Status;
962
963                         int NextTd = (Td + 1) % NumdTD;
964
965                         XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
966
967                         /* Set NEXT link pointer. */
968                         XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
969                                           &Out->dTDs[NextTd]);
970
971                         /* Set the OUT descriptor ACTIVE and enable the
972                          * interrupt on complete.
973                          */
974                         XUsbPs_dTDSetActive(&Out->dTDs[Td]);
975                         XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
976
977
978                         /* Set up the data buffer with the descriptor. If the
979                          * buffer pointer is NULL it means that we do not need
980                          * to attach a buffer to this descriptor.
981                          */
982                         if (NULL == Out->dTDBufs) {
983                                 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
984                                 continue;
985                         }
986
987                         Status = XUsbPs_dTDAttachBuffer(
988                                         &Out->dTDs[Td],
989                                         Out->dTDBufs +
990                                                 (Td * EpCfg[EpNum].Out.BufSize),
991                                         EpCfg[EpNum].Out.BufSize);
992                         if (XST_SUCCESS != Status) {
993                                 return XST_FAILURE;
994                         }
995
996                         XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
997                 }
998
999
1000                 /* IN Descriptors
1001                  * ==============
1002                  *
1003                  * + Set the next link pointer
1004                  * + Set the Terminate bit to mark it available
1005                  */
1006                 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
1007                         NumdTD = EpCfg[EpNum].In.NumBufs;
1008                 }
1009                 else {
1010                         NumdTD = 0;
1011                 }
1012
1013                 for (Td = 0; Td < NumdTD; ++Td) {
1014                         int NextTd = (Td + 1) % NumdTD;
1015
1016                         XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
1017
1018                         /* Set NEXT link pointer. */
1019                         XUsbPs_WritedTD(In->dTDs[Td], XUSBPS_dTDNLP,
1020                                           In->dTDs[NextTd]);
1021
1022                         /* Set the IN descriptor's TERMINATE bits. */
1023                         XUsbPs_dTDSetTerminate(In->dTDs[Td]);
1024
1025                         XUsbPs_dTDFlushCache(&In->dTDs[Td]);
1026                 }
1027         }
1028
1029         return XST_SUCCESS;
1030 }
1031
1032
1033 /*****************************************************************************/
1034 /**
1035  *
1036  * This function associates a buffer with a Transfer Descriptor. The function
1037  * will take care of splitting the buffer into multiple 4kB aligned segments if
1038  * the buffer happens to span one or more 4kB pages.
1039  *
1040  * @param       dTDIndex is a pointer to the Transfer Descriptor
1041  * @param       BufferPtr is pointer to the buffer to link to the descriptor.
1042  * @param       BufferLen is the length of the buffer.
1043  *
1044  * @return
1045  *              - XST_SUCCESS: The operation completed successfully.
1046  *              - XST_FAILURE: An error occured.
1047  *              - XST_USB_BUF_TOO_BIG: The provided buffer is bigger than tha
1048  *              maximum allowed buffer size (16k).
1049  *
1050  * @note
1051  *              Cache invalidation and flushing needs to be handler by the
1052  *              caller of this function.
1053  *
1054  ******************************************************************************/
1055 static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
1056                                         const u8 *BufferPtr, u32 BufferLen)
1057 {
1058         u32     BufAddr;
1059         u32     BufEnd;
1060         u32     PtrNum;
1061
1062         Xil_AssertNonvoid(dTDPtr    != NULL);
1063
1064         /* Check if the buffer is smaller than 16kB. */
1065         if (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) {
1066                 return XST_USB_BUF_TOO_BIG;
1067         }
1068
1069         /* Get a u32 of the buffer pointer to avoid casting in the following
1070          * logic operations.
1071          */
1072         BufAddr = (u32) BufferPtr;
1073
1074
1075         /* Set the buffer pointer 0. Buffer pointer 0 can point to any location
1076          * in memory. It does not need to be 4kB aligned. However, if the
1077          * provided buffer spans one or more 4kB boundaries, we need to set up
1078          * the subsequent buffer pointers which must be 4kB aligned.
1079          */
1080         XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(0), BufAddr);
1081
1082         /* Check if the buffer spans a 4kB boundary.
1083          *
1084          * Only do this check, if we are not sending a 0-length buffer.
1085          */
1086         if (BufferLen > 0) {
1087                 BufEnd = BufAddr + BufferLen -1;
1088                 PtrNum = 1;
1089
1090                 while ((BufAddr & 0xFFFFF000) != (BufEnd & 0xFFFFF000)) {
1091                         /* The buffer spans at least one boundary, let's set
1092                          * the next buffer pointer and repeat the procedure
1093                          * until the end of the buffer and the pointer written
1094                          * are in the same 4kB page.
1095                          */
1096                         BufAddr = (BufAddr + 0x1000) & 0xFFFFF000;
1097                         XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(PtrNum),
1098                                                                 BufAddr);
1099                         PtrNum++;
1100                 }
1101         }
1102
1103         /* Set the length of the buffer. */
1104         XUsbPs_dTDSetTransferLen(dTDPtr, BufferLen);
1105
1106
1107         /* We remember the buffer pointer in the user data field (reserved
1108          * field in the dTD). This makes it easier to reset the buffer pointer
1109          * after a buffer has been received on the endpoint. The buffer pointer
1110          * needs to be reset because the DMA engine modifies the buffer pointer
1111          * while receiving.
1112          */
1113         XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDUSERDATA, BufferPtr);
1114
1115         return XST_SUCCESS;
1116 }
1117
1118
1119 /*****************************************************************************/
1120 /**
1121  * This function set the Max PacketLen for the queue head for isochronous EP.
1122  *
1123  * If the max packet length is greater than XUSBPS_MAX_PACKET_SIZE, then
1124  * Mult bits are set to reflect that.
1125  *
1126  * @param       dQHPtr is a pointer to the dQH element.
1127  * @param       Len is the Length to be set.
1128  *
1129  ******************************************************************************/
1130 static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len)
1131 {
1132         u32 Mult = (Len & ENDPOINT_MAXP_MULT_MASK) >> ENDPOINT_MAXP_MULT_SHIFT;
1133         u32 MaxPktSize = (Mult > 1) ? ENDPOINT_MAXP_LENGTH : Len;
1134
1135         if (MaxPktSize > XUSBPS_MAX_PACKET_SIZE) {
1136                 return;
1137         }
1138
1139         if (Mult > 3) {
1140                 return;
1141         }
1142
1143         /* Set Max packet size */
1144         XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG,
1145                 (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) &
1146                         ~XUSBPS_dQHCFG_MPL_MASK) |
1147                         (MaxPktSize << XUSBPS_dQHCFG_MPL_SHIFT));
1148
1149         /* Set Mult to tell hardware how many transactions in each microframe */
1150         XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG,
1151                 (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) &
1152                         ~XUSBPS_dQHCFG_MULT_MASK) |
1153                         (Mult << XUSBPS_dQHCFG_MULT_SHIFT));
1154
1155 }
1156
1157 /*****************************************************************************/
1158 /**
1159 * This function reconfigures one Ep corresponding to host's request of setting
1160 * alternate interface. The endpoint has been disabled before this call.
1161 *
1162 * Both QH and dTDs are updated for the new configuration.
1163 *
1164 * @param        InstancePtr is a pointer to the XUsbPs instance of the
1165 *               controller.
1166 * @param        CfgPtr
1167 *               Pointer to the updated XUsbPs DEVICE configuration structure.
1168 *
1169 * @param        EpNum
1170 *               The endpoint to be reconfigured.
1171 *
1172 * @param NewDirection
1173 *               The new transfer direction the endpoint.
1174 *
1175 * @param DirectionChanged
1176 *               A boolean value indicate whether the transfer direction has changed.
1177 *
1178 * @return
1179 *       XST_SUCCESS upon success, XST_FAILURE otherwise.
1180 *
1181 ******************************************************************************/
1182 int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr,
1183                                 int EpNum, unsigned short NewDirection,
1184                                 int DirectionChanged) {
1185
1186         int Status = XST_SUCCESS;
1187         XUsbPs_Endpoint *Ep;
1188         XUsbPs_EpConfig *EpCfg;
1189
1190         Xil_AssertNonvoid(InstancePtr != NULL);
1191         Xil_AssertNonvoid(CfgPtr      != NULL);
1192
1193         Ep = CfgPtr->Ep;
1194         EpCfg = CfgPtr->EpCfg;
1195
1196         /* If transfer direction changes, dTDs has to be reset
1197          * Number of buffers are preset and should not to be changed.
1198          */
1199         if(DirectionChanged) {
1200                 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1201                         u8 *p;
1202
1203                         /* Swap the pointer to the dTDs.
1204                          */
1205                         Ep[EpNum].Out.dTDs = Ep[EpNum].In.dTDs;
1206                         p = (u8 *)(Ep[EpNum].Out.dTDs + XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs);
1207
1208                         /* Set the OUT buffer if buffer size is not zero
1209                          */
1210                         if(EpCfg[EpNum].Out.BufSize > 0) {
1211                                 Ep[EpNum].Out.dTDBufs = p;
1212                         }
1213                 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1214                         Ep[EpNum].In.dTDs = Ep[EpNum].Out.dTDs;
1215                 }
1216         }
1217
1218         /* Reset dTD progress tracking pointers
1219          */
1220         if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1221                 Ep[EpNum].In.dTDHead = Ep[EpNum].In.dTDTail = Ep[EpNum].In.dTDs;
1222         } else if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1223                 Ep[EpNum].Out.dTDCurr = Ep[EpNum].Out.dTDs;
1224         }
1225
1226         /* Reinitialize information in QH
1227          */
1228         XUsbPs_dQHReinitEp(CfgPtr, EpNum, NewDirection);
1229
1230         /* Reinitialize the dTD linked list, and flush the cache
1231          */
1232         Status = XUsbPs_dTDReinitEp(CfgPtr, EpNum, NewDirection);
1233         if(Status != XST_SUCCESS) {
1234                 return Status;
1235         }
1236
1237         return XST_SUCCESS;
1238 }
1239
1240
1241 /*****************************************************************************/
1242 /**
1243  * This function re-initializes the Queue Head List in memory.
1244  * The endpoint 1 has been disabled before this call.
1245  *
1246  * @param       DevCfgPtr
1247  *              Pointer to the updated XUsbPs DEVICE configuration structure.
1248  *
1249  * @param       EpNum
1250  *              The endpoint to be reconfigured.
1251  *
1252  * @param       NewDirection
1253  *              The new transfer direction of endpoint 1
1254  *
1255  * @return      none
1256  *
1257  ******************************************************************************/
1258 static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
1259 int EpNum, unsigned short NewDirection)
1260 {
1261         XUsbPs_Endpoint *Ep;
1262         XUsbPs_EpConfig *EpCfg;
1263
1264         /* Setup pointers for simpler access.
1265          */
1266         Ep      = DevCfgPtr->Ep;
1267         EpCfg   = DevCfgPtr->EpCfg;
1268
1269
1270         /* Go through the list of Queue Head entries and:
1271          *
1272          * - Set Transfer Descriptor addresses
1273          * - Set Maximum Packet Size
1274          * - Disable Zero Length Termination (ZLT) for non-isochronous transfers
1275          * - Enable Interrupt On Setup (IOS)
1276          *
1277          */
1278         if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1279                 /* OUT Queue Heads.
1280                  */
1281                 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
1282                         XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
1283
1284                 /* For isochronous, ep max packet size translates to different
1285                  * values in queue head than other types.
1286                  * Also enable ZLT for isochronous.
1287                  */
1288                 if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {
1289                         XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,
1290                                         EpCfg[EpNum].Out.MaxPacketSize);
1291                         XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);
1292                 }else {
1293                         XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
1294                                     EpCfg[EpNum].Out.MaxPacketSize);
1295                         XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
1296                 }
1297
1298                 XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
1299
1300                 /* Set up the overlay next dTD pointer.
1301                  */
1302                 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
1303                                 XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
1304
1305                 XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
1306
1307         } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1308
1309                 /* IN Queue Heads.
1310                  */
1311                 XUsbPs_WritedQH(Ep[EpNum].In.dQH,
1312                           XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
1313
1314                 /* Isochronous ep packet size can be larger than 1024. */
1315                 if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {
1316                         XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,
1317                                 EpCfg[EpNum].In.MaxPacketSize);
1318                         XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);
1319                 }else {
1320                         XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
1321                             EpCfg[EpNum].In.MaxPacketSize);
1322                         XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
1323                 }
1324
1325                 XUsbPs_dQHSetIOS(Ep[EpNum].In.dQH);
1326
1327                 XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
1328         }
1329
1330 }
1331
1332 /*****************************************************************************/
1333 /**
1334  *
1335  * This function re-initializes the Transfer Descriptors lists in memory.
1336  * The endpoint has been disabled before the call. The transfer descriptors
1337  * list pointer has been initialized too.
1338  *
1339  * @param       DevCfgPtr
1340  *              Pointer to the XUsbPs DEVICE configuration structure.
1341  *
1342  * @param       EpNum
1343  *              The endpoint to be reconfigured.
1344  *
1345  * @param       NewDirection
1346  *              The new transfer direction of endpoint 1
1347  *
1348  * @return
1349  *              - XST_SUCCESS: The operation completed successfully.
1350  *              - XST_FAILURE: An error occured.
1351  *
1352  ******************************************************************************/
1353 static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
1354 int EpNum, unsigned short NewDirection)
1355 {
1356         XUsbPs_Endpoint *Ep;
1357         XUsbPs_EpConfig *EpCfg;
1358         int     Td;
1359         int     NumdTD;
1360
1361
1362         /* Setup pointers for simpler access.
1363          */
1364         Ep      = DevCfgPtr->Ep;
1365         EpCfg   = DevCfgPtr->EpCfg;
1366
1367
1368         if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1369                 XUsbPs_EpOut    *Out = &Ep[EpNum].Out;
1370
1371                 /* OUT Descriptors
1372                  * ===============
1373                  *
1374                  * + Set the next link pointer
1375                  * + Set the interrupt complete and the active bit
1376                  * + Attach the buffer to the dTD
1377                  */
1378                 NumdTD = EpCfg[EpNum].Out.NumBufs;
1379
1380                 for (Td = 0; Td < NumdTD; ++Td) {
1381                         int     Status;
1382
1383                         int NextTd = (Td + 1) % NumdTD;
1384
1385                         XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
1386
1387                         /* Set NEXT link pointer.
1388                          */
1389                         XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
1390                                           &Out->dTDs[NextTd]);
1391
1392                         /* Set the OUT descriptor ACTIVE and enable the
1393                          * interrupt on complete.
1394                          */
1395                         XUsbPs_dTDSetActive(&Out->dTDs[Td]);
1396                         XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
1397
1398                         /* Set up the data buffer with the descriptor. If the
1399                          * buffer pointer is NULL it means that we do not need
1400                          * to attach a buffer to this descriptor.
1401                          */
1402                         if (Out->dTDBufs != NULL) {
1403
1404                                 Status = XUsbPs_dTDAttachBuffer(
1405                                                 &Out->dTDs[Td],
1406                                                 Out->dTDBufs +
1407                                                         (Td * EpCfg[EpNum].Out.BufSize),
1408                                                 EpCfg[EpNum].Out.BufSize);
1409                                 if (Status != XST_SUCCESS) {
1410                                         return XST_FAILURE;
1411                                 }
1412                         }
1413                         XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
1414                 }
1415         } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1416                 XUsbPs_EpIn     *In  = &Ep[EpNum].In;
1417
1418                 /* IN Descriptors
1419                  * ==============
1420                  *
1421                  * + Set the next link pointer
1422                  * + Set the Terminate bit to mark it available
1423                  */
1424                 NumdTD = EpCfg[EpNum].In.NumBufs;
1425
1426                 for (Td = 0; Td < NumdTD; ++Td) {
1427                         int NextTd = (Td + 1) % NumdTD;
1428
1429                         XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
1430
1431                         /* Set NEXT link pointer.
1432                          */
1433                         XUsbPs_WritedTD(&In->dTDs[Td], XUSBPS_dTDNLP,
1434                                           &In->dTDs[NextTd]);
1435
1436                         /* Set the IN descriptor's TERMINATE bits.
1437                          */
1438                         XUsbPs_dTDSetTerminate(&In->dTDs[Td]);
1439
1440                         XUsbPs_dTDFlushCache(&In->dTDs[Td]);
1441                 }
1442         }
1443
1444         return XST_SUCCESS;
1445 }
1446