summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik/net/if_mve/testing.c
blob: a1233bdb0b120219ff98c100dbf9a362903a2484 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
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;
}