BlinkenArea - GitList
Repositories
Blog
Wiki
mips_sys
Code
Commits
Branches
Tags
Search
Tree:
2a4b80d
Branches
Tags
master
mips_sys
fw
eth.c
handle padding to minimum ethernet frame size (TX) in HW
Stefan Schuermans
commited
2a4b80d
at 2012-03-24 16:42:53
eth.c
Blame
History
Raw
#include "config.h" #include "eth.h" static volatile unsigned int *const eth_ptr = (volatile unsigned int *)0x80000400; static unsigned int eth_idx_hw; static unsigned int eth_rx_buf[2][381]; /* max frame: 1522 byte = 380.5 int */ static unsigned int *eth_rx_pos; static unsigned int eth_rx_cnt; static unsigned int eth_tx_cnt; /** * @brief set MAC address * @param[in] mac MAC address */ static void eth_mac_set(const unsigned char mac[6]) { unsigned int i; for (i = 0; i < 6; ++i) ((volatile unsigned char *)(eth_ptr + 12))[i] = mac[i]; } /** * @brief provide new receive buffer * @param[in] ptr pointer to new receive buffer * @param[in] sz size of new receive buffer */ static void eth_rx_new_buf(void *ptr, unsigned int sz) { eth_ptr[4] = (unsigned int)ptr; /* new start */ eth_ptr[5] = (unsigned int)ptr + sz; /* new end */ eth_ptr[6] = 1; /* set flag */ while (eth_ptr[6] == 1); /* wait until processed */ } /** * @brief get buffer position of ethernet receiver * @return current buffer position of ethernet receiver * * eveything before this position can be read */ static void * eth_rx_get_pos(void) { return (void *)eth_ptr[0]; } /** initialize MAC address */ void eth_mac_init(void) { eth_mac_set(config_mac.mac); } /** initialize receiver */ void eth_rx_init(void) { /* give buffer 0 to HW */ eth_idx_hw = 0; eth_rx_new_buf(eth_rx_buf[0], sizeof(eth_rx_buf[0])); /* buffer 1 owned by SW is empty */ eth_rx_buf[1][0] = 0; eth_rx_pos = eth_rx_buf[1]; /* no packets received yet */ eth_rx_cnt = 0; } /** initialize transmitter */ void eth_tx_init(void) { /* no packets transmitted yet */ eth_tx_cnt = 0; } /** * @brief get next received packet * @param[out] *pptr pointer to packet data * @param[out] *psz size of packet * @return if a packet was received */ int eth_rx(void **pptr, unsigned int *psz) { /* current SW buffer is empty and HW buffer contains a packet */ if (*eth_rx_pos == 0 && eth_rx_get_pos() != eth_rx_buf[eth_idx_hw]) { /* swap buffers */ eth_idx_hw = 1 - eth_idx_hw; /* give new HW buffer to HW */ eth_rx_new_buf(eth_rx_buf[eth_idx_hw], sizeof(eth_rx_buf[eth_idx_hw])); /* start reading packet data at begin of new SW buffer */ eth_rx_pos = eth_rx_buf[1 - eth_idx_hw]; } /* SW buffer contains a packet */ if (*eth_rx_pos > 0) { /* return size and pointer, advance position */ *psz = *eth_rx_pos; eth_rx_pos++; *pptr = eth_rx_pos; eth_rx_pos += *psz >> 2; ++eth_rx_cnt; /* count received packets */ return 1; } /* no packet received */ return 0; } /** * @brief transmit packet * @param[in] ptr pointer to packet data * @param[in] sz size of packet * * Padding will be appended if sz is not a multiple of 4 or smaller 60 bytes. * The buffer pointed to by ptr must be sufficiently large. */ void eth_tx(const void *ptr, unsigned int sz) { while(sz & 3) /* pad with zeros */ ((unsigned char *)ptr)[sz++] = 0; eth_ptr[8] = (unsigned int)ptr; /* start */ eth_ptr[9] = (unsigned int)ptr + sz; /* end */ eth_ptr[10] = 1; /* set flag */ while (eth_ptr[10] == 1); /* wait until processed */ ++eth_tx_cnt; /* count transmitted packets */ } /** get number of received packets */ unsigned int eth_rx_get_cnt(void) { return eth_rx_cnt; } /** get number of transmitted packets */ unsigned int eth_tx_get_cnt(void) { return eth_tx_cnt; }