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