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