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

📄 net_nic.c

📁 Micrium专门针对AT91SAM7X256发布的网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    NIC_BUF_DESC  *searchPtr;


    n_rdy    = 0;
    searchPtr = NIC_RxBufDescPtrStart;

    while (searchPtr != NIC_RxBufDescPtrEnd) {
        if (((searchPtr->status & EMAC_RXBUF_EOF_MASK) > 0) &&
            ((searchPtr->addr & EMAC_RXBUF_SW_OWNED) > 0)) {
            n_rdy++;
        }
        searchPtr++;
    }

    return (n_rdy);
}

/*
---------------------------------------------------------------------------------------------------------
     THE FOLLOWING FUNCTIONS ARE CALLED FROM THE RX TASK DURING THE PROCESSING OF A SINGLE RX FRAME

The following functions are called in the order described below.

GetSize(), followed by (RxPkt(), OR RxPktDiscard())
---------------------------------------------------------------------------------------------------------
*/

/*
*********************************************************************************************************
*                                         NetNIC_RxPktGetSize()
*
* Description : Get network packet size from NIC.
*
* Argument(s) : none.
*
* Return(s)   : Size, in octets, of next frame to be read from the EMAC buffers
*
* Caller(s)   : NetIF_RxTaskHandler()
*
* Notes       : 1) On occassion, it is possible to have frame fragments in the descriptor list. As mentioned
*                  above in Note 1) of NIC_GetNRdy(), should 2 start of frame descriptors be found without
*                  corresponding EOF descriptors , then softwares must free the rogue descriptors. This
*                  function will free rogue descriptors if they are found while searching for the next
*                  frame and its corresponding size
*
*               2) This routine causes the TCP/IP stack to service received frames in a random order.
*                  In other words, frames that arrive before other frames are not guarrenteed to be
*                  serviced first. This is a result of always searching through the descriptor list from
*                  top to bottom, and not from an expected start point and wrapping around. The benefit to
*                  this approach however is that you dont have to keep state information about where the
*                  next expected SOF flag will be. Nor do you have check if the expected SOF pointer is
*                  correct and make changes should Note 1) effect the correctness of that pointer.
*
*               3) There MUST be at least 1 SOF / EOF combination in the descriptor list, otherwise
*                  interrupt generation would not have occured since interrupt generation takes place
*                  after the complete frame has been trasferred via DMA to RAM.
*********************************************************************************************************
*/

