if_mcf5272.c

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

C
1,887
字号

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


    /*   Set the flag to indicate that the device is up and running.        */

    PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_UP;

}

/*      A routine to halt the FEC.                                          */
static void
MCF5272_fec_stop(struct eth_drv_sc *sc)
{

    /*   Stop the packet transmission gracefully.                           */

    /*   Set the Graceful Transmit Stop bit.                                */

    put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr)
                                   | MCF5272_FEC_TCR_GTS);

    /*   Wait for the current transmission to complete.                     */

    while( !(get_reg(MCF5272_SIM->enet.eir) & MCF5272_FEC_EIR_GRA));

    /*   Clear the GRA event.                                               */

    put_reg(MCF5272_SIM->enet.eir, MCF5272_FEC_EIR_GRA);

    /*   Disable all FEC interrupts by clearing the IMR register.           */

    put_reg(MCF5272_SIM->enet.eimr,  0);

    /*   Clear the GTS bit so frames can be tranmitted when restarted       */

    put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr) &
                                   ~MCF5272_FEC_TCR_GTS);

    /*   Set the Ethernet control register to zero to disable the FEC.      */

    put_reg(MCF5272_SIM->enet.ecr, 0);

    /*   Deliver any pending frames and acknowledge any transmitted frames.   */

    MCF5272_fec_deliver(sc);

    /*   Set the flag to indicate that the device is down.                  */

    PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN;

}

/*      This routine is called to perform special "control" opertions.       */

static int
MCF5272_fec_control(struct eth_drv_sc *sc, unsigned long key,
                    void *data, int data_length)
{
    switch (key)
    {

    case ETH_DRV_SET_MAC_ADDRESS:

        {
            /*   Set the hardware address of the Ethernet controller.       */

            struct ifreq* p_ifreq = data;

            /*   If the length of the strcutre is not equal to the size  of */
            /* ifreq, then exit with an error.                              */

            if (data_length != sizeof(*p_ifreq))
            {
                return 0;
            }

            /*   Set the lower 4-byte address.                              */

            put_reg(MCF5272_SIM->enet.malr,0
                            		       | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[0] <<24)
                            		       | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[1] <<16)	
                            		       | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[2] <<8)
                            		       | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[3] <<0));

            /*   Set the upper 2-byte address.                              */

            put_reg(MCF5272_SIM->enet.maur,
                                           0
                            		       | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[4] <<24)
                            		       | (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[5] <<16));


            /*   Return 1 to indicate  that  programming  of  the  new  MAC */
            /* address is successful.                                       */

            return 1;
        }


        break;
    #ifdef CYGPKG_NET

    case ETH_DRV_GET_IF_STATS:
    case ETH_DRV_GET_IF_STATS_UD:

        #if 0
        {

            struct ether_drv_stats* pstats = (struct ether_drv_stats*)
                                                data;
            MCF5272_FEC_DIAG diag;

            /* Retrieve the driver defined diagnostic structure. */
            MCF5272_get_stats(sc, &diag);

            strcpy(pstats->description, ether_device_name);
            pstats->duplex = ETH_MODE_UNKNWON;
            pstats->operational = (unsigned char )PMCF5272_FEC_DATA(sc)->operational;
            pstats->speed = 0;

            /*   Translate the device specific  diagnostic  values  to  the */
            /* generic ether_drv_stats values.                              */

            /* Get the receive bytes count. */
            pstats->rx_count = diag.rx_bytes_cnt;

            /* Get the number of successful packet received. */
            pstats->rx_good = diag.rx_pk_cnt;

            /* Get the receive CRC error count. */
            pstats->rx_crc_errors = diag.rx_crc_err_cnt;

            /* Get the receive overrun error count. */
            pstats->rx_overrun_errors = diag.rx_overrun_err_cnt;

            /* Get the received short frame error count. */
            pstats->rx_short_frames = diag.rx_short_frm_err_cnt;

            /* Get the received long frame error count. */
            pstats->rx_too_long_frames = diag.rx_long_frm_err_cnt;

            /* Get the number of transmitted bytes. */
            pstats->tx_count = diag.tx_bytes_cnt;

            /* Get the number of defered packets. */
            pstats->tx_deferred = diag.tx_def_cnt;

            /* The number of successfully transmitted packets. */
            pstats->tx_good = diag.tx_pk_cnt;

            /* Get the transmit late collision count. */
            pstats->tx_late_collisions = diag.tx_late_col_cnt;

            /* Get the transmit underrun count. */
            pstats->tx_underrun = diag.tx_underrun_cnt;

            /* Get the transmit late collision count. */
            pstats->tx_total_collisions = diag.tx_late_col_cnt;
            return 1;
        }
        #else
        {

            /*   Copy the ethernet name device over.                        */

            strcpy(((struct mcf5272_ether_drv_stats*)data)->description,
                   ether_device_name);

            /* Get the stats. */
            MCF5272_get_stats(sc,
                              &((struct mcf5272_ether_drv_stats*)data)->stats);

            /* Copy the mode over. */

            ((struct mcf5272_ether_drv_stats*)data)->duplex =
                PMCF5272_FEC_DATA(sc)->duplex;

            /* The ethernet driver is operational. */

            ((struct mcf5272_ether_drv_stats*)data)->operational =
                PMCF5272_FEC_DATA(sc)->operational;

            /*   Copy the speed over.                                       */

            ((struct mcf5272_ether_drv_stats*)data)->speed =
                PMCF5272_FEC_DATA(sc)->speed;

            return 1;
        }

        #endif
        break;

    #endif /* CYGPKG_NET */
    default:
        return 1;
        break;
    }

}


