1 /******************************************************************************
3 * Copyright (C) 2010 - 2014 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
36 * Endpoint specific function implementations.
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ---- -------- --------------------------------------------------------
45 * 1.00a jz 10/10/10 First release
46 * 1.03a nm 09/21/12 Fixed CR#678977. Added proper sequence for setup packet
48 * 1.04a nm 11/02/12 Fixed CR#683931. Mult bits are set properly in dQH.
49 * 2.00a kpc 04/03/14 Fixed CR#777763. Updated the macro names
50 * 2.1 kpc 04/28/14 Added XUsbPs_EpBufferSendWithZLT api and merged common
51 * code to XUsbPs_EpQueueRequest.
53 ******************************************************************************/
55 /***************************** Include Files **********************************/
57 #include <string.h> /* for bzero() */
61 #include "xusbps_endpoint.h"
63 /************************** Constant Definitions ******************************/
65 /**************************** Type Definitions ********************************/
67 /************************** Variable Definitions ******************************/
69 /************************** Function Prototypes ******************************/
71 static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr);
72 static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr);
73 static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr);
74 static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
75 const u8 *BufferPtr, u32 BufferLen);
77 static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len);
79 /* Functions to reconfigure endpoint upon host's set alternate interface
82 static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
83 int EpNum, unsigned short NewDirection);
84 static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
85 int EpNum, unsigned short NewDirection);
86 static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
87 const u8 *BufferPtr, u32 BufferLen, u8 ReqZero);
89 /******************************* Functions ************************************/
91 /*****************************************************************************/
94 * This function configures the DEVICE side of the controller. The caller needs
95 * to pass in the desired configuration (e.g. number of endpoints) and a
96 * DMAable buffer that will hold the Queue Head List and the Transfer
97 * Descriptors. The required size for this buffer can be obtained by the caller
98 * using the: XUsbPs_DeviceMemRequired() macro.
100 * @param InstancePtr is a pointer to the XUsbPs instance of the
102 * @param CfgPtr is a pointer to the configuration structure that contains
103 * the desired DEVICE side configuration.
106 * - XST_SUCCESS: The operation completed successfully.
107 * - XST_FAILURE: An error occured.
110 * The caller may configure the controller for both, DEVICE and
113 ******************************************************************************/
114 int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr,
115 const XUsbPs_DeviceConfig *CfgPtr)
120 Xil_AssertNonvoid(InstancePtr != NULL);
121 Xil_AssertNonvoid(CfgPtr != NULL);
123 /* Copy the configuration data over into the local instance structure */
124 InstancePtr->DeviceConfig = *CfgPtr;
127 /* Align the buffer to a 2048 byte (XUSBPS_dQH_BASE_ALIGN) boundary.*/
128 InstancePtr->DeviceConfig.PhysAligned =
129 (InstancePtr->DeviceConfig.DMAMemPhys +
130 XUSBPS_dQH_BASE_ALIGN) &
131 ~(XUSBPS_dQH_BASE_ALIGN -1);
133 /* Initialize the endpoint pointer list data structure. */
134 XUsbPs_EpListInit(&InstancePtr->DeviceConfig);
137 /* Initialize the Queue Head structures in DMA memory. */
138 XUsbPs_dQHInit(&InstancePtr->DeviceConfig);
141 /* Initialize the Transfer Descriptors in DMA memory.*/
142 Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig);
143 if (XST_SUCCESS != Status) {
147 /* Changing the DEVICE mode requires a controller RESET. */
148 if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) {
152 /* Set the Queue Head List address. */
153 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
154 XUSBPS_EPLISTADDR_OFFSET,
155 InstancePtr->DeviceConfig.PhysAligned);
157 /* Set the USB mode register to configure DEVICE mode.
159 * XUSBPS_MODE_SLOM_MASK note:
160 * Disable Setup Lockout. Setup Lockout is not required as we
161 * will be using the tripwire mechanism when handling setup
164 ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK;
166 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
167 XUSBPS_MODE_OFFSET, ModeValue);
169 XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET,
170 XUSBPS_OTGSC_OT_MASK);
175 /*****************************************************************************/
177 * This function sends a given data buffer.
179 * @param InstancePtr is a pointer to XUsbPs instance of the controller.
180 * @param EpNum is the number of the endpoint to receive data from.
181 * @param BufferPtr is a pointer to the buffer to send.
182 * @param BufferLen is the Buffer length.
185 * - XST_SUCCESS: The operation completed successfully.
186 * - XST_FAILURE: An error occured.
187 * - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
188 * - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
190 ******************************************************************************/
191 int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum,
192 const u8 *BufferPtr, u32 BufferLen)
194 Xil_AssertNonvoid(InstancePtr != NULL);
195 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
197 return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
201 /*****************************************************************************/
203 * This function sends a given data buffer and also zero length packet if the
204 * Bufferlen is in multiples of endpoint max packet size.
206 * @param InstancePtr is a pointer to XUsbPs instance of the controller.
207 * @param EpNum is the number of the endpoint to receive data from.
208 * @param BufferPtr is a pointer to the buffer to send.
209 * @param BufferLen is the Buffer length.
212 * - XST_SUCCESS: The operation completed successfully.
213 * - XST_FAILURE: An error occured.
214 * - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
215 * - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
217 ******************************************************************************/
218 int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum,
219 const u8 *BufferPtr, u32 BufferLen)
224 Xil_AssertNonvoid(InstancePtr != NULL);
225 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
227 Ep = &InstancePtr->DeviceConfig.EpCfg[EpNum].In;
229 if ((BufferLen >= Ep->MaxPacketSize) &&
230 (BufferLen % Ep->MaxPacketSize == 0)) {
234 return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr,
238 /*****************************************************************************/
240 * This function sends a given data buffer and also sends ZLT packet if it is
243 * @param InstancePtr is a pointer to XUsbPs instance of the controller.
244 * @param EpNum is the number of the endpoint to receive data from.
245 * @param BufferPtr is a pointer to the buffer to send.
246 * @param BufferLen is the Buffer length.
247 * @param ReqZero is the
250 * - XST_SUCCESS: The operation completed successfully.
251 * - XST_FAILURE: An error occured.
252 * - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB).
253 * - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available.
255 ******************************************************************************/
256 static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum,
257 const u8 *BufferPtr, u32 BufferLen, u8 ReqZero)
265 u32 Mask = 0x00010000;
266 u32 BitMask = Mask << EpNum;
272 /* Locate the next available buffer in the ring. A buffer is available
273 * if its descriptor is not active.
275 Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In;
277 Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen);
279 if(Ep->dTDTail != Ep->dTDHead) {
282 XUsbPs_dTDInvalidateCache(Ep->dTDHead);
284 /* Tell the caller if we do not have any descriptors available. */
285 if (XUsbPs_dTDIsActive(Ep->dTDHead)) {
286 return XST_USB_NO_DESC_AVAILABLE;
289 /* Remember the current head. */
290 DescPtr = Ep->dTDHead;
293 Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen;
294 /* Attach the provided buffer to the current descriptor.*/
295 Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length);
296 if (XST_SUCCESS != Status) {
302 XUsbPs_dTDSetActive(Ep->dTDHead);
303 if (BufferLen == 0 && (ReqZero == FALSE)) {
304 XUsbPs_dTDSetIOC(Ep->dTDHead);
307 XUsbPs_dTDClrTerminate(Ep->dTDHead);
308 XUsbPs_dTDFlushCache(Ep->dTDHead);
310 /* Advance the head descriptor pointer to the next descriptor. */
311 Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead);
312 /* Terminate the next descriptor and flush the cache.*/
313 XUsbPs_dTDInvalidateCache(Ep->dTDHead);
314 /* Tell the caller if we do not have any descriptors available. */
315 if (XUsbPs_dTDIsActive(Ep->dTDHead)) {
316 return XST_USB_NO_DESC_AVAILABLE;
319 if (ReqZero && BufferLen == 0) {
323 } while(BufferLen || exit);
325 XUsbPs_dTDSetTerminate(Ep->dTDHead);
326 XUsbPs_dTDFlushCache(Ep->dTDHead);
329 /* Read the endpoint prime register. */
330 RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET);
331 if(RegValue & BitMask) {
336 RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);
337 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
338 RegValue | XUSBPS_CMD_ATDTW_MASK);
339 Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET)
341 } while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) &
342 XUSBPS_CMD_ATDTW_MASK));
344 RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET);
345 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET,
346 RegValue & ~XUSBPS_CMD_ATDTW_MASK);
353 /* Check, if the DMA engine is still running. If it is running, we do
354 * not clear Queue Head fields.
356 * Same cache rule as for the Transfer Descriptor applies for the Queue
359 XUsbPs_dQHInvalidateCache(Ep->dQH);
360 /* Add the dTD to the dQH */
361 XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr);
362 Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN);
363 Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK);
364 XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token);
366 XUsbPs_dQHFlushCache(Ep->dQH);
368 Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN);
373 /*****************************************************************************/
375 * This function receives a data buffer from the endpoint of the given endpoint
378 * @param InstancePtr is a pointer to the XUsbPs instance of the
380 * @param EpNum is the number of the endpoint to receive data from.
381 * @param BufferPtr (OUT param) is a pointer to the buffer pointer to hold
382 * the reference of the data buffer.
383 * @param BufferLenPtr (OUT param) is a pointer to the integer that will
384 * hold the buffer length.
385 * @param Handle is the opaque handle to be used when the buffer is
389 * - XST_SUCCESS: The operation completed successfully.
390 * - XST_FAILURE: An error occured.
391 * - XST_USB_NO_BUF: No buffer available.
394 * After handling the data in the buffer, the user MUST release
395 * the buffer using the Handle by calling the
396 * XUsbPs_EpBufferRelease() function.
398 ******************************************************************************/
399 int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum,
400 u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle)
403 XUsbPs_EpSetup *EpSetup;
406 Xil_AssertNonvoid(InstancePtr != NULL);
407 Xil_AssertNonvoid(BufferPtr != NULL);
408 Xil_AssertNonvoid(BufferLenPtr != NULL);
409 Xil_AssertNonvoid(Handle != NULL);
410 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
412 /* Locate the next available buffer in the ring. A buffer is available
413 * if its descriptor is not active.
415 Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;
417 XUsbPs_dTDInvalidateCache(Ep->dTDCurr);
419 if (XUsbPs_dTDIsActive(Ep->dTDCurr)) {
420 return XST_USB_NO_BUF;
423 /* The buffer is not active which means that it has been processed by
424 * the DMA engine and contains valid data.
426 EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out;
429 /* Use the buffer pointer stored in the "user data" field of the
430 * Transfer Descriptor.
432 *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr,
435 length = EpSetup->BufSize -
436 XUsbPs_dTDGetTransferLen(Ep->dTDCurr);
439 *BufferLenPtr = length;
444 *Handle = (u32) Ep->dTDCurr;
447 /* Reset the descriptor's BufferPointer0 and Transfer Length fields to
448 * their original value. Note that we can not yet re-activate the
449 * descriptor as the caller will be using the attached buffer. Once the
450 * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we
451 * can re-activate the descriptor.
453 XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr);
454 XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize);
456 XUsbPs_dTDFlushCache(Ep->dTDCurr);
462 /*****************************************************************************/
464 * This function returns a previously received data buffer to the driver.
466 * @param Handle is a pointer to the buffer that is returned.
470 ******************************************************************************/
471 void XUsbPs_EpBufferRelease(u32 Handle)
475 /* Perform sanity check on Handle.*/
476 Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN)));
478 /* Activate the descriptor and clear the Terminate bit. Make sure to do
479 * the proper cache handling.
481 dTDPtr = (XUsbPs_dTD *) Handle;
483 XUsbPs_dTDInvalidateCache(dTDPtr);
485 XUsbPs_dTDClrTerminate(dTDPtr);
486 XUsbPs_dTDSetActive(dTDPtr);
487 XUsbPs_dTDSetIOC(dTDPtr);
489 XUsbPs_dTDFlushCache(dTDPtr);
494 /*****************************************************************************/
496 * This function sets the handler for endpoint events.
498 * @param InstancePtr is a pointer to the XUsbPs instance of the
500 * @param EpNum is the number of the endpoint to receive data from.
501 * @param Direction is the direction of the endpoint (bitfield):
502 * - XUSBPS_EP_DIRECTION_OUT
503 * - XUSBPS_EP_DIRECTION_IN
504 * @param CallBackFunc is the Handler callback function.
505 * Can be NULL if the user wants to disable the handler entry.
506 * @param CallBackRef is the user definable data pointer that will be
507 * passed back if the handler is called. May be NULL.
510 * - XST_SUCCESS: The operation completed successfully.
511 * - XST_FAILURE: An error occured.
512 * - XST_INVALID_PARAM: Invalid parameter passed.
515 * The user can disable a handler by setting the callback function
518 ******************************************************************************/
519 int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction,
520 XUsbPs_EpHandlerFunc CallBackFunc,
525 Xil_AssertNonvoid(InstancePtr != NULL);
526 Xil_AssertNonvoid(CallBackFunc != NULL);
527 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
529 Ep = &InstancePtr->DeviceConfig.Ep[EpNum];
531 if(Direction & XUSBPS_EP_DIRECTION_OUT) {
532 Ep->Out.HandlerFunc = CallBackFunc;
533 Ep->Out.HandlerRef = CallBackRef;
536 if(Direction & XUSBPS_EP_DIRECTION_IN) {
537 Ep->In.HandlerFunc = CallBackFunc;
538 Ep->In.HandlerRef = CallBackRef;
545 /*****************************************************************************/
547 * This function primes an endpoint.
549 * @param InstancePtr is pointer to the XUsbPs instance.
550 * @param EpNum is the number of the endpoint to receive data from.
551 * @param Direction is the direction of the endpoint (bitfield):
552 * - XUSBPS_EP_DIRECTION_OUT
553 * - XUSBPS_EP_DIRECTION_IN
556 * - XST_SUCCESS: The operation completed successfully.
557 * - XST_FAILURE: An error occured.
558 * - XST_INVALID_PARAM: Invalid parameter passed.
562 ******************************************************************************/
563 int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction)
567 Xil_AssertNonvoid(InstancePtr != NULL);
568 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
570 /* Get the right bit mask for the endpoint direction. */
573 case XUSBPS_EP_DIRECTION_OUT:
577 case XUSBPS_EP_DIRECTION_IN:
582 return XST_INVALID_PARAM;
585 /* Write the endpoint prime register. */
586 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
587 XUSBPS_EPPRIME_OFFSET, Mask << EpNum);
593 /*****************************************************************************/
595 * This function extracts the Setup Data from a given endpoint.
597 * @param InstancePtr is a pointer to the XUsbPs instance of the
599 * @param EpNum is the number of the endpoint to receive data from.
600 * @param SetupDataPtr is a pointer to the setup data structure to be
604 * - XST_SUCCESS: The operation completed successfully.
605 * - XST_FAILURE: An error occured.
608 ******************************************************************************/
609 int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum,
610 XUsbPs_SetupData *SetupDataPtr)
619 Xil_AssertNonvoid(InstancePtr != NULL);
620 Xil_AssertNonvoid(SetupDataPtr != NULL);
621 Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints);
623 Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out;
626 /* Get the data from the Queue Heads Setup buffer into local variables
627 * so we can extract the setup data values.
630 /* Arm the tripwire. The tripwire will tell us if a new setup
631 * packet arrived (in which case the tripwire bit will be
632 * cleared) while we were reading the buffer. If a new setup
633 * packet arrived the buffer is corrupted and we continue
636 XUsbPs_SetSetupTripwire(InstancePtr);
638 XUsbPs_dQHInvalidateCache(Ep->dQH);
640 Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0);
641 Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1);
642 } while (FALSE == XUsbPs_SetupTripwireIsSet(InstancePtr));
644 /* Clear the pending endpoint setup stat bit.
646 XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
647 XUSBPS_EPSTAT_OFFSET, 1 << EpNum);
649 /* Clear the Tripwire bit and continue.
651 XUsbPs_ClrSetupTripwire(InstancePtr);
654 /* Data in the setup buffer is being converted by the core to big
655 * endian format. We have to take care of proper byte swapping when
656 * reading the setup data values.
658 * Need to check if there is a smarter way to do this and take the
659 * processor/memory-controller endianess into account?
663 SetupDataPtr->bmRequestType = p[0];
664 SetupDataPtr->bRequest = p[1];
665 SetupDataPtr->wValue = (p[3] << 8) | p[2];
666 SetupDataPtr->wIndex = (p[5] << 8) | p[4];
667 SetupDataPtr->wLength = (p[7] << 8) | p[6];
669 /* Before we leave we need to make sure that the endpoint setup bit has
670 * cleared. It needs to be 0 before the endpoint can be re-primed.
672 * Note: According to the documentation this endpoint setup bit should
673 * clear within 1-2us after it has been written above. This means that
674 * we should never catch it being 1 here. However, we still need to
675 * poll it to make sure. Just in case, we use a counter 'Timeout' so we
676 * won't hang here if the bit is stuck for some reason.
678 Timeout = XUSBPS_TIMEOUT_COUNTER;
679 while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress,
680 XUSBPS_EPSTAT_OFFSET) &
681 (1 << EpNum)) && --Timeout) {
692 /*****************************************************************************/
695 * This function initializes the endpoint pointer data structure.
697 * The function sets up the local data structure with the aligned addresses for
698 * the Queue Head and Transfer Descriptors.
700 * @param DevCfgPtr is pointer to the XUsbPs DEVICE configuration
706 * Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the
707 * system. Therefore no memory is reserved for them.
709 ******************************************************************************/
710 static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr)
716 XUsbPs_EpConfig *EpCfg;
718 /* Set up the XUsbPs_Endpoint array. This array is used to define the
719 * location of the Queue Head list and the Transfer Descriptors in the
720 * block of DMA memory that has been passed into the driver.
722 * 'p' is used to set the pointers in the local data structure.
723 * Initially 'p' is pointed to the beginning of the DMAable memory
724 * block. As pointers are assigned, 'p' is incremented by the size of
725 * the respective object.
728 EpCfg = DevCfgPtr->EpCfg;
730 /* Start off with 'p' pointing to the (aligned) beginning of the DMA
733 p = (u8 *) DevCfgPtr->PhysAligned;
736 /* Initialize the Queue Head pointer list.
738 * Each endpoint has two Queue Heads. One for the OUT direction and one
739 * for the IN direction. An OUT Queue Head is always followed by an IN
742 * Queue Head alignment is XUSBPS_dQH_ALIGN.
744 * Note that we have to reserve space here for unused endpoints.
746 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
748 Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p;
749 p += XUSBPS_dQH_ALIGN;
752 Ep[EpNum].In.dQH = (XUsbPs_dQH *) p;
753 p += XUSBPS_dQH_ALIGN;
757 /* 'p' now points to the first address after the Queue Head list. The
758 * Transfer Descriptors start here.
760 * Each endpoint has a variable number of Transfer Descriptors
761 * depending on user configuration.
763 * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN.
765 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
768 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
769 Ep[EpNum].Out.dTDs = (XUsbPs_dTD *) p;
770 Ep[EpNum].Out.dTDCurr = (XUsbPs_dTD *) p;
771 p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs;
776 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
777 Ep[EpNum].In.dTDs = (XUsbPs_dTD *) p;
778 Ep[EpNum].In.dTDHead = (XUsbPs_dTD *) p;
779 Ep[EpNum].In.dTDTail = (XUsbPs_dTD *) p;
780 p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].In.NumBufs;
785 /* 'p' now points to the first address after the Transfer Descriptors.
786 * The data buffers for the OUT Transfer Desciptors start here.
788 * Note that IN (TX) Transfer Descriptors are not assigned buffers at
789 * this point. Buffers will be assigned when the user calls the send()
792 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
794 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
795 /* If BufSize for this endpoint is set to 0 it means
796 * that we do not need to attach a buffer to this
797 * descriptor. We also initialize it's buffer pointer
800 if (0 == EpCfg[EpNum].Out.BufSize) {
801 Ep[EpNum].Out.dTDBufs = NULL;
805 Ep[EpNum].Out.dTDBufs = p;
806 p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs;
811 /* Initialize the endpoint event handlers to NULL.
813 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
814 Ep[EpNum].Out.HandlerFunc = NULL;
815 Ep[EpNum].In.HandlerFunc = NULL;
820 /*****************************************************************************/
823 * This function initializes the Queue Head List in memory.
825 * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
832 ******************************************************************************/
833 static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr)
838 XUsbPs_EpConfig *EpCfg;
840 /* Setup pointers for simpler access. */
842 EpCfg = DevCfgPtr->EpCfg;
845 /* Go through the list of Queue Head entries and:
847 * - Set Transfer Descriptor addresses
848 * - Set Maximum Packet Size
849 * - Disable Zero Length Termination (ZLT) for non-isochronous transfers
850 * - Enable Interrupt On Setup (IOS)
853 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
855 /* OUT Queue Heads.*/
856 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
857 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
858 XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
860 /* For isochronous, ep max packet size translates to different
861 * values in queue head than other types.
862 * Also enable ZLT for isochronous.
864 if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {
865 XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,
866 EpCfg[EpNum].Out.MaxPacketSize);
867 XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);
869 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
870 EpCfg[EpNum].Out.MaxPacketSize);
871 XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
874 /* Only control OUT needs this */
875 if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) {
876 XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
879 /* Set up the overlay next dTD pointer. */
880 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
881 XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
883 XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
887 /* IN Queue Heads. */
888 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
889 XUsbPs_WritedQH(Ep[EpNum].In.dQH,
890 XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
893 /* Isochronous ep packet size can be larger than 1024.*/
894 if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {
895 XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,
896 EpCfg[EpNum].In.MaxPacketSize);
897 XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);
899 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
900 EpCfg[EpNum].In.MaxPacketSize);
901 XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
904 XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
910 /*****************************************************************************/
913 * This function initializes the Transfer Descriptors lists in memory.
915 * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration
919 * - XST_SUCCESS: The operation completed successfully.
920 * - XST_FAILURE: An error occured.
922 ******************************************************************************/
923 static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr)
928 XUsbPs_EpConfig *EpCfg;
930 /* Setup pointers for simpler access. */
932 EpCfg = DevCfgPtr->EpCfg;
935 /* Walk through the list of endpoints and initialize their Transfer
938 for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) {
942 XUsbPs_EpOut *Out = &Ep[EpNum].Out;
943 XUsbPs_EpIn *In = &Ep[EpNum].In;
949 * + Set the next link pointer
950 * + Set the interrupt complete and the active bit
951 * + Attach the buffer to the dTD
953 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) {
954 NumdTD = EpCfg[EpNum].Out.NumBufs;
960 for (Td = 0; Td < NumdTD; ++Td) {
963 int NextTd = (Td + 1) % NumdTD;
965 XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
967 /* Set NEXT link pointer. */
968 XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
971 /* Set the OUT descriptor ACTIVE and enable the
972 * interrupt on complete.
974 XUsbPs_dTDSetActive(&Out->dTDs[Td]);
975 XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
978 /* Set up the data buffer with the descriptor. If the
979 * buffer pointer is NULL it means that we do not need
980 * to attach a buffer to this descriptor.
982 if (NULL == Out->dTDBufs) {
983 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
987 Status = XUsbPs_dTDAttachBuffer(
990 (Td * EpCfg[EpNum].Out.BufSize),
991 EpCfg[EpNum].Out.BufSize);
992 if (XST_SUCCESS != Status) {
996 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
1003 * + Set the next link pointer
1004 * + Set the Terminate bit to mark it available
1006 if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) {
1007 NumdTD = EpCfg[EpNum].In.NumBufs;
1013 for (Td = 0; Td < NumdTD; ++Td) {
1014 int NextTd = (Td + 1) % NumdTD;
1016 XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
1018 /* Set NEXT link pointer. */
1019 XUsbPs_WritedTD(In->dTDs[Td], XUSBPS_dTDNLP,
1022 /* Set the IN descriptor's TERMINATE bits. */
1023 XUsbPs_dTDSetTerminate(In->dTDs[Td]);
1025 XUsbPs_dTDFlushCache(&In->dTDs[Td]);
1033 /*****************************************************************************/
1036 * This function associates a buffer with a Transfer Descriptor. The function
1037 * will take care of splitting the buffer into multiple 4kB aligned segments if
1038 * the buffer happens to span one or more 4kB pages.
1040 * @param dTDIndex is a pointer to the Transfer Descriptor
1041 * @param BufferPtr is pointer to the buffer to link to the descriptor.
1042 * @param BufferLen is the length of the buffer.
1045 * - XST_SUCCESS: The operation completed successfully.
1046 * - XST_FAILURE: An error occured.
1047 * - XST_USB_BUF_TOO_BIG: The provided buffer is bigger than tha
1048 * maximum allowed buffer size (16k).
1051 * Cache invalidation and flushing needs to be handler by the
1052 * caller of this function.
1054 ******************************************************************************/
1055 static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr,
1056 const u8 *BufferPtr, u32 BufferLen)
1062 Xil_AssertNonvoid(dTDPtr != NULL);
1064 /* Check if the buffer is smaller than 16kB. */
1065 if (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) {
1066 return XST_USB_BUF_TOO_BIG;
1069 /* Get a u32 of the buffer pointer to avoid casting in the following
1072 BufAddr = (u32) BufferPtr;
1075 /* Set the buffer pointer 0. Buffer pointer 0 can point to any location
1076 * in memory. It does not need to be 4kB aligned. However, if the
1077 * provided buffer spans one or more 4kB boundaries, we need to set up
1078 * the subsequent buffer pointers which must be 4kB aligned.
1080 XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(0), BufAddr);
1082 /* Check if the buffer spans a 4kB boundary.
1084 * Only do this check, if we are not sending a 0-length buffer.
1086 if (BufferLen > 0) {
1087 BufEnd = BufAddr + BufferLen -1;
1090 while ((BufAddr & 0xFFFFF000) != (BufEnd & 0xFFFFF000)) {
1091 /* The buffer spans at least one boundary, let's set
1092 * the next buffer pointer and repeat the procedure
1093 * until the end of the buffer and the pointer written
1094 * are in the same 4kB page.
1096 BufAddr = (BufAddr + 0x1000) & 0xFFFFF000;
1097 XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(PtrNum),
1103 /* Set the length of the buffer. */
1104 XUsbPs_dTDSetTransferLen(dTDPtr, BufferLen);
1107 /* We remember the buffer pointer in the user data field (reserved
1108 * field in the dTD). This makes it easier to reset the buffer pointer
1109 * after a buffer has been received on the endpoint. The buffer pointer
1110 * needs to be reset because the DMA engine modifies the buffer pointer
1113 XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDUSERDATA, BufferPtr);
1119 /*****************************************************************************/
1121 * This function set the Max PacketLen for the queue head for isochronous EP.
1123 * If the max packet length is greater than XUSBPS_MAX_PACKET_SIZE, then
1124 * Mult bits are set to reflect that.
1126 * @param dQHPtr is a pointer to the dQH element.
1127 * @param Len is the Length to be set.
1129 ******************************************************************************/
1130 static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len)
1132 u32 Mult = (Len & ENDPOINT_MAXP_MULT_MASK) >> ENDPOINT_MAXP_MULT_SHIFT;
1133 u32 MaxPktSize = (Mult > 1) ? ENDPOINT_MAXP_LENGTH : Len;
1135 if (MaxPktSize > XUSBPS_MAX_PACKET_SIZE) {
1143 /* Set Max packet size */
1144 XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG,
1145 (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) &
1146 ~XUSBPS_dQHCFG_MPL_MASK) |
1147 (MaxPktSize << XUSBPS_dQHCFG_MPL_SHIFT));
1149 /* Set Mult to tell hardware how many transactions in each microframe */
1150 XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG,
1151 (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) &
1152 ~XUSBPS_dQHCFG_MULT_MASK) |
1153 (Mult << XUSBPS_dQHCFG_MULT_SHIFT));
1157 /*****************************************************************************/
1159 * This function reconfigures one Ep corresponding to host's request of setting
1160 * alternate interface. The endpoint has been disabled before this call.
1162 * Both QH and dTDs are updated for the new configuration.
1164 * @param InstancePtr is a pointer to the XUsbPs instance of the
1167 * Pointer to the updated XUsbPs DEVICE configuration structure.
1170 * The endpoint to be reconfigured.
1172 * @param NewDirection
1173 * The new transfer direction the endpoint.
1175 * @param DirectionChanged
1176 * A boolean value indicate whether the transfer direction has changed.
1179 * XST_SUCCESS upon success, XST_FAILURE otherwise.
1181 ******************************************************************************/
1182 int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr,
1183 int EpNum, unsigned short NewDirection,
1184 int DirectionChanged) {
1186 int Status = XST_SUCCESS;
1187 XUsbPs_Endpoint *Ep;
1188 XUsbPs_EpConfig *EpCfg;
1190 Xil_AssertNonvoid(InstancePtr != NULL);
1191 Xil_AssertNonvoid(CfgPtr != NULL);
1194 EpCfg = CfgPtr->EpCfg;
1196 /* If transfer direction changes, dTDs has to be reset
1197 * Number of buffers are preset and should not to be changed.
1199 if(DirectionChanged) {
1200 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1203 /* Swap the pointer to the dTDs.
1205 Ep[EpNum].Out.dTDs = Ep[EpNum].In.dTDs;
1206 p = (u8 *)(Ep[EpNum].Out.dTDs + XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs);
1208 /* Set the OUT buffer if buffer size is not zero
1210 if(EpCfg[EpNum].Out.BufSize > 0) {
1211 Ep[EpNum].Out.dTDBufs = p;
1213 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1214 Ep[EpNum].In.dTDs = Ep[EpNum].Out.dTDs;
1218 /* Reset dTD progress tracking pointers
1220 if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1221 Ep[EpNum].In.dTDHead = Ep[EpNum].In.dTDTail = Ep[EpNum].In.dTDs;
1222 } else if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1223 Ep[EpNum].Out.dTDCurr = Ep[EpNum].Out.dTDs;
1226 /* Reinitialize information in QH
1228 XUsbPs_dQHReinitEp(CfgPtr, EpNum, NewDirection);
1230 /* Reinitialize the dTD linked list, and flush the cache
1232 Status = XUsbPs_dTDReinitEp(CfgPtr, EpNum, NewDirection);
1233 if(Status != XST_SUCCESS) {
1241 /*****************************************************************************/
1243 * This function re-initializes the Queue Head List in memory.
1244 * The endpoint 1 has been disabled before this call.
1247 * Pointer to the updated XUsbPs DEVICE configuration structure.
1250 * The endpoint to be reconfigured.
1252 * @param NewDirection
1253 * The new transfer direction of endpoint 1
1257 ******************************************************************************/
1258 static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
1259 int EpNum, unsigned short NewDirection)
1261 XUsbPs_Endpoint *Ep;
1262 XUsbPs_EpConfig *EpCfg;
1264 /* Setup pointers for simpler access.
1267 EpCfg = DevCfgPtr->EpCfg;
1270 /* Go through the list of Queue Head entries and:
1272 * - Set Transfer Descriptor addresses
1273 * - Set Maximum Packet Size
1274 * - Disable Zero Length Termination (ZLT) for non-isochronous transfers
1275 * - Enable Interrupt On Setup (IOS)
1278 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1281 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
1282 XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs);
1284 /* For isochronous, ep max packet size translates to different
1285 * values in queue head than other types.
1286 * Also enable ZLT for isochronous.
1288 if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) {
1289 XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH,
1290 EpCfg[EpNum].Out.MaxPacketSize);
1291 XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH);
1293 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH,
1294 EpCfg[EpNum].Out.MaxPacketSize);
1295 XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH);
1298 XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH);
1300 /* Set up the overlay next dTD pointer.
1302 XUsbPs_WritedQH(Ep[EpNum].Out.dQH,
1303 XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs);
1305 XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH);
1307 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1311 XUsbPs_WritedQH(Ep[EpNum].In.dQH,
1312 XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs);
1314 /* Isochronous ep packet size can be larger than 1024. */
1315 if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) {
1316 XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH,
1317 EpCfg[EpNum].In.MaxPacketSize);
1318 XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH);
1320 XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH,
1321 EpCfg[EpNum].In.MaxPacketSize);
1322 XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH);
1325 XUsbPs_dQHSetIOS(Ep[EpNum].In.dQH);
1327 XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH);
1332 /*****************************************************************************/
1335 * This function re-initializes the Transfer Descriptors lists in memory.
1336 * The endpoint has been disabled before the call. The transfer descriptors
1337 * list pointer has been initialized too.
1340 * Pointer to the XUsbPs DEVICE configuration structure.
1343 * The endpoint to be reconfigured.
1345 * @param NewDirection
1346 * The new transfer direction of endpoint 1
1349 * - XST_SUCCESS: The operation completed successfully.
1350 * - XST_FAILURE: An error occured.
1352 ******************************************************************************/
1353 static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr,
1354 int EpNum, unsigned short NewDirection)
1356 XUsbPs_Endpoint *Ep;
1357 XUsbPs_EpConfig *EpCfg;
1362 /* Setup pointers for simpler access.
1365 EpCfg = DevCfgPtr->EpCfg;
1368 if(NewDirection == XUSBPS_EP_DIRECTION_OUT) {
1369 XUsbPs_EpOut *Out = &Ep[EpNum].Out;
1374 * + Set the next link pointer
1375 * + Set the interrupt complete and the active bit
1376 * + Attach the buffer to the dTD
1378 NumdTD = EpCfg[EpNum].Out.NumBufs;
1380 for (Td = 0; Td < NumdTD; ++Td) {
1383 int NextTd = (Td + 1) % NumdTD;
1385 XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]);
1387 /* Set NEXT link pointer.
1389 XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP,
1390 &Out->dTDs[NextTd]);
1392 /* Set the OUT descriptor ACTIVE and enable the
1393 * interrupt on complete.
1395 XUsbPs_dTDSetActive(&Out->dTDs[Td]);
1396 XUsbPs_dTDSetIOC(&Out->dTDs[Td]);
1398 /* Set up the data buffer with the descriptor. If the
1399 * buffer pointer is NULL it means that we do not need
1400 * to attach a buffer to this descriptor.
1402 if (Out->dTDBufs != NULL) {
1404 Status = XUsbPs_dTDAttachBuffer(
1407 (Td * EpCfg[EpNum].Out.BufSize),
1408 EpCfg[EpNum].Out.BufSize);
1409 if (Status != XST_SUCCESS) {
1413 XUsbPs_dTDFlushCache(&Out->dTDs[Td]);
1415 } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) {
1416 XUsbPs_EpIn *In = &Ep[EpNum].In;
1421 * + Set the next link pointer
1422 * + Set the Terminate bit to mark it available
1424 NumdTD = EpCfg[EpNum].In.NumBufs;
1426 for (Td = 0; Td < NumdTD; ++Td) {
1427 int NextTd = (Td + 1) % NumdTD;
1429 XUsbPs_dTDInvalidateCache(&In->dTDs[Td]);
1431 /* Set NEXT link pointer.
1433 XUsbPs_WritedTD(&In->dTDs[Td], XUSBPS_dTDNLP,
1436 /* Set the IN descriptor's TERMINATE bits.
1438 XUsbPs_dTDSetTerminate(&In->dTDs[Td]);
1440 XUsbPs_dTDFlushCache(&In->dTDs[Td]);