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

📄 xemac_intr_fifo.c

📁 powerpc405开发板的linux网口驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
         * of the hardware is reflected (we have to do this because the status         * is level in the device but latched in the interrupt status register).         */        XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,                               XEM_EIR_RECV_LFIFO_EMPTY_MASK);        return XST_NO_DATA;    }    /*     * If configured with DMA, make sure the DMA engine is not busy     */    if (XEmac_mIsDma(InstancePtr))    {        if (XDmaChannel_GetStatus(&InstancePtr->RecvChannel) & XDC_DMASR_BUSY_MASK)        {            return XST_DEVICE_BUSY;        }    }    /*     * Determine, from the MAC, the length of the next packet available     * in the data FIFO (there should be a non-zero length here)     */    PktLength = XIo_In32(InstancePtr->BaseAddress + XEM_RPLR_OFFSET);    if (PktLength == 0)    {        return XST_NO_DATA;    }    /*     * We assume that the MAC never has a length bigger than the largest     * Ethernet frame, so no need to make another check here.     *     * Receive either by directly reading the FIFO or using the DMA engine     */    if (!XEmac_mIsDma(InstancePtr))    {        /*         * This is a non-blocking read. The FIFO returns an error if there is         * not at least the requested amount of data in the FIFO.         */        Result = XPacketFifoV200a_Read(&InstancePtr->RecvFifo, BufPtr, PktLength);        if (Result != XST_SUCCESS)        {            return Result;        }    }    else    {        /*         * Call on DMA to transfer from the FIFO to the buffer. First set up         * the DMA control register.         */        XDmaChannel_SetControl(&InstancePtr->RecvChannel,                               XDC_DMACR_DEST_INCR_MASK |                               XDC_DMACR_SOURCE_LOCAL_MASK |                               XDC_DMACR_SG_DISABLE_MASK);        /*         * Now transfer the data         */        XDmaChannel_Transfer(&InstancePtr->RecvChannel,                (Xuint32 *)(InstancePtr->BaseAddress + XEM_PFIFO_RXDATA_OFFSET),                (Xuint32 *)BufPtr, PktLength);        /*         * 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->RecvChannel);        }        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;        }    }    *ByteCountPtr = PktLength;    InstancePtr->Stats.RecvFrames++;    InstancePtr->Stats.RecvBytes += PktLength;    return XST_SUCCESS;}/*****************************************************************************//**** The interrupt handler for the Ethernet driver when configured for direct FIFO* communication or simple DMA.** Get the interrupt status from the IpIf to determine the source of the* interrupt.  The source can be: MAC, Recv Packet FIFO, or Send Packet FIFO.* The packet FIFOs only interrupt during "deadlock" conditions.  All other* FIFO-related interrupts are generated by the MAC.** @param InstancePtr is a pointer to the XEmac instance that just interrupted.** @return** None.** @note** None.*******************************************************************************/void XEmac_IntrHandlerFifo(void *InstancePtr){    Xuint32 IntrStatus;    XEmac *EmacPtr = (XEmac *)InstancePtr;    EmacPtr->Stats.TotalIntrs++;    /*     * Get the interrupt status from the IPIF. There is no clearing of     * interrupts in the IPIF. Interrupts must be cleared at the source.     */    IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress);    if (IntrStatus & XEM_IPIF_EMAC_MASK)        /* MAC interrupt */    {        EmacPtr->Stats.EmacInterrupts++;        HandleEmacFifoIntr(EmacPtr);    }    if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK)   /* Receive FIFO interrupt */    {        EmacPtr->Stats.RecvInterrupts++;        XEmac_CheckFifoRecvError(EmacPtr);    }    if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK)   /* Send FIFO interrupt */    {        EmacPtr->Stats.XmitInterrupts++;        XEmac_CheckFifoSendError(EmacPtr);    }    if (IntrStatus & XIIF_V123B_ERROR_MASK)    {        /*         * An error occurred internal to the IPIF. This is more of a debug and         * integration issue rather than a production error. Don't do anything         * other than clear it, which provides a spot for software to trap         * on the interrupt and begin debugging.         */        XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress, XIIF_V123B_ERROR_MASK);    }}/*****************************************************************************//**** Set the callback function for handling confirmation of transmitted frames when* configured for direct memory-mapped I/O using FIFOs. The upper layer software* should call this function during initialization. The callback is called by the* driver once per frame sent. The callback is responsible for freeing the* transmitted buffer if necessary.** The callback is invoked by the driver within interrupt context, so it needs* to do its job quickly. If there are potentially slow operations within the* callback, these should be done at task-level.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param CallBackRef is a reference pointer to be passed back to the adapter in*        the callback. This helps the adapter correlate the callback to a*        particular driver.* @param FuncPtr is the pointer to the callback function.** @return** None.** @note** None.*******************************************************************************/void XEmac_SetFifoRecvHandler(XEmac *InstancePtr, void *CallBackRef,                              XEmac_FifoHandler FuncPtr){    XASSERT_VOID(InstancePtr != XNULL);    XASSERT_VOID(FuncPtr != XNULL);    XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    InstancePtr->FifoRecvHandler = FuncPtr;    InstancePtr->FifoRecvRef = CallBackRef;}/*****************************************************************************//**** Set the callback function for handling received frames when configured for* direct memory-mapped I/O using FIFOs. The upper layer software should call* this function during initialization. The callback is called once per frame* received. During the callback, the upper layer software should call FifoRecv* to retrieve the received frame.** The callback is invoked by the driver within interrupt context, so it needs* to do its job quickly. Sending the received frame up the protocol stack* should be done at task-level. If there are other potentially slow operations* within the callback, these too should be done at task-level.** @param InstancePtr is a pointer to the XEmac instance to be worked on.* @param CallBackRef is a reference pointer to be passed back to the adapter in*        the callback. This helps the adapter correlate the callback to a*        particular driver.* @param FuncPtr is the pointer to the callback function.** @return** None.** @note** None.*******************************************************************************/void XEmac_SetFifoSendHandler(XEmac *InstancePtr, void *CallBackRef,                              XEmac_FifoHandler FuncPtr){    XASSERT_VOID(InstancePtr != XNULL);    XASSERT_VOID(FuncPtr != XNULL);    XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    InstancePtr->FifoSendHandler = FuncPtr;    InstancePtr->FifoSendRef = CallBackRef;}/******************************************************************************** Handle an interrupt from the Ethernet MAC when configured for direct FIFO* communication.  The interrupts handled are:* - Transmit done (transmit status FIFO is non-empty). Used to determine when*   a transmission has been completed.* - Receive done (receive length FIFO is non-empty). Used to determine when a*   valid frame has been received.** In addition, the interrupt status is checked for errors.** @param InstancePtr is a pointer to the XEmac instance to be worked on.** @return** None.** @note** None.*******************************************************************************/static void HandleEmacFifoIntr(XEmac *InstancePtr){    Xuint32 IntrStatus;    /*     * The EMAC generates interrupts for errors and generates the transmit     * and receive done interrupts for data. We clear the interrupts     * immediately so that any latched status interrupt bits will reflect the     * true status of the device, and so any pulsed interrupts (non-status)     * generated during the Isr will not be lost.     */    IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);    XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus);    if (IntrStatus & XEM_EIR_RECV_DONE_MASK)    {        /*         * Configured for direct memory-mapped I/O using FIFO with interrupts.         * This interrupt means the RPLR is non-empty, indicating a frame has         * arrived.         */        InstancePtr->Stats.RecvInterrupts++;        InstancePtr->FifoRecvHandler(InstancePtr->FifoRecvRef);        /*         * The upper layer has removed as many frames as it wants to, so we         * need to clear the RECV_DONE bit before leaving the ISR so that it         * reflects the current state of the hardware (because it's a level         * interrupt that is latched in the IPIF interrupt status register).         * Note that if we've reached this point the bit is guaranteed to be         * set because it was cleared at the top of this ISR before any frames         * were serviced, so the bit was set again immediately by hardware         * because the RPLR was not yet emptied by software.         */        XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_RECV_DONE_MASK);    }    /*     * If configured for direct memory-mapped I/O using FIFO, the xmit status     * FIFO must be read and the callback invoked regardless of success or not.     */    if (IntrStatus & XEM_EIR_XMIT_DONE_MASK)    {        Xuint32 XmitStatus;        InstancePtr->Stats.XmitInterrupts++;        XmitStatus = XIo_In32(InstancePtr->BaseAddress + XEM_TSR_OFFSET);        /*         * Collision errors are stored in the transmit status register         * instead of the interrupt status register         */        if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK)        {            InstancePtr->Stats.XmitExcessDeferral++;        }        if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK)        {            InstancePtr->Stats.XmitLateCollisionErrors++;        }        InstancePtr->FifoSendHandler(InstancePtr->FifoSendRef);        /*         * Only one status is retrieved per interrupt. We need to clear the         * XMIT_DONE bit before leaving the ISR so that it reflects the current         * state of the hardware (because it's a level interrupt that is latched         * in the IPIF interrupt status register). Note that if we've reached         * this point the bit is guaranteed to be set because it was cleared at         * the top of this ISR before any statuses were serviced, so the bit was         * set again immediately by hardware because the TSR was not yet emptied         * by software.         */        XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_XMIT_DONE_MASK);    }    /*     * Check the MAC for errors     */    XEmac_CheckEmacError(InstancePtr, IntrStatus);}

⌨️ 快捷键说明

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