xref: /openbsd-src/sys/dev/ic/am79900.c (revision 63bcfa73e917a5ed3d06db2c3eab553f722c3b1f)
1 /*	$OpenBSD: am79900.c,v 1.8 2020/07/10 13:22:19 patrick Exp $	*/
2 /*	$NetBSD: am79900.c,v 1.23 2012/02/02 19:43:02 tls Exp $	*/
3 
4 /*-
5  * Copyright (c) 1997 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*-
34  * Copyright (c) 1992, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * This code is derived from software contributed to Berkeley by
38  * Ralph Campbell and Rick Macklem.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. Neither the name of the University nor the names of its contributors
49  *    may be used to endorse or promote products derived from this software
50  *    without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  *
64  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
65  */
66 
67 /*-
68  * Copyright (c) 1998
69  *	Matthias Drochner.  All rights reserved.
70  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
71  *
72  * This code is derived from software contributed to Berkeley by
73  * Ralph Campbell and Rick Macklem.
74  *
75  * Redistribution and use in source and binary forms, with or without
76  * modification, are permitted provided that the following conditions
77  * are met:
78  * 1. Redistributions of source code must retain the above copyright
79  *    notice, this list of conditions and the following disclaimer.
80  * 2. Redistributions in binary form must reproduce the above copyright
81  *    notice, this list of conditions and the following disclaimer in the
82  *    documentation and/or other materials provided with the distribution.
83  * 3. All advertising materials mentioning features or use of this software
84  *    must display the following acknowledgement:
85  *	This product includes software developed by the University of
86  *	California, Berkeley and its contributors.
87  * 4. Neither the name of the University nor the names of its contributors
88  *    may be used to endorse or promote products derived from this software
89  *    without specific prior written permission.
90  *
91  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
92  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
95  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
97  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
100  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
101  * SUCH DAMAGE.
102  *
103  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
104  */
105 
106 #include "bpfilter.h"
107 
108 #include <sys/param.h>
109 #include <sys/systm.h>
110 #include <sys/mbuf.h>
111 #include <sys/syslog.h>
112 #include <sys/socket.h>
113 #include <sys/device.h>
114 #include <sys/malloc.h>
115 #include <sys/ioctl.h>
116 #include <sys/errno.h>
117 
118 #include <net/if.h>
119 #include <net/if_media.h>
120 
121 #include <netinet/in.h>
122 #include <netinet/if_ether.h>
123 
124 #if NBPFILTER > 0
125 #include <net/bpf.h>
126 #endif
127 
128 #include <dev/ic/lancereg.h>
129 #include <dev/ic/lancevar.h>
130 #include <dev/ic/am79900reg.h>
131 #include <dev/ic/am79900var.h>
132 
133 void	am79900_meminit(struct lance_softc *);
134 void	am79900_start(struct ifnet *);
135 
136 void	am79900_rint(struct lance_softc *);
137 void	am79900_tint(struct lance_softc *);
138 
139 #ifdef LEDEBUG
140 void	am79900_recv_print(struct lance_softc *, int);
141 void	am79900_xmit_print(struct lance_softc *, int);
142 #endif
143 
144 void
am79900_config(struct am79900_softc * sc)145 am79900_config(struct am79900_softc *sc)
146 {
147 	int mem, i;
148 
149 	sc->lsc.sc_meminit = am79900_meminit;
150 	sc->lsc.sc_start = am79900_start;
151 
152 	lance_config(&sc->lsc);
153 
154 	mem = 0;
155 	sc->lsc.sc_initaddr = mem;
156 	mem += sizeof(struct leinit);
157 	sc->lsc.sc_rmdaddr = mem;
158 	mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
159 	sc->lsc.sc_tmdaddr = mem;
160 	mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
161 	for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN)
162 		sc->lsc.sc_rbufaddr[i] = mem;
163 	for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN)
164 		sc->lsc.sc_tbufaddr[i] = mem;
165 
166 	if (mem > sc->lsc.sc_memsize)
167 		panic("%s: memsize", sc->lsc.sc_dev.dv_xname);
168 }
169 
170 /*
171  * Set up the initialization block and the descriptor rings.
172  */
173 void
am79900_meminit(struct lance_softc * sc)174 am79900_meminit(struct lance_softc *sc)
175 {
176 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
177 	u_long a;
178 	int bix;
179 	struct leinit init;
180 	struct lermd rmd;
181 	struct letmd tmd;
182 	uint8_t *myaddr;
183 
184 	if (ifp->if_flags & IFF_PROMISC)
185 		init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
186 	else
187 		init.init_mode = LE_MODE_NORMAL;
188 	if (sc->sc_initmodemedia == 1)
189 		init.init_mode |= LE_MODE_PSEL0;
190 
191 	init.init_mode |= ((ffs(sc->sc_ntbuf) - 1) << 28) |
192 	    ((ffs(sc->sc_nrbuf) - 1) << 20);
193 
194 	/*
195 	 * Update our private copy of the Ethernet address.
196 	 * We NEED the copy so we can ensure its alignment!
197 	 */
198 	memcpy(sc->sc_enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
199 	myaddr = sc->sc_enaddr;
200 
201 	init.init_padr[0] = myaddr[0] | (myaddr[1] << 8) |
202 	    (myaddr[2] << 16) | (myaddr[3] << 24);
203 	init.init_padr[1] = myaddr[4] | (myaddr[5] << 8);
204 	lance_setladrf(&sc->sc_arpcom, init.init_ladrf);
205 
206 	sc->sc_last_rd = 0;
207 	sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
208 
209 	a = sc->sc_addr + LE_RMDADDR(sc, 0);
210 	init.init_rdra = a;
211 
212 	a = sc->sc_addr + LE_TMDADDR(sc, 0);
213 	init.init_tdra = a;
214 
215 	(*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
216 
217 	/*
218 	 * Set up receive ring descriptors.
219 	 */
220 	for (bix = 0; bix < sc->sc_nrbuf; bix++) {
221 		a = sc->sc_addr + LE_RBUFADDR(sc, bix);
222 		rmd.rmd0 = a;
223 		rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff);
224 		rmd.rmd2 = 0;
225 		rmd.rmd3 = 0;
226 		(*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
227 		    sizeof(rmd));
228 	}
229 
230 	/*
231 	 * Set up transmit ring descriptors.
232 	 */
233 	for (bix = 0; bix < sc->sc_ntbuf; bix++) {
234 		a = sc->sc_addr + LE_TBUFADDR(sc, bix);
235 		tmd.tmd0 = a;
236 		tmd.tmd1 = LE_T1_ONES;
237 		tmd.tmd2 = 0;
238 		tmd.tmd3 = 0;
239 		(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
240 		    sizeof(tmd));
241 	}
242 }
243 
244 void
am79900_rint(struct lance_softc * sc)245 am79900_rint(struct lance_softc *sc)
246 {
247 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
248 	struct mbuf *m;
249 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
250 	int bix;
251 	int rp;
252 	struct lermd rmd;
253 
254 	bix = sc->sc_last_rd;
255 
256 	/* Process all buffers with valid data. */
257 	for (;;) {
258 		rp = LE_RMDADDR(sc, bix);
259 		(*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
260 
261 		if (rmd.rmd1 & LE_R1_OWN)
262 			break;
263 
264 		if (rmd.rmd1 & LE_R1_ERR) {
265 			if (rmd.rmd1 & LE_R1_ENP) {
266 #ifdef LEDEBUG
267 				if ((rmd.rmd1 & LE_R1_OFLO) == 0) {
268 					if (rmd.rmd1 & LE_R1_FRAM)
269 						printf("%s: framing error\n",
270 						    sc->sc_dev.dv_xname);
271 					if (rmd.rmd1 & LE_R1_CRC)
272 						printf("%s: crc mismatch\n",
273 						    sc->sc_dev.dv_xname);
274 				}
275 #endif
276 			} else {
277 				if (rmd.rmd1 & LE_R1_OFLO)
278 					printf("%s: overflow\n",
279 					    sc->sc_dev.dv_xname);
280 			}
281 			if (rmd.rmd1 & LE_R1_BUFF)
282 				printf("%s: receive buffer error\n",
283 				    sc->sc_dev.dv_xname);
284 			ifp->if_ierrors++;
285 		} else if ((rmd.rmd1 & (LE_R1_STP | LE_R1_ENP)) !=
286 		    (LE_R1_STP | LE_R1_ENP)) {
287 			printf("%s: dropping chained buffer\n",
288 			    sc->sc_dev.dv_xname);
289 			ifp->if_ierrors++;
290 		} else {
291 #ifdef LEDEBUG
292 			if (sc->sc_debug > 1)
293 				am79900_recv_print(sc, sc->sc_last_rd);
294 #endif
295 			m = lance_read(sc, LE_RBUFADDR(sc, bix),
296 			    (rmd.rmd2  & 0xfff) - 4);
297 			if (m != NULL)
298 				ml_enqueue(&ml, m);
299 		}
300 
301 		rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff);
302 		rmd.rmd2 = 0;
303 		rmd.rmd3 = 0;
304 		(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
305 
306 #ifdef LEDEBUG
307 		if (sc->sc_debug)
308 			printf("sc->sc_last_rd = %x, rmd: "
309 			       "adr %08x, flags/blen %08x\n",
310 				sc->sc_last_rd,
311 				rmd.rmd0, rmd.rmd1);
312 #endif
313 
314 		if (++bix == sc->sc_nrbuf)
315 			bix = 0;
316 	}
317 
318 	sc->sc_last_rd = bix;
319 
320 	if_input(ifp, &ml);
321 }
322 
323 void
am79900_tint(struct lance_softc * sc)324 am79900_tint(struct lance_softc *sc)
325 {
326 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
327 	int bix;
328 	struct letmd tmd;
329 
330 	bix = sc->sc_first_td;
331 
332 	for (;;) {
333 		if (sc->sc_no_td <= 0)
334 			break;
335 
336 		(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
337 		    sizeof(tmd));
338 
339 #ifdef LEDEBUG
340 		if (sc->sc_debug)
341 			printf("trans tmd: "
342 			    "adr %08x, flags/blen %08x\n",
343 			    tmd.tmd0, tmd.tmd1);
344 #endif
345 
346 		if (tmd.tmd1 & LE_T1_OWN)
347 			break;
348 
349 		ifq_clr_oactive(&ifp->if_snd);
350 
351 		if (tmd.tmd1 & LE_T1_ERR) {
352 			if (tmd.tmd2 & LE_T2_BUFF)
353 				printf("%s: transmit buffer error\n",
354 				    sc->sc_dev.dv_xname);
355 			else if (tmd.tmd2 & LE_T2_UFLO)
356 				printf("%s: underflow\n", sc->sc_dev.dv_xname);
357 			if (tmd.tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) {
358 				lance_reset(sc);
359 				return;
360 			}
361 			if (tmd.tmd2 & LE_T2_LCAR) {
362 				sc->sc_havecarrier = 0;
363 				if (sc->sc_nocarrier)
364 					(*sc->sc_nocarrier)(sc);
365 				else
366 					printf("%s: lost carrier\n",
367 					    sc->sc_dev.dv_xname);
368 			}
369 			if (tmd.tmd2 & LE_T2_LCOL)
370 				ifp->if_collisions++;
371 			if (tmd.tmd2 & LE_T2_RTRY) {
372 #ifdef LEDEBUG
373 				printf("%s: excessive collisions\n",
374 				    sc->sc_dev.dv_xname);
375 #endif
376 				ifp->if_collisions += 16;
377 			}
378 			ifp->if_oerrors++;
379 		} else {
380 			if (tmd.tmd1 & LE_T1_ONE)
381 				ifp->if_collisions++;
382 			else if (tmd.tmd1 & LE_T1_MORE)
383 				/* Real number is unknown. */
384 				ifp->if_collisions += 2;
385 		}
386 
387 		if (++bix == sc->sc_ntbuf)
388 			bix = 0;
389 
390 		--sc->sc_no_td;
391 	}
392 
393 	sc->sc_first_td = bix;
394 
395 	am79900_start(ifp);
396 
397 	if (sc->sc_no_td == 0)
398 		ifp->if_timer = 0;
399 }
400 
401 /*
402  * Controller interrupt.
403  */
404 int
am79900_intr(void * arg)405 am79900_intr(void *arg)
406 {
407 	struct lance_softc *sc = arg;
408 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
409 	uint16_t isr;
410 
411 	isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
412 	sc->sc_saved_csr0 = 0;
413 #if defined(LEDEBUG) && LEDEBUG > 1
414 	if (sc->sc_debug)
415 		printf("%s: am79900_intr entering with isr=%04x\n",
416 		    sc->sc_dev.dv_xname, isr);
417 #endif
418 	if ((isr & LE_C0_INTR) == 0)
419 		return (0);
420 
421 	(*sc->sc_wrcsr)(sc, LE_CSR0,
422 	    isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
423 		   LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
424 	if (isr & LE_C0_ERR) {
425 		if (isr & LE_C0_BABL) {
426 #ifdef LEDEBUG
427 			printf("%s: babble\n", sc->sc_dev.dv_xname);
428 #endif
429 			ifp->if_oerrors++;
430 		}
431 #if 0
432 		if (isr & LE_C0_CERR) {
433 			printf("%s: collision error\n",
434 			    sc->sc_dev.dv_xname);
435 			ifp->if_collisions++;
436 		}
437 #endif
438 		if (isr & LE_C0_MISS) {
439 #ifdef LEDEBUG
440 			printf("%s: missed packet\n", sc->sc_dev.dv_xname);
441 #endif
442 			ifp->if_ierrors++;
443 		}
444 		if (isr & LE_C0_MERR) {
445 			printf("%s: memory error\n", sc->sc_dev.dv_xname);
446 			lance_reset(sc);
447 			return (1);
448 		}
449 	}
450 
451 	if ((isr & LE_C0_RXON) == 0) {
452 		printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
453 		ifp->if_ierrors++;
454 		lance_reset(sc);
455 		return (1);
456 	}
457 	if ((isr & LE_C0_TXON) == 0) {
458 		printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
459 		ifp->if_oerrors++;
460 		lance_reset(sc);
461 		return (1);
462 	}
463 
464 	/*
465 	 * Pretend we have carrier; if we don't this will be cleared
466 	 * shortly.
467 	 */
468 	sc->sc_havecarrier = 1;
469 
470 	if (isr & LE_C0_RINT)
471 		am79900_rint(sc);
472 	if (isr & LE_C0_TINT)
473 		am79900_tint(sc);
474 
475 	return (1);
476 }
477 
478 /*
479  * Setup output on interface.
480  * Get another datagram to send off of the interface queue, and map it to the
481  * interface before starting the output.
482  * Called only at splnet or interrupt level.
483  */
484 void
am79900_start(struct ifnet * ifp)485 am79900_start(struct ifnet *ifp)
486 {
487 	struct lance_softc *sc = ifp->if_softc;
488 	int bix;
489 	struct mbuf *m;
490 	struct letmd tmd;
491 	int rp;
492 	int len;
493 
494 	if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
495 		return;
496 
497 	bix = sc->sc_last_td;
498 
499 	for (;;) {
500 		rp = LE_TMDADDR(sc, bix);
501 		(*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
502 
503 		if (tmd.tmd1 & LE_T1_OWN) {
504 			ifq_set_oactive(&ifp->if_snd);
505 			printf("missing buffer, no_td = %d, last_td = %d\n",
506 			    sc->sc_no_td, sc->sc_last_td);
507 		}
508 
509 		m = ifq_dequeue(&ifp->if_snd);
510 		if (m == NULL)
511 			break;
512 
513 #if NBPFILTER > 0
514 		/*
515 		 * If BPF is listening on this interface, let it see the packet
516 		 * before we commit it to the wire.
517 		 */
518 		if (ifp->if_bpf)
519 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
520 #endif
521 
522 		/*
523 		 * Copy the mbuf chain into the transmit buffer.
524 		 */
525 		len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
526 
527 #ifdef LEDEBUG
528 		if (len > ETHERMTU + sizeof(struct ether_header))
529 			printf("packet length %d\n", len);
530 #endif
531 
532 		ifp->if_timer = 5;
533 
534 		/*
535 		 * Init transmit registers, and set transmit start flag.
536 		 */
537 		tmd.tmd1 = LE_T1_OWN | LE_T1_STP | LE_T1_ENP | LE_T1_ONES |
538 		    (-len & 0xfff);
539 		tmd.tmd2 = 0;
540 		tmd.tmd3 = 0;
541 
542 		(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
543 
544 #ifdef LEDEBUG
545 		if (sc->sc_debug > 1)
546 			am79900_xmit_print(sc, sc->sc_last_td);
547 #endif
548 
549 		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
550 
551 		if (++bix == sc->sc_ntbuf)
552 			bix = 0;
553 
554 		if (++sc->sc_no_td == sc->sc_ntbuf) {
555 			ifq_set_oactive(&ifp->if_snd);
556 			break;
557 		}
558 
559 	}
560 
561 	sc->sc_last_td = bix;
562 }
563 
564 #ifdef LEDEBUG
565 void
am79900_recv_print(struct lance_softc * sc,int no)566 am79900_recv_print(struct lance_softc *sc, int no)
567 {
568 	struct lermd rmd;
569 	uint16_t len;
570 	struct ether_header eh;
571 
572 	(*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
573 	len = (rmd.rmd2  & 0xfff) - 4;
574 	printf("%s: receive buffer %d, len = %d\n",
575 	    sc->sc_dev.dv_xname, no, len);
576 	printf("%s: status %04x\n", sc->sc_dev.dv_xname,
577 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
578 	printf("%s: adr %08x, flags/blen %08x\n",
579 	    sc->sc_dev.dv_xname, rmd.rmd0, rmd.rmd1);
580 	if (len >= sizeof(eh)) {
581 		(*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
582 		printf("%s: dst %s", sc->sc_dev.dv_xname,
583 			ether_sprintf(eh.ether_dhost));
584 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
585 			ntohs(eh.ether_type));
586 	}
587 }
588 
589 void
am79900_xmit_print(struct lance_softc * sc,int no)590 am79900_xmit_print(struct lance_softc *sc, int no)
591 {
592 	struct letmd tmd;
593 	uint16_t len;
594 	struct ether_header eh;
595 
596 	(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
597 	len = -(tmd.tmd1 & 0xfff);
598 	printf("%s: transmit buffer %d, len = %d\n",
599 	    sc->sc_dev.dv_xname, no, len);
600 	printf("%s: status %04x\n", sc->sc_dev.dv_xname,
601 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
602 	printf("%s: adr %08x, flags/blen %08x\n",
603 	    sc->sc_dev.dv_xname, tmd.tmd0, tmd.tmd1);
604 	if (len >= sizeof(eh)) {
605 		(*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
606 		printf("%s: dst %s", sc->sc_dev.dv_xname,
607 			ether_sprintf(eh.ether_dhost));
608 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
609 		    ntohs(eh.ether_type));
610 	}
611 }
612 #endif /* LEDEBUG */
613