if_mcf5272.c

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

C
1,887
字号

/*      This routine updates the Ethernet statistics counters.  This method */
/* is called by eCos every second.                                          */

static void one_second_alarm_func(cyg_handle_t alarm, cyg_addrword_t data)
{
    #define WRAP_SUBTRACT(_VAL1_,_VAL2_) \
        ({unsigned long val;if (_VAL1_ >= _VAL2_) val = _VAL1_ - _VAL2_; \
         else val=(0-_VAL2_)+_VAL1_; val;})

    ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt_sec =
        WRAP_SUBTRACT(
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt,
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_bytes_cnt);

    ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt_sec =
        WRAP_SUBTRACT(
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt,
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_bytes_cnt);

    ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt_sec =
        WRAP_SUBTRACT(
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt,
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_pk_cnt);

    ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt_sec =
        WRAP_SUBTRACT(
            ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt,
            ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_pk_cnt);


    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_bytes_cnt =
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_bytes_cnt;
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_bytes_cnt =
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_bytes_cnt;
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_rx_pk_cnt =
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.rx_pk_cnt;
    ((MCF5272_fec_priv_data_t*)data)->diag_info_sup.old_tx_pk_cnt =
        ((MCF5272_fec_priv_data_t*)data)->diag_counters.tx_pk_cnt;
}

/*      Retrieve the stats information.                                     */

void MCF5272_get_stats(struct eth_drv_sc *sc, MCF5272_FEC_DIAG* stats)
{
    memcpy(stats, &PMCF5272_FEC_DATA(sc)->diag_counters,
           sizeof (MCF5272_FEC_DIAG));

    /*   Retrieve the  number  of  available  buffer  descriptors  and  the */
    /* minimum value.                                                       */

    PMCF5272_FEC_DATA(sc)->diag_counters.tx_free_bd_cnt =
        NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd;
    PMCF5272_FEC_DATA(sc)->diag_counters.tx_free_min_bd_cnt =
        NUM_TXBDS - PBUF_INFO(sc)->max_num_busy_bd;
}


/*****************************************************************************

     The following  functions  provide  an  interface  directly  to  the
ethernet driver for applications that wish to circumvent the IP stack.

     Applications that wish  to take advantage  of this should  override
these routine with their own.  Leaving these routines as default  routes
all data through the IP stack.

*****************************************************************************/

/*****************************************************************************
eth_rx_pkt_filter -- Ethernet receive packet filter

     This is an ethernet packet filter function that allows the application
to receive raw ethernet frames from  the driver.  The return value of  this
function determines whether or not to pass the packet to the IP stack.

     We declare it weak so that other routine can override it.

INPUT:

     pkt: Pointer to the packet.

     pkt_len: The length of  the packet including  all headers, the  32-bit
Ethernet CRC, and any Ethernet frame padding.

OUTPUT:

RETURN VALUE:

     true: Do not send the packet to the IP stack.

     false: Send the packet to the IP stack.

*****************************************************************************/
int_t eth_rx_pkt_filter(u8_t * pkt, uint_t pkt_len)
{

    /*   Always return false by default. */

    return false;
}

/*****************************************************************************
eth_tx_check -- Watch transmitting Ethernet packets

     The driver calls this routine before transmitting packets from  the
IP stack.  It provides a hook for applications to watch all packets that
the IP stack transmits.

     We declare it weak so that other routine can override it.

INPUT:

     sg_list: Pointer to the scatter-gather list.

     sg_len: The number of scatter-gather entries in the list.

OUTPUT:

RETURN VALUE:

     None

*****************************************************************************/
void eth_tx_check(struct eth_drv_sg * sg_list, unsigned int sg_len)
{

    /*   Do nothing by default.                                             */

}

/*****************************************************************************
eth_send -- Transmit a raw Ethernet packet

     This function sends  a  packet  to  the  Ethernet  controller  thus
passing the eCos IP stack.

     Note that the application must reuse the buffer parameters to  this
function until the driver releases  the buffer with the  eth_send_done()
function.

INPUT:

     sg_list: Pointer to the scatter-gather list to send.

     sg_len: The size of the scatter-gather list.

     tag: A value  that  we  pass  as  a  parameter  to  eth_send_done()
function when the FEC has completed sending the packet.

OUTPUT:

RETURN VALUE:

     true: if the packet is  successfully queued to the device  driver's
queue.

     false : If the routine fails to send the packet.

*****************************************************************************/
int_t eth_send(struct eth_drv_sg* sg_list, unsigned int sg_len,
              int total_len,
              unsigned long tag)
{
    int_t success;
    cyg_uint32 s;

    s = cyg_splsoftnet();

    /*   If there is enough  buffer  descriptors,  then  send  the  packet. */
    /* Otherwise, throw the packet away and return a false value.           */

    if (NUM_TXBDS - PBUF_INFO(&MCF5272_fec_sc)->num_busy_bd > sg_len)
    {

        /*   Call the common send routine to send the packet.               */

        MCF5272_fec_common_send(&MCF5272_fec_sc,
                                sg_list,
                                sg_len,
                                total_len,
                                tag,
                                TX_KEY_USER);

        success = true;
    }
    else
    {

        /*   Fail to send the packet.                                       */

        success = false;
    }

    /*   Release the Ethernet driver lock.                                  */

    cyg_splx(s);

    return success;
}

