/** * Return the length of a received packet. If a packet is waiting in the * receive packet FIFO, then it may be copied to a user buffer with * XTemac_FifoRead(). * * @param InstancePtr is a pointer to the instance to be worked on. * @param ByteCountPtr is the length of the next received packet if the return * status is XST_SUCCESS. * * @return * - XST_SUCCESS if a packet has been received and a value has been written to * ByteCountPtr. * - XST_DEVICE_IS_STOPPED if the device has been stopped. * - XST_NO_DATA if no packet length is available. ByteCountPtr is not modified. * ******************************************************************************/ XStatus XTemac_FifoRecv(XTemac * InstancePtr, u32 * ByteCountPtr) { u32 RegIPISR; volatile u32 RegRSR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(ByteCountPtr != NULL); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return (XST_DEVICE_IS_STOPPED); } /* If the receive length FIFO is empty, then there's no packet waiting */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (!(RegIPISR & XTE_IPXR_RECV_DONE_MASK)) { return (XST_NO_DATA); } /* Get the length */ *ByteCountPtr = XTemac_mGetIpifReg(XTE_RPLR_OFFSET); /* The IPXR_RECV_DONE_MASK status bit is tied to the RSR register. To clear * this condition, read from the RSR (which has no information) then write * to the IPISR register to ack the status. */ RegRSR = XTemac_mGetIpifReg(XTE_RSR_OFFSET); XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_RECV_DONE_MASK); /* Return sucess */ return (XST_SUCCESS); }
/** * Initiate a transmit of one packet of data previously written with * XTemac_FifoWrite(). The given length in bytes is written to the transmit * length FIFO. There should be at least this many bytes in the packet FIFO * ready for transmit. * * If FIFO interrupts are enabled (see XTemac_IntrFifoEnable()), then upon * completion of the transmit, the registered XTemac_FifoSendHandler() is * invoked. * * If more bytes that are in the packet FIFO are specified in the TxByteCount * parameter, then a packet FIFO underrun error will result. * * @param InstancePtr is a pointer to the instance to be worked on. * @param TxByteCount is the number of bytes to transmit. Range is 1 to the * total number of bytes available in the packet FIFO to be transmitted. * * @return * - XST_SUCCESS if transmit was initiated. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_FIFO_NO_ROOM if the transmit was not initiated because the transmit * length FIFO was full. This is not a fatal condition. The user may need to * wait for other packets to transmit before this condition clears itself. * ******************************************************************************/ XStatus XTemac_FifoSend(XTemac * InstancePtr, u32 TxByteCount) { u32 RegIPISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(TxByteCount != 0); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return (XST_DEVICE_IS_STOPPED); } /* See if transmit length FIFO is full. If it is, try to clear the * status. If it the status remains, then return an error */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_LFIFO_FULL_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_XMIT_LFIFO_FULL_MASK); RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_LFIFO_FULL_MASK) { XTemac_mBumpStats(FifoErrors, 1); return (XST_FIFO_NO_ROOM); } } /* Start transmit */ XTemac_mSetIpifReg(XTE_TPLR_OFFSET, TxByteCount); /* Return sucess */ return (XST_SUCCESS); }
/** * Query the device for the latest transmit status for FIFO direct frame * transfer mode. This function should be used for polled mode operation only. * * @param InstancePtr is a pointer to the instance to be worked on. * @param SendStatusPtr is the contents of the XTE_TSR_OFFSET register when the * return code is XST_FAILURE. Otherwise 0 is returned. * * @return * - XST_NO_DATA if a transmit status is not currently available. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_NOT_POLLED if the device has not been set to polled mode. * - XST_SUCCESS if a transmit status was found and indicates that there was * no error. * - XST_FIFO_ERROR if the transmit length or transmit status FIFOs error has * been detected. If this error is returned, then the device must be reset * before this function will return a valid transmit status indication. * - XST_PFIFO_ERROR if the transmit packet FIFO is deadlocked. If this error * is returned, then the device must be reset before this function will * return a valid transmit status indication * - XST_IPIF_ERROR if there has been a data phase timeout or transaction error * in the IPIF. This is a fatal error. * * @note * When XST_FAILURE is returned with the XTE_TSR_PFIFOU_MASK bit set in the * SendStatusPtr parameter, then an attempt was made to transmit more data than * was present in the packet FIFO. No reset is required in this situation. * ******************************************************************************/ XStatus XTemac_FifoQuerySendStatus(XTemac * InstancePtr, u32 * SendStatusPtr) { u32 RegDISR; u32 RegIPISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(SendStatusPtr != NULL); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return (XST_DEVICE_IS_STOPPED); } /* Have to be in polled mode to use this function */ if (!(InstancePtr->Options & XTE_POLLED_OPTION)) { return (XST_NOT_POLLED); } /* Make sure send packet FIFO isn't deadlocked */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); if (RegDISR & XTE_DXR_SEND_FIFO_MASK) { XTemac_mBumpStats(TxPktFifoErrors, 1); return (XST_PFIFO_ERROR); } /* Make sure no IPIF errors are present */ if (RegDISR & (XTE_DXR_TERR_MASK | XTE_DXR_DPTO_MASK)) { XTemac_mBumpStats(IpifErrors, 1); return (XST_IPIF_ERROR); } /* Read the IPISR * If any errors are detetected, try to clear and return error */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_ERROR_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, RegIPISR & XTE_IPXR_XMIT_ERROR_MASK); XTemac_mBumpStats(FifoErrors, 1); return (XST_FIFO_ERROR); } /* No FIFO errors, so see of a transmit has completed */ if (!(RegIPISR & XTE_IPXR_XMIT_DONE_MASK)) { return (XST_NO_DATA); } /* Transmit has completed, get the status, ack the condition */ *SendStatusPtr = XTemac_mGetIpifReg(XTE_TSR_OFFSET); XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_XMIT_DONE_MASK); /* no errors to report */ return (XST_SUCCESS); }
/** * Free a set of BDs that had been retrieved by XTemac_SgGetProcessed(). If BDs * are not freed, then eventually the channel will run out of BDs to * XTemac_SgAlloc(). * * This function and XTemac_SgGetProcessed() must be called in the correct * order. See xtemac.h for more information on the SGDMA use model. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction is the channel to address (XTE_SEND or XTE_RECV). * @param BdPtr is the first BD in the set to free. This is typically the same * value returned by XTemac_SgGetProcessed(). * @param NumBd is the number of BDs to free. This is typically the same value * returned by XTemac_SgGetProcessed(). * * @return * - XST_SUCCESS if the requested number of BDs was returned. * - XST_INVALID_PARAM if Direction did not specify a valid channel. * - XST_DMA_SG_LIST_ERROR if BdPtr parameter does not reflect the correct * insertion point within the internally maintained BD ring. This error occurs * when this function and XTemac_SgGetProcessed() are called out of order. * * @note * This function is not thread-safe. The user must provide mutually exclusive * access to this function if there are to be multiple threads that can call it. * ******************************************************************************/ XStatus XTemac_SgFree(XTemac * InstancePtr, u32 Direction, unsigned NumBd, XDmaBdV2 * BdPtr) { u32 DgieReg; XDmaV2 *DmaPtr; XStatus Status; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Which channel to address */ if (Direction == XTE_RECV) { DmaPtr = &InstancePtr->RecvDma; } else if (Direction == XTE_SEND) { DmaPtr = &InstancePtr->SendDma; } else { return (XST_INVALID_PARAM); } /* This is a critical section. Prevent interrupts from the device while * the BD ring is being modified. */ DgieReg = XTemac_mGetIpifReg(XTE_DGIE_OFFSET); XTemac_mSetIpifReg(XTE_DGIE_OFFSET, 0); Status = XDmaV2_SgBdFree(DmaPtr, NumBd, BdPtr); XTemac_mSetIpifReg(XTE_DGIE_OFFSET, DgieReg); return (Status); }
/** * Commit a set of BDs to the SGDMA engine that had been allocated by * XTemac_SgAlloc() and prepared by the user to describe SGDMA transaction(s). * * This function and XTemac_SgAlloc() must be called in the correct order. See * xtemac.h for more information on the SGDMA use model. * * Upon return, the committed BDs go under hardware control. Do not modify BDs * after they have been committed. Doing so may cause data corruption and system * instability. * * This function may be called if the TEMAC device is started or stopped. If * started (see XTemac_Start()), then the BDs may be processed by HW at any * time. * * This function is non-blocking. Notification of error or successful * transmission/reception is done asynchronously through callback functions. * * For transmit (XTE_SEND): * * It is assumed that the upper layer software supplies a correctly formatted * Ethernet frame, including the destination and source addresses, the * type/length field, and the data field. * * For receive (XTE_RECV): * * It is assumed that BDs have an appropriately sized frame buffer attached * that corresponds to the network MTU. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction is the channel to address (XTE_SEND or XTE_RECV). * @param NumBd is the number of BDs to commit. This is typically the same * value used when the BDs were allocated with XTemac_SgAlloc(). * @param BdPtr is the first BD in the set to commit and is typically the * same value returned by XTemac_SgAlloc(). * * @return * - XST_SUCCESS if the requested number of BDs was returned. * - XST_INVALID_PARAM if Direction did not specify a valid channel. * - XST_FAILURE if the last BD in the set does not have its "last" bit * set (see XDmaBdV2_mSetLast()). * - XST_DMA_SG_LIST_ERROR if BdPtr parameter does not reflect the correct * insertion point within the internally maintained BD ring. This error occurs * when this function and XTemac_SgAlloc() are called out of order. * * @note * This function is not thread-safe. The user must provide mutually exclusive * access to this function if there are to be multiple threads that can call it. * ******************************************************************************/ XStatus XTemac_SgCommit(XTemac * InstancePtr, u32 Direction, unsigned NumBd, XDmaBdV2 * BdPtr) { XStatus Status; XDmaV2 *DmaPtr; u32 DgieReg; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Which channel to address */ if (Direction == XTE_RECV) { DmaPtr = &InstancePtr->RecvDma; } else if (Direction == XTE_SEND) { DmaPtr = &InstancePtr->SendDma; } else { return (XST_INVALID_PARAM); } /* XDmaV2_SgToHw() will return either XST_SUCCESS, XST_FAILURE, or * XST_DMA_SG_LIST_ERROR * * This is a critical section, prevent interrupts from the device while * the BD ring is being modified. */ DgieReg = XTemac_mGetIpifReg(XTE_DGIE_OFFSET); XTemac_mSetIpifReg(XTE_DGIE_OFFSET, 0); Status = XDmaV2_SgBdToHw(DmaPtr, NumBd, BdPtr); XTemac_mSetIpifReg(XTE_DGIE_OFFSET, DgieReg); return (Status); }
/** * * Disable FIFO related interrupts for FIFO direct frame transfer mode. Dma * interrupts are not affected. * * Do not use this function when using SG DMA frame transfer mode. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction specifies whether the transmit related (XTE_SEND) or * receive related (XTE_RECV) interrupts should be affected, or * both (XTE_SEND | XTE_RECV). * * @return None * * @note The state of the transmitter and receiver are not modified by this * function. * * @note If the device is configured for SGDMA, then this function has no * effect. Use XTemac_IntrSgDmaDisable() instead. * ******************************************************************************/ void XTemac_IntrFifoDisable(XTemac * InstancePtr, u32 Direction) { u32 RegIPIER; XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_VOID(!(Direction & ~(XTE_SEND | XTE_RECV))); /* Don't allow if device is configured for SGDMA */ if (XTemac_mIsSgDma(InstancePtr)) { return; } /* Get contents of IPIER register */ RegIPIER = XTemac_mGetIpifReg(XTE_IPIER_OFFSET); /* Handle send direction */ if (Direction & XTE_SEND) { RegIPIER &= ~(XTE_IPXR_XMIT_ERROR_MASK | XTE_IPXR_XMIT_DONE_MASK); InstancePtr->Flags &= ~XTE_FLAGS_SEND_FIFO_INT_ENABLE; } /* Handle receive direction */ if (Direction & XTE_RECV) { RegIPIER &= ~(XTE_IPXR_RECV_ERROR_MASK | XTE_IPXR_RECV_DONE_MASK); InstancePtr->Flags &= ~XTE_FLAGS_RECV_FIFO_INT_ENABLE; } /* Update IPIER with new setting */ XTemac_mSetIpifReg(XTE_IPIER_OFFSET, RegIPIER); }
/** * Retrieve the number of free bytes in the packet FIFOs. * * For the transmit packet FIFO, the number returned is the number of bytes * that can be written by XTemac_FifoWrite(). If a non-zero number is returned, * then at least 1 packet of that size can be transmitted. * * For the receive packet FIFO, the number returned is the number of bytes that * can arrive from an external Ethernet device. This number does not reflect * the state of the receive length FIFO. If this FIFO is full, then arriving * packets will get dropped by the HW if there is no place to store the length. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction selects which packet FIFO to examine. If XTE_SEND, then * the transmit packet FIFO is selected. If XTE_RECV, then the receive * packet FIFO is selected. * * @return * Number of bytes available in the selected packet FIFO. * ******************************************************************************/ u32 XTemac_FifoGetFreeBytes(XTemac * InstancePtr, u32 Direction) { u32 RegIPISR; u32 Count; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(!(Direction & ~(XTE_SEND | XTE_RECV))); /* For the send direction, even though there may be room in the * packet FIFO, the length FIFO may be full. When this is the case, * another packet cannot be transmiited so return 0. */ if (Direction == XTE_SEND) { /* Check length FIFO */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); if (RegIPISR & XTE_IPXR_XMIT_LFIFO_FULL_MASK) { return (0); } /* Get FIFO entries */ Count = XPF_V200A_GET_COUNT(&InstancePtr->SendFifo.Fifo); } /* Handle receive direction */ else { Count = XPF_V200A_COUNT_MASK - XPF_V200A_GET_COUNT(&InstancePtr->RecvFifo.Fifo); } /* Multiply free entries by the width of the packet FIFO to arrive at * bytes */ return (Count * InstancePtr->RecvFifo.Width); }
/** * Retrieve BDs that have been processed by the SGDMA channel. This function is * called typically after the XTE_HANDLER_SGRECV handler has been invoked for * the receive channel or XTE_HANDLER_SGSEND for the transmit channel. * * The set of BDs returned is a list starting with the BdPtr and extending * for 1 or more BDs (the exact number is the return value of this function). * The list can be navigated with macros XTemac_mSgRecvBdNext() for the * XTE_RECV channel, and XTemac_mSgSendBdNext() for the XTE_SEND channel. * Treat the returned BDs as read-only. * * This function and XTemac_SgFree() must be called in the correct order. See * xtemac.h for more information on the SGDMA use model. * * The last BD in the returned list is guaranteed to have the "Last" bit set * (i.e. XDmaBdV2_IsLast evaluates to true). * * The returned BDs can be examined for the outcome of the SGDMA transaction. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction is the channel to address (XTE_SEND or XTE_RECV). * @param BdPtr is an output parameter that points to the 1st BD in the returned * list. If no BDs were ready, then this parameter is unchanged. * @param NumBd is an upper limit to the number of BDs to retrieve. * * @return * Number of BDs that are ready for post processing. If the direction parameter * is invalid, then 0 is returned. * * @note * This function is not thread-safe. The user must provide mutually exclusive * access to this function if there are to be multiple threads that can call it. * ******************************************************************************/ unsigned XTemac_SgGetProcessed(XTemac * InstancePtr, u32 Direction, unsigned NumBd, XDmaBdV2 ** BdPtr) { u32 DgieReg; XDmaV2 *DmaPtr; unsigned Rc; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(BdPtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Which channel to address */ if (Direction == XTE_RECV) { DmaPtr = &InstancePtr->RecvDma; } else if (Direction == XTE_SEND) { DmaPtr = &InstancePtr->SendDma; } else { return (0); } /* This is a critical section. Prevent interrupts from the device while * the BD ring is being modified. */ DgieReg = XTemac_mGetIpifReg(XTE_DGIE_OFFSET); XTemac_mSetIpifReg(XTE_DGIE_OFFSET, 0); /* Extract ready BDs */ Rc = XDmaV2_SgBdFromHw(DmaPtr, NumBd, BdPtr); /* This is where we ack IPXR_PCTR interrupt for the dma channel. This * cannot be done in XTemac_IntrSgDmaHandler() because HW will keep the * interrupt asserted as long as the DMA channel's PCT > threshold. Calling * SgBdFromHw above will decrement PCT which should in most cases allow * the acknowledgement to take effect. * * We have to read the status 1st and test it before clearing * it. Bloody toggle-on-write statuses. Grrrr! */ if (XDmaV2_GetInterruptStatus(DmaPtr) & XDMAV2_IPXR_PCTR_MASK) { XDmaV2_SetInterruptStatus(DmaPtr, XDMAV2_IPXR_PCTR_MASK); } /* End critical section */ XTemac_mSetIpifReg(XTE_DGIE_OFFSET, DgieReg); return (Rc); }
/** * * Enable FIFO related interrupts for FIFO direct frame transfer mode. Dma * interrupts are not affected. * * Do not use this function when using SG DMA frame transfer mode. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Direction specifies whether the transmit related (XTE_SEND) or * receive related (XTE_RECV) interrupts should be affected, or * both (XTE_SEND | XTE_RECV). * * @return None * * @note The state of the transmitter and receiver are not modified by this * function. * * @note If the device is configured for SGDMA, then this function has no * effect. Use XTemac_IntrSgDmaDisable() instead. * ******************************************************************************/ void XTemac_IntrFifoEnable(XTemac * InstancePtr, u32 Direction) { u32 RegIPIER; XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_VOID(!(Direction & ~(XTE_SEND | XTE_RECV))); /* Don't allow if device is configured for SGDMA */ if (XTemac_mIsSgDma(InstancePtr)) { return; } /* Get contents of IPIER register */ RegIPIER = XTemac_mGetIpifReg(XTE_IPIER_OFFSET); /* Handle send direction */ if (Direction & XTE_SEND) { RegIPIER |= (XTE_IPXR_XMIT_ERROR_MASK | XTE_IPXR_XMIT_DONE_MASK); InstancePtr->Flags |= XTE_FLAGS_SEND_FIFO_INT_ENABLE; /* Don't allow Tx status overrun interrupt if option is cleared */ if (! (InstancePtr-> Options & XTE_REPORT_TXSTATUS_OVERRUN_OPTION)) { RegIPIER &= ~XTE_IPXR_XMIT_SFIFO_OVER_MASK;; } } /* Handle receive direction */ if (Direction & XTE_RECV) { RegIPIER |= (XTE_IPXR_RECV_ERROR_MASK | XTE_IPXR_RECV_DONE_MASK); InstancePtr->Flags |= XTE_FLAGS_RECV_FIFO_INT_ENABLE; /* Don't enable recv reject errors if option is cleared */ if (!(InstancePtr->Options & XTE_REPORT_RXERR_OPTION)) { RegIPIER &= ~XTE_IPXR_RECV_DROPPED_MASK; } } /* Update IPIER with new setting */ XTemac_mSetIpifReg(XTE_IPIER_OFFSET, RegIPIER); }
/** * Copy data from a user buffer to the transmit packet FIFO. The data copied * may comprise of single, multiple, or partial packets. The data is not * transmitted until XTemac_FifoSend() is called. * * If the user buffer contains multiple packets, then extra care must be taken. * In this special situation, the end of one packet and the beginning of a new * packet is specified within the user buffer. The beginning of each NEW packet * must begin on a 4 byte alignment. The user is responsible for adding filler * data between packets to acheive this alignment. The amount of filler data * depends on what byte the end of the previous packet falls on. When calling * XTemac_FifoSend() to transmit the packets, DO NOT specify the filler bytes * in the TxByteCount parameter. For example, if a user buffer contains two * complete packets of 15 bytes each with 1 byte of filler between them, then * XTemac_FifoWrite() is called once to write all 31 bytes to the FIFO. * XTemac_FifoSend() is called twice specifying 15 bytes each time to transmit * the packets (the 1 byte of filler data is ignored by the TEMAC). Of course * you could also just call XTemac_FifoWrite() once for each packet. This way, * the driver will manage the filler data. * * If the user's buffer is not aligned on a 4 byte boundary, then the transfer * may take longer to complete. * * @param InstancePtr is a pointer to the instance to be worked on. * @param BufPtr is the buffer containing user data that will be transferred * into the transmit FIFO. The buffer may be on any alignment. * @param ByteCount is the number of bytes to transfer from 1 to the number * of bytes available in the FIFO at the time of invocation. See usage * note for situations when a value of 0 is legal. * @param Eop specifies whether the last byte of BufPtr marks the End Of Packet. * If set to XTE_END_OF_PACKET, then any partial bytes being buffered by * the driver are flushed into the packet FIFO. If set to * XTE_PARTIAL_PACKET, then more packet data is expected to be written * through more calls to this function. Failure to use XTE_END_OF_PACKET * prior to calling XTemac_FifoSend() may cause a packet FIFO underrun. * * @return * - XST_SUCCESS if the data was transferred to the FIFO. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_PFIFO_ERROR if there was a packet FIFO overflow during the transfer. * This is a fatal condition. If this value is returned in polled mode, then * the device must be reset. For interrupt driven modes, an interrupt will be * asserted resulting in a call to the registered error handler which should * handle reset of the device. * - XST_IPIF_ERROR if a data or bus error occurred within the TEMAC's IPIF. * Like the PFIFO error, this is a fatal condition and should be handled * in the same manner. * * @note * Calling this function with ByteCount = 0 will not result in the transfer of * data from BufPtr to the FIFO. However, if at the same time Eop is set to * XTE_END_OF_PACKET, then all data previously written with this function is * guaranteed to be flushed into the packet FIFO and available for transmission * with XTemac_FifoSend(). ******************************************************************************/ XStatus XTemac_FifoWrite(XTemac * InstancePtr, void *BufPtr, u32 ByteCount, int Eop) { u32 RegDISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); XASSERT_NONVOID(! ((Eop != XTE_END_OF_PACKET) && (Eop != XTE_PARTIAL_PACKET))); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return (XST_DEVICE_IS_STOPPED); } /* Transfer the data using the best/fastest method */ InstancePtr->SendFifo.XferFn(&InstancePtr->SendFifo, BufPtr, ByteCount, Eop); /* Make sure the packet FIFO didn't report an error */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); if (RegDISR & XTE_DXR_SEND_FIFO_MASK) { /* Only bump stats in polled mode. For interrupt driven mode, this stat * is bumped in XTemac_IntrFifoHandler() */ if (InstancePtr->Options & XTE_POLLED_OPTION) { XTemac_mBumpStats(TxPktFifoErrors, 1); } return (XST_PFIFO_ERROR); } /* Verify no IPIF errors */ if (RegDISR & (XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK)) { /* Only bump stats in polled mode. For interrupt driven mode, this stat * is bumped in XTemac_IntrFifoHandler() */ if (InstancePtr->Options & XTE_POLLED_OPTION) { XTemac_mBumpStats(IpifErrors, 1); } return (XST_IPIF_ERROR); } return (XST_SUCCESS); }
/** * * Master interrupt handler for FIFO direct frame transfer mode. This routine * will query the status of the device, bump statistics, and invoke user * callbacks in the following priority: * * - XTE_HANDLER_ERROR for error class XST_PFIFO_DEADLOCK. * - XTE_HANDLER_ERROR for error class XST_DMA_ERROR for reads. * - XTE_HANDLER_FIFODMAREAD for successfull DMA reads * - XTE_HANDLER_ERROR for error class XST_DMA_ERROR for writes. * - XTE_HANDLER_FIFODMAWRITE for successfull DMA writes * - XTE_HANDLER_ERROR for error class XST_FIFO_ERROR. * - XTE_HANDLER_FIFORECV for newly received frames * - XTE_HANDLER_ERROR for error class XST_SEND_ERROR. * - XTE_HANDLER_FIFOSEND for completed transmits * - XTE_HANDLER_ERROR for error class XST_RECV_ERROR. * * This routine must be connected to an interrupt controller using OS/BSP * specific methods. * * @param InstancePtr is a pointer to the TEMAC instance that has caused the * interrupt. * * @return None * ******************************************************************************/ void XTemac_IntrFifoHandler(void *TemacPtr) { u32 RegDISR; u32 CorePending; u32 RegMisc; u32 Bytes; unsigned Cnt; XTemac *InstancePtr = (XTemac *) TemacPtr; XASSERT_VOID(InstancePtr != NULL); /* This ISR will try to handle as many interrupts as it can in a single * call. However, in most of the places where the user's error handler is * called, this ISR exits because it is expected that the user will reset * the device most of the time. */ /* Log interrupt */ XTemac_mBumpStats(Interrupts, 1); /* Get top level interrupt status. The status is self clearing when the * interrupt source is cleared */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); /* Handle IPIF and packet FIFO errors */ if (RegDISR & (XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK | XTE_DXR_RECV_FIFO_MASK | XTE_DXR_SEND_FIFO_MASK)) { /* IPIF transaction or data phase error */ if (RegDISR & (XTE_DXR_DPTO_MASK | XTE_DXR_TERR_MASK)) { XTemac_mBumpStats(IpifErrors, 1); ERR_HANDLER(XST_IPIF_ERROR, RegDISR, 0); return; } /* Receive packet FIFO is deadlocked */ if (RegDISR & XTE_DXR_RECV_FIFO_MASK) { XTemac_mBumpStats(RxPktFifoErrors, 1); ERR_HANDLER(XST_PFIFO_DEADLOCK, XTE_RECV, 0); return; } /* Transmit packet FIFO is deadlocked */ if (RegDISR & XTE_DXR_SEND_FIFO_MASK) { XTemac_mBumpStats(TxPktFifoErrors, 1); ERR_HANDLER(XST_PFIFO_DEADLOCK, XTE_SEND, 0); return; } } /* Handle receive side simple DMA channel interrupt. Read and ack the * DMA's interrupt status. If an error is indicated then call the * error handler. If a transfer complete is indicated then call the * DMA read handler */ if (RegDISR & XTE_DXR_RECV_DMA_MASK) { RegMisc = XDmaV2_GetInterruptStatus(&InstancePtr->RecvDma); XDmaV2_SetInterruptStatus(&InstancePtr->RecvDma, RegMisc); if (RegMisc & XDMAV2_IPXR_DE_MASK) { XTemac_mBumpStats(RxDmaErrors, 1); ERR_HANDLER(XST_DMA_ERROR, XTE_RECV, XDmaV2_mGetStatus(&InstancePtr->RecvDma)); return; } if (RegMisc & XDMAV2_IPXR_DD_MASK) { Bytes = InstancePtr->DmaReadLengthRef; InstancePtr->DmaReadLengthRef = 0; DMAREAD_HANDLER(Bytes); } } /* Handle send side simple DMA channel interrupt. Read and ack the * DMA's interrupt status. If an error is indicated then call the * error handler. If a transfer complete is indicated then call the * DMA write handler */ if (RegDISR & XTE_DXR_SEND_DMA_MASK) { RegMisc = XDmaV2_GetInterruptStatus(&InstancePtr->SendDma); XDmaV2_SetInterruptStatus(&InstancePtr->SendDma, RegMisc); if (RegMisc & XDMAV2_IPXR_DE_MASK) { XTemac_mBumpStats(TxDmaErrors, 1); ERR_HANDLER(XST_DMA_ERROR, XTE_SEND, XDmaV2_mGetStatus(&InstancePtr->SendDma)); return; } if (RegMisc & XDMAV2_IPXR_DD_MASK) { Bytes = InstancePtr->DmaWriteLengthRef; InstancePtr->DmaWriteLengthRef = 0; DMAWRITE_HANDLER(Bytes); } } /* Handle core interrupts */ if (RegDISR & XTE_DXR_CORE_MASK) { /* Calculate which enabled interrupts have been asserted */ CorePending = XTemac_mGetIpifReg(XTE_IPIER_OFFSET) & XTemac_mGetIpifReg(XTE_IPISR_OFFSET); /* Check for fatal status/length FIFO errors. These errors can't be * cleared */ if (CorePending & XTE_IPXR_FIFO_FATAL_ERROR_MASK) { XTemac_mBumpStats(FifoErrors, 1); ERR_HANDLER(XST_FIFO_ERROR, CorePending & XTE_IPXR_FIFO_FATAL_ERROR_MASK, 0); return; } /* A receive packet has arrived. Call the receive handler. * * Acking this interrupt is not done here. The handler has a choice: * 1) Call XTemac_FifoRecv() which will ack this interrupt source, or * 2) Call XTemac_IntrFifoDisable() and defer XTEmac_FifoRecv() to a * later time. Failure to do one of these actions will leave this * interupt still pending resulting in an exception loop. */ if (CorePending & XTE_IPXR_RECV_DONE_MASK) { FIFORECV_HANDLER(); } /* A transmit has completed. Pull off all statuses that are available. * For each status that contains a non-fatal error, the error handler * is invoked. For fatal errors, the error handler is invoked once and * assumes the callback will reset the device. * * Unless there was a fatal error, then call the send handler since * resources in the packet FIFO, transmit length FIFO, and transmit * status FIFO have been freed up. This gives the handler a chance * to enqueue new frame(s). */ if (CorePending & XTE_IPXR_XMIT_DONE_MASK) { Cnt = 0; /* While XMIT_DONE persists */ do { /* Get TSR, try to clear XMIT_DONE */ RegMisc = XTemac_mGetIpifReg(XTE_TSR_OFFSET); XTemac_mSetIpifReg(XTE_IPISR_OFFSET, XTE_IPXR_XMIT_DONE_MASK); /* Does TSR indicate error? */ if (RegMisc & XTE_TSR_ERROR_MASK) { XTemac_mBumpStats(TxStatusErrors, 1); ERR_HANDLER(XST_SEND_ERROR, RegMisc, 0); /* Fatal errors end processing immediately */ if (RegMisc & XTE_TSR_PFIFOU_MASK) { return; } } Cnt++; /* Read IPISR and test XMIT_DONE again */ RegMisc = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); } while (RegMisc & XTE_IPXR_XMIT_DONE_MASK); FIFOSEND_HANDLER(Cnt); } /* Check for dropped receive frame. Ack the interupt then call the * error handler */ if (CorePending & XTE_IPXR_RECV_DROPPED_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, CorePending & XTE_IPXR_RECV_DROPPED_MASK); XTemac_mBumpStats(RxRejectErrors, 1); ERR_HANDLER(XST_RECV_ERROR, CorePending & XTE_IPXR_RECV_DROPPED_MASK, 0); /* no return here, nonfatal error */ } } }
/** * Query the device for the latest receive status for FIFO direct frame * transfer mode. This function should be used for polled mode operation only. * * @param InstancePtr is a pointer to the instance to be worked on. * * @return * - XST_SUCCESS if a frame has been received and no receive error was detected. * - XST_DEVICE_IS_STOPPED if the device has not been started. * - XST_NO_DATA if no frame has been received and no receive related error has * been detected. * - XST_NOT_POLLED if the device has not been set to polled mode. * - XST_DATA_LOST if the device reports that it dropped a receive frame. This * is not a serious problem but may indicate that frames are arriving faster * than the system can process them. * - XST_FIFO_ERROR if an error was detected with the receive length FIFO. If * this error is returned, then the device must be reset before any new frame * can be received. * - XST_PFIFO_ERROR if the receive packet FIFO is deadlocked. If this error is * returned, then the device must be reset before any new frame can be * received. * - XST_IPIF_ERROR if there has been a data phase timeout or transaction error * in the IPIF. This is a fatal error. * * @note * In situations where simultaneously a frame has been received for which an * XST_SUCCESS can be returned and a dropped frame for which an XST_DATA_LOST * can be returned, then this function will give priority to XST_SUCCESS so the * user can receive the frame. ******************************************************************************/ XStatus XTemac_FifoQueryRecvStatus(XTemac * InstancePtr) { u32 RegDISR; u32 RegIPISR; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Make sure device is ready for this operation */ if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { return (XST_DEVICE_IS_STOPPED); } /* Have to be in polled mode to use this function */ if (!(InstancePtr->Options & XTE_POLLED_OPTION)) { return (XST_NOT_POLLED); } /* Read the DISR */ RegDISR = XTemac_mGetIpifReg(XTE_DISR_OFFSET); /* Make sure recv packet FIFO isn't deadlocked */ if (RegDISR & XTE_DXR_RECV_FIFO_MASK) { XTemac_mBumpStats(RxPktFifoErrors, 1); return (XST_PFIFO_ERROR); } /* Make sure no IPIF errors are present */ if (RegDISR & (XTE_DXR_TERR_MASK | XTE_DXR_DPTO_MASK)) { XTemac_mBumpStats(IpifErrors, 1); return (XST_IPIF_ERROR); } /* Read the IPISR */ RegIPISR = XTemac_mGetIpifReg(XTE_IPISR_OFFSET); /* Check for other recv related FIFO errors */ if (RegIPISR & (XTE_IPXR_RECV_ERROR_MASK - XTE_IPXR_RECV_DROPPED_MASK)) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, RegIPISR & XTE_IPXR_RECV_ERROR_MASK); XTemac_mBumpStats(FifoErrors, 1); return (XST_FIFO_ERROR); } /* See if a frame has been received */ if (RegIPISR & XTE_IPXR_RECV_DONE_MASK) { return (XST_SUCCESS); } /* If option to detect recv reject errors is set, check for rejected * receive frames. If one is detected, clear it and return error. */ if (InstancePtr->Options & XTE_REPORT_RXERR_OPTION) { if (RegIPISR & XTE_IPXR_RECV_DROPPED_MASK) { XTemac_mSetIpifReg(XTE_IPISR_OFFSET, RegIPISR & XTE_IPXR_RECV_DROPPED_MASK); return (XST_DATA_LOST); } } /* No frame has been received and no errors detected */ return (XST_NO_DATA); }