CPU_INT16U  NetNIC_RxPktGetSize (void)
{                                                                       /* WARNING: No code should never be inserted between a  */
    CPU_INT16U     size;                                                /* ptr increment, and the following end of list check   */
    NIC_BUF_DESC  *searchPtr;                                           /* This function contains several pointer increments    */


    NIC_CurrentFrameStart  =  NULL;                                     /* Initialize the Current Frame Start pointer to NULL   */
    NIC_CurrentFrameEnd    =  NULL;                                     /* Initialize the Current Frame Start pointer to NULL   */

    searchPtr              =  NIC_ExpectedFrameStart;                   /* Begin searching from the expected SOF descriptor     */

    while (((searchPtr->status & EMAC_RXBUF_SOF_MASK) == 0) ||          /* While the expected SOF is NOT pointing to a software */
           ((searchPtr->addr   & EMAC_RXBUF_SW_OWNED) == 0)) {          /* owned SOF descriptor (precautionary code)            */
        searchPtr++;                                                    /* Move the next descriptor in the list                 */

        if (searchPtr     ==  NIC_RxBufDescPtrEnd) {                    /* If we are at the end of the list                     */
            searchPtr      =  NIC_RxBufDescPtrStart;                    /* Wrap around to the beginning                         */
        }
    }
                                                                        /* We now point to a SOF desc that software ownes       */
    NIC_CurrentFrameStart  =  searchPtr;                                /* Save the location of the SOF descriptor              */

    while (((searchPtr->status & EMAC_RXBUF_EOF_MASK) == 0) ||          /* Loop until we find the matching EOF descriptor       */
           ((searchPtr->addr   & EMAC_RXBUF_SW_OWNED) == 0)) {          /* that is software owned                               */
            searchPtr++;

        if (searchPtr     ==  NIC_RxBufDescPtrEnd) {                    /* If we are at the end of the list                     */
            searchPtr      =  NIC_RxBufDescPtrStart;                    /* Wrap around to the beginning                         */
        }

        if (((searchPtr->status & EMAC_RXBUF_SOF_MASK)  > 0) &&         /* If while searching for EOF we find another SW owned  */
            ((searchPtr->addr   & EMAC_RXBUF_SW_OWNED)  > 0)) {         /* SOF, then we must free the incomplete frame desc's   */
            while (NIC_CurrentFrameStart != searchPtr) {                /* Loop from the last found SOF, to the newly found SOF */
                NIC_CurrentFrameStart->addr &= ~EMAC_RXBUF_SW_OWNED;    /* Free a descriptor belonging to the incomplete frame  */
                NIC_CurrentFrameStart++;                                /* Point to the next descriptor that needs to be freed  */
                if (NIC_CurrentFrameStart ==  NIC_RxBufDescPtrEnd) {    /* If we are at the end of the descriptor list          */
                    NIC_CurrentFrameStart  =  NIC_RxBufDescPtrStart;    /* Wrap around to the beginning of the list             */
                }
            }
                                                                        /* Done freeing incomplete frame descriptors            */
            NIC_CurrentFrameStart          =  searchPtr;                /* However, we must now save the new SOF location       */
        }
    }
                                                                        /* We now point to a SW owned  EOF descriptor           */
    NIC_CurrentFrameEnd    =  searchPtr;                                /* Save the location of the EOF descriptor              */

    NIC_ExpectedFrameStart = (searchPtr + 1);                           /* The next expected SOF is in the next descriptor      */
                                                                        /* We store this information now to improve search      */
                                                                        /* performance on the next NetNIC_RxPktGetSize()        */

    if (NIC_ExpectedFrameStart == NIC_RxBufDescPtrEnd) {                /* If the next expected frame points after the end of   */
        NIC_ExpectedFrameStart  = NIC_RxBufDescPtrStart;                /* the list, wrap back around to the beginning          */
    }
                                                                        /* Retrieve the frame size for the frame to be read     */
                                                                        /* next from the buffers using the 'Current' pointers   */
    size                   =  NIC_CurrentFrameEnd->status & EMAC_RXBUF_LEN_MASK;

    return (size);
}

/*
*********************************************************************************************************
*                                            NetNIC_RxPkt()
*
* Description : Read network packet from NIC into buffer.
*
* Argument(s) : ppkt        Pointer to memory buffer to receive NIC packet.
*
*               size        Number of packet frame octets to read into buffer.
*
*               perr        Pointer to variable that will hold the return error code from this function :
*
*                               NET_NIC_ERR_NONE            Packet successfully read.
*                               NET_ERR_INIT_INCOMPLETE     Network initialization NOT complete.
*                               NET_NIC_ERR_NULL_PTR        Argument 'ppkt' passed a NULL pointer.
*                               NET_NIC_ERR_INVALID_SIZE    Invalid size.
*
* Return(s)   : none.
*
* Caller(s)   : NetIF_RxTaskHandler().
*
* Note(s)     : 1) NetNIC_RxPkt() blocked until network initialization completes; perform NO action.
*********************************************************************************************************
*/

void  NetNIC_RxPkt (void        *ppkt,
                    CPU_INT16U   size,
                    NET_ERR     *perr)
{
#if (NET_CTR_CFG_STAT_EN     == DEF_ENABLED)
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR   cpu_sr;
#endif
#endif


    if (Net_InitDone != DEF_YES) {                                      /* If init NOT complete, exit rx (see Note #2).         */
       *perr = NET_ERR_INIT_INCOMPLETE;
        return;
    }

#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)                         /* ------------------- VALIDATE PTR ------------------  */
    if (ppkt == (void *)0) {
       *perr = NET_NIC_ERR_NULL_PTR;
        return;
    }

                                                                        /* ------------------- VALIDATE SIZE -----------------  */
    if (size < NET_IF_FRAME_MIN_SIZE) {
       *perr = NET_NIC_ERR_INVALID_SIZE;
        return;
    }
#endif

    EMAC_RxPkt(ppkt, size, perr);                                       /* Read the received Frame from the EMAC buffers        */
    if (*perr != NET_NIC_ERR_NONE) {
        return;
    }

    NET_CTR_STAT_INC(NetNIC_StatRxPktCtr);

    *perr = NET_NIC_ERR_NONE;
}