/*      This routine is  called to see  if it is  possible to send  another */
/* packet.  It will  return  non-zero  if  a  transmit  is  possible,  zero */
/* otherwise.                                                               */

static int
MCF5272_fec_can_send(struct eth_drv_sc *sc)
{
    const int buffer_window = 5; /* Specifies the minimum empty buffer descrpitors */

    if ((NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd) > buffer_window)
    {
        return 1;
    }
    else
    {
        PMCF5272_FEC_DATA(sc)->diag_counters.tx_full_cnt++;
        return 0;
    }
}


/*      This routine is called  by eCos  to send  a frame  to the  ethernet */
/* controller.                                                              */

static void
MCF5272_fec_send(struct eth_drv_sc *sc,
                 struct eth_drv_sg *sg_list,
                 int sg_len,
                 int total_len,
                 unsigned long key)
{

    /*   Call eth_tx_check() routine for any packet transmitted by eCos.    */

    eth_tx_check(sg_list, sg_len);


    /*   If   we   do   have   enough    buffer    to    send    we    call */
    /* MCF5272_fec_common_send routine to send  the packet.  Otherwise,  we */
    /* throw away the packet and call eCos's tx_done rutine to notify  that */
    /* the packet has been sent.                                            */

    if (NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd > sg_len)
    {
        MCF5272_fec_common_send(sc, sg_list, sg_len, total_len, key, TX_KEY_ECOS);


    }
    else
    {

        CYG_ASSERT(false, "ETH: Send buffer full");

        /*   Inform the upper layer of a completion of the packet.          */

        (sc->funs->eth_drv->tx_done)(sc,
                                     key,
                                     0);
    }

}

/*      This routine is called to send a frame to the ethernet  controller. */
/* This is a generic send routine.                                          */
/*

  INPUT:
    sc - Ethernet driver sc.
    sg_glist - scatter gather list.
    sg_len - The number of scattter gather entries in the list.
    total_len - The total length of the frame.

*/


static void
MCF5272_fec_common_send(struct eth_drv_sc *sc,
                        struct eth_drv_sg *sg_list,
                        int sg_len,
                        int total_len,
                        unsigned long key,
                        tx_key_type_t key_type)
{
    int i = 0;
    NBUF *pBD = NULL;
    NBUF *first_bd;
    buf_info_t* p_buf = PBUF_INFO(sc);


    CYG_ASSERT(sg_len > 0,  "ETH: sg_len cannot be zero");


    /* Update the number of used transmitted buffer desciptors. */

    p_buf->num_busy_bd += sg_len;

    /*   Keep  track  of  the  maximum  number  of  busy  transmit   buffer */
    /* descriptors.                                                         */

    if (p_buf->num_busy_bd > p_buf->max_num_busy_bd)
    {
        p_buf->max_num_busy_bd = p_buf->num_busy_bd;
    }

    /*   Enqueue the key, the index to first and last buffer desriptor, the */
    /* number of  buffer descriptors,  the packet  length and  the type  of */
    /* packet to the transmit queue.                                        */

    nbuf_enq_tx_key(p_buf, (p_buf->iTxbd + sg_len - 1) % NUM_TXBDS,
                    key,
                    p_buf->iTxbd,
                    sg_len,
                    total_len,
                    key_type);

    /*   Get the pointer to the first buffer descriptor of the packet.   We */
    /* don't set the R bit for the first packet until we have allocated and */
    /* initialized all the buffer descriptors.                              */

    first_bd = pBD = nbuf_tx_allocate(p_buf);

    do
    {

        CYG_ASSERT(pBD != NULL, "ETH: nbuf_tx_allocate() returned NULL");


        /*   Copy the address of the buffer and the length to the allocated */
        /* buffer descriptor.  Note that  buf_index indexes  to the  buffer */
        /* descriptor it returns.                                           */

        pBD->data = (uint8*)sg_list[i].buf;
        pBD->length = sg_list[i].len;

        if (i == sg_len - 1)
        {

            /*   Set the the L,  TC and R bit  to indicate that the  buffer */
            /* descriptor  is  the  last  buffer  descriptor,  the  CRC  is */
            /* appended by the FEC and  the buffer descriptor is ready  for */
            /* transmission.                                                */

            pBD->status |= TX_BD_L | TX_BD_TC | TX_BD_R;

            /*   When we have  reached the  last buffer  scatther list,  we */
            /* break from the loop.                                         */

            break;

        }
        else
        {

            if (i)
            {

                /*   If the buffer  descriptor  is  not  the  first  buffer */
                /* descriptor, then set the  R bit to  notify the FEC  that */
                /* the buffer descriptor is  read  for  transmission.   FEC */
                /* must reset R bit after transmitted for buffer.           */

    	        pBD->status |= TX_BD_R;

            }

            /*   Allocate the next buffer descriptor.                       */

            pBD = nbuf_tx_allocate(p_buf);

        }

        /*   Advance to the next index.                                     */

        i++;

⌨️ 快捷键说明

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