1 /******************************************************************************
3 * Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /******************************************************************************/
34 * @file xusbps_endpoint.c
35 * @addtogroup usbps_v2_2
38 * Endpoint specific function implementations.
43 * MODIFICATION HISTORY:
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
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...)
58 ******************************************************************************/
60 /***************************** Include Files **********************************/
62 #include <string.h> /* for bzero() */
66 #include "xusbps_endpoint.h"
68 /************************** Constant Definitions ******************************/
70 /**************************** Type Definitions ********************************/
72 /************************** Variable Definitions ******************************/
74 /************************** Function Prototypes ******************************/
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);
82 static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len);
84 /* Functions to reconfigure endpoint upon host's set alternate interface
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);
94 /******************************* Functions ************************************/
96 /*****************************************************************************/
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.
105 * @param InstancePtr is a pointer to the XUsbPs instance of the
107 * @param CfgPtr is a pointer to the configuration structure that contains
108 * the desired DEVICE side configuration.
111 * - XST_SUCCESS: The operation completed successfully.
112 * - XST_FAILURE: An error occured.
115 * The caller may configure the controller for both, DEVICE and
118 ******************************************************************************/
119 int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr,
120 const XUsbPs_DeviceConfig *CfgPtr)
125 Xil_AssertNonvoid(InstancePtr != NULL);
126 Xil_AssertNonvoid(CfgPtr != NULL);
128 /* Copy the configuration data over into the local instance structure */
129 InstancePtr->DeviceConfig = *CfgPtr;
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);
138 /* Initialize the endpoint pointer list data structure. */
139 XUsbPs_EpListInit(&InstancePtr->DeviceConfig);
142 /* Initialize the Queue Head structures in DMA memory. */
143 XUsbPs_dQHInit(&InstancePtr->DeviceConfig);
146 /* Initialize the Transfer Descriptors in DMA memory.*/
147 Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig);
148 if (XST_SUCCESS != Status) {
152 /* Changing the DEVICE mode requires a controller RESET. */
153 if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) {
157 /* Set the Queue Head List address. */
158 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
159 XUSBPS_EPLISTADDR_OFFSET,
160 InstancePtr->DeviceConfig.PhysAligned);
162 /* Set the USB mode register to configure DEVICE mode.
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
169 ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK;
171 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
172 XUSBPS_MODE_OFFSET, ModeValue);
174 XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET,
175 XUSBPS_OTGSC_OT_MASK);
180 /*****************************************************************************/
182 * This function sends a given data buffer.
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.
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.
195 ******************************************************************************/
196 int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum,
197 const u8 *BufferPtr, u32 BufferLen)
199 Xil_AssertNonvoid(InstancePtr != NULL);
200 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
202 return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
206 /*****************************************************************************/
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.
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.
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.
222 ******************************************************************************/
223 int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum,
224 const u8 *BufferPtr, u32 BufferLen)
229 Xil_AssertNonvoid(InstancePtr != NULL);
230 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
232 Ep = &InstancePtr->DeviceConfig.EpCfg[EpNum].In;
234 if ((BufferLen >= Ep->MaxPacketSize) &&
235 (BufferLen % Ep->MaxPacketSize == 0)) {
239 return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
243 /*****************************************************************************/
245 * This function sends a given data buffer and also sends ZLT packet if it is
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
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.
260 ******************************************************************************/
261 static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
262 const u8 *BufferPtr, u32 BufferLen, u8 ReqZero)
270 u32 Mask = 0x00010000;
271 u32 BitMask = Mask << EpNum;
277 /* Locate the next available buffer in the ring. A buffer is available
278 * if its descriptor is not active.
280 Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In;
282 Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen);
284 if(Ep->dTDTail != Ep->dTDHead) {
287 XUsbPs_dTDInvalidateCache(Ep->dTDHead);
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;
294 /* Remember the current head. */
295 DescPtr = Ep->dTDHead;
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;
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) {
313 XUsbPs_dTDSetActive(Ep->dTDHead);
314 if (BufferLen == 0 && (ReqZero == FALSE)) {
315 XUsbPs_dTDSetIOC(Ep->dTDHead);
318 XUsbPs_dTDClrTerminate(Ep->dTDHead);
319 XUsbPs_dTDFlushCache(Ep->dTDHead);
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);
326 if (ReqZero && BufferLen == 0) {
330 } while(BufferLen || exit);
332 XUsbPs_dTDSetTerminate(Ep->dTDHead);
333 XUsbPs_dTDFlushCache(Ep->dTDHead);
336 /* Read the endpoint prime register. */
337 RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET);
338 if(RegValue & BitMask) {
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)
348 } while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) &
349 XUSBPS_CMD_ATDTW_MASK));
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);
360 /* Check, if the DMA engine is still running. If it is running, we do
361 * not clear Queue Head fields.
363 * Same cache rule as for the Transfer Descriptor applies for the Queue
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);
373 XUsbPs_dQHFlushCache(Ep->dQH);
375 Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN);
380 /*****************************************************************************/
382 * This function receives a data buffer from the endpoint of the given endpoint
385 * @param InstancePtr is a pointer to the XUsbPs instance of the
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
396 * - XST_SUCCESS: The operation completed successfully.
397 * - XST_FAILURE: An error occured.
398 * - XST_USB_NO_BUF: No buffer available.
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.
405 ******************************************************************************/
406 int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum,
407 u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle)
410 XUsbPs_EpSetup *EpSetup;
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);
419 /* Locate the next available buffer in the ring. A buffer is available
420 * if its descriptor is not active.
422 Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;
424 XUsbPs_dTDInvalidateCache(Ep->dTDCurr);
426 if (XUsbPs_dTDIsActive(Ep->dTDCurr)) {
427 return XST_USB_NO_BUF;
430 /* The buffer is not active which means that it has been processed by
431 * the DMA engine and contains valid data.
433 EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out;
436 /* Use the buffer pointer stored in the "user data" field of the
437 * Transfer Descriptor.
439 *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr,
442 length = EpSetup->BufSize -
443 XUsbPs_dTDGetTransferLen(Ep->dTDCurr);
446 *BufferLenPtr = length;
451 *Handle = (u32) Ep->dTDCurr;
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.
460 XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr);
461 XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize);
463 XUsbPs_dTDFlushCache(Ep->dTDCurr);
469 /*****************************************************************************/
471 * This function returns a previously received data buffer to the driver.
473 * @param Handle is a pointer to the buffer that is returned.
477 ******************************************************************************/
478 void XUsbPs_EpBufferRelease(u32 Handle)
482 /* Perform sanity check on Handle.*/
483 Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN)));
485 /* Activate the descriptor and clear the Terminate bit. Make sure to do
486 * the proper cache handling.
488 dTDPtr = (XUsbPs_dTD *) Handle;
490 XUsbPs_dTDInvalidateCache(dTDPtr);
492 XUsbPs_dTDClrTerminate(dTDPtr);
493 XUsbPs_dTDSetActive(dTDPtr);
494 XUsbPs_dTDSetIOC(dTDPtr);
496 XUsbPs_dTDFlushCache(dTDPtr);
501 /*****************************************************************************/
503 * This function sets the handler for endpoint events.
505 * @param InstancePtr is a pointer to the XUsbPs instance of the
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.
517 * - XST_SUCCESS: The operation completed successfully.
518 * - XST_FAILURE: An error occured.
519 * - XST_INVALID_PARAM: Invalid parameter passed.
522 * The user can disable a handler by setting the callback function
525 ******************************************************************************/
526 int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction,
527 XUsbPs_EpHandlerFunc CallBackFunc,
532 Xil_AssertNonvoid(InstancePtr != NULL);
533 Xil_AssertNonvoid(CallBackFunc != NULL);
534 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
536 Ep = &InstancePtr->DeviceConfig.Ep[EpNum];
538 if(Direction & XUSBPS_EP_DIRECTION_OUT) {
539 Ep->Out.HandlerFunc = CallBackFunc;
540 Ep->Out.HandlerRef = CallBackRef;
543 if(Direction & XUSBPS_EP_DIRECTION_IN) {
544 Ep->In.HandlerFunc = CallBackFunc;
545 Ep->In.HandlerRef = CallBackRef;
552 /*****************************************************************************/
554 * This function primes an endpoint.
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
563 * - XST_SUCCESS: The operation completed successfully.
564 * - XST_FAILURE: An error occured.
565 * - XST_INVALID_PARAM: Invalid parameter passed.
569 ******************************************************************************/
570 int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction)
574 Xil_AssertNonvoid(InstancePtr != NULL);
575 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
577 /* Get the right bit mask for the endpoint direction. */
580 case XUSBPS_EP_DIRECTION_OUT:
584 case XUSBPS_EP_DIRECTION_IN:
589 return XST_INVALID_PARAM;
592 /* Write the endpoint prime register. */
593 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
594 XUSBPS_EPPRIME_OFFSET, Mask << EpNum);
600 /*****************************************************************************/
602 * This function extracts the Setup Data from a given endpoint.
604 * @param InstancePtr is a pointer to the XUsbPs instance of the
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
611 * - XST_SUCCESS: The operation completed successfully.
612 * - XST_FAILURE: An error occured.
615 ******************************************************************************/
616 int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum,
617 XUsbPs_SetupData *SetupDataPtr)
626 Xil_AssertNonvoid(InstancePtr != NULL);
627 Xil_AssertNonvoid(SetupDataPtr != NULL);
628 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
630 Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;
633 /* Get the data from the Queue Heads Setup buffer into local variables
634 * so we can extract the setup data values.
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
643 XUsbPs_SetSetupTripwire(InstancePtr);
645 XUsbPs_dQHInvalidateCache(Ep->dQH);
647 Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0);
648 Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1);
649 } while (FALSE == XUsbPs_SetupTripwireIsSet(InstancePtr));
651 /* Clear the pending endpoint setup stat bit.
653 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
654 XUSBPS_EPSTAT_OFFSET, 1 << EpNum);
656 /* Clear the Tripwire bit and continue.
658 XUsbPs_ClrSetupTripwire(InstancePtr);
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.
665 * Need to check if there is a smarter way to do this and take the
666 * processor/memory-controller endianess into account?
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];
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.
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.
685 Timeout = XUSBPS_TIMEOUT_COUNTER;
686 while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
687 XUSBPS_EPSTAT_OFFSET) &
688 (1 << EpNum)) && --Timeout) {
699 /*****************************************************************************/
702 * This function initializes the endpoint pointer data structure.
704 * The function sets up the local data structure with the aligned addresses for
705 * the Queue Head and Transfer Descriptors.
707 * @param DevCfgPtr is pointer to the XUsbPs DEVICE configuration
713 * Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the
714 * system. Therefore no memory is reserved for them.
716 ******************************************************************************/
717 static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr)
723 XUsbPs_EpConfig *EpCfg;
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.
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.
735 EpCfg = DevCfgPtr->EpCfg;
737 /* Start off with 'p' pointing to the (aligned) beginning of the DMA
740 p = (u8 *) DevCfgPtr->PhysAligned;
743 /* Initialize the Queue Head pointer list.
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
749 * Queue Head alignment is XUSBPS_dQH_ALIGN.
751 * Note that we have to reserve space here for unused endpoints.
753 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
755 Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p;
756 p += XUSBPS_dQH_ALIGN;
759 Ep[EpNum].In.dQH = (XUsbPs_dQH *) p;
760 p += XUSBPS_dQH_ALIGN;
764 /* 'p' now points to the first address after the Queue Head list. The
765 * Transfer Descriptors start here.
767 * Each endpoint has a variable number of Transfer Descriptors
768 * depending on user configuration.
770 * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN.
772 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
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;
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;
792 /* 'p' now points to the first address after the Transfer Descriptors.
793 * The data buffers for the OUT Transfer Desciptors start here.
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()
799 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
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
807 if (0 == EpCfg[EpNum].Out.BufSize) {
808 Ep[EpNum].Out.dTDBufs = NULL;
812 Ep[EpNum].Out.dTDBufs = p;
813 p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs;
818 /* Initialize the endpoint event handlers to NULL.
820 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
821 Ep[EpNum].Out.HandlerFunc = NULL;
822 Ep[EpNum].In.HandlerFunc = NULL;
827 /*****************************************************************************/
830 * This function initializes the Queue Head List in memory.
832 * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
839 ******************************************************************************/
840 static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr)
845 XUsbPs_EpConfig *EpCfg;
847 /* Setup pointers for simpler access. */
849 EpCfg = DevCfgPtr->EpCfg;
852 /* Go through the list of Queue Head entries and:
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)
860 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
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);
867 /* For isochronous, ep max packet size translates to different
868 * values in queue head than other types.
869 * Also enable ZLT for isochronous.
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);
876 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
877 EpCfg[EpNum].Out.MaxPacketSize);
878 XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
881 /* Only control OUT needs this */
882 if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) {
883 XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
886 /* Set up the overlay next dTD pointer. */
887 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
888 XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
890 XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
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);
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);
906 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
907 EpCfg[EpNum].In.MaxPacketSize);
908 XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
911 XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
917 /*****************************************************************************/
920 * This function initializes the Transfer Descriptors lists in memory.
922 * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
926 * - XST_SUCCESS: The operation completed successfully.
927 * - XST_FAILURE: An error occured.
929 ******************************************************************************/
930 static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr)
935 XUsbPs_EpConfig *EpCfg;
937 /* Setup pointers for simpler access. */
939 EpCfg = DevCfgPtr->EpCfg;
942 /* Walk through the list of endpoints and initialize their Transfer
945 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
949 XUsbPs_EpOut *Out = &Ep[EpNum].Out;
950 XUsbPs_EpIn *In = &Ep[EpNum].In;
956 * + Set the next link pointer
957 * + Set the interrupt complete and the active bit
958 * + Attach the buffer to the dTD
960 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
961 NumdTD = EpCfg[EpNum].Out.NumBufs;
967 for (Td = 0; Td < NumdTD; ++Td) {
970 int NextTd = (Td + 1) % NumdTD;
972 XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
974 /* Set NEXT link pointer. */
975 XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
978 /* Set the OUT descriptor ACTIVE and enable the
979 * interrupt on complete.
981 XUsbPs_dTDSetActive(&Out->dTDs[Td]);
982 XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
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.
989 if (NULL == Out->dTDBufs) {
990 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
994 Status = XUsbPs_dTDAttachBuffer(
997 (Td * EpCfg[EpNum].Out.BufSize),
998 EpCfg[EpNum].Out.BufSize);
999 if (XST_SUCCESS != Status) {
1003 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
1010 * + Set the next link pointer
1011 * + Set the Terminate bit to mark it available
1013 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
1014 NumdTD = EpCfg[EpNum].In.NumBufs;
1020 for (Td = 0; Td < NumdTD; ++Td) {
1021 int NextTd = (Td + 1) % NumdTD;
1023 XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
1025 /* Set NEXT link pointer. */
1026 XUsbPs_WritedTD(In->dTDs[Td], XUSBPS_dTDNLP,
1029 /* Set the IN descriptor's TERMINATE bits. */
1030 XUsbPs_dTDSetTerminate(In->dTDs[Td]);
1032 XUsbPs_dTDFlushCache(&In->dTDs[Td]);
1040 /*****************************************************************************/
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.
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.
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).
1058 * Cache invalidation and flushing needs to be handler by the
1059 * caller of this function.
1061 ******************************************************************************/
1062 static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
1063 const u8 *BufferPtr, u32 BufferLen)
1069 Xil_AssertNonvoid(dTDPtr != NULL);
1071 /* Check if the buffer is smaller than 16kB. */
1072 if (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) {
1073 return XST_USB_BUF_TOO_BIG;
1076 /* Get a u32 of the buffer pointer to avoid casting in the following
1079 BufAddr = (u32) BufferPtr;
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.
1087 XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(0), BufAddr);
1089 /* Check if the buffer spans a 4kB boundary.
1091 * Only do this check, if we are not sending a 0-length buffer.
1093 if (BufferLen > 0) {
1094 BufEnd = BufAddr + BufferLen -1;
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.
1103 BufAddr = (BufAddr + 0x1000) & 0xFFFFF000;
1104 XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(PtrNum),
1110 /* Set the length of the buffer. */
1111 XUsbPs_dTDSetTransferLen(dTDPtr, BufferLen);
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
1120 XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDUSERDATA, BufferPtr);
1126 /*****************************************************************************/
1128 * This function set the Max PacketLen for the queue head for isochronous EP.
1130 * If the max packet length is greater than XUSBPS_MAX_PACKET_SIZE, then
1131 * Mult bits are set to reflect that.
1133 * @param dQHPtr is a pointer to the dQH element.
1134 * @param Len is the Length to be set.
1136 ******************************************************************************/
1137 static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len)
1139 u32 Mult = (Len & ENDPOINT_MAXP_MULT_MASK) >> ENDPOINT_MAXP_MULT_SHIFT;
1140 u32 MaxPktSize = (Mult > 1) ? ENDPOINT_MAXP_LENGTH : Len;
1142 if (MaxPktSize > XUSBPS_MAX_PACKET_SIZE) {
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));
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));
1164 /*****************************************************************************/
1166 * This function reconfigures one Ep corresponding to host's request of setting
1167 * alternate interface. The endpoint has been disabled before this call.
1169 * Both QH and dTDs are updated for the new configuration.
1171 * @param InstancePtr is a pointer to the XUsbPs instance of the
1174 * Pointer to the updated XUsbPs DEVICE configuration structure.
1177 * The endpoint to be reconfigured.
1179 * @param NewDirection
1180 * The new transfer direction the endpoint.
1182 * @param DirectionChanged
1183 * A boolean value indicate whether the transfer direction has changed.
1186 * XST_SUCCESS upon success, XST_FAILURE otherwise.
1188 ******************************************************************************/
1189 int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr,
1190 int EpNum, unsigned short NewDirection,
1191 int DirectionChanged) {
1193 int Status = XST_SUCCESS;
1194 XUsbPs_Endpoint *Ep;
1195 XUsbPs_EpConfig *EpCfg;
1197 Xil_AssertNonvoid(InstancePtr != NULL);
1198 Xil_AssertNonvoid(CfgPtr != NULL);
1201 EpCfg = CfgPtr->EpCfg;
1203 /* If transfer direction changes, dTDs has to be reset
1204 * Number of buffers are preset and should not to be changed.
1206 if(DirectionChanged) {
1207 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1210 /* Swap the pointer to the dTDs.
1212 Ep[EpNum].Out.dTDs = Ep[EpNum].In.dTDs;
1213 p = (u8 *)(Ep[EpNum].Out.dTDs + XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs);
1215 /* Set the OUT buffer if buffer size is not zero
1217 if(EpCfg[EpNum].Out.BufSize > 0) {
1218 Ep[EpNum].Out.dTDBufs = p;
1220 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1221 Ep[EpNum].In.dTDs = Ep[EpNum].Out.dTDs;
1225 /* Reset dTD progress tracking pointers
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;
1233 /* Reinitialize information in QH
1235 XUsbPs_dQHReinitEp(CfgPtr, EpNum, NewDirection);
1237 /* Reinitialize the dTD linked list, and flush the cache
1239 Status = XUsbPs_dTDReinitEp(CfgPtr, EpNum, NewDirection);
1240 if(Status != XST_SUCCESS) {
1248 /*****************************************************************************/
1250 * This function re-initializes the Queue Head List in memory.
1251 * The endpoint 1 has been disabled before this call.
1254 * Pointer to the updated XUsbPs DEVICE configuration structure.
1257 * The endpoint to be reconfigured.
1259 * @param NewDirection
1260 * The new transfer direction of endpoint 1
1264 ******************************************************************************/
1265 static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
1266 int EpNum, unsigned short NewDirection)
1268 XUsbPs_Endpoint *Ep;
1269 XUsbPs_EpConfig *EpCfg;
1271 /* Setup pointers for simpler access.
1274 EpCfg = DevCfgPtr->EpCfg;
1277 /* Go through the list of Queue Head entries and:
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)
1285 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1288 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
1289 XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
1291 /* For isochronous, ep max packet size translates to different
1292 * values in queue head than other types.
1293 * Also enable ZLT for isochronous.
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);
1300 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
1301 EpCfg[EpNum].Out.MaxPacketSize);
1302 XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
1305 XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
1307 /* Set up the overlay next dTD pointer.
1309 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
1310 XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
1312 XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
1314 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1318 XUsbPs_WritedQH(Ep[EpNum].In.dQH,
1319 XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
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);
1327 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
1328 EpCfg[EpNum].In.MaxPacketSize);
1329 XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
1332 XUsbPs_dQHSetIOS(Ep[EpNum].In.dQH);
1334 XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
1339 /*****************************************************************************/
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.
1347 * Pointer to the XUsbPs DEVICE configuration structure.
1350 * The endpoint to be reconfigured.
1352 * @param NewDirection
1353 * The new transfer direction of endpoint 1
1356 * - XST_SUCCESS: The operation completed successfully.
1357 * - XST_FAILURE: An error occured.
1359 ******************************************************************************/
1360 static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
1361 int EpNum, unsigned short NewDirection)
1363 XUsbPs_Endpoint *Ep;
1364 XUsbPs_EpConfig *EpCfg;
1369 /* Setup pointers for simpler access.
1372 EpCfg = DevCfgPtr->EpCfg;
1375 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1376 XUsbPs_EpOut *Out = &Ep[EpNum].Out;
1381 * + Set the next link pointer
1382 * + Set the interrupt complete and the active bit
1383 * + Attach the buffer to the dTD
1385 NumdTD = EpCfg[EpNum].Out.NumBufs;
1387 for (Td = 0; Td < NumdTD; ++Td) {
1390 int NextTd = (Td + 1) % NumdTD;
1392 XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
1394 /* Set NEXT link pointer.
1396 XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
1397 &Out->dTDs[NextTd]);
1399 /* Set the OUT descriptor ACTIVE and enable the
1400 * interrupt on complete.
1402 XUsbPs_dTDSetActive(&Out->dTDs[Td]);
1403 XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
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.
1409 if (Out->dTDBufs != NULL) {
1411 Status = XUsbPs_dTDAttachBuffer(
1414 (Td * EpCfg[EpNum].Out.BufSize),
1415 EpCfg[EpNum].Out.BufSize);
1416 if (Status != XST_SUCCESS) {
1420 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
1422 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1423 XUsbPs_EpIn *In = &Ep[EpNum].In;
1428 * + Set the next link pointer
1429 * + Set the Terminate bit to mark it available
1431 NumdTD = EpCfg[EpNum].In.NumBufs;
1433 for (Td = 0; Td < NumdTD; ++Td) {
1434 int NextTd = (Td + 1) % NumdTD;
1436 XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
1438 /* Set NEXT link pointer.
1440 XUsbPs_WritedTD(&In->dTDs[Td], XUSBPS_dTDNLP,
1443 /* Set the IN descriptor's TERMINATE bits.
1445 XUsbPs_dTDSetTerminate(&In->dTDs[Td]);
1447 XUsbPs_dTDFlushCache(&In->dTDs[Td]);