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