if_mcf5272.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,887 行 · 第 1/5 页

C
1,887
字号
    }while(1);

    /*   Set the R bit in the first buffer descriptor to indicate that  the */
    /* buffer is ready for transmission if  there are more than one  buffer */
    /* descriptors.                                                         */

    if (sg_len > 1)
        first_bd->status  |= TX_BD_R;

    /*   Indicate that there is a transmit buffer ready.                    */

    put_reg(MCF5272_SIM->enet.tdar, 1);

}


/*      This function is called  as a result  of the "eth_drv_recv()"  call */
/* above.  It's job is to  actually  fetch  data  for  a  packet  from  the */
/* hardware once memory buffers have  been allocated for the packet.   Note */
/* that the buffers may come in pieces, using a scatter-gather list.   This */
/* allows for more efficient processing in the upper layers of the stack.   */

/*      Note that the  total buffer allocated  for the scatter-gather  list */
/* can be smaller than the packet or the buffer that in the scatter  gather */
/* list is invalid.  This happens when  the upper layer driver runs out  of */
/* buffers for the scatter-gather list.                                     */

static void
MCF5272_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
{	
    uint_t fill_count = 0, buf_count;
    uint_t frame_length = 0, buf_len;
    NBUF *pNbuf = NULL;
    cyg_uint8* buf = NULL;
    cyg_bool_t done = false;
    uint_t sg_index = 0;

    /*   If the scatter-gather list is zero,  set buf to NULL so that  this */
    /* routine would not copy the buffer to the scatter-gatther buffer.     */

    if (sg_len > 0)
    {
        buf = (cyg_uint8*)sg_list[0].buf;
    }

    do
    {

        /*   Get the next buffer descriptor (bd).                           */

        pNbuf = nbuf_rx_get_next(PBUF_INFO(sc));

        CYG_ASSERT(pNbuf != NULL, "Cannot get the next bd");

        if (pNbuf->status & TX_BD_L)
        {

            /*   Calculate the remaining numer of bytes in the packet  that */
            /* needed to be copied out since  the the length of the in  the */
            /* last BD contains the total length of the packet and not  the */
            /* length of the buffer.                                        */

            buf_len = (uint_t)pNbuf->length - frame_length;

            /*   Since the last bd, set done  to true in order to exit  the */
            /* loop.                                                        */

            done = true;
        }
        else
        {
            buf_len = RX_BUFFER_SIZE;

            /*   Update the frame length.                                   */

            frame_length += RX_BUFFER_SIZE;
        }


       /*   Copy the packet to the scatter gather list if there is a buffer */
       /* to copy the packet to.                                            */

       for (buf_count = 0; buf_count < buf_len && buf != NULL;)
       {

           uint_t copy_len;

           /*   Retrieve the minimum copy length.  We basically copy  based */
           /* on the smaller size: the buffer from the scatther list or the */
           /* from the buffer descriptor.                                   */

           copy_len =  (((uint_t)sg_list[sg_index].len - fill_count) <
                        (buf_len - buf_count) ?
                        (uint_t)sg_list[sg_index].len - fill_count :
                        (buf_len - buf_count));

           /*   Copy the buffer to the upper layer driver buffer.           */

           memcpy(&buf[fill_count],
                  &pNbuf->data[buf_count],
                  copy_len);

           /*   Update the counts to reflect the number of bytes copied.    */

           fill_count += copy_len;
           buf_count += copy_len;

           /*   If the buffer  in  the  scatter-gather  list  is  full,  we */
           /* attempt to retrieve the next buffer in the list.              */

           if (fill_count >= sg_list[sg_index].len)
           {

               /*   If there is no more  buffer, set  the buf  to NULL  and */
               /* exit the loop.                                            */

               if (++sg_index >= sg_len)
               {
                   buf = NULL;
                   break;
               }
               else
               {
                   buf = (cyg_uint8*)sg_list[sg_index].buf;
                   fill_count = 0;
               }
           }
       }


       /*   Release the buffer scriotor so it cab be used to receive  other */
       /* packets.                                                          */

        nbuf_rx_release(pNbuf);

    }while(done == false);

    /*   Notify the FEC that there are receive buffer descriptors available */
    /* for the FEC.                                                         */

    put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
}