/*****************************************************************************
eth_send_done -- eth_send callback

     The driver calls this  function when  it has  sent out  the packet.   The
parameter tag is the same  value as the  tag value when  the caller calls  the
eth_send to send the packet.

     We declare it weak so that other routine can override it.

INPUT:

     tag: A value  that  we  pass  as  a  parameter  to  eth_send_done()
function when the FEC has completed sending the packet.

OUTPUT:

RETURN VALUE:

     None

*****************************************************************************/
void eth_send_done(unsigned long tag)
{

}


#if 0


/* Defined Ethernet Frame Types */
#define FRAME_IP	(0x0800)
#define FRAME_ARP	(0x0806)
#define FRAME_RARP	(0x8035)

/* Offset and size of protocol headers */
#define ETH_HDR_OFFSET	0	/* Ethernet header at the top of the frame */
#define ETH_HDR_SIZE	14

/* Assign a protocol number for the loop test */
static uint16 eth_type = 0x0300;

/* Global variable containing length of data to transmit */
static uint16 data_length = 512;

/* Transmit data size of each transmti buffer descriptor. */

#define TX_BUFFER_SIZE (576)	/* must be divisible by 16 */


void
fec_start_loopback_test(void)
{
    /* Initalize the buffer descriptors. */

    nbuf_init(&MCF5272_fec_priv_data.nbuffer);

    /* Initalize the Ethernet controllder device. */

    MCF5272_fec_init(&MCF5272_fec_netdev);


}

/********************************************************************/
static void
loop_fill_buffers(void)
{
	/* Fill all the buffers in the TX buffer ring with a unique data pattern */
	uint16 index, pattern, i;
    static unsigned char output_buffer[NUM_TXBDS][TX_BUFFER_SIZE];


    uint_t data_length = TX_BUFFER_SIZE;

	for (i = 0; i < NUM_TXBDS; i++)
	{

        MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data = output_buffer[i];
		switch (i % 8)
		{
			/* Load buffers 0 through 3 with a single data patterns */
			case (0):
				memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0x55,data_length);
				break;	
			case (1):
				memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0xAA,data_length);
				break;
			case (2):
				memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0x00,data_length);
				break;
			case (3):
				memset(&MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[ETH_HDR_SIZE],0xFF,data_length);
				break;

			/* Buffer[4]: Load increasing walking ones */
			case (4):
				pattern = 1;
				for (index = 0; index < data_length; index++)
				{
					if (pattern == 0x0100)
						pattern = 0x01;	
					MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)pattern;
					pattern <<= 1;
				}
				break;
			
			/* Buffer[5]: Load decreasing walking ones */
			case(5):
				pattern = 0x80;
				for (index = 0; index < data_length; index++)
				{
					if (pattern == 0x00)
						pattern = 0x80;
					MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)pattern;
					pattern >>= 1;
				}		
				break;

			/* Buffer[6]: Load "Increment from 0" pattern */
			case (6):
				for (index = 0; index < data_length; index++)
					MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8) ((index-14)%256);
				break;
			
			/* Buffer[7]: Load "Decrement from 255" pattern */
			case (7):
				for (index = 0; index < data_length; index++)
					MCF5272_fec_priv_data.nbuffer.TxNBUF[i].data[index] = (uint8)(255- ((index-14)%256));
				break;
		}
	}
}

/********************************************************************/
void
loop_handler(void)
{
	
    /*   This is the loop  specific RX  handler called  from the  interrupt */
    /* receive routine.  This routine  gets  bound  to  the  loop  protocol */
    /* (0x0300) by  a call  to nif_bind_protocol()  and is  then called  in */
    /* fec_receive().  This function  simply checks to  make sure that  the */
    /* receive buffer matches the transmit buffer.                          */
	
	int i;

	/* Compare what I received to what I transmitted */
	for (i = 0; i < (data_length + ETH_HDR_SIZE); i++)
	{
		if (TxBuffer[fec_nif->f_rx % NUM_TXBDS].data[i] != pNbuf->data[i])
		{
			/* Increment reception error count */
			fec_nif->f_rx_err++;
		}
	}

	/* Increment reception count */
	fec_nif->f_rx++;

	/* Update progress indicator */
	if (!(fec_nif->f_rx % 200))
	{
		ihash = (ihash + 1) % 4;
		diag_printf("\b%c",hash[ihash]);
	}

	return;
}

#endif


⌨️ 快捷键说明

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