/** * 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); }
/** * 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); }
/** * 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); }