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