summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik/net/if_mve/mve_smallbuf_tst.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/beatnik/net/if_mve/mve_smallbuf_tst.c')
-rw-r--r--bsps/powerpc/beatnik/net/if_mve/mve_smallbuf_tst.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/bsps/powerpc/beatnik/net/if_mve/mve_smallbuf_tst.c b/bsps/powerpc/beatnik/net/if_mve/mve_smallbuf_tst.c
new file mode 100644
index 0000000000..721ade30d1
--- /dev/null
+++ b/bsps/powerpc/beatnik/net/if_mve/mve_smallbuf_tst.c
@@ -0,0 +1,145 @@
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/if_mve_pub.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Demo for the mv64360 ethernet quirk:
+ *
+ * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ * $$ buffer segments < 8 bytes must be aligned $$
+ * $$ to 8 bytes but larger segments are not $$
+ * $$ sensitive to alignment. $$
+ * $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ *
+ * How to use:
+ *
+ * Init MVE driver on (unused) unit 2:
+ *
+ * mve = mvtst_init(2)
+ *
+ * data = { 1,2,3,4,5,6,7,8,9,0xa,0xb, ... }
+ *
+ * Alloc 2-element mbuf chain (1st holds an
+ * ethernet header which is > 8bytes so we can't
+ * test this with only 1 mbuf. The 2nd mbuf holds
+ * a small fragment of data).
+ *
+ * mb = mvtst_getbuf(mve)
+ *
+ * Copy data into aligned area inside 2nd mbuf,
+ * (so that you can see if the chip starts using
+ * the aligned area rather than the unaligned
+ * buffer pointer). Point mbuf's data pointer
+ * at 'off'set from the aligned area:
+ *
+ * mvtst_putbuf(mb, data, len, offset)
+ *
+ * Send chain off:
+ *
+ * BSP_mve_send_buf(mve, mb, 0, 0)
+ *
+ * Watch raw data:
+ *
+ * tcpdump -XX -vv -s0 ether host <my-ether-addr>
+ *
+ * E.g, if offset = 1, len = 2 then we would like
+ * to see
+ *
+ * GOOD:
+ * < 14 header bytes > 0x02, 0x03
+
+ * but if the chip starts DMA at aligned address
+ * we see instead
+ * BAD:
+ * < 14 header bytes > 0x01, 0x02
+ */
+
+static inline void *rmalloc(size_t l) { return malloc(l); }
+static inline void rfree(void *p) { return free(p); }
+
+#define _KERNEL
+#include <sys/param.h>
+#include <sys/mbuf.h>
+
+static void
+cleanup_buf(void *u_b, void *closure, int error)
+{
+rtems_bsdnet_semaphore_obtain();
+ m_freem((struct mbuf*)u_b);
+rtems_bsdnet_semaphore_release();
+}
+
+struct mbuf *mvtst_getbuf(struct mveth_private *mp)
+{
+struct mbuf *m,*n;
+
+ if ( !mp ) {
+ printf("need driver ptr arg\n");
+ return 0;
+ }
+rtems_bsdnet_semaphore_obtain();
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ MGET(n, M_DONTWAIT, MT_DATA);
+ m->m_next = n;
+rtems_bsdnet_semaphore_release();
+ /* Ethernet header */
+ memset( mtod(m, unsigned char*), 0xff, 6);
+ BSP_mve_read_eaddr(mp, mtod(m, unsigned char*) + 6);
+ /* Arbitrary; setting to IP but we don't bother
+ * to setup a real IP header. We just watch the
+ * raw packet contents...
+ */
+ mtod(m, unsigned char*)[12] = 0x08;
+ mtod(m, unsigned char*)[13] = 0x00;
+ m->m_pkthdr.len = m->m_len = 14;
+ n->m_len = 0;
+ return m;
+}
+
+int
+mvtst_putbuf(struct mbuf *m, void *data, int len, int off)
+{
+int i;
+ if ( m ) {
+ m->m_pkthdr.len += len;
+ if ( ( m= m->m_next ) ) {
+ m->m_len = len;
+ memcpy(mtod(m, void*), data, 32);
+ m->m_data += off;
+ printf("m.dat: 0x%08x, m.data: 0x%08x\n", m->m_dat, m->m_data);
+ for ( i=0; i< 16; i++ ) {
+ printf(" %02x,",mtod(m, unsigned char*)[i]);
+ }
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
+
+static void *alloc_rxbuf(int *p_size, unsigned long *paddr)
+{
+ return *(void**)paddr = rmalloc((*p_size = 1800));
+}
+
+static void consume_buf(void *buf, void *closure, int len)
+{
+ rfree(buf);
+}
+
+void *
+mvtst_init(int unit)
+{
+struct mveth_private *mp;
+ mp = BSP_mve_setup(
+ unit, 0,
+ cleanup_buf, 0,
+ alloc_rxbuf,
+ consume_buf, 0,
+ 10, 10,
+ 0);
+ if ( mp )
+ BSP_mve_init_hw(mp, 0, 0);
+ return mp;
+}