1 /* $NetBSD: am7990.c,v 1.68 2005/12/11 12:21:25 christos Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause
5 *
6 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
11 * Simulation Facility, NASA Ames Research Center.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*-
36 * Copyright (c) 1992, 1993
37 * The Regents of the University of California. All rights reserved.
38 *
39 * This code is derived from software contributed to Berkeley by
40 * Ralph Campbell and Rick Macklem.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 */
66
67 #include <sys/param.h>
68 #include <sys/bus.h>
69 #include <sys/endian.h>
70 #include <sys/lock.h>
71 #include <sys/mbuf.h>
72 #include <sys/mutex.h>
73 #include <sys/socket.h>
74
75 #include <net/bpf.h>
76 #include <net/ethernet.h>
77 #include <net/if.h>
78 #include <net/if_arp.h>
79 #include <net/if_dl.h>
80 #include <net/if_media.h>
81 #include <net/if_var.h>
82
83 #include <machine/bus.h>
84
85 #include <dev/le/lancereg.h>
86 #include <dev/le/lancevar.h>
87 #include <dev/le/am7990reg.h>
88 #include <dev/le/am7990var.h>
89
90 static void am7990_meminit(struct lance_softc *);
91 static void am7990_rint(struct lance_softc *);
92 static void am7990_tint(struct lance_softc *);
93 static void am7990_start_locked(struct lance_softc *sc);
94
95 #ifdef LEDEBUG
96 static void am7990_recv_print(struct lance_softc *, int);
97 static void am7990_xmit_print(struct lance_softc *, int);
98 #endif
99
100 int
am7990_config(struct am7990_softc * sc,const char * name,int unit)101 am7990_config(struct am7990_softc *sc, const char* name, int unit)
102 {
103 int error, mem;
104
105 sc->lsc.sc_meminit = am7990_meminit;
106 sc->lsc.sc_start_locked = am7990_start_locked;
107
108 error = lance_config(&sc->lsc, name, unit);
109 if (error != 0)
110 return (error);
111
112 mem = 0;
113 sc->lsc.sc_initaddr = mem;
114 mem += sizeof(struct leinit);
115 sc->lsc.sc_rmdaddr = mem;
116 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
117 sc->lsc.sc_tmdaddr = mem;
118 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
119 sc->lsc.sc_rbufaddr = mem;
120 mem += LEBLEN * sc->lsc.sc_nrbuf;
121 sc->lsc.sc_tbufaddr = mem;
122 mem += LEBLEN * sc->lsc.sc_ntbuf;
123
124 if (mem > sc->lsc.sc_memsize)
125 panic("%s: memsize", __func__);
126
127 lance_attach(&sc->lsc);
128
129 return (0);
130 }
131
132 void
am7990_detach(struct am7990_softc * sc)133 am7990_detach(struct am7990_softc *sc)
134 {
135
136 lance_detach(&sc->lsc);
137 }
138
139 /*
140 * Set up the initialization block and the descriptor rings.
141 */
142 static void
am7990_meminit(struct lance_softc * sc)143 am7990_meminit(struct lance_softc *sc)
144 {
145 if_t ifp = sc->sc_ifp;
146 struct leinit init;
147 struct lermd rmd;
148 struct letmd tmd;
149 u_long a;
150 int bix;
151
152 LE_LOCK_ASSERT(sc, MA_OWNED);
153
154 if (if_getflags(ifp) & IFF_PROMISC)
155 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
156 else
157 init.init_mode = LE_MODE_NORMAL;
158
159 init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
160 init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
161 init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
162 lance_setladrf(sc, init.init_ladrf);
163
164 sc->sc_last_rd = 0;
165 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
166
167 a = sc->sc_addr + LE_RMDADDR(sc, 0);
168 init.init_rdra = a;
169 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
170
171 a = sc->sc_addr + LE_TMDADDR(sc, 0);
172 init.init_tdra = a;
173 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
174
175 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
176
177 /*
178 * Set up receive ring descriptors.
179 */
180 for (bix = 0; bix < sc->sc_nrbuf; bix++) {
181 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
182 rmd.rmd0 = a;
183 rmd.rmd1_hadr = a >> 16;
184 rmd.rmd1_bits = LE_R1_OWN;
185 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
186 rmd.rmd3 = 0;
187 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
188 sizeof(rmd));
189 }
190
191 /*
192 * Set up transmit ring descriptors.
193 */
194 for (bix = 0; bix < sc->sc_ntbuf; bix++) {
195 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
196 tmd.tmd0 = a;
197 tmd.tmd1_hadr = a >> 16;
198 tmd.tmd1_bits = 0;
199 tmd.tmd2 = LE_XMD2_ONES;
200 tmd.tmd3 = 0;
201 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
202 sizeof(tmd));
203 }
204 }
205
206 static void
am7990_rint(struct lance_softc * sc)207 am7990_rint(struct lance_softc *sc)
208 {
209 if_t ifp = sc->sc_ifp;
210 struct mbuf *m;
211 struct lermd rmd;
212 int bix, rp;
213 #if defined(LANCE_REVC_BUG)
214 struct ether_header *eh;
215 /* Make sure this is short-aligned, for ether_cmp(). */
216 static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 };
217 #endif
218
219 bix = sc->sc_last_rd;
220
221 /* Process all buffers with valid data. */
222 for (;;) {
223 rp = LE_RMDADDR(sc, bix);
224 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
225
226 if (rmd.rmd1_bits & LE_R1_OWN)
227 break;
228
229 m = NULL;
230 if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
231 (LE_R1_STP | LE_R1_ENP)) {
232 if (rmd.rmd1_bits & LE_R1_ERR) {
233 #ifdef LEDEBUG
234 if (rmd.rmd1_bits & LE_R1_ENP) {
235 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
236 if (rmd.rmd1_bits & LE_R1_FRAM)
237 if_printf(ifp,
238 "framing error\n");
239 if (rmd.rmd1_bits & LE_R1_CRC)
240 if_printf(ifp,
241 "crc mismatch\n");
242 }
243 } else
244 if (rmd.rmd1_bits & LE_R1_OFLO)
245 if_printf(ifp, "overflow\n");
246 #endif
247 if (rmd.rmd1_bits & LE_R1_BUFF)
248 if_printf(ifp,
249 "receive buffer error\n");
250 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
251 (LE_R1_STP | LE_R1_ENP))
252 if_printf(ifp, "dropping chained buffer\n");
253 } else {
254 #ifdef LEDEBUG
255 if (sc->sc_flags & LE_DEBUG)
256 am7990_recv_print(sc, bix);
257 #endif
258 /* Pull the packet off the interface. */
259 m = lance_get(sc, LE_RBUFADDR(sc, bix),
260 (int)rmd.rmd3 - ETHER_CRC_LEN);
261 }
262
263 rmd.rmd1_bits = LE_R1_OWN;
264 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
265 rmd.rmd3 = 0;
266 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
267
268 if (++bix == sc->sc_nrbuf)
269 bix = 0;
270
271 if (m != NULL) {
272 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
273
274 #ifdef LANCE_REVC_BUG
275 /*
276 * The old LANCE (Rev. C) chips have a bug which
277 * causes garbage to be inserted in front of the
278 * received packet. The workaround is to ignore
279 * packets with an invalid destination address
280 * (garbage will usually not match).
281 * Of course, this precludes multicast support...
282 */
283 eh = mtod(m, struct ether_header *);
284 if (ether_cmp(eh->ether_dhost, sc->sc_enaddr) &&
285 ether_cmp(eh->ether_dhost, bcast_enaddr)) {
286 m_freem(m);
287 continue;
288 }
289 #endif
290
291 /* Pass the packet up. */
292 LE_UNLOCK(sc);
293 if_input(ifp, m);
294 LE_LOCK(sc);
295 } else
296 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
297 }
298
299 sc->sc_last_rd = bix;
300 }
301
302 static void
am7990_tint(struct lance_softc * sc)303 am7990_tint(struct lance_softc *sc)
304 {
305 if_t ifp = sc->sc_ifp;
306 struct letmd tmd;
307 int bix;
308
309 bix = sc->sc_first_td;
310
311 for (;;) {
312 if (sc->sc_no_td <= 0)
313 break;
314
315 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
316 sizeof(tmd));
317
318 #ifdef LEDEBUG
319 if (sc->sc_flags & LE_DEBUG)
320 if_printf(ifp, "trans tmd: "
321 "ladr %04x, hadr %02x, flags %02x, "
322 "bcnt %04x, mcnt %04x\n",
323 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
324 tmd.tmd2, tmd.tmd3);
325 #endif
326
327 if (tmd.tmd1_bits & LE_T1_OWN)
328 break;
329
330 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
331
332 if (tmd.tmd1_bits & LE_T1_ERR) {
333 if (tmd.tmd3 & LE_T3_BUFF)
334 if_printf(ifp, "transmit buffer error\n");
335 else if (tmd.tmd3 & LE_T3_UFLO)
336 if_printf(ifp, "underflow\n");
337 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
338 lance_init_locked(sc);
339 return;
340 }
341 if (tmd.tmd3 & LE_T3_LCAR) {
342 if (sc->sc_flags & LE_CARRIER)
343 if_link_state_change(ifp,
344 LINK_STATE_DOWN);
345 sc->sc_flags &= ~LE_CARRIER;
346 if (sc->sc_nocarrier)
347 (*sc->sc_nocarrier)(sc);
348 else
349 if_printf(ifp, "lost carrier\n");
350 }
351 if (tmd.tmd3 & LE_T3_LCOL)
352 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
353 if (tmd.tmd3 & LE_T3_RTRY) {
354 #ifdef LEDEBUG
355 if_printf(ifp, "excessive collisions, tdr %d\n",
356 tmd.tmd3 & LE_T3_TDR_MASK);
357 #endif
358 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16);
359 }
360 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
361 } else {
362 if (tmd.tmd1_bits & LE_T1_ONE)
363 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
364 else if (tmd.tmd1_bits & LE_T1_MORE)
365 /* Real number is unknown. */
366 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2);
367 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
368 }
369
370 if (++bix == sc->sc_ntbuf)
371 bix = 0;
372
373 --sc->sc_no_td;
374 }
375
376 sc->sc_first_td = bix;
377
378 sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0;
379 }
380
381 /*
382 * Controller interrupt
383 */
384 void
am7990_intr(void * arg)385 am7990_intr(void *arg)
386 {
387 struct lance_softc *sc = arg;
388 if_t ifp = sc->sc_ifp;
389 uint16_t isr;
390
391 LE_LOCK(sc);
392
393 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) {
394 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
395 lance_init_locked(sc);
396 LE_UNLOCK(sc);
397 return;
398 }
399
400 isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
401 #if defined(LEDEBUG) && LEDEBUG > 1
402 if (sc->sc_flags & LE_DEBUG)
403 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr);
404 #endif
405 if ((isr & LE_C0_INTR) == 0) {
406 LE_UNLOCK(sc);
407 return;
408 }
409
410 /*
411 * Clear interrupt source flags and turn off interrupts. If we
412 * don't clear these flags before processing their sources we
413 * could completely miss some interrupt events as the NIC can
414 * change these flags while we're in this handler. We toggle
415 * the interrupt enable bit in order to keep receiving them
416 * (some chips work without this, some don't).
417 */
418 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD |
419 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT));
420
421 if (isr & LE_C0_ERR) {
422 if (isr & LE_C0_BABL) {
423 #ifdef LEDEBUG
424 if_printf(ifp, "babble\n");
425 #endif
426 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
427 }
428 #if 0
429 if (isr & LE_C0_CERR) {
430 if_printf(ifp, "collision error\n");
431 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
432 }
433 #endif
434 if (isr & LE_C0_MISS) {
435 #ifdef LEDEBUG
436 if_printf(ifp, "missed packet\n");
437 #endif
438 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
439 }
440 if (isr & LE_C0_MERR) {
441 if_printf(ifp, "memory error\n");
442 lance_init_locked(sc);
443 LE_UNLOCK(sc);
444 return;
445 }
446 }
447
448 if ((isr & LE_C0_RXON) == 0) {
449 if_printf(ifp, "receiver disabled\n");
450 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
451 lance_init_locked(sc);
452 LE_UNLOCK(sc);
453 return;
454 }
455 if ((isr & LE_C0_TXON) == 0) {
456 if_printf(ifp, "transmitter disabled\n");
457 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
458 lance_init_locked(sc);
459 LE_UNLOCK(sc);
460 return;
461 }
462
463 /*
464 * Pretend we have carrier; if we don't this will be cleared shortly.
465 */
466 if (!(sc->sc_flags & LE_CARRIER))
467 if_link_state_change(ifp, LINK_STATE_UP);
468 sc->sc_flags |= LE_CARRIER;
469
470 if (isr & LE_C0_RINT)
471 am7990_rint(sc);
472 if (isr & LE_C0_TINT)
473 am7990_tint(sc);
474
475 /* Enable interrupts again. */
476 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
477
478 if (!if_sendq_empty(ifp))
479 am7990_start_locked(sc);
480
481 LE_UNLOCK(sc);
482 }
483
484 /*
485 * Set up output on interface.
486 * Get another datagram to send off of the interface queue, and map it to the
487 * interface before starting the output.
488 */
489 static void
am7990_start_locked(struct lance_softc * sc)490 am7990_start_locked(struct lance_softc *sc)
491 {
492 if_t ifp = sc->sc_ifp;
493 struct letmd tmd;
494 struct mbuf *m;
495 int bix, enq, len, rp;
496
497 LE_LOCK_ASSERT(sc, MA_OWNED);
498
499 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
500 IFF_DRV_RUNNING)
501 return;
502
503 bix = sc->sc_last_td;
504 enq = 0;
505
506 for (; sc->sc_no_td < sc->sc_ntbuf &&
507 !if_sendq_empty(ifp);) {
508 rp = LE_TMDADDR(sc, bix);
509 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
510
511 if (tmd.tmd1_bits & LE_T1_OWN) {
512 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
513 if_printf(ifp,
514 "missing buffer, no_td = %d, last_td = %d\n",
515 sc->sc_no_td, sc->sc_last_td);
516 }
517
518 m = if_dequeue(ifp);
519 if (m == NULL)
520 break;
521
522 /*
523 * If BPF is listening on this interface, let it see the packet
524 * before we commit it to the wire.
525 */
526 BPF_MTAP(ifp, m);
527
528 /*
529 * Copy the mbuf chain into the transmit buffer.
530 */
531 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
532
533 #ifdef LEDEBUG
534 if (len > ETHERMTU + ETHER_HDR_LEN)
535 if_printf(ifp, "packet length %d\n", len);
536 #endif
537
538 /*
539 * Init transmit registers, and set transmit start flag.
540 */
541 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
542 tmd.tmd2 = -len | LE_XMD2_ONES;
543 tmd.tmd3 = 0;
544
545 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
546
547 #ifdef LEDEBUG
548 if (sc->sc_flags & LE_DEBUG)
549 am7990_xmit_print(sc, bix);
550 #endif
551
552 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
553 enq++;
554
555 if (++bix == sc->sc_ntbuf)
556 bix = 0;
557
558 if (++sc->sc_no_td == sc->sc_ntbuf) {
559 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
560 break;
561 }
562 }
563
564 sc->sc_last_td = bix;
565
566 if (enq > 0)
567 sc->sc_wdog_timer = 5;
568 }
569
570 #ifdef LEDEBUG
571 static void
am7990_recv_print(struct lance_softc * sc,int no)572 am7990_recv_print(struct lance_softc *sc, int no)
573 {
574 if_t ifp = sc->sc_ifp;
575 struct ether_header eh;
576 struct lermd rmd;
577 uint16_t len;
578
579 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
580 len = rmd.rmd3;
581 if_printf(ifp, "receive buffer %d, len = %d\n", no, len);
582 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
583 if_printf(ifp,
584 "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
585 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
586 if (len - ETHER_CRC_LEN >= sizeof(eh)) {
587 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
588 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
589 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
590 ntohs(eh.ether_type));
591 }
592 }
593
594 static void
am7990_xmit_print(struct lance_softc * sc,int no)595 am7990_xmit_print(struct lance_softc *sc, int no)
596 {
597 if_t ifp = sc->sc_ifp;
598 struct ether_header eh;
599 struct letmd tmd;
600 uint16_t len;
601
602 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
603 len = -tmd.tmd2;
604 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len);
605 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
606 if_printf(ifp,
607 "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
608 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
609 if (len >= sizeof(eh)) {
610 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
611 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
612 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
613 ntohs(eh.ether_type));
614 }
615 }
616 #endif /* LEDEBUG */
617