1 /*	$NetBSD: am7990.c,v 1.75 2015/04/13 16:33:24 riastradh Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9  * Simulation Facility, NASA Ames Research Center.
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 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: am7990.c,v 1.75 2015/04/13 16:33:24 riastradh Exp $");
69 
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/mbuf.h>
73 #include <sys/syslog.h>
74 #include <sys/socket.h>
75 #include <sys/device.h>
76 #include <sys/malloc.h>
77 #include <sys/ioctl.h>
78 #include <sys/errno.h>
79 #include <sys/rndsource.h>
80 
81 #include <net/if.h>
82 #include <net/if_dl.h>
83 #include <net/if_ether.h>
84 #include <net/if_media.h>
85 
86 #include <net/bpf.h>
87 #include <net/bpfdesc.h>
88 
89 #include <dev/ic/lancereg.h>
90 #include <dev/ic/lancevar.h>
91 #include <dev/ic/am7990reg.h>
92 #include <dev/ic/am7990var.h>
93 
94 static void	am7990_meminit(struct lance_softc *);
95 static void	am7990_start(struct ifnet *);
96 
97 #if defined(_KERNEL_OPT)
98 #include "opt_ddb.h"
99 #endif
100 
101 #ifdef LEDEBUG
102 static void	am7990_recv_print(struct lance_softc *, int);
103 static void	am7990_xmit_print(struct lance_softc *, int);
104 #endif
105 
106 #define	ifp	(&sc->sc_ethercom.ec_if)
107 
108 void
am7990_config(struct am7990_softc * sc)109 am7990_config(struct am7990_softc *sc)
110 {
111 	int mem, i;
112 
113 	sc->lsc.sc_meminit = am7990_meminit;
114 	sc->lsc.sc_start = am7990_start;
115 
116 	lance_config(&sc->lsc);
117 
118 	mem = 0;
119 	sc->lsc.sc_initaddr = mem;
120 	mem += sizeof(struct leinit);
121 	sc->lsc.sc_rmdaddr = mem;
122 	mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
123 	sc->lsc.sc_tmdaddr = mem;
124 	mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
125 	for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN)
126 		sc->lsc.sc_rbufaddr[i] = mem;
127 	for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN)
128 		sc->lsc.sc_tbufaddr[i] = mem;
129 #ifdef notyet
130 	if (mem > ...)
131 		panic(...);
132 #endif
133 }
134 
135 /*
136  * Set up the initialization block and the descriptor rings.
137  */
138 static void
am7990_meminit(struct lance_softc * sc)139 am7990_meminit(struct lance_softc *sc)
140 {
141 	u_long a;
142 	int bix;
143 	struct leinit init;
144 	struct lermd rmd;
145 	struct letmd tmd;
146 	uint8_t *myaddr;
147 
148 	if (ifp->if_flags & IFF_PROMISC)
149 		init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
150 	else
151 		init.init_mode = LE_MODE_NORMAL;
152 	if (sc->sc_initmodemedia == 1)
153 		init.init_mode |= LE_MODE_PSEL0;
154 
155 	/*
156 	 * Update our private copy of the Ethernet address.
157 	 * We NEED the copy so we can ensure its alignment!
158 	 */
159 	memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
160 	myaddr = sc->sc_enaddr;
161 
162 	init.init_padr[0] = (myaddr[1] << 8) | myaddr[0];
163 	init.init_padr[1] = (myaddr[3] << 8) | myaddr[2];
164 	init.init_padr[2] = (myaddr[5] << 8) | myaddr[4];
165 	lance_setladrf(&sc->sc_ethercom, init.init_ladrf);
166 
167 	sc->sc_last_rd = 0;
168 	sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
169 
170 	a = sc->sc_addr + LE_RMDADDR(sc, 0);
171 	init.init_rdra = a;
172 	init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
173 
174 	a = sc->sc_addr + LE_TMDADDR(sc, 0);
175 	init.init_tdra = a;
176 	init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
177 
178 	(*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
179 
180 	/*
181 	 * Set up receive ring descriptors.
182 	 */
183 	for (bix = 0; bix < sc->sc_nrbuf; bix++) {
184 		a = sc->sc_addr + LE_RBUFADDR(sc, bix);
185 		rmd.rmd0 = a;
186 		rmd.rmd1_hadr = a >> 16;
187 		rmd.rmd1_bits = LE_R1_OWN;
188 		rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
189 		rmd.rmd3 = 0;
190 		(*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
191 		    sizeof(rmd));
192 	}
193 
194 	/*
195 	 * Set up transmit ring descriptors.
196 	 */
197 	for (bix = 0; bix < sc->sc_ntbuf; bix++) {
198 		a = sc->sc_addr + LE_TBUFADDR(sc, bix);
199 		tmd.tmd0 = a;
200 		tmd.tmd1_hadr = a >> 16;
201 		tmd.tmd1_bits = 0;
202 		tmd.tmd2 = 0 | LE_XMD2_ONES;
203 		tmd.tmd3 = 0;
204 		(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
205 		    sizeof(tmd));
206 	}
207 }
208 
209 static void
am7990_rint(struct lance_softc * sc)210 am7990_rint(struct lance_softc *sc)
211 {
212 	int bix;
213 	int rp;
214 	struct lermd rmd;
215 
216 	bix = sc->sc_last_rd;
217 
218 	/* Process all buffers with valid data. */
219 	for (;;) {
220 		rp = LE_RMDADDR(sc, bix);
221 		(*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
222 
223 		if (rmd.rmd1_bits & LE_R1_OWN)
224 			break;
225 
226 		if (rmd.rmd1_bits & LE_R1_ERR) {
227 			if (rmd.rmd1_bits & LE_R1_ENP) {
228 #ifdef LEDEBUG
229 				if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
230 					if (rmd.rmd1_bits & LE_R1_FRAM)
231 						printf("%s: framing error\n",
232 						    device_xname(sc->sc_dev));
233 					if (rmd.rmd1_bits & LE_R1_CRC)
234 						printf("%s: crc mismatch\n",
235 						    device_xname(sc->sc_dev));
236 				}
237 #endif
238 			} else {
239 				if (rmd.rmd1_bits & LE_R1_OFLO)
240 					printf("%s: overflow\n",
241 					    device_xname(sc->sc_dev));
242 			}
243 			if (rmd.rmd1_bits & LE_R1_BUFF)
244 				printf("%s: receive buffer error\n",
245 				    device_xname(sc->sc_dev));
246 			ifp->if_ierrors++;
247 		} else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
248 		    (LE_R1_STP | LE_R1_ENP)) {
249 			printf("%s: dropping chained buffer\n",
250 			    device_xname(sc->sc_dev));
251 			ifp->if_ierrors++;
252 		} else {
253 #ifdef LEDEBUG
254 			if (sc->sc_debug > 1)
255 				am7990_recv_print(sc, sc->sc_last_rd);
256 #endif
257 			lance_read(sc, LE_RBUFADDR(sc, bix),
258 				   (int)rmd.rmd3 - 4);
259 		}
260 
261 		rmd.rmd1_bits = LE_R1_OWN;
262 		rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
263 		rmd.rmd3 = 0;
264 		(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
265 
266 #ifdef LEDEBUG
267 		if (sc->sc_debug)
268 			printf("sc->sc_last_rd = %x, rmd: "
269 			       "ladr %04x, hadr %02x, flags %02x, "
270 			       "bcnt %04x, mcnt %04x\n",
271 				sc->sc_last_rd,
272 				rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
273 				rmd.rmd2, rmd.rmd3);
274 #endif
275 
276 		if (++bix == sc->sc_nrbuf)
277 			bix = 0;
278 	}
279 
280 	sc->sc_last_rd = bix;
281 }
282 
283 static void
am7990_tint(struct lance_softc * sc)284 am7990_tint(struct lance_softc *sc)
285 {
286 	int bix;
287 	struct letmd tmd;
288 
289 	bix = sc->sc_first_td;
290 
291 	for (;;) {
292 		if (sc->sc_no_td <= 0)
293 			break;
294 
295 		(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
296 		    sizeof(tmd));
297 
298 #ifdef LEDEBUG
299 		if (sc->sc_debug)
300 			printf("trans tmd: "
301 			    "ladr %04x, hadr %02x, flags %02x, "
302 			    "bcnt %04x, mcnt %04x\n",
303 			    tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
304 			    tmd.tmd2, tmd.tmd3);
305 #endif
306 
307 		if (tmd.tmd1_bits & LE_T1_OWN)
308 			break;
309 
310 		ifp->if_flags &= ~IFF_OACTIVE;
311 
312 		if (tmd.tmd1_bits & LE_T1_ERR) {
313 			if (tmd.tmd3 & LE_T3_BUFF)
314 				printf("%s: transmit buffer error\n",
315 				    device_xname(sc->sc_dev));
316 			else if (tmd.tmd3 & LE_T3_UFLO)
317 				printf("%s: underflow\n",
318 				    device_xname(sc->sc_dev));
319 			if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
320 				lance_reset(sc);
321 				return;
322 			}
323 			if (tmd.tmd3 & LE_T3_LCAR) {
324 				sc->sc_havecarrier = 0;
325 				if (sc->sc_nocarrier)
326 					(*sc->sc_nocarrier)(sc);
327 				else
328 					printf("%s: lost carrier\n",
329 					    device_xname(sc->sc_dev));
330 			}
331 			if (tmd.tmd3 & LE_T3_LCOL)
332 				ifp->if_collisions++;
333 			if (tmd.tmd3 & LE_T3_RTRY) {
334 #ifdef LEDEBUG
335 				printf("%s: excessive collisions, tdr %d\n",
336 				    device_xname(sc->sc_dev),
337 				    tmd.tmd3 & LE_T3_TDR_MASK);
338 #endif
339 				ifp->if_collisions += 16;
340 			}
341 			ifp->if_oerrors++;
342 		} else {
343 			if (tmd.tmd1_bits & LE_T1_ONE)
344 				ifp->if_collisions++;
345 			else if (tmd.tmd1_bits & LE_T1_MORE)
346 				/* Real number is unknown. */
347 				ifp->if_collisions += 2;
348 			ifp->if_opackets++;
349 		}
350 
351 		if (++bix == sc->sc_ntbuf)
352 			bix = 0;
353 
354 		--sc->sc_no_td;
355 	}
356 
357 	sc->sc_first_td = bix;
358 
359 	am7990_start(ifp);
360 
361 	if (sc->sc_no_td == 0)
362 		ifp->if_timer = 0;
363 }
364 
365 /*
366  * Controller interrupt.
367  */
368 int
am7990_intr(void * arg)369 am7990_intr(void *arg)
370 {
371 	struct lance_softc *sc = arg;
372 	uint16_t isr;
373 
374 	isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
375 	sc->sc_saved_csr0 = 0;
376 #if defined(LEDEBUG) && LEDEBUG > 1
377 	if (sc->sc_debug)
378 		printf("%s: am7990_intr entering with isr=%04x\n",
379 		    device_xname(sc->sc_dev), isr);
380 #endif
381 	if ((isr & LE_C0_INTR) == 0)
382 		return (0);
383 
384 #ifdef __vax__
385 	/*
386 	 * DEC needs this write order to the registers, don't know
387 	 * the results on other arch's.  Ragge 991029
388 	 */
389 	isr &= ~LE_C0_INEA;
390 	(*sc->sc_wrcsr)(sc, LE_CSR0, isr);
391 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
392 #else
393 	(*sc->sc_wrcsr)(sc, LE_CSR0,
394 	    isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
395 		   LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
396 #endif
397 	if (isr & LE_C0_ERR) {
398 		if (isr & LE_C0_BABL) {
399 #ifdef LEDEBUG
400 			printf("%s: babble\n", device_xname(sc->sc_dev));
401 #endif
402 			ifp->if_oerrors++;
403 		}
404 #if 0
405 		if (isr & LE_C0_CERR) {
406 			printf("%s: collision error\n",
407 			    device_xname(sc->sc_dev));
408 			ifp->if_collisions++;
409 		}
410 #endif
411 		if (isr & LE_C0_MISS) {
412 #ifdef LEDEBUG
413 			printf("%s: missed packet\n", device_xname(sc->sc_dev));
414 #endif
415 			ifp->if_ierrors++;
416 		}
417 		if (isr & LE_C0_MERR) {
418 			printf("%s: memory error\n", device_xname(sc->sc_dev));
419 			lance_reset(sc);
420 			return (1);
421 		}
422 	}
423 
424 	if ((isr & LE_C0_RXON) == 0) {
425 		printf("%s: receiver disabled\n", device_xname(sc->sc_dev));
426 		ifp->if_ierrors++;
427 		lance_reset(sc);
428 		return (1);
429 	}
430 	if ((isr & LE_C0_TXON) == 0) {
431 		printf("%s: transmitter disabled\n", device_xname(sc->sc_dev));
432 		ifp->if_oerrors++;
433 		lance_reset(sc);
434 		return (1);
435 	}
436 
437 	/*
438 	 * Pretend we have carrier; if we don't this will be cleared
439 	 * shortly.
440 	 */
441 	sc->sc_havecarrier = 1;
442 
443 	if (isr & LE_C0_RINT)
444 		am7990_rint(sc);
445 	if (isr & LE_C0_TINT)
446 		am7990_tint(sc);
447 
448 	rnd_add_uint32(&sc->rnd_source, isr);
449 
450 	return (1);
451 }
452 
453 #undef ifp
454 
455 /*
456  * Setup output on interface.
457  * Get another datagram to send off of the interface queue, and map it to the
458  * interface before starting the output.
459  * Called only at splnet or interrupt level.
460  */
461 static void
am7990_start(struct ifnet * ifp)462 am7990_start(struct ifnet *ifp)
463 {
464 	struct lance_softc *sc = ifp->if_softc;
465 	int bix;
466 	struct mbuf *m;
467 	struct letmd tmd;
468 	int rp;
469 	int len;
470 
471 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
472 		return;
473 
474 	bix = sc->sc_last_td;
475 
476 	for (;;) {
477 		rp = LE_TMDADDR(sc, bix);
478 		(*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
479 
480 		if (tmd.tmd1_bits & LE_T1_OWN) {
481 			ifp->if_flags |= IFF_OACTIVE;
482 			printf("missing buffer, no_td = %d, last_td = %d\n",
483 			    sc->sc_no_td, sc->sc_last_td);
484 		}
485 
486 		IFQ_DEQUEUE(&ifp->if_snd, m);
487 		if (m == 0)
488 			break;
489 
490 		/*
491 		 * If BPF is listening on this interface, let it see the packet
492 		 * before we commit it to the wire.
493 		 */
494 		bpf_mtap(ifp, m);
495 
496 		/*
497 		 * Copy the mbuf chain into the transmit buffer.
498 		 */
499 		len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
500 
501 #ifdef LEDEBUG
502 		if (len > ETHERMTU + sizeof(struct ether_header))
503 			printf("packet length %d\n", len);
504 #endif
505 
506 		ifp->if_timer = 5;
507 
508 		/*
509 		 * Init transmit registers, and set transmit start flag.
510 		 */
511 		tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
512 		tmd.tmd2 = -len | LE_XMD2_ONES;
513 		tmd.tmd3 = 0;
514 
515 		(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
516 
517 #ifdef LEDEBUG
518 		if (sc->sc_debug > 1)
519 			am7990_xmit_print(sc, sc->sc_last_td);
520 #endif
521 
522 		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
523 
524 		if (++bix == sc->sc_ntbuf)
525 			bix = 0;
526 
527 		if (++sc->sc_no_td == sc->sc_ntbuf) {
528 			ifp->if_flags |= IFF_OACTIVE;
529 			break;
530 		}
531 
532 	}
533 
534 	sc->sc_last_td = bix;
535 }
536 
537 #ifdef LEDEBUG
538 static void
am7990_recv_print(struct lance_softc * sc,int no)539 am7990_recv_print(struct lance_softc *sc, int no)
540 {
541 	struct lermd rmd;
542 	uint16_t len;
543 	struct ether_header eh;
544 
545 	(*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
546 	len = rmd.rmd3;
547 	printf("%s: receive buffer %d, len = %d\n",
548 	    device_xname(sc->sc_dev), no, len);
549 	printf("%s: status %04x\n", device_xname(sc->sc_dev),
550 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
551 	printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
552 	    device_xname(sc->sc_dev),
553 	    rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
554 	if (len >= sizeof(eh)) {
555 		(*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
556 		printf("%s: dst %s", device_xname(sc->sc_dev),
557 			ether_sprintf(eh.ether_dhost));
558 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
559 			ntohs(eh.ether_type));
560 	}
561 }
562 
563 static void
am7990_xmit_print(struct lance_softc * sc,int no)564 am7990_xmit_print(struct lance_softc *sc, int no)
565 {
566 	struct letmd tmd;
567 	uint16_t len;
568 	struct ether_header eh;
569 
570 	(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
571 	len = -tmd.tmd2;
572 	printf("%s: transmit buffer %d, len = %d\n",
573 	    device_xname(sc->sc_dev), no, len);
574 	printf("%s: status %04x\n", device_xname(sc->sc_dev),
575 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
576 	printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
577 	    device_xname(sc->sc_dev),
578 	    tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
579 	if (len >= sizeof(eh)) {
580 		(*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
581 		printf("%s: dst %s", device_xname(sc->sc_dev),
582 			ether_sprintf(eh.ether_dhost));
583 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
584 		    ntohs(eh.ether_type));
585 	}
586 }
587 #endif /* LEDEBUG */
588