summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik/net/if_mve/testing.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/beatnik/net/if_mve/testing.c')
-rw-r--r--bsps/powerpc/beatnik/net/if_mve/testing.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/bsps/powerpc/beatnik/net/if_mve/testing.c b/bsps/powerpc/beatnik/net/if_mve/testing.c
new file mode 100644
index 0000000000..a1233bdb0b
--- /dev/null
+++ b/bsps/powerpc/beatnik/net/if_mve/testing.c
@@ -0,0 +1,324 @@
+#ifndef KERNEL
+#define KERNEL
+#endif
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet_internal.h>
+#include <bsp.h>
+#include <sys/param.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;
+}