⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xemac_intr_fifo.c

📁 powerpc405开发板的linux网口驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: xemac_intr_fifo.c,v 1.1 2005/10/26 15:44:52 meinelte Exp $ *//********************************************************************************       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS*       FOR A PARTICULAR PURPOSE.**       (c) Copyright 2003 Xilinx Inc.*       All rights reserved.*******************************************************************************//*****************************************************************************//**** @file xemac_intr_fifo.c** Contains functions related to interrupt mode using direct FIFO I/O or simple* DMA. The driver uses simple DMA if the device is configured with DMA,* otherwise it uses direct FIFO access.** The interrupt handler, XEmac_IntrHandlerFifo(), must be connected by the user* to the interrupt controller.** <pre>* MODIFICATION HISTORY:** Ver   Who  Date     Changes* ----- ---- -------- -----------------------------------------------* 1.00a rpm  07/31/01 First release* 1.00b rpm  02/20/02 Repartitioned files and functions* 1.00c rpm  12/05/02 New version includes support for simple DMA* 1.00c rpm  04/01/03 Added check in FifoSend for room in the data FIFO*                     before starting a simple DMA transfer.* 1.00d rpm  09/26/03 New version includes support PLB Ethernet and v2.00a of*                     the packet fifo driver.* </pre>*******************************************************************************//***************************** Include Files *********************************/#include "xbasic_types.h"#include "xemac_i.h"#include "xio.h"#include "xipif_v1_23_b.h"      /* Uses v1.23b of the IPIF *//************************** Constant Definitions *****************************//**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Variable Definitions *****************************//************************** Function Prototypes ******************************/static void HandleEmacFifoIntr(XEmac *InstancePtr);/*****************************************************************************//**** Send an Ethernet frame using direct FIFO I/O or simple DMA with interrupts.* The caller provides a contiguous-memory buffer and its length. The buffer* must be 32-bit aligned. If using simple DMA and the PLB 10/100 Ethernet core,* the buffer must be 64-bit aligned. The callback function set by using* SetFifoSendHandler is invoked when the transmission is complete.** 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.** If the device is configured with DMA, simple DMA will be used to transfer* the buffer from memory to the Emac. This means that this buffer should not* be cached.  See the comment section "Simple DMA" in xemac.h for more* information.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param BufPtr is a pointer to a aligned buffer containing the Ethernet*        frame to be sent.* @param ByteCount is the size of the Ethernet frame.** @return** - XST_SUCCESS if the frame was successfully sent. An interrupt is generated*   when the EMAC transmits the frame and the driver calls the callback set*   with XEmac_SetFifoSendHandler()* - XST_DEVICE_IS_STOPPED  if the device has not yet been started* - XST_NOT_INTERRUPT if the device is not in interrupt mode* - XST_FIFO_NO_ROOM if there is no room in the FIFO for this frame* - XST_DEVICE_BUSY if configured for simple DMA and the DMA engine is busy* - XST_DMA_ERROR if an error occurred during the DMA transfer (simple DMA).*   The user should treat this as a fatal error that requires a reset of the*   EMAC device.** @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.** @internal** The Ethernet MAC uses FIFOs behind its length and status registers. For this* reason, it is important to keep the length, status, and data FIFOs in sync* when reading or writing to them.*******************************************************************************/XStatus XEmac_FifoSend(XEmac *InstancePtr, Xuint8 *BufPtr, Xuint32 ByteCount){    XStatus Result;    volatile Xuint32 StatusReg;    XASSERT_NONVOID(InstancePtr != XNULL);    XASSERT_NONVOID(BufPtr != XNULL);    XASSERT_NONVOID(ByteCount > XEM_HDR_SIZE);   /* send at least 1 byte */    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    /*     * Be sure the device is configured for interrupt mode and it is started     */    if (InstancePtr->IsPolled)    {        return XST_NOT_INTERRUPT;    }    if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED)    {        return XST_DEVICE_IS_STOPPED;    }    /*     * Before writing to the data FIFO, make sure the length FIFO is not     * full.  The data FIFO might not be full yet even though the length FIFO     * is. This avoids an overrun condition on the length FIFO and keeps the     * FIFOs in sync.     */    StatusReg = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);    if (StatusReg & XEM_EIR_XMIT_LFIFO_FULL_MASK)    {        return XST_FIFO_NO_ROOM;    }    /*     * Send either by directly writing to the FIFOs or using the DMA engine     */    if (!XEmac_mIsDma(InstancePtr))    {        /*         * This is a non-blocking write. The packet FIFO returns an error if there         * is not enough room in the FIFO for this frame.         */        Result = XPacketFifoV200a_Write(&InstancePtr->SendFifo, BufPtr, ByteCount);        if (Result != XST_SUCCESS)        {            return Result;        }    }    else    {        Xuint32 Vacancy;        /*         * Need to make sure there is room in the data FIFO for the packet         * before trying to DMA into it. Get the vacancy count (in words)         * and make sure the packet will fit.         */        Vacancy = XPF_V200A_GET_COUNT(&InstancePtr->SendFifo);        if ((Vacancy * sizeof(Xuint32)) < ByteCount)        {            return XST_FIFO_NO_ROOM;        }        /*         * Check the DMA engine to make sure it is not already busy         */        if (XDmaChannel_GetStatus(&InstancePtr->SendChannel) & XDC_DMASR_BUSY_MASK)        {            return XST_DEVICE_BUSY;        }        /*         * Set the DMA control register up properly         */        XDmaChannel_SetControl(&InstancePtr->SendChannel,                               XDC_DMACR_SOURCE_INCR_MASK |                               XDC_DMACR_DEST_LOCAL_MASK |                               XDC_DMACR_SG_DISABLE_MASK);        /*         * Now transfer the data from the buffer to the FIFO         */        XDmaChannel_Transfer(&InstancePtr->SendChannel, (Xuint32 *)BufPtr,                 (Xuint32 *)(InstancePtr->BaseAddress + XEM_PFIFO_TXDATA_OFFSET),                  ByteCount);        /*         * Poll here waiting for DMA to be not busy. We think this will         * typically be a single read since DMA should be ahead of the SW.         */        do        {            StatusReg = XDmaChannel_GetStatus(&InstancePtr->SendChannel);        }        while (StatusReg & XDC_DMASR_BUSY_MASK);        /* Return an error if there was a problem with DMA */        if ((StatusReg & XDC_DMASR_BUS_ERROR_MASK) ||            (StatusReg & XDC_DMASR_BUS_TIMEOUT_MASK))        {            InstancePtr->Stats.DmaErrors++;            return XST_DMA_ERROR;        }    }    /*     * Set the MAC's transmit packet length register to tell it to transmit     */    XIo_Out32(InstancePtr->BaseAddress + XEM_TPLR_OFFSET, ByteCount);    /*     * Bump stats here instead of the Isr since we know the byte count     * here but would have to save it in the instance in order to know the     * byte count at interrupt time.     */    InstancePtr->Stats.XmitFrames++;    InstancePtr->Stats.XmitBytes += ByteCount;    return XST_SUCCESS;}/*****************************************************************************//**** Receive an Ethernet frame into the buffer passed as an argument. This* function is called in response to the callback function for received frames* being called by the driver. The callback function is set up using* SetFifoRecvHandler, and is invoked when the driver receives an interrupt* indicating a received frame. The driver expects the upper layer software to* call this function, FifoRecv, to receive the frame. The buffer supplied* should be large enough to hold a maximum-size Ethernet frame.** The buffer into which the frame will be received must be 32-bit aligned. If* using simple DMA and the PLB 10/100 Ethernet core, the buffer must be 64-bit* aligned.** If the device is configured with DMA, simple DMA will be used to transfer* the buffer from the Emac to memory. This means that this buffer should not* be cached. See the comment section "Simple DMA" in xemac.h for more* information.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param BufPtr is a pointer to a aligned buffer into which the received*        Ethernet frame will be copied.* @param ByteCountPtr is both an input and an output parameter. It is a pointer*        to a 32-bit word that contains the size of the buffer on entry into*        the function and the size the received frame on return from the*        function.** @return** - XST_SUCCESS if the frame was sent successfully* - XST_DEVICE_IS_STOPPED if the device has not yet been started* - XST_NOT_INTERRUPT if the device is not in interrupt mode* - XST_NO_DATA if there is no frame to be received from the FIFO* - XST_BUFFER_TOO_SMALL if the buffer to receive the frame is too small for*   the frame waiting in the FIFO.* - XST_DEVICE_BUSY if configured for simple DMA and the DMA engine is busy* - XST_DMA_ERROR if an error occurred during the DMA transfer (simple DMA).*   The user should treat this as a fatal error that requires a reset of the*   EMAC device.** @note** The input buffer must be big enough to hold the largest Ethernet frame.** @internal** The Ethernet MAC uses FIFOs behind its length and status registers. For this* reason, it is important to keep the length, status, and data FIFOs in sync* when reading or writing to them.*******************************************************************************/XStatus XEmac_FifoRecv(XEmac *InstancePtr, Xuint8 *BufPtr,                       Xuint32 *ByteCountPtr){    XStatus Result;    Xuint32 PktLength;    Xuint32 StatusReg;    XASSERT_NONVOID(InstancePtr != XNULL);    XASSERT_NONVOID(BufPtr != XNULL);    XASSERT_NONVOID(ByteCountPtr != XNULL);    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    /*     * Be sure the device is not configured for polled mode and it is started     */    if (InstancePtr->IsPolled)    {        return XST_NOT_INTERRUPT;    }    if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED)    {        return XST_DEVICE_IS_STOPPED;    }    /*     * Make sure the buffer is big enough to hold the maximum frame size.     * We need to do this because as soon as we read the MAC's packet length     * register, which is actually a FIFO, we remove that length from the     * FIFO.  We do not want to read the length FIFO without also reading the     * data FIFO since this would get the FIFOs out of sync.  So we have to     * make this restriction.     */    if (*ByteCountPtr < XEM_MAX_FRAME_SIZE)    {        return XST_BUFFER_TOO_SMALL;    }    /*     * Before reading from the length FIFO, make sure the length FIFO is not     * empty. We could cause an underrun error if we try to read from an     * empty FIFO.     */    StatusReg = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);    if (StatusReg & XEM_EIR_RECV_LFIFO_EMPTY_MASK)    {        /*         * Clear the empty status so the next time through the current status

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -