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