/*******************************************************************************
MCF5252_fec_recv_handler() - Receive handler to read the received
buffer descriptors and inform the upper layer driver of the arrival
of the packet.
*/
inline static
bool MCF5252_fec_recv_handler(struct eth_drv_sc * sc)
{

    /*   Receive interrupt has occurred informing  driver that a frame  has */
    /* been written to the buffer.                                          */

    NBUF* pNBuf;
    buf_info_t* p_buf_info = PBUF_INFO(sc);
    MCF5272_fec_priv_data_t* eth_data = PMCF5272_FEC_DATA(sc);
    uint_t len;

    /*   Pointer to the first buffer descriptor.                            */

    NBUF* p_first_bd;

    /*   Check to see if the buffer descrpitor is not busy.                 */

    if  (nbuf_rx_next_ready(p_buf_info))
    {

        /*   Flag that indicates whether the buffer is wrapped.             */

        cyg_bool_t wrap = false;

        /*   Get the index of the buffer desrciptor of the next frame.       */

        uint_t index = nbuf_rx_get_index(p_buf_info);
        cyg_bool_t error = false;
        len = 0;

        /* Get the pointer to the first buffer descriptor. */

        p_first_bd = nbuf_rx_get(p_buf_info, index);

        do
        {
            pNBuf = nbuf_rx_get(p_buf_info, index);

            if (pNBuf->status & RX_BD_E)
            {

                /*   The buffer is empty or the FEC is stll writing to  the */
                /* buffer.  then exit.                                      */

                return false;

            }

            /*   Advance the index  to the  next buffer  descriptor in  the */
            /* ring buffer.                                                 */

            index = (index + 1) % NUM_RXBDS;

            if ((pNBuf->status & (RX_BD_L | RX_BD_W)) == RX_BD_W)
            {

                /*   If the buffer descriptor wraps, set the wrap flag  and */
                /* initalize  the  index  pointer   to  the  first   buffer */
                /* descriptor in the ring.                                  */

                wrap = true;

            }

            if (pNBuf->status & RX_BD_TR)
            {

                /*   Packet truncate count.                                 */

                eth_data->diag_counters.rx_trunc_error_cnt++;

                /*   Release the bds.                                       */

                nbuf_rx_release_pkt(p_buf_info);

                /*   Update the receive error count.                        */

                eth_data->diag_counters.rx_err_cnt++;

                /*   Notify  the  FEC   that  there   are  receive   buffer */
                /* descriptors available from the FEC.                      */

                put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);

                error = true;
                break;
            }

            if (pNBuf->status & RX_BD_L)
            {

                /*   Get the length of frame contain in the buffers.        */

                len = pNBuf->length;

                /*   If there is an  error  in  receiving  the  packet,  we */
                /* proceed to update the counters.  Otherwise, we just fall */
                /* through.                                                 */

                if (pNBuf->status & (RX_BD_LG | RX_BD_SH | RX_BD_CR |
                                     RX_BD_OV))
                {

                    /*   Update the diagnostic counters.                    */

                    if (pNBuf->status & RX_BD_LG)
                    {
                        /* Larget frame error count. */
                        eth_data->diag_counters.rx_long_frm_err_cnt++;
                    }

                    if (pNBuf->status & RX_BD_SH)
                    {
                        /* Short  frame error count. */
                        eth_data->diag_counters.rx_short_frm_err_cnt++;
                    }

                    if (pNBuf->status & RX_BD_CR)
                    {
                        /* CRC error count. */
                        eth_data->diag_counters.rx_crc_err_cnt++;
                    }

                    if (pNBuf->status & RX_BD_OV)
                    {
                        /* Overrun error count. */
                        eth_data->diag_counters.rx_overrun_err_cnt++;
                    }

                    /*   Release the packet.                                */

                    nbuf_rx_release_pkt(p_buf_info);

                    /*   Update the receive error count.                    */

                    eth_data->diag_counters.rx_err_cnt++;

                    /*   Notify the  FEC  that  there  are  receive  buffer */
                    /* descriptors available for the FEC                    */

                    put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);

                    /*   Set the error flag to true to indicate that  there */
                    /* is an error.                                         */

                    error = true;

                }
            }
        }while(!(pNBuf->status & RX_BD_L));

        if (error == false)
        {
            cyg_uint8* buf_ptr =  p_first_bd->data;

            /*   Since there is no error,  we  update  the  good  statistic */
            /* counters.                                                    */

            /*   Update the number of frames received.                      */

            eth_data->diag_counters.rx_pk_cnt++;

            /*   Update the number of bytes in the frame received.          */

            /*   Subract  4  bytes  from  the  length  because  the  packet */
            /* includes the 4-byte FCS.                                     */

            eth_data->diag_counters.rx_bytes_cnt += (len - 4);


            /*   If the  packet  wraps  then  copy  the  packet  to  the  a */
            /* temporary buffer in  order  to  make  the  packet  contigous */
            /* packet in memory.                                            */

            if (wrap)
            {

                uint_t count_len = 0;
                uint_t pk_len;

                /*   Set p_buf the pointer to temporary packet biffer which */
                /* we will use to copy the packet.                          */

                u8_t* p_buf =  (u8_t*)&eth_data->pkt_buf;

                /* Get the index of the buffer desrcitor of the next frame. */

                uint_t index = nbuf_rx_get_index(p_buf_info);

                do
                {

                    /*   Get the buffer descriptor.                         */

                    pNBuf = nbuf_rx_get(p_buf_info, index);

                    /*   Calculate the  length of  the data  in the  buffer */
                    /* descriptor.  If we reach the last buffer descriptor, */
                    /* the  the  actual  data  size  in  the  last   buffer */
                    /* descriptor is  the number  of bytes  we have  copied */
                    /* less from the value of the length field of the  last */
                    /* buffer descriptor.                                   */

                    if (pNBuf->status & RX_BD_L)
                    {
                        pk_len = len - count_len;
                    }
                    else
                    {
                        pk_len = RX_BUFFER_SIZE;
                    }

                    /*   Copy the content of  the buffer  to the  temporary */
                    /* packet buffer.                                       */

                    memcpy(&p_buf[count_len], pNBuf->data, pk_len);


                    /*   Keep count of  the number of  bytes read from  the */
                    /* buffer descriptor.                                   */

                    count_len += pk_len;

                    /*   Advance to the to next buffer descriptor.          */

                    index = (index + 1) % NUM_RXBDS;

                }while(!(pNBuf->status & RX_BD_L));

⌨️ 快捷键说明

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