/** * * Receive a frame. Wait for a frame to arrive. * * @param BaseAddress is the base address of the device * @param FramePtr is a pointer to a buffer where the frame will * be stored. * * @return * * The type/length field of the frame received. When the type/length field * contains the type , XEL_MAX_FRAME_SIZE bytes will be copied out of the * buffer and it is up to the higher layers to sort out the frame. * * @note * * This function call is blocking in nature, i.e. it will wait until a * frame arrives. * * If the ping buffer is the source of the data, the argument should be * DeviceAddress + XEL_RXBUFF_OFFSET. * If the pong buffer is the source of the data, the argument should be * DeviceAddress + XEL_RXBUFF_OFFSET + XEL_BUFFER_OFFSET. * The function does not take the different buffers into consideration. ******************************************************************************/ u16 XEmacLite_RecvFrame(u32 BaseAddress, u8 *FramePtr) { u16 LengthType; u16 Length; u32 Register; /* * Wait for a frame to arrive - this is a blocking call */ while (XEmacLite_mIsRxEmpty(BaseAddress)); /* * Get the length of the frame that arrived */ LengthType = XIo_In32(BaseAddress + XEL_RPLR_OFFSET); LengthType &= (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO); /* check if length is valid */ if (LengthType > XEL_MAX_FRAME_SIZE) { /* Field contain type, use max frame size and let user parse it */ Length = XEL_MAX_FRAME_SIZE; } else { /* Use the length in the frame, plus the header and trailer */ Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE; } /* * Read each byte from the EMAC Lite */ XEmacLite_AlignedRead((u32 *) (BaseAddress + XEL_RXBUFF_OFFSET), FramePtr, Length); /* * Acknowledge the frame */ Register = XIo_In32(BaseAddress + XEL_RSR_OFFSET); Register &= ~XEL_RSR_RECV_DONE_MASK; XIo_Out32(BaseAddress + XEL_RSR_OFFSET, Register); return LengthType; }
/** * * Interrupt handler for the EmacLite driver. It performs the following * processing: * * - Get the interrupt status from the registers to determine the source * of the interrupt. * - Call the appropriate handler based on the source of the interrupt. * * @param InstancePtr contains a pointer to the EmacLite device instance * for the interrupt. * * @return None. * * @note None. * * ******************************************************************************/ void XEmacLite_InterruptHandler(void *InstancePtr) { XEmacLite *EmacLitePtr; int TxCompleteIntr = FALSE; u32 BaseAddress; u32 TxStatus; /* * Verify that each of the inputs are valid. */ XASSERT_VOID(InstancePtr != NULL); /* * Convert the non-typed pointer to an EmacLite instance pointer * such that there is access to the device. */ EmacLitePtr = (XEmacLite *) InstancePtr; BaseAddress = EmacLitePtr->EmacLiteConfig.BaseAddress; if ((XEmacLite_mIsRxEmpty(BaseAddress) != TRUE) || (XEmacLite_mIsRxEmpty(BaseAddress + XEL_BUFFER_OFFSET) != TRUE)) { /* * Call the RX callback. */ EmacLitePtr->RecvHandler(EmacLitePtr->RecvRef); } TxStatus = XEmacLite_mGetTxStatus(BaseAddress); if (((TxStatus & XEL_TSR_XMIT_BUSY_MASK) == 0) && (TxStatus & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { /* * Clear the Tx Active bit in the Tx Status Register. */ TxStatus &= ~XEL_TSR_XMIT_ACTIVE_MASK; XEmacLite_mSetTxStatus(BaseAddress, TxStatus); /* * Update the flag indicating that there was a Tx Interrupt. */ TxCompleteIntr = TRUE; } TxStatus = XEmacLite_mGetTxStatus(BaseAddress + XEL_BUFFER_OFFSET); if (((TxStatus & XEL_TSR_XMIT_BUSY_MASK) == 0) && (TxStatus & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { /* * Clear the Tx Active bit in the Tx Status Register. */ TxStatus &= ~XEL_TSR_XMIT_ACTIVE_MASK; XEmacLite_mSetTxStatus(BaseAddress + XEL_BUFFER_OFFSET, TxStatus); /* * Update the flag indicating that there was a Tx Interrupt. */ TxCompleteIntr = TRUE; } /* * If there was a TX interrupt, call the callback. */ if (TxCompleteIntr == TRUE) { /* * Call the TX callback. */ EmacLitePtr->SendHandler(EmacLitePtr->SendRef); } }