/** * This function handles TX buffer interrupts. It is called by the interrupt * when a transmit complete interrupt occurs. It returns buffers of completed * descriptors to the caller. * * @param InstancePtr is a pointer to the XUsbPs instance of the * controller. * @param EpCompl is the Bit mask of endpoints that caused a transmit * complete interrupt. * * @return None * * @note None. * ******************************************************************************/ static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl) { int Index; u32 Mask; int NumEp; /* Check all endpoints for TX complete bits. */ Mask = 0x00010000; NumEp = InstancePtr->DeviceConfig.NumEndpoints; /* Check for every endpoint if its TX complete bit is * set. */ for (Index = 0; Index < NumEp; Index++, Mask <<= 1) { XUsbPs_EpIn *Ep; if (!(EpCompl & Mask)) { continue; } /* The TX complete bit for this endpoint is * set. Walk the list of descriptors to see * which ones are completed. */ Ep = &InstancePtr->DeviceConfig.Ep[Index].In; while (Ep->dTDTail != Ep->dTDHead) { XUsbPs_dTDInvalidateCache(Ep->dTDTail); /* If the descriptor is not active then the buffer has * not been sent yet. */ if (XUsbPs_dTDIsActive(Ep->dTDTail)) { break; } if (Ep->HandlerFunc) { void *BufPtr; BufPtr = (void *) XUsbPs_ReaddTD(Ep->dTDTail, XUSBPS_dTDUSERDATA); Ep->HandlerFunc(Ep->HandlerRef, Index, XUSBPS_EP_EVENT_DATA_TX, BufPtr); } Ep->dTDTail = XUsbPs_dTDGetNLP(Ep->dTDTail); } } }
/** * This function receives a data buffer from the endpoint of the given endpoint * number. * * @param InstancePtr is a pointer to the XUsbPs instance of the * controller. * @param EpNum is the number of the endpoint to receive data from. * @param BufferPtr (OUT param) is a pointer to the buffer pointer to hold * the reference of the data buffer. * @param BufferLenPtr (OUT param) is a pointer to the integer that will * hold the buffer length. * @param Handle is the opaque handle to be used when the buffer is * released. * * @return * - XST_SUCCESS: The operation completed successfully. * - XST_FAILURE: An error occured. * - XST_USB_NO_BUF: No buffer available. * * @note * After handling the data in the buffer, the user MUST release * the buffer using the Handle by calling the * XUsbPs_EpBufferRelease() function. * ******************************************************************************/ int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum, u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle) { XUsbPs_EpOut *Ep; XUsbPs_EpSetup *EpSetup; u32 length = 0; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(BufferPtr != NULL); Xil_AssertNonvoid(BufferLenPtr != NULL); Xil_AssertNonvoid(Handle != NULL); Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); /* Locate the next available buffer in the ring. A buffer is available * if its descriptor is not active. */ Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; XUsbPs_dTDInvalidateCache(Ep->dTDCurr); if (XUsbPs_dTDIsActive(Ep->dTDCurr)) { return XST_USB_NO_BUF; } /* The buffer is not active which means that it has been processed by * the DMA engine and contains valid data. */ EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out; /* Use the buffer pointer stored in the "user data" field of the * Transfer Descriptor. */ *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr, XUSBPS_dTDUSERDATA); length = EpSetup->BufSize - XUsbPs_dTDGetTransferLen(Ep->dTDCurr); if(length > 0) { *BufferLenPtr = length; }else { *BufferLenPtr = 0; } *Handle = (u32) Ep->dTDCurr; /* Reset the descriptor's BufferPointer0 and Transfer Length fields to * their original value. Note that we can not yet re-activate the * descriptor as the caller will be using the attached buffer. Once the * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we * can re-activate the descriptor. */ XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr); XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize); XUsbPs_dTDFlushCache(Ep->dTDCurr); return XST_SUCCESS; }