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