Deleted Added
full compact
am79900.c (263289) am79900.c (271849)
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>
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: head/sys/dev/le/am79900.c 263289 2014-03-18 01:40:25Z emaste $");
106__FBSDID("$FreeBSD: head/sys/dev/le/am79900.c 271849 2014-09-19 03:51:26Z glebius $");
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) {
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++;
316 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
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
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++;
336 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
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)
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++;
394 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
395 if (tmd2 & LE_T2_RTRY) {
396#ifdef LEDEBUG
397 if_printf(ifp, "excessive collisions\n");
398#endif
395 if (tmd2 & LE_T2_RTRY) {
396#ifdef LEDEBUG
397 if_printf(ifp, "excessive collisions\n");
398#endif
399 ifp->if_collisions += 16;
399 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16);
400 }
400 }
401 ifp->if_oerrors++;
401 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
402 } else {
403 if (tmd1 & LE_T1_ONE)
402 } else {
403 if (tmd1 & LE_T1_ONE)
404 ifp->if_collisions++;
404 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
405 else if (tmd1 & LE_T1_MORE)
406 /* Real number is unknown. */
405 else if (tmd1 & LE_T1_MORE)
406 /* Real number is unknown. */
407 ifp->if_collisions += 2;
408 ifp->if_opackets++;
407 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2);
408 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
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) {
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++;
435 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
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
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++;
467 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
468 }
469#if 0
470 if (isr & LE_C0_CERR) {
471 if_printf(ifp, "collision error\n");
468 }
469#if 0
470 if (isr & LE_C0_CERR) {
471 if_printf(ifp, "collision error\n");
472 ifp->if_collisions++;
472 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
473 }
474#endif
475 if (isr & LE_C0_MISS) {
476#ifdef LEDEBUG
477 if_printf(ifp, "missed packet\n");
478#endif
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++;
479 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
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");
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++;
491 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
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");
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++;
498 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
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 */
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 */