diff options
Diffstat (limited to 'c/src/lib/libbsp/powerpc/beatnik/network/if_mve/testing.c')
-rw-r--r-- | c/src/lib/libbsp/powerpc/beatnik/network/if_mve/testing.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/testing.c b/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/testing.c new file mode 100644 index 0000000000..71090a3aa0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/beatnik/network/if_mve/testing.c @@ -0,0 +1,323 @@ +#ifndef KERNEL +#define KERNEL +#endif + +#include <rtems.h> +#include <rtems/rtems_bsdnet_internal.h> +#include <bsp.h> +#include <sys/mbuf.h> + +#include "mv64340_eth_ll.h" + +#include <string.h> +#include <assert.h> + +#include <netinet/in.h> +#include <stdio.h> + +#define RX_SPACING 1 +#define TX_SPACING 1 + +#define RX_RING_SIZE (MV64340_RX_QUEUE_SIZE*RX_SPACING) +#define TX_RING_SIZE (MV64340_TX_QUEUE_SIZE*TX_SPACING) + + +struct eth_rx_desc rx_ring[RX_RING_SIZE] __attribute__((aligned(32))); +struct eth_rx_desc rx_ring[RX_RING_SIZE] = {{0},}; + +struct eth_tx_desc tx_ring[TX_RING_SIZE] __attribute__((aligned(32))); +struct eth_tx_desc tx_ring[TX_RING_SIZE] = {{0},}; + +/* packet buffers */ +char rx_buf[MV64340_RX_QUEUE_SIZE][2048] __attribute__((aligned(8))); +char rx_buf[MV64340_RX_QUEUE_SIZE][2048]; + +char tx_buf[MV64340_RX_QUEUE_SIZE][2048] __attribute__((aligned(8))); +char tx_buf[MV64340_RX_QUEUE_SIZE][2048]; + +char BcHeader[22] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* dst */ + 0x00, 0x01, 0xaf, 0x13, 0xb5, 0x3e, /* src */ + 00, 00, /* len */ + 0xAA, /* dsap */ + 0xAA, /* ssap */ + 0x03, /* ctrl */ + 0x08, 0x00, 0x56, /* snap_org [stanford] */ + 0x80, 0x5b, /* snap_type (stanford kernel) */ +}; + +struct mv64340_private mveth = { + port_num: 0, + port_mac_addr: {0x00,0x01,0xAF,0x13,0xB5,0x3C}, + /* port_config .. tx_resource_err are set by port_init */ + 0 +}; + +struct pkt_info p0,p1; + +static inline void rx_stopq(int port) +{ + MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port), 0x0000ff00); +} + +static inline void tx_stopq(int port) +{ + MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port), 0x0000ff00); +} + +#define MV64360_ENET2MEM_SNOOP_NONE 0x0000 +#define MV64360_ENET2MEM_SNOOP_WT 0x1000 +#define MV64360_ENET2MEM_SNOOP_WB 0x2000 + +#if 0 +int +mveth_init(struct mv64340_private *mp) +{ +int i; + mp->p_rx_desc_area = rx_ring; + mp->p_tx_desc_area = tx_ring; + + rx_stopq(mp->port_num); + tx_stopq(mp->port_num); + + /* MotLoad has cache snooping disabled on the ENET2MEM windows. + * Some comments in (linux) indicate that there are errata + * which cause problems which is a real bummer. + * We try it anyways... + */ + { + unsigned long disbl, bar; + disbl = MV_READ(MV64340_ETH_BASE_ADDR_ENABLE_REG); + /* disable all 6 windows */ + MV_WRITE(MV64340_ETH_BASE_ADDR_ENABLE_REG, 0x3f); + /* set WB snooping */ + for ( i=0; i<6*8; i+=8 ) { + if ( (bar = MV_READ(MV64340_ETH_BAR_0 + i)) && MV_READ(MV64340_ETH_SIZE_REG_0 + i) ) { + MV_WRITE(MV64340_ETH_BAR_0 + i, bar | MV64360_ENET2MEM_SNOOP_WB); + /* read back to flush fifo [linux comment] */ + (void)MV_READ(MV64340_ETH_BAR_0 + i); + } + } + /* restore/re-enable */ + MV_WRITE(MV64340_ETH_BASE_ADDR_ENABLE_REG, disbl); + } + + eth_port_init(mp); + + sleep(1); + + mveth_init_tx_desc_ring(mp); + mveth_init_rx_desc_ring(mp); +#if 0 + for ( i = 0; i<MV64340_RX_QUEUE_SIZE; i++ ) { + p0.byte_cnt = sizeof(rx_buf[0]); + p0.buf_ptr = (dma_addr_t)rx_buf[i]; + p0.return_info = (void*)i; + /* other fields are not used by ll driver */ + assert ( ETH_OK == eth_rx_return_buff(mp,&p0) ); + } + memset(&p0, 0, sizeof(p0)); +#endif + + return eth_port_start(mp); +} +#endif + +void +mveth_stop(struct mv64340_private *mp) +{ +extern void mveth_stop_hw(); + rtems_bsdnet_semaphore_obtain(); + mveth_stop_hw(mp); + rtems_bsdnet_semaphore_release(); +} + +extern int mveth_send_mbuf(); +extern int mveth_swipe_tx(); + +int +mveth_tx(struct mv64340_private *mp, char *data, int len, int nbufs) +{ +int rval = -1,l; +char *p; +struct mbuf *m; +char *emsg = 0; + + rtems_bsdnet_semaphore_obtain(); + MGETHDR(m, M_WAIT, MT_DATA); + if ( !m ) { + emsg="Unable to allocate header\n"; + goto bail; + } + MCLGET(m, M_WAIT); + if ( !(m->m_flags & M_EXT) ) { + m_freem(m); + emsg="Unable to allocate cluster\n"; + goto bail; + } + p = mtod(m, char *); + l = 0; + switch (nbufs) { + case 3: + default: + emsg="nbufs arg must be 1..3\n"; + goto bail; + + case 1: + l += sizeof(BcHeader); + memcpy(p, &BcHeader, sizeof(BcHeader)); + p += sizeof(BcHeader); + + case 2: + memcpy(p,data,len); + l += len; + m->m_len = m->m_pkthdr.len = l; + if ( 2 == nbufs ) { + M_PREPEND(m, sizeof (BcHeader), M_WAIT); + if (!m) { + emsg = "Unable to prepend\n"; + goto bail; + } + p = mtod(m, char*); + memcpy(p,&BcHeader,sizeof(BcHeader)); + l += sizeof(BcHeader); + } + break; + } + *(short*)(mtod(m, char*) + 12) = htons(l-14); + rval = mveth_send_mbuf(mp,m); + +bail: + rtems_bsdnet_semaphore_release(); + if (emsg) + printf(emsg); + +#if 0 + /* + * Add local net header. If no space in first mbuf, + * allocate another. + */ + M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); + if (m == 0) + senderr(ENOBUFS); + eh = mtod(m, struct ether_header *); + (void)memcpy(&eh->ether_type, &type, + sizeof(eh->ether_type)); + (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); + (void)memcpy(eh->ether_shost, ac->ac_enaddr, + sizeof(eh->ether_shost)); +#endif + return rval; +} + +int +mveth_protected(int (*p)(struct mv64340_private*), struct mv64340_private *mp) +{ +int rval; + rtems_bsdnet_semaphore_obtain(); + rval = p(mp); + rtems_bsdnet_semaphore_release(); + return rval; +} + +int +mveth_rx(struct mv64340_private *mp) +{ +extern int mveth_swipe_rx(); + return mveth_protected(mveth_swipe_rx,mp); +} + +int +mveth_reclaim(struct mv64340_private *mp) +{ +extern int mveth_swipe_tx(); + return mveth_protected(mveth_swipe_tx,mp); +} + + +int preth(FILE *f, char *p) +{ +int i; + for (i=0; i<4; i++) + fprintf(f,"%02X:",p[i]); + fprintf(f,"%02X",p[i]); + return 6; +} + +char *errcode2str(st) +{ +char *rval; + switch(st) { + case ETH_OK: + rval = "OK"; + break; + case ETH_ERROR: + rval = "Fundamental error."; + break; + case ETH_RETRY: + rval = "Could not process request. Try later."; + break; + case ETH_END_OF_JOB: + rval = "Ring has nothing to process."; + break; + case ETH_QUEUE_FULL: + rval = "Ring resource error."; + break; + case ETH_QUEUE_LAST_RESOURCE: + rval = "Ring resources about to exhaust."; + break; + default: + rval = "UNKNOWN"; break; + } + return rval; +} + + +#if 0 +int +mveth_rx(struct mv64340_private *mp) +{ +int st; +struct pkt_info p; + if ( ETH_OK != (st=eth_port_receive(mp, &p)) ) { + fprintf(stderr,"receive: %s\n", errcode2str(st)); + return -1; + } + printf("%i bytes received from ", p.byte_cnt); + preth(stdout,(char*)p.buf_ptr+6); + printf(" (desc. stat: 0x%08x)\n", p.cmd_sts); + + p.byte_cnt = sizeof(rx_buf[0]); + p.buf_ptr -= RX_BUF_OFFSET; + if ( ETH_OK != (st=eth_rx_return_buff(mp,&p) ) ) { + fprintf(stderr,"returning buffer: %s\n", errcode2str(st)); + return -1; + } + return 0; +} +#endif + +int +dring() +{ +int i; +if (1) { +struct eth_rx_desc *pr; +printf("RX:\n"); + for (i=0, pr=rx_ring; i<RX_RING_SIZE; i+=RX_SPACING, pr+=RX_SPACING) { + dcbi(pr); + printf("cnt: 0x%04x, size: 0x%04x, stat: 0x%08x, next: 0x%08x, buf: 0x%08x\n", + pr->byte_cnt, pr->buf_size, pr->cmd_sts, pr->next_desc_ptr, pr->buf_ptr); + } +} +if (1) { +struct eth_tx_desc *pt; +printf("TX:\n"); + for (i=0, pt=tx_ring; i<TX_RING_SIZE; i+=TX_SPACING, pt+=TX_SPACING) { + dcbi(pt); + printf("cnt: 0x%04x, stat: 0x%08x, next: 0x%08x, buf: 0x%08x\n", + pt->byte_cnt, pt->cmd_sts, pt->next_desc_ptr, pt->buf_ptr); + } +} + return 0; +} |