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