xref: /netbsd-src/sys/arch/ews4800mips/stand/common/lance.c (revision e067b4e4e4a2aee9510843306e58a9a5714a094d)
1 /*	$NetBSD: lance.c,v 1.8 2021/12/05 03:04:41 msaitoh Exp $	*/
2 
3 /*-
4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /* LANCE driver for EWS4800/360 */
33 
34 #include <lib/libsa/stand.h>
35 #include <lib/libkern/libkern.h>
36 
37 #include <dev/ic/am7990reg.h>
38 #include <dev/ic/lancereg.h>
39 
40 #include "local.h"
41 
42 /* Register Address Pointer */
43 #define	LANCE_RAP	((volatile uint16_t *)0xbe400006)
44 /* Register Data Port */
45 #define	LANCE_RDP	((volatile uint16_t *)0xbe400000)
46 
47 #define	RX_DESC_NUM	8
48 #define	TX_DESC_NUM	8
49 #define	TX_BUFSIZE	0x1000
50 #define	RX_BUFSIZE	0x1000
51 struct {
52 	struct leinit leinit;
53 	struct lermd lermd[RX_DESC_NUM];
54 	struct letmd letmd[TX_DESC_NUM];
55 	uint8_t eaddr[6];
56 	uint8_t txdata[TX_BUFSIZE] __attribute__((__aligned__(0x1000)));
57 	uint8_t rxdata[RX_BUFSIZE] __attribute__((__aligned__(0x1000)));
58 } lance_mem __attribute__((__aligned__(64)));
59 
60 bool lance_init(void);
61 void lance_eaddr(uint8_t *);
62 bool lance_get(void *, size_t);
63 bool lance_put(void *, size_t);
64 
65 void lance_setup(void);
66 bool lance_set_initblock(struct leinit *);
67 bool lance_do_initialize(void);
68 
69 bool lance_test(void);
70 bool lance_internal_loopback_test(bool);
71 void lance_internal_loopback_setup(bool);
72 void lance_internal_loopback_testdata(void);
73 bool lance_internal_loopback_data_check(bool);
74 bool __poll_interrupt(void);
75 bool __poll_lance_c0(uint16_t);
76 
77 bool
lance_init(void)78 lance_init(void)
79 {
80 
81 	lance_setup();
82 
83 	if (!lance_set_initblock(&lance_mem.leinit))
84 		return false;
85 
86 	if (!lance_do_initialize())
87 		return false;
88 
89 	*LANCE_RDP = LE_C0_STRT;
90 
91 	return true;
92 }
93 
94 void
lance_eaddr(uint8_t * p)95 lance_eaddr(uint8_t *p)
96 {
97 	int i;
98 
99 	for (i = 0; i < 6; i++)
100 		p[i] = lance_mem.eaddr[i];
101 }
102 
103 bool
lance_get(void * data,size_t len)104 lance_get(void *data, size_t len)
105 {
106 	static int current;
107 	struct lermd *rmd;
108 	int i, j, k, n;
109 	int start, end;
110 	uint8_t *q, *p = data, *p_end = p + len;
111 
112 	while ((*LANCE_RDP & (LE_C0_RINT | LE_C0_INTR)) == 0)
113 		;
114 	*LANCE_RDP = LE_C0_RINT;
115 
116 	start = end = -1;
117 	n = 0;
118 	for (i = 0; i < 8; i++) {
119 		rmd = &lance_mem.lermd[(current + i) & 0x7];
120 		if (rmd->rmd1_bits & LE_R1_STP)
121 			start = i;
122 		if (rmd->rmd1_bits & LE_R1_ENP) {
123 			end = i;
124 			n = rmd->rmd3;		/* total amount of packet */
125 			break;
126 		}
127 	}
128 #ifdef DEBUG
129 	printf("%s: %d [%d,%d] %d\n", __func__, len, start, end, n);
130 #endif
131 	if (start < 0 || end < 0)
132 		return false;
133 
134 	for (i = start; i <= end; i++) {
135 		rmd = &lance_mem.lermd[(current + i) & 0x7];
136 		q = (uint8_t *)((rmd->rmd1_hadr << 16) | rmd->rmd0 |
137 		    0xa0000000);
138 		j = i == end ? n : -rmd->rmd2;
139 		for (k = 0; k < j; k++)
140 			if (p < p_end)
141 				*p++ = *q++;
142 		n -= j;
143 		rmd->rmd1_bits = LE_R1_OWN;	/* return to LANCE */
144 	}
145 	current = (current + i) & 0x7;
146 
147 	return true;
148 }
149 
150 bool
lance_put(void * data,size_t len)151 lance_put(void *data, size_t len)
152 {
153 	static int current;
154 	struct letmd *tmd;
155 	uint16_t r;
156 	uint8_t *p, *q = data;
157 	int i, j, n, start;
158 
159 	start = current;
160 	tmd = &lance_mem.letmd[current];
161 	tmd->tmd1_bits = LE_T1_STP;
162 	for (i = 0; i < 8; i++) {
163 		current = (current + 1) & 0x7;
164 		n = uimin(len, 512);
165 		p = (uint8_t *)((tmd->tmd1_hadr << 16) | tmd->tmd0 |
166 		    0xa0000000);
167 		for (j = 0; j < n; j++)
168 			*p++ = *q++;
169 		len -= n;
170 #if 1
171 		tmd->tmd2 = -uimax(n, 64) | 0xf000;
172 #else
173 		tmd->tmd2 = -n | 0xf000;
174 #endif
175 		tmd->tmd3 = 0;
176 		if (len == 0) {
177 			tmd->tmd1_bits |= LE_T1_ENP;
178 			break;
179 		}
180 		tmd = &lance_mem.letmd[current];
181 	}
182 
183 	n = i + 1;
184 
185 	for (i = 0; i < n; i++) {
186 		tmd = &lance_mem.letmd[start + i];
187 		*LANCE_RDP = LE_C0_INEA;
188 		tmd->tmd1_bits |= LE_T1_OWN;
189 		j = 0;
190 		do {
191 			*LANCE_RAP;
192 			r = *LANCE_RDP;
193 			if (r & LE_C0_ERR) {
194 				printf("Error. CSR0=%x\n", r);
195 				return false;
196 			}
197 			if (j++ > 0xa0000) {
198 				printf("Timeout CSR0=%x\n", r);
199 				return false;
200 			}
201 		} while ((r & (LE_C0_TINT | LE_C0_INTR)) == 0);
202 
203 		*LANCE_RDP = LE_C0_TINT;
204 	}
205 
206 	for (i = 0; i < n; i++) {
207 		uint8_t *bits = &lance_mem.letmd[i].tmd1_bits;
208 		if (*bits & LE_T1_OWN || *bits & LE_T1_ERR) {
209 			printf("desc%d not transmitted. cause=%x\n", i, *bits);
210 			return false;
211 		}
212 		*bits = 0;
213 	}
214 
215 	return true;
216 }
217 
218 bool
lance_set_initblock(struct leinit * leinit)219 lance_set_initblock(struct leinit *leinit)
220 {
221 	uint16_t test_data[] = { 0xffff, 0xaaaa, 0x5555, 0x0000 };
222 	uint16_t t;
223 	uint32_t addr = (uint32_t)leinit;
224 	int i;
225 
226 	/* Control and status register */
227 	for (i = 3; i >= 0; i--) {
228 		*LANCE_RAP = i;
229 		if ((*LANCE_RAP & 3) != i)
230 			goto reg_rw_error;
231 	}
232 	*LANCE_RDP = LE_C0_STOP;	/* disable all external activity */
233 	if (*LANCE_RDP != LE_C0_STOP)
234 		goto reg_rw_error;
235 
236 	/* Low address of init block */
237 	for (i = 0; i < 4; i++) {
238 		t = test_data[i] & 0xfffe;
239 		*LANCE_RAP = LE_CSR1;
240 		*LANCE_RDP = t;
241 		if (*LANCE_RDP != t)
242 			goto reg_rw_error;
243 	}
244 	*LANCE_RDP = addr & 0xfffe;
245 #if DEBUG
246 	printf("initblock low addr=%x\n", *LANCE_RDP);
247 #endif
248 
249 	/* High address of init block */
250 	for (i = 0; i < 4; i++) {
251 		t = test_data[i] & 0x00ff;
252 		*LANCE_RAP = LE_CSR2;
253 		*LANCE_RDP = t;
254 		if (*LANCE_RDP != t)
255 			goto reg_rw_error;
256 	}
257 	*LANCE_RDP = (addr >> 16) & 0x00ff;
258 #ifdef DEBUG
259 	printf("initblock high addr=%x\n", *LANCE_RDP);
260 #endif
261 
262 	/* Bus master and control */
263 	*LANCE_RAP = LE_CSR3;
264 	*LANCE_RDP = 7;
265 	if (*LANCE_RDP != 7)
266 		goto reg_rw_error;
267 
268 	*LANCE_RAP = LE_CSR3;
269 	*LANCE_RDP = 0;
270 	if (*LANCE_RDP != 0)
271 		goto reg_rw_error;
272 
273 	*LANCE_RDP = LE_C3_BSWP | LE_C3_BCON;
274 
275 	return true;
276 
277  reg_rw_error:
278 	printf("LANCE register r/w error.\n");
279 	return false;
280 }
281 
282 bool
lance_do_initialize(void)283 lance_do_initialize(void)
284 {
285 
286 	/* Initialize LANCE */
287 	*LANCE_RAP = LE_CSR0;
288 	*LANCE_RDP = LE_C0_INEA | LE_C0_INIT;
289 
290 	/* Wait interrupt */
291 	if (!__poll_interrupt())
292 		return false;
293 	*LANCE_RDP = *LANCE_RDP;
294 
295 	return true;
296 }
297 
298 void
lance_setup(void)299 lance_setup(void)
300 {
301 	struct leinit *init = &lance_mem.leinit;
302 	struct lermd *lermd = lance_mem.lermd;
303 	struct letmd *letmd = lance_mem.letmd;
304 	uint32_t addr;
305 	uint8_t *eaddr;
306 	int i;
307 
308 	memset(&lance_mem, 0, sizeof lance_mem);
309 	/* Ethernet address from NVSRAM */
310 	eaddr = lance_mem.eaddr;
311 	for (i = 0; i < 6; i++)
312 		eaddr[i] = *(uint8_t *)(0xbe491008 + i * 4);
313 
314 	/* Init block */
315 	init->init_mode = 0;
316 	init->init_padr[0] = (eaddr[1] << 8) | eaddr[0];
317 	init->init_padr[1] = (eaddr[3] << 8) | eaddr[2];
318 	init->init_padr[2] = (eaddr[5] << 8) | eaddr[4];
319 	/* Logical address filter */
320 	for (i = 0; i < 4; i++)
321 		init->init_ladrf[i] = 0x0000;
322 
323 	/* Location of Rx descriptor ring */
324 	addr = (uint32_t)lermd;
325 	init->init_rdra = addr & 0xffff;
326 	init->init_rlen = ((ffs(RX_DESC_NUM) - 1) << 13) |
327 	    ((addr >> 16) & 0xff);
328 
329 	/* Location of Tx descriptor ring */
330 	addr = (uint32_t)letmd;
331 	init->init_tdra = addr & 0xffff;
332 	init->init_tlen = ((ffs(RX_DESC_NUM) - 1) << 13) |
333 	    ((addr >> 16) & 0xff);
334 
335 	/* Rx descriptor */
336 	addr = (uint32_t)lance_mem.rxdata;
337 	for (i = 0; i < RX_DESC_NUM; i++, lermd++) {
338 		lermd->rmd0 = (addr & 0xffff) +  i * 512; /* data block size */
339 		lermd->rmd1_hadr = (addr >> 16) & 0xff;
340 		lermd->rmd1_bits = LE_R1_OWN;
341 		lermd->rmd2 = -512;
342 		lermd->rmd3 = 0;
343 	}
344 
345 	/* Tx descriptor */
346 	addr = (uint32_t)lance_mem.txdata;
347 	for (i = 0; i < TX_DESC_NUM; i++, letmd++) {
348 		letmd->tmd0 = (addr & 0xffff) + i * 512; /* data block size */
349 		letmd->tmd1_hadr = (addr >> 16) & 0xff;
350 		letmd->tmd1_bits = 0;
351 		letmd->tmd2 = 0;
352 		letmd->tmd3 = 0;
353 	}
354 }
355 
356 /*
357  * Internal loopback test.
358  */
359 bool
lance_test(void)360 lance_test(void)
361 {
362 
363 	/* Internal loop back test. (no CRC) */
364 	if (!lance_internal_loopback_test(false))
365 		return false;
366 
367 	/* Internal loop back test. (with CRC) */
368 	if (!lance_internal_loopback_test(true))
369 		return false;
370 
371 	return true;
372 }
373 
374 bool
lance_internal_loopback_test(bool crc)375 lance_internal_loopback_test(bool crc)
376 {
377 
378 	lance_internal_loopback_setup(crc);
379 
380 	if (!lance_set_initblock(&lance_mem.leinit))
381 		return false;
382 
383 	if (!lance_do_initialize())
384 		return false;
385 
386 	/* Transmit Start */
387 	*LANCE_RAP = LE_CSR0;	/* Control and status register */
388 	*LANCE_RDP = LE_C0_INEA | LE_C0_STRT;
389 
390 	/* Check trasmited data. */
391 	return lance_internal_loopback_data_check(crc);
392 }
393 
394 void
lance_internal_loopback_setup(bool crc)395 lance_internal_loopback_setup(bool crc)
396 {
397 	struct leinit *init = &lance_mem.leinit;
398 	struct lermd *lermd = lance_mem.lermd;
399 	struct letmd *letmd = lance_mem.letmd;
400 	uint32_t addr;
401 	int i;
402 
403 	memset(&lance_mem, 0, sizeof lance_mem);
404 
405 	/* Init block */
406 	init->init_mode = LE_C15_INTL | LE_C15_LOOP;
407 	if (!crc)
408 		init->init_mode |= LE_C15_DXMTFCS;
409 
410 	init->init_padr[0] = 0x0000;
411 	init->init_padr[1] = 0x8400;
412 	init->init_padr[2] = 0x0000;
413 	for (i = 0; i < 4; i++)
414 		init->init_ladrf[i] = 0x0000;
415 
416 	addr = (uint32_t)lermd;
417 	init->init_rdra = addr & 0xffff;
418 	init->init_rlen = (ffs(RX_DESC_NUM) << 13) | ((addr >> 16) & 0xff);
419 	addr = (uint32_t)letmd;
420 	init->init_tdra = addr & 0xffff;
421 	init->init_tlen = (ffs(RX_DESC_NUM) << 13) | ((addr >> 16) & 0xff);
422 
423 	/* Rx descriptor */
424 	addr = (uint32_t)lance_mem.rxdata;
425 	for (i = 0; i < RX_DESC_NUM; i++, lermd++) {
426 		lermd->rmd0 = (addr & 0xffff) +  i * 64; /* data block size */
427 		lermd->rmd1_hadr = (addr >> 16) & 0xff;
428 		lermd->rmd1_bits = LE_R1_OWN;
429 		lermd->rmd2 = -64;
430 		lermd->rmd3 = 0;
431 	}
432 
433 	/* Tx descriptor */
434 	addr = (uint32_t)lance_mem.txdata;
435 	for (i = 0; i < TX_DESC_NUM; i++, letmd++) {
436 		letmd->tmd0 = (addr & 0xffff) + i * 64;	/* data block size */
437 		letmd->tmd1_hadr = (addr >> 16) & 0xff;
438 		letmd->tmd1_bits = LE_T1_STP | LE_T1_ENP;
439 		if (crc)
440 			letmd->tmd2 = -28;
441 		else
442 			letmd->tmd2 = -32;
443 		letmd->tmd3 = 0;
444 	}
445 
446 	lance_internal_loopback_testdata();
447 }
448 
449 void
lance_internal_loopback_testdata(void)450 lance_internal_loopback_testdata(void)
451 {
452 	uint16_t test_data[] = {
453 		0x55aa, 0xff00, 0x0102, 0x0304, 0x0506, 0x0708, 0x0910,
454 		0x40db, 0xdfcf, /* CRC */
455 		0x23dc, 0x23dc, 0x1918, 0x1716, 0x1514, 0x1312, 0x1110,
456 		0x7081, 0x90cb, /* CRC */
457 		0x6699, 0xaa55, 0x0515, 0x2535, 0x4555, 0x6575,	0x8595,
458 		0x55f6, 0xa448, /* CRC */
459 		0x4e4e, 0x5a5a, 0x6969, 0x7878, 0x0f0f,	0x1e1e, 0x2d2d,
460 		0xa548, 0x7404, /* CRC */
461 	};
462 	uint16_t test_header[] = {
463 		0x0000, 0x0084, 0x0000,	/* dst */
464 		0x0000, 0x0084, 0x0000,	/* src */
465 		0x000e
466 	};
467 	uint16_t *p = (uint16_t *)lance_mem.txdata;
468 	int i, j, k;
469 
470 	for (i = 0; i < 2; i++) {			/* 64byte * 8 */
471 		uint16_t *r = test_data;
472 		for (j = 0; j < 4; j++) {		/* 64byte * 4 */
473 			uint16_t *q = test_header;
474 			for (k = 0; k < 7; k++)		/* 14byte */
475 				*p++ = *q++;
476 			for (k = 0; k < 9; k++)		/* 18byte */
477 				*p++ = *r++;
478 			p += 16;			/* 32byte skip */
479 		}
480 	}
481 }
482 
483 bool
lance_internal_loopback_data_check(bool crc_check)484 lance_internal_loopback_data_check(bool crc_check)
485 {
486 	uint32_t *p = (uint32_t *)lance_mem.txdata;
487 	uint32_t *q = (uint32_t *)lance_mem.rxdata;
488 	int i, j;
489 
490 	/* Read all data block */
491 	for (i = 0; i < 8; i++) {
492 		printf("block %d ", i);
493 		lance_mem.letmd[i].tmd1_bits |= LE_T1_OWN;/* buffer is filled */
494 		/* wait interrupt */
495 		if (!__poll_interrupt())
496 			goto timeout_error;
497 		/* wait LANCE status */
498 		if (!__poll_lance_c0(LE_C0_RINT | LE_C0_TINT | LE_C0_INTR |
499 		    LE_C0_INEA | LE_C0_RXON | LE_C0_TXON | LE_C0_STRT |
500 		    LE_C0_INIT))
501 			goto timeout_error;
502 
503 		/* check Tx descriptor */
504 		if (lance_mem.letmd[i].tmd1_bits & LE_T1_ERR) {
505 			printf("tx desc error.\n");
506 			goto tx_rx_error;
507 		}
508 
509 		/* check Rx descriptor */
510 		if (lance_mem.lermd[i].rmd1_bits & LE_R1_ERR) {
511 			printf("rx desc error.\n");
512 			goto tx_rx_error;
513 		}
514 
515 		/* Compare transmitted data */
516 		for (j = 0; j < 7; j++)	/* first 28byte */
517 			if (*p++ != *q++) {
518 				printf("data error.\n");
519 				goto tx_rx_error;
520 			}
521 
522 		/* check CRC */
523 		if (crc_check) {
524 			printf("CRC=%x ", *p);
525 			if (*p != *q) {	/* CRC */
526 				goto crc_error;
527 			}
528 		}
529 		printf("ok.\n");
530 
531 		p += 9;	/* 36byte skip */
532 		q += 9;
533 	}
534 	return true;
535  timeout_error:
536 	printf("LANCE timeout.\n");
537 	return false;
538  tx_rx_error:
539 	printf("LANCE Tx/Rx data error.\n");
540 	return false;
541  crc_error:
542 	printf("LANCE CRC error.\n");
543 	return false;
544 }
545 
546 bool
__poll_interrupt(void)547 __poll_interrupt(void)
548 {
549 	int j;
550 
551 	for (j = 0; j < 0x10000; j++) {
552 		*LANCE_RAP;
553 		if (*(volatile uint32_t *)0xbe40a008 & 1)
554 			break;
555 	}
556 	if (j == 0x10000) {
557 		printf ("interrupt timeout.\n");
558 		return false;
559 	}
560 
561 	return true;
562 }
563 
564 bool
__poll_lance_c0(uint16_t r)565 __poll_lance_c0(uint16_t r)
566 {
567 	int j;
568 
569 	for (j = 0; j < 0x60000; j++)
570 		if (*LANCE_RDP == r)
571 			break;
572 	if (j == 0x60000) {
573 		printf("lance CSR0 %x != %x\n", *LANCE_RDP, r);
574 		return false;
575 	}
576 
577 	*LANCE_RDP = (LE_C0_RINT | LE_C0_TINT| LE_C0_INEA) & r;
578 
579 	return true;
580 }
581