Exemple #1
0
/**
 * 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);
}
Exemple #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);
}
Exemple #3
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);
}
Exemple #4
0
/**
 * 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);
}
Exemple #5
0
/**
 * 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);
}
Exemple #6
0
/**
 *
 * 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);
}
Exemple #7
0
/**
 * 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);
}
Exemple #8
0
/**
 * 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);
}
Exemple #9
0
/**
 *
 * 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);
}
Exemple #10
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);
}
Exemple #11
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 */
		}
	}
}
Exemple #12
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);
}