/*
*********************************************************************************************************
*                                        EMAC_RxPkt()
*
* Description : (1) Read network packet from NIC into buffer :
*                   (a) Read received frame from AT91SAM7X256 DMA memory space.
*                   (b) Release descriptors once data has been read
*
* Argument(s) : ppkt        Pointer to memory buffer to receive NIC packet.
*               ----        Argument checked in NetNIC_RxPkt().
*
*               size        Number of packet frame octets to read into buffer.
*               ----        Argument checked in NetNIC_RxPkt().
*
*               perr        Pointer to variable that will hold the return error code from this function :
*
*                               NET_NIC_ERR_NONE                Packet successfully transmitted.
*                               NET_ERR_RX                      Error Reading Buffers (EOF not found)
*
* Return(s)   : none.
*
* Caller(s)   : NetNIC_RxPkt().
*
* Note(s)     : 1) See 'AT91SAM7X256 EMAC RECEIVE BUFFER DESCRIPTOR' for packet frame format.
*               2) Operational Description:
*                   a) If we are operating on a descriptor that is both SOF and EOF, we only
*                      execute the code below the while loop.
*
*                   b) If the received frame is contained in 2 descriptors, we ONLY execute the
*                      outside 'if' block within the while loop, AND, the code below the while loop.
*
*                   c) If the received frame fills 3 or more descriptors, we first execute code
*                      within the outside 'if' statement if the while loop once, followed by
*                      (numberOfFilledDescriptors - 1) iterations of the outside 'else' block
*                      within the while loop, and for the very last descriptor, the code below
*                      the while loop.
*********************************************************************************************************
*/

static  void  EMAC_RxPkt (void        *ppkt,
                          CPU_INT16U   size,
                          NET_ERR     *perr)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR       cpu_sr;
#endif
    CPU_INT16U    sizeLeftToCopy;
    CPU_INT08U    dataOffset;
    CPU_INT08U   *pStackBuf;
    CPU_INT08U   *pEMACBuf;
    NIC_BUF_DESC *searchPtr;
    CPU_BOOLEAN   doMemCpy;


   *perr               =  NET_NIC_ERR_NONE;                             /* Begin with no error code being returned              */

    doMemCpy           =  TRUE;                                         /* Error Control. If an error occurs, we can stop       */
                                                                        /* performing mem copies, will still executing the loop */
                                                                        /* freeing the remaining descriptors without            */
                                                                        /* accidently overwriting other memory                  */

    sizeLeftToCopy     =  size;                                         /* Make a copy of size for debugging purposes           */
    searchPtr          =  NIC_CurrentFrameStart;                        /* Point to the SOF descriptor. Start copy from here    */
    pStackBuf          = (CPU_INT08U *)ppkt;                            /* Point to the TCP/IP stacks buffer, copy into here    */

                                                                        /* Determine the data offset for the first descriptor   */
    dataOffset         = (searchPtr->status & EMAC_RXBUF_OFF_MASK) >> 12;

    while (searchPtr  !=  NIC_CurrentFrameEnd) {                        /* Copy from SOF to EOF descriptor (EOF not inclusive)  */
                                                                        /* Get the address of the buffer we wish to copy        */
        pEMACBuf       = (CPU_INT08U *)((searchPtr->addr & EMAC_RXBUF_ADDRESS_MASK));		

        if (searchPtr ==  NIC_CurrentFrameStart) {                      /* If its the SOF, include the offset in the copy size  */
            if (doMemCpy == TRUE) {
                Mem_Copy((void *)(pStackBuf), (void *)(pEMACBuf + dataOffset), NIC_RX_BUF_SIZE - dataOffset);
                pStackBuf += (NIC_RX_BUF_SIZE - dataOffset);            /* Advance the pointer into the TCP/IP stacks buffer    */
            }
            if ((sizeLeftToCopy - NIC_RX_BUF_SIZE - dataOffset) >= 0) { /* Subtract the amount copied from the total left       */

⌨️ 快捷键说明

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