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

📄 xemac_intr_dma.c

📁 powerpc405开发板的linux网口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
                    break;                }                /* Bump statistics */                InstancePtr->Stats.RecvBytes += XBufDescriptor_GetLength(BdPtr);                /* Have all BDs been read for this packet */                if (XBufDescriptor_IsLastStatus(BdPtr))                {                    /*                     * Decrement the packet count register to reflect the fact                     * we just processed a packet                     */                    XDmaChannel_DecrementPktCount(&InstancePtr->RecvChannel);                    /* Bump statistics */                    InstancePtr->Stats.RecvFrames++;                    /* Test loop exit condition */                    if (--PacketsLeft == 0)                    {                        break;                    }                }                /* Get the next buffer descriptor in the list */                Result = XDmaChannel_GetDescriptor(&InstancePtr->RecvChannel,                                                   &BdPtr);            } /* while */            /*             * Check for error that occurred inside the while loop, and break             * out of the for loop if there was one so other interrupts can             * be serviced.             */            if (Result == XST_SUCCESS)            {                /*                 * Make the callback to the upper layers, passing it the first                 * descriptor in the first packet and the number of descriptors                 * in the list.                 */                InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef, BdHeadPtr,                                           NumBds);            }        } /* if (PacketsLeft) */        /*         * If the interrupt was an end-ack, check the descriptor list again to         * see if it is empty. If not, go ahead and restart the scatter-gather         * channel. This is to fix a possible race condition where, on receive,         * the driver attempted to start a scatter-gather channel that was         * already started, which resulted in no action from the XDmaChannel         * component. But, just after the XDmaChannel component saw that the         * hardware was already started, the hardware stopped because it         * reached the end of the list.  In that case, this interrupt is         * generated and we can restart the hardware here.         */        if (IntrStatus & XDC_IXR_SG_END_MASK)        {            /*             * Ignore the return status since we know the list exists and we             * don't care if the list is empty or the channel is already started.             */            (void)XDmaChannel_SgStart(&InstancePtr->RecvChannel);        }    }    /*     * All interrupts are handled (except the error below) so acknowledge     * (clear) the interrupts by writing the value read above back to the status     * register. The packet count interrupt must be acknowledged after the     * decrement, otherwise it will come right back. We clear the interrupts     * before we handle the error interrupt because the ErrorHandler should     * result in a reset, which clears the interrupt status register. So we     * don't want to toggle the interrupt back on by writing the interrupt     * status register with an old value after a reset.     */    XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus);    /*     * Check for DMA errors and call the error callback function if an error     * occurred (DMA bus or timeout error), which should result in a reset of     * the device by the upper layer software.     */    if (IntrStatus & XDC_IXR_DMA_ERROR_MASK)    {        InstancePtr->Stats.DmaErrors++;        InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);    }}/*****************************************************************************//*** Handle an interrupt from the DMA send channel. DMA interrupts are:** - DMA error. DMA encountered a bus error or timeout. This is a fatal error*   that requires reset of the channel.  The driver calls the error handler*   of the upper layer software with an error code indicating the device should*   be reset.* - Packet count threshold reached.  For scatter-gather operations, indicates*   the threshold for the number of packets not serviced by software has been*   reached. The driver behaves as follows:*       - Get the value of the packet counter, which tells us how many packets*         are ready to be serviced*       - For each packet*           - For each descriptor, remove it from the scatter-gather list*           - Check for the last descriptor in the frame, and if set*               - Bump frame statistics*               - Decrement the packet counter by one*       - Call the scatter-gather receive callback function*       Note that there are no receive errors reported in the status word of*       the buffer descriptor.  If receive errors occur, the MAC drops the*       packet, and we only find out about the errors through various error*       count registers.* - Packet wait bound reached.  For scatter-gather, indicates the time to wait*   for the next packet has expired.  The driver follows the same logic as when*   the packet count threshold interrupt is received.* - Scatter-gather end acknowledge.  Hardware has reached the end of the*   descriptor list.  The driver follows the same logic as when the packet count*   threshold interrupt is received. In addition, the driver restarts the DMA*   scatter-gather channel in case there are newly inserted descriptors.** @param InstancePtr is a pointer to the XEmac instance to be worked on.** @return** Although the function returns void, there are asynchronous errors* that can be generated from this function.  These are:* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from*   the DMA channel, but there was not one ready for software.* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a*   fatal error that requires reset.** @note** None.*******************************************************************************/static void HandleDmaSendIntr(XEmac *InstancePtr){    XStatus Result;    Xuint32 IntrStatus;    Xuint32 NumBds;    Xuint32 PacketsLeft;    Xuint32 XmitStatus;    int PacketStart;    XBufDescriptor *BdHeadPtr;    XBufDescriptor *BdPtr;    /*     * Read the interrupt status     */    IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel);    /*     * For packet threshold or wait bound interrupt, process descriptors. Also     * process descriptors on a SG end acknowledgement, which means the end of     * the descriptor list has been reached by the hardware. For transmit,     * this is a normal condition during times of light traffic.  In fact, the     * wait bound interrupt may be masked for transmit since the end-ack would     * always occur before the wait bound expires.     */    if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |        XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK))    {        /* Get the number of packets that need processing */        PacketsLeft = XDmaChannel_GetPktCount(&InstancePtr->SendChannel);        if (PacketsLeft)        {            /* Get the buffer descriptor at the head of the list */            Result = XDmaChannel_GetDescriptor(&InstancePtr->SendChannel,                                               &BdHeadPtr);            BdPtr = BdHeadPtr;            NumBds = 0;            PacketStart = 1;            /* Loop until all packets have been pulled or an error occurs */            while(1)            {                NumBds++;                /*                 * An error getting a buffer descriptor from the list.                 * This should not happen, but if it does, report it to                 * the error callback and break out of the loop to service                 * other interrupts.                 */                if (Result != XST_SUCCESS)                {                    InstancePtr->ErrorHandler(InstancePtr->ErrorRef, Result);                    break;                }                /* Bump statistics */                InstancePtr->Stats.XmitBytes += XBufDescriptor_GetLength(BdPtr);                /* If 1st BD in a packet, then check xmit status */                if (PacketStart)                {                    XmitStatus = XBufDescriptor_GetDeviceStatus(BdPtr);                    if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK)                    {                        InstancePtr->Stats.XmitExcessDeferral++;                    }                    if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK)                    {                        InstancePtr->Stats.XmitLateCollisionErrors++;                    }                    PacketStart = 0;                }                /* Have all BDs been read for this packet */                if (XBufDescriptor_IsLastStatus(BdPtr))                {                    /*                     * Decrement the packet count register to reflect the fact                     * we just processed a packet                     */                    XDmaChannel_DecrementPktCount(&InstancePtr->SendChannel);                    (InstancePtr->SendChannel).ActivePacketCount--;                    /* Bump statistics */                    InstancePtr->Stats.XmitFrames++;                    /* Test loop exit condition */                    if (--PacketsLeft == 0)                    {                        break;                    }                    /* Next BD will mark the beginning of a new packet */                    PacketStart = 1;                }                /* Get the next buffer descriptor in the list */                Result = XDmaChannel_GetDescriptor(&InstancePtr->SendChannel,                                                   &BdPtr);            } /* while */            /*             * Check for error that occurred inside the while loop, and break             * out of the for loop if there was one so other interrupts can             * be serviced.             */            if (Result == XST_SUCCESS)            {                /*                 * Make the callback to the upper layers, passing it the first                 * descriptor in the first packet and the number of descriptors                 * in the list.                 */                InstancePtr->SgSendHandler(InstancePtr->SgSendRef, BdHeadPtr,                                           NumBds);            }        } /* if (PacketsLeft) */        /*         * If the interrupt was an end-ack, check the descriptor list again to         * see if it is empty. If not, go ahead and restart the scatter-gather         * channel. This is to fix a possible race condition where, on transmit,         * the driver attempted to start a scatter-gather channel that was         * already started, which resulted in no action from the XDmaChannel         * component. But, just after the XDmaChannel component saw that the         * hardware was already started, the hardware stopped because it         * reached the end of the list.  In that case, this interrupt is         * generated and we can restart the hardware here.         */        if ((IntrStatus & XDC_IXR_SG_END_MASK) &&            ((InstancePtr->SendChannel).ActivePacketCount > 0) &&            ((InstancePtr->SendChannel).Committed == XTRUE))        {            /*             * Ignore the return status since we know the list exists and we             * don't care if the list is empty or the channel is already started.             */            (void)XDmaChannel_SgStart(&InstancePtr->SendChannel);            (InstancePtr->SendChannel).Committed = XFALSE;        }    }    /*     * All interrupts are handled (except the error below) so acknowledge     * (clear) the interrupts by writing the value read above back to the status     * register. The packet count interrupt must be acknowledged after the     * decrement, otherwise it will come right back. We clear the interrupts     * before we handle the error interrupt because the ErrorHandler should     * result in a reset, which clears the interrupt status register. So we     * don't want to toggle the interrupt back on by writing the interrupt     * status register with an old value after a reset.     */    XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus);    /*     * Check for DMA errors and call the error callback function if an error     * occurred (DMA bus or timeout error), which should result in a reset of     * the device by the upper layer software.     */    if (IntrStatus & XDC_IXR_DMA_ERROR_MASK)    {        InstancePtr->Stats.DmaErrors++;        InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);    }}/*****************************************************************************//*** Handle an interrupt from the Ethernet MAC when configured with scatter-gather* DMA. The only interrupts handled in this case are errors.** @param InstancePtr is a pointer to the XEmac instance to be worked on.** @return** None.** @note** None.*******************************************************************************/static void HandleEmacDmaIntr(XEmac *InstancePtr){    Xuint32 IntrStatus;    /*     * When configured with DMA, the EMAC generates interrupts only when errors     * occur. 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);    /*     * Check the MAC for errors     */    XEmac_CheckEmacError(InstancePtr, IntrStatus);}

⌨️ 快捷键说明

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