summaryrefslogblamecommitdiffstats
path: root/bsps/powerpc/beatnik/net/if_mve/testing.c
blob: a1233bdb0b120219ff98c100dbf9a362903a2484 (plain) (tree)
1
2
3
4
5
6
7
8






                                        
                      



























































































































































































































































































































                                                                                                      
#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;
}