Esempio n. 1
0
/**
 * 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);
}
Esempio n. 2
0
/**
 * 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);
}
Esempio n. 3
0
/**
 * 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);
}
Esempio n. 4
0
/**
 *
 * 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 */
		}
	}
}
Esempio n. 5
0
/**
 * 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);
}