if_le.c revision 1.1 1 1.1 chuck /* $NetBSD: if_le.c,v 1.1 1995/07/25 23:12:09 chuck Exp $ */
2 1.1 chuck
3 1.1 chuck /*-
4 1.1 chuck * Copyright (c) 1982, 1992, 1993
5 1.1 chuck * The Regents of the University of California. All rights reserved.
6 1.1 chuck *
7 1.1 chuck * Redistribution and use in source and binary forms, with or without
8 1.1 chuck * modification, are permitted provided that the following conditions
9 1.1 chuck * are met:
10 1.1 chuck * 1. Redistributions of source code must retain the above copyright
11 1.1 chuck * notice, this list of conditions and the following disclaimer.
12 1.1 chuck * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 chuck * notice, this list of conditions and the following disclaimer in the
14 1.1 chuck * documentation and/or other materials provided with the distribution.
15 1.1 chuck * 3. All advertising materials mentioning features or use of this software
16 1.1 chuck * must display the following acknowledgement:
17 1.1 chuck * This product includes software developed by the University of
18 1.1 chuck * California, Berkeley and its contributors.
19 1.1 chuck * 4. Neither the name of the University nor the names of its contributors
20 1.1 chuck * may be used to endorse or promote products derived from this software
21 1.1 chuck * without specific prior written permission.
22 1.1 chuck *
23 1.1 chuck * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 chuck * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 chuck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 chuck * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 chuck * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 chuck * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 chuck * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 chuck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 chuck * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 chuck * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 chuck * SUCH DAMAGE.
34 1.1 chuck *
35 1.1 chuck * @(#)if_le.c 8.2 (Berkeley) 10/30/93
36 1.1 chuck */
37 1.1 chuck
38 1.1 chuck #include "bpfilter.h"
39 1.1 chuck
40 1.1 chuck /*
41 1.1 chuck * AMD 7990 LANCE
42 1.1 chuck */
43 1.1 chuck #include <sys/param.h>
44 1.1 chuck #include <sys/device.h>
45 1.1 chuck #include <sys/systm.h>
46 1.1 chuck #include <sys/kernel.h>
47 1.1 chuck #include <sys/mbuf.h>
48 1.1 chuck #include <sys/buf.h>
49 1.1 chuck #include <sys/socket.h>
50 1.1 chuck #include <sys/syslog.h>
51 1.1 chuck #include <sys/ioctl.h>
52 1.1 chuck #include <sys/malloc.h>
53 1.1 chuck #include <sys/errno.h>
54 1.1 chuck
55 1.1 chuck #include <vm/vm.h>
56 1.1 chuck
57 1.1 chuck #include <net/if.h>
58 1.1 chuck #include <net/netisr.h>
59 1.1 chuck #include <net/route.h>
60 1.1 chuck #if NBPFILTER > 0
61 1.1 chuck #include <sys/select.h>
62 1.1 chuck #include <net/bpf.h>
63 1.1 chuck #include <net/bpfdesc.h>
64 1.1 chuck #endif
65 1.1 chuck
66 1.1 chuck #ifdef INET
67 1.1 chuck #include <netinet/in.h>
68 1.1 chuck #include <netinet/in_systm.h>
69 1.1 chuck #include <netinet/in_var.h>
70 1.1 chuck #include <netinet/ip.h>
71 1.1 chuck #include <netinet/if_ether.h>
72 1.1 chuck #endif
73 1.1 chuck
74 1.1 chuck #ifdef NS
75 1.1 chuck #include <netns/ns.h>
76 1.1 chuck #include <netns/ns_if.h>
77 1.1 chuck #endif
78 1.1 chuck
79 1.1 chuck #ifdef APPLETALK
80 1.1 chuck #include <netddp/atalk.h>
81 1.1 chuck #endif
82 1.1 chuck
83 1.1 chuck #include <machine/cpu.h>
84 1.1 chuck #include <machine/pmap.h>
85 1.1 chuck
86 1.1 chuck #include <mvme68k/dev/iio.h>
87 1.1 chuck #include <mvme68k/dev/if_lereg.h>
88 1.1 chuck #include <mvme68k/dev/pccreg.h>
89 1.1 chuck
90 1.1 chuck /* DVMA address to LANCE address -- the Sbus/MMU will resupply the 0xff */
91 1.1 chuck #define LANCE_ADDR(x) ((int)x)
92 1.1 chuck
93 1.1 chuck int ledebug = 0; /* console error messages */
94 1.1 chuck
95 1.1 chuck #ifdef PACKETSTATS
96 1.1 chuck long lexpacketsizes[LEMTU+1];
97 1.1 chuck long lerpacketsizes[LEMTU+1];
98 1.1 chuck #endif
99 1.1 chuck
100 1.1 chuck /* Per interface statistics */
101 1.1 chuck /* XXX this should go in something like if_levar.h */
102 1.1 chuck struct lestats {
103 1.1 chuck long lexints; /* transmitter interrupts */
104 1.1 chuck long lerints; /* receiver interrupts */
105 1.1 chuck long lerbufs; /* total buffers received during interrupts */
106 1.1 chuck long lerhits; /* times current rbuf was full */
107 1.1 chuck long lerscans; /* rbufs scanned before finding first full */
108 1.1 chuck };
109 1.1 chuck
110 1.1 chuck /*
111 1.1 chuck * Ethernet software status per interface.
112 1.1 chuck *
113 1.1 chuck * Each interface is referenced by a network interface structure,
114 1.1 chuck * le_if, which the routing code uses to locate the interface.
115 1.1 chuck * This structure contains the output queue for the interface, its address, ...
116 1.1 chuck */
117 1.1 chuck struct le_softc {
118 1.1 chuck struct device sc_dev; /* base device */
119 1.1 chuck struct evcnt sc_intrcnt; /* # of interrupts, per le */
120 1.1 chuck struct evcnt sc_errcnt; /* # of errors, per le */
121 1.1 chuck
122 1.1 chuck struct arpcom sc_ac; /* common Ethernet structures */
123 1.1 chuck #define sc_if sc_ac.ac_if /* network-visible interface */
124 1.1 chuck #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
125 1.1 chuck struct lereg1 *sc_r1; /* LANCE registers */
126 1.1 chuck struct lereg2 *sc_r2; /* dual-port RAM */
127 1.1 chuck int sc_rmd; /* predicted next rmd to process */
128 1.1 chuck int sc_runt;
129 1.1 chuck int sc_jab;
130 1.1 chuck int sc_merr;
131 1.1 chuck int sc_babl;
132 1.1 chuck int sc_cerr;
133 1.1 chuck int sc_miss;
134 1.1 chuck int sc_xint;
135 1.1 chuck int sc_xown;
136 1.1 chuck int sc_uflo;
137 1.1 chuck int sc_rxlen;
138 1.1 chuck int sc_rxoff;
139 1.1 chuck int sc_txoff;
140 1.1 chuck int sc_busy;
141 1.1 chuck short sc_iflags;
142 1.1 chuck struct lestats sc_lestats; /* per interface statistics */
143 1.1 chuck };
144 1.1 chuck
145 1.1 chuck
146 1.1 chuck /* autoconfiguration driver */
147 1.1 chuck void leattach(struct device *, struct device *, void *);
148 1.1 chuck int lematch(struct device *, void *, void *);
149 1.1 chuck struct cfdriver lecd =
150 1.1 chuck { NULL, "le", lematch, leattach, DV_IFNET, sizeof(struct le_softc) };
151 1.1 chuck
152 1.1 chuck /* Forwards */
153 1.1 chuck void leattach(struct device *, struct device *, void *);
154 1.1 chuck void lesetladrf(struct le_softc *);
155 1.1 chuck void lereset(struct device *);
156 1.1 chuck int leinit(int);
157 1.1 chuck void lestart(struct ifnet *);
158 1.1 chuck int leintr(void *);
159 1.1 chuck void lexint(struct le_softc *);
160 1.1 chuck void lerint(struct le_softc *);
161 1.1 chuck void leread(struct le_softc *, char *, int);
162 1.1 chuck int leput(char *, struct mbuf *);
163 1.1 chuck struct mbuf *leget(char *, int, int, struct ifnet *);
164 1.1 chuck int leioctl(struct ifnet *, u_long, caddr_t);
165 1.1 chuck void leerror(struct le_softc *, int);
166 1.1 chuck void lererror(struct le_softc *, char *);
167 1.1 chuck void lexerror(struct le_softc *);
168 1.1 chuck
169 1.1 chuck void *ledatabuf; /* XXXCDC hack from pmap bootstrap */
170 1.1 chuck
171 1.1 chuck int
172 1.1 chuck lematch(parent, vcf, args)
173 1.1 chuck struct device *parent;
174 1.1 chuck void *vcf, *args;
175 1.1 chuck {
176 1.1 chuck struct cfdata *cf = vcf;
177 1.1 chuck struct iioargs *ia = args;
178 1.1 chuck
179 1.1 chuck return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
180 1.1 chuck }
181 1.1 chuck
182 1.1 chuck /*
183 1.1 chuck * Interface exists: make available by filling in network interface
184 1.1 chuck * record. System will initialize the interface when it is ready
185 1.1 chuck * to accept packets.
186 1.1 chuck */
187 1.1 chuck void
188 1.1 chuck leattach(parent, self, args)
189 1.1 chuck struct device *parent;
190 1.1 chuck struct device *self;
191 1.1 chuck void *args;
192 1.1 chuck {
193 1.1 chuck register struct le_softc *sc = (struct le_softc *)self;
194 1.1 chuck register struct lereg2 *ler2;
195 1.1 chuck struct ifnet *ifp = &sc->sc_if;
196 1.1 chuck register int a;
197 1.1 chuck int pri = IIO_CFLOC_LEVEL(self->dv_cfdata);
198 1.1 chuck
199 1.1 chuck /* XXX the following declarations should be elsewhere */
200 1.1 chuck extern void myetheraddr(u_char *);
201 1.1 chuck
202 1.1 chuck iio_print(self->dv_cfdata);
203 1.1 chuck
204 1.1 chuck /* connect the interrupt */
205 1.1 chuck pccintr_establish(PCCV_LE, leintr, pri, sc);
206 1.1 chuck
207 1.1 chuck sc->sc_r1 = (struct lereg1 *) IIO_CFLOC_ADDR(self->dv_cfdata);
208 1.1 chuck
209 1.1 chuck
210 1.1 chuck ler2 = sc->sc_r2 = (struct lereg2 *) ledatabuf;
211 1.1 chuck
212 1.1 chuck myetheraddr(sc->sc_addr);
213 1.1 chuck printf(" ler2 0x%x address %s\n", ler2, ether_sprintf(sc->sc_addr));
214 1.1 chuck
215 1.1 chuck /*
216 1.1 chuck * Setup for transmit/receive
217 1.1 chuck *
218 1.1 chuck * According to Van, some versions of the Lance only use this
219 1.1 chuck * address to receive packets; it doesn't put them in
220 1.1 chuck * output packets. We'll want to make sure that lestart()
221 1.1 chuck * installs the address.
222 1.1 chuck */
223 1.1 chuck ler2->ler2_padr[0] = sc->sc_addr[1];
224 1.1 chuck ler2->ler2_padr[1] = sc->sc_addr[0];
225 1.1 chuck ler2->ler2_padr[2] = sc->sc_addr[3];
226 1.1 chuck ler2->ler2_padr[3] = sc->sc_addr[2];
227 1.1 chuck ler2->ler2_padr[4] = sc->sc_addr[5];
228 1.1 chuck ler2->ler2_padr[5] = sc->sc_addr[4];
229 1.1 chuck a = LANCE_ADDR(&ler2->ler2_rmd);
230 1.1 chuck ler2->ler2_rlen = LE_RLEN | (a >> 16);
231 1.1 chuck ler2->ler2_rdra = a;
232 1.1 chuck a = LANCE_ADDR(&ler2->ler2_tmd);
233 1.1 chuck ler2->ler2_tlen = LE_TLEN | (a >> 16);
234 1.1 chuck ler2->ler2_tdra = a;
235 1.1 chuck
236 1.1 chuck /*
237 1.1 chuck * Set up event counters.
238 1.1 chuck */
239 1.1 chuck evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
240 1.1 chuck evcnt_attach(&sc->sc_dev, "errs", &sc->sc_errcnt);
241 1.1 chuck
242 1.1 chuck ifp->if_unit = sc->sc_dev.dv_unit;
243 1.1 chuck ifp->if_name = "le";
244 1.1 chuck ifp->if_ioctl = leioctl;
245 1.1 chuck ifp->if_start = lestart;
246 1.1 chuck ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
247 1.1 chuck #ifdef IFF_NOTRAILERS
248 1.1 chuck /* XXX still compile when the blasted things are gone... */
249 1.1 chuck ifp->if_flags |= IFF_NOTRAILERS;
250 1.1 chuck #endif
251 1.1 chuck #if NBPFILTER > 0
252 1.1 chuck bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
253 1.1 chuck #endif
254 1.1 chuck if_attach(ifp);
255 1.1 chuck ether_ifattach(ifp);
256 1.1 chuck sys_pcc->le_int = pri | PCC_IENABLE;
257 1.1 chuck
258 1.1 chuck }
259 1.1 chuck
260 1.1 chuck /*
261 1.1 chuck * Setup the logical address filter
262 1.1 chuck */
263 1.1 chuck void
264 1.1 chuck lesetladrf(sc)
265 1.1 chuck register struct le_softc *sc;
266 1.1 chuck {
267 1.1 chuck register struct lereg2 *ler2 = sc->sc_r2;
268 1.1 chuck register struct ifnet *ifp = &sc->sc_if;
269 1.1 chuck register struct ether_multi *enm;
270 1.1 chuck register u_char *cp, c;
271 1.1 chuck register u_long crc;
272 1.1 chuck register int i, len;
273 1.1 chuck struct ether_multistep step;
274 1.1 chuck
275 1.1 chuck /*
276 1.1 chuck * Set up multicast address filter by passing all multicast
277 1.1 chuck * addresses through a crc generator, and then using the high
278 1.1 chuck * order 6 bits as a index into the 64 bit logical address
279 1.1 chuck * filter. The high order two bits select the word, while the
280 1.1 chuck * rest of the bits select the bit within the word.
281 1.1 chuck */
282 1.1 chuck
283 1.1 chuck ler2->ler2_ladrf[0] = 0;
284 1.1 chuck ler2->ler2_ladrf[1] = 0;
285 1.1 chuck ler2->ler2_ladrf[2] = 0;
286 1.1 chuck ler2->ler2_ladrf[3] = 0;
287 1.1 chuck ifp->if_flags &= ~IFF_ALLMULTI;
288 1.1 chuck ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
289 1.1 chuck while (enm != NULL) {
290 1.1 chuck if (bcmp((caddr_t)&enm->enm_addrlo,
291 1.1 chuck (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) {
292 1.1 chuck /*
293 1.1 chuck * We must listen to a range of multicast
294 1.1 chuck * addresses. For now, just accept all
295 1.1 chuck * multicasts, rather than trying to set only
296 1.1 chuck * those filter bits needed to match the range.
297 1.1 chuck * (At this time, the only use of address
298 1.1 chuck * ranges is for IP multicast routing, for
299 1.1 chuck * which the range is big enough to require all
300 1.1 chuck * bits set.)
301 1.1 chuck */
302 1.1 chuck ler2->ler2_ladrf[0] = 0xffff;
303 1.1 chuck ler2->ler2_ladrf[1] = 0xffff;
304 1.1 chuck ler2->ler2_ladrf[2] = 0xffff;
305 1.1 chuck ler2->ler2_ladrf[3] = 0xffff;
306 1.1 chuck ifp->if_flags |= IFF_ALLMULTI;
307 1.1 chuck return;
308 1.1 chuck }
309 1.1 chuck
310 1.1 chuck /*
311 1.1 chuck * One would think, given the AM7990 document's polynomial
312 1.1 chuck * of 0x04c11db6, that this should be 0x6db88320 (the bit
313 1.1 chuck * reversal of the AMD value), but that is not right. See
314 1.1 chuck * the BASIC listing: bit 0 (our bit 31) must then be set.
315 1.1 chuck */
316 1.1 chuck cp = (unsigned char *)&enm->enm_addrlo;
317 1.1 chuck crc = 0xffffffff;
318 1.1 chuck for (len = 6; --len >= 0;) {
319 1.1 chuck c = *cp++;
320 1.1 chuck for (i = 0; i < 8; i++) {
321 1.1 chuck if ((c & 0x01) ^ (crc & 0x01)) {
322 1.1 chuck crc >>= 1;
323 1.1 chuck crc = crc ^ 0xedb88320;
324 1.1 chuck } else
325 1.1 chuck crc >>= 1;
326 1.1 chuck c >>= 1;
327 1.1 chuck }
328 1.1 chuck }
329 1.1 chuck /* Just want the 6 most significant bits. */
330 1.1 chuck crc = crc >> 26;
331 1.1 chuck
332 1.1 chuck /* Turn on the corresponding bit in the filter. */
333 1.1 chuck ler2->ler2_ladrf[crc >> 4] |= 1 << (crc & 0xf);
334 1.1 chuck
335 1.1 chuck ETHER_NEXT_MULTI(step, enm);
336 1.1 chuck }
337 1.1 chuck }
338 1.1 chuck
339 1.1 chuck void
340 1.1 chuck lereset(dev)
341 1.1 chuck struct device *dev;
342 1.1 chuck {
343 1.1 chuck register struct le_softc *sc = (struct le_softc *)dev;
344 1.1 chuck register struct lereg1 *ler1 = sc->sc_r1;
345 1.1 chuck register struct lereg2 *ler2 = sc->sc_r2;
346 1.1 chuck register int i, a, timo, stat;
347 1.1 chuck
348 1.1 chuck #if NBPFILTER > 0
349 1.1 chuck if (sc->sc_if.if_flags & IFF_PROMISC)
350 1.1 chuck ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM;
351 1.1 chuck else
352 1.1 chuck #endif
353 1.1 chuck ler2->ler2_mode = LE_MODE_NORMAL;
354 1.1 chuck ler1->ler1_rap = LE_CSR0;
355 1.1 chuck ler1->ler1_rdp = LE_C0_STOP;
356 1.1 chuck
357 1.1 chuck /* Setup the logical address filter */
358 1.1 chuck lesetladrf(sc);
359 1.1 chuck
360 1.1 chuck /* init receive and transmit rings */
361 1.1 chuck for (i = 0; i < LERBUF; i++) {
362 1.1 chuck a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
363 1.1 chuck ler2->ler2_rmd[i].rmd0 = a;
364 1.1 chuck ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
365 1.1 chuck ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
366 1.1 chuck ler2->ler2_rmd[i].rmd2 = -LEMTU | LE_XMD2_ONES;
367 1.1 chuck ler2->ler2_rmd[i].rmd3 = 0;
368 1.1 chuck }
369 1.1 chuck for (i = 0; i < LETBUF; i++) {
370 1.1 chuck a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
371 1.1 chuck ler2->ler2_tmd[i].tmd0 = a;
372 1.1 chuck ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
373 1.1 chuck ler2->ler2_tmd[i].tmd1_bits = 0;
374 1.1 chuck ler2->ler2_tmd[i].tmd2 = LE_XMD2_ONES;
375 1.1 chuck ler2->ler2_tmd[i].tmd3 = 0;
376 1.1 chuck }
377 1.1 chuck
378 1.1 chuck bzero((void *)&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU);
379 1.1 chuck /* lance will stuff packet into receive buffer 0 next */
380 1.1 chuck sc->sc_rmd = 0;
381 1.1 chuck
382 1.1 chuck /* tell the chip where to find the initialization block */
383 1.1 chuck a = LANCE_ADDR(&ler2->ler2_mode);
384 1.1 chuck ler1->ler1_rap = LE_CSR1;
385 1.1 chuck ler1->ler1_rdp = a;
386 1.1 chuck ler1->ler1_rap = LE_CSR2;
387 1.1 chuck ler1->ler1_rdp = a >> 16;
388 1.1 chuck ler1->ler1_rap = LE_CSR3;
389 1.1 chuck ler1->ler1_rdp = LE_C3_BSWP /*| LE_C3_ACON | LE_C3_BCON*/;
390 1.1 chuck ler1->ler1_rap = LE_CSR0;
391 1.1 chuck ler1->ler1_rdp = LE_C0_INIT;
392 1.1 chuck timo = 100000;
393 1.1 chuck while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) {
394 1.1 chuck if (--timo == 0) {
395 1.1 chuck printf("%s: init timeout, stat=%b\n",
396 1.1 chuck sc->sc_dev.dv_xname, stat, LE_C0_BITS);
397 1.1 chuck break;
398 1.1 chuck }
399 1.1 chuck }
400 1.1 chuck if (stat & LE_C0_ERR)
401 1.1 chuck printf("%s: init failed, ler1=0x%x, stat=%b\n",
402 1.1 chuck sc->sc_dev.dv_xname, ler1, stat, LE_C0_BITS);
403 1.1 chuck else
404 1.1 chuck ler1->ler1_rdp = LE_C0_IDON; /* clear IDON */
405 1.1 chuck ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA;
406 1.1 chuck sc->sc_if.if_flags &= ~IFF_OACTIVE;
407 1.1 chuck }
408 1.1 chuck
409 1.1 chuck /*
410 1.1 chuck * Initialization of interface
411 1.1 chuck */
412 1.1 chuck int
413 1.1 chuck leinit(unit)
414 1.1 chuck int unit;
415 1.1 chuck {
416 1.1 chuck register struct le_softc *sc = lecd.cd_devs[unit];
417 1.1 chuck register struct ifnet *ifp = &sc->sc_if;
418 1.1 chuck register int s;
419 1.1 chuck
420 1.1 chuck if ((ifp->if_flags & IFF_RUNNING) == 0) {
421 1.1 chuck s = splimp();
422 1.1 chuck ifp->if_flags |= IFF_RUNNING;
423 1.1 chuck lereset(&sc->sc_dev);
424 1.1 chuck lestart(ifp);
425 1.1 chuck splx(s);
426 1.1 chuck }
427 1.1 chuck return (0);
428 1.1 chuck }
429 1.1 chuck
430 1.1 chuck /*
431 1.1 chuck * Start output on interface. Get another datagram to send
432 1.1 chuck * off of the interface queue, and copy it to the interface
433 1.1 chuck * before starting the output.
434 1.1 chuck */
435 1.1 chuck void
436 1.1 chuck lestart(ifp)
437 1.1 chuck register struct ifnet *ifp;
438 1.1 chuck {
439 1.1 chuck register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
440 1.1 chuck register struct letmd *tmd;
441 1.1 chuck register struct mbuf *m;
442 1.1 chuck register int len;
443 1.1 chuck if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
444 1.1 chuck return;
445 1.1 chuck IF_DEQUEUE(&sc->sc_if.if_snd, m);
446 1.1 chuck if (m == 0)
447 1.1 chuck return;
448 1.1 chuck
449 1.1 chuck len = leput((char *)sc->sc_r2->ler2_tbuf[0], m);
450 1.1 chuck
451 1.1 chuck #if NBPFILTER > 0
452 1.1 chuck /*
453 1.1 chuck * If bpf is listening on this interface, let it
454 1.1 chuck * see the packet before we commit it to the wire.
455 1.1 chuck */
456 1.1 chuck if (sc->sc_if.if_bpf)
457 1.1 chuck bpf_tap(sc->sc_if.if_bpf, (char *)sc->sc_r2->ler2_tbuf[0], len);
458 1.1 chuck #endif
459 1.1 chuck
460 1.1 chuck #ifdef PACKETSTATS
461 1.1 chuck if (len <= LEMTU)
462 1.1 chuck lexpacketsizes[len]++;
463 1.1 chuck #endif
464 1.1 chuck tmd = sc->sc_r2->ler2_tmd;
465 1.1 chuck tmd->tmd3 = 0;
466 1.1 chuck tmd->tmd2 = -len | LE_XMD2_ONES;
467 1.1 chuck tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
468 1.1 chuck sc->sc_if.if_flags |= IFF_OACTIVE;
469 1.1 chuck return;
470 1.1 chuck }
471 1.1 chuck
472 1.1 chuck int
473 1.1 chuck leintr(dev)
474 1.1 chuck register void *dev;
475 1.1 chuck {
476 1.1 chuck register struct le_softc *sc = dev;
477 1.1 chuck register struct lereg1 *ler1 = sc->sc_r1;
478 1.1 chuck register int csr0;
479 1.1 chuck
480 1.1 chuck csr0 = ler1->ler1_rdp;
481 1.1 chuck if ((csr0 & LE_C0_INTR) == 0)
482 1.1 chuck return (0);
483 1.1 chuck sc->sc_intrcnt.ev_count++;
484 1.1 chuck
485 1.1 chuck if (csr0 & LE_C0_ERR) {
486 1.1 chuck sc->sc_errcnt.ev_count++;
487 1.1 chuck leerror(sc, csr0);
488 1.1 chuck if (csr0 & LE_C0_MERR) {
489 1.1 chuck sc->sc_merr++;
490 1.1 chuck lereset(&sc->sc_dev);
491 1.1 chuck return (1);
492 1.1 chuck }
493 1.1 chuck if (csr0 & LE_C0_BABL)
494 1.1 chuck sc->sc_babl++;
495 1.1 chuck if (csr0 & LE_C0_CERR)
496 1.1 chuck sc->sc_cerr++;
497 1.1 chuck if (csr0 & LE_C0_MISS)
498 1.1 chuck sc->sc_miss++;
499 1.1 chuck ler1->ler1_rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_INEA;
500 1.1 chuck }
501 1.1 chuck if ((csr0 & LE_C0_RXON) == 0) {
502 1.1 chuck sc->sc_rxoff++;
503 1.1 chuck lereset(&sc->sc_dev);
504 1.1 chuck return (1);
505 1.1 chuck }
506 1.1 chuck if ((csr0 & LE_C0_TXON) == 0) {
507 1.1 chuck sc->sc_txoff++;
508 1.1 chuck lereset(&sc->sc_dev);
509 1.1 chuck return (1);
510 1.1 chuck }
511 1.1 chuck if (csr0 & LE_C0_RINT) {
512 1.1 chuck /* interrupt is cleared in lerint */
513 1.1 chuck lerint(sc);
514 1.1 chuck }
515 1.1 chuck if (csr0 & LE_C0_TINT) {
516 1.1 chuck ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;
517 1.1 chuck lexint(sc);
518 1.1 chuck }
519 1.1 chuck return (1);
520 1.1 chuck }
521 1.1 chuck
522 1.1 chuck /*
523 1.1 chuck * Ethernet interface transmitter interrupt.
524 1.1 chuck * Start another output if more data to send.
525 1.1 chuck */
526 1.1 chuck void
527 1.1 chuck lexint(sc)
528 1.1 chuck register struct le_softc *sc;
529 1.1 chuck {
530 1.1 chuck register struct letmd *tmd = sc->sc_r2->ler2_tmd;
531 1.1 chuck
532 1.1 chuck sc->sc_lestats.lexints++;
533 1.1 chuck if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
534 1.1 chuck sc->sc_xint++;
535 1.1 chuck return;
536 1.1 chuck }
537 1.1 chuck if (tmd->tmd1_bits & LE_T1_OWN) {
538 1.1 chuck sc->sc_xown++;
539 1.1 chuck return;
540 1.1 chuck }
541 1.1 chuck if (tmd->tmd1_bits & LE_T1_ERR) {
542 1.1 chuck err:
543 1.1 chuck lexerror(sc);
544 1.1 chuck sc->sc_if.if_oerrors++;
545 1.1 chuck if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {
546 1.1 chuck sc->sc_uflo++;
547 1.1 chuck lereset(&sc->sc_dev);
548 1.1 chuck } else if (tmd->tmd3 & LE_T3_LCOL)
549 1.1 chuck sc->sc_if.if_collisions++;
550 1.1 chuck else if (tmd->tmd3 & LE_T3_RTRY)
551 1.1 chuck sc->sc_if.if_collisions += 16;
552 1.1 chuck }
553 1.1 chuck else if (tmd->tmd3 & LE_T3_BUFF)
554 1.1 chuck /* XXX documentation says BUFF not included in ERR */
555 1.1 chuck goto err;
556 1.1 chuck else if (tmd->tmd1_bits & LE_T1_ONE)
557 1.1 chuck sc->sc_if.if_collisions++;
558 1.1 chuck else if (tmd->tmd1_bits & LE_T1_MORE)
559 1.1 chuck /* what is the real number? */
560 1.1 chuck sc->sc_if.if_collisions += 2;
561 1.1 chuck else
562 1.1 chuck sc->sc_if.if_opackets++;
563 1.1 chuck sc->sc_if.if_flags &= ~IFF_OACTIVE;
564 1.1 chuck lestart(&sc->sc_if);
565 1.1 chuck }
566 1.1 chuck
567 1.1 chuck #define LENEXTRMP \
568 1.1 chuck if (++bix == LERBUF) bix = 0, rmd = sc->sc_r2->ler2_rmd; else ++rmd
569 1.1 chuck
570 1.1 chuck /*
571 1.1 chuck * Ethernet interface receiver interrupt.
572 1.1 chuck * If input error just drop packet.
573 1.1 chuck * Decapsulate packet based on type and pass to type specific
574 1.1 chuck * higher-level input routine.
575 1.1 chuck */
576 1.1 chuck void
577 1.1 chuck lerint(sc)
578 1.1 chuck register struct le_softc *sc;
579 1.1 chuck {
580 1.1 chuck register int bix = sc->sc_rmd;
581 1.1 chuck register struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
582 1.1 chuck
583 1.1 chuck sc->sc_lestats.lerints++;
584 1.1 chuck /*
585 1.1 chuck * Out of sync with hardware, should never happen?
586 1.1 chuck */
587 1.1 chuck if (rmd->rmd1_bits & LE_R1_OWN) {
588 1.1 chuck do {
589 1.1 chuck sc->sc_lestats.lerscans++;
590 1.1 chuck LENEXTRMP;
591 1.1 chuck } while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);
592 1.1 chuck if (bix == sc->sc_rmd)
593 1.1 chuck printf("%s: RINT with no buffer\n",
594 1.1 chuck sc->sc_dev.dv_xname);
595 1.1 chuck } else
596 1.1 chuck sc->sc_lestats.lerhits++;
597 1.1 chuck
598 1.1 chuck /*
599 1.1 chuck * Process all buffers with valid data
600 1.1 chuck */
601 1.1 chuck while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {
602 1.1 chuck int len = rmd->rmd3;
603 1.1 chuck
604 1.1 chuck /* Clear interrupt to avoid race condition */
605 1.1 chuck sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
606 1.1 chuck
607 1.1 chuck if (rmd->rmd1_bits & LE_R1_ERR) {
608 1.1 chuck sc->sc_rmd = bix;
609 1.1 chuck lererror(sc, "bad packet");
610 1.1 chuck sc->sc_if.if_ierrors++;
611 1.1 chuck } else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=
612 1.1 chuck (LE_R1_STP|LE_R1_ENP)) {
613 1.1 chuck /* XXX make a define for LE_R1_STP|LE_R1_ENP? */
614 1.1 chuck /*
615 1.1 chuck * Find the end of the packet so we can see how long
616 1.1 chuck * it was. We still throw it away.
617 1.1 chuck */
618 1.1 chuck do {
619 1.1 chuck sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
620 1.1 chuck rmd->rmd3 = 0;
621 1.1 chuck rmd->rmd1_bits = LE_R1_OWN;
622 1.1 chuck LENEXTRMP;
623 1.1 chuck } while (!(rmd->rmd1_bits &
624 1.1 chuck (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));
625 1.1 chuck sc->sc_rmd = bix;
626 1.1 chuck lererror(sc, "chained buffer");
627 1.1 chuck sc->sc_rxlen++;
628 1.1 chuck /*
629 1.1 chuck * If search terminated without successful completion
630 1.1 chuck * we reset the hardware (conservative).
631 1.1 chuck */
632 1.1 chuck if ((rmd->rmd1_bits &
633 1.1 chuck (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=
634 1.1 chuck LE_R1_ENP) {
635 1.1 chuck lereset(&sc->sc_dev);
636 1.1 chuck return;
637 1.1 chuck }
638 1.1 chuck } else {
639 1.1 chuck leread(sc, (char *)sc->sc_r2->ler2_rbuf[bix], len);
640 1.1 chuck #ifdef PACKETSTATS
641 1.1 chuck lerpacketsizes[len]++;
642 1.1 chuck #endif
643 1.1 chuck sc->sc_lestats.lerbufs++;
644 1.1 chuck }
645 1.1 chuck rmd->rmd3 = 0;
646 1.1 chuck rmd->rmd1_bits = LE_R1_OWN;
647 1.1 chuck LENEXTRMP;
648 1.1 chuck }
649 1.1 chuck sc->sc_rmd = bix;
650 1.1 chuck }
651 1.1 chuck
652 1.1 chuck void
653 1.1 chuck leread(sc, pkt, len)
654 1.1 chuck register struct le_softc *sc;
655 1.1 chuck char *pkt;
656 1.1 chuck int len;
657 1.1 chuck {
658 1.1 chuck register struct ether_header *et;
659 1.1 chuck register struct ifnet *ifp = &sc->sc_if;
660 1.1 chuck struct mbuf *m;
661 1.1 chuck struct ifqueue *inq;
662 1.1 chuck int flags;
663 1.1 chuck
664 1.1 chuck ifp->if_ipackets++;
665 1.1 chuck et = (struct ether_header *)pkt;
666 1.1 chuck et->ether_type = ntohs((u_short)et->ether_type);
667 1.1 chuck /* adjust input length to account for header and CRC */
668 1.1 chuck len -= sizeof(struct ether_header) + 4;
669 1.1 chuck
670 1.1 chuck if (len <= 0) {
671 1.1 chuck if (ledebug)
672 1.1 chuck log(LOG_WARNING,
673 1.1 chuck "%s: ierror(runt packet): from %s: len=%d\n",
674 1.1 chuck sc->sc_dev.dv_xname,
675 1.1 chuck ether_sprintf(et->ether_shost), len);
676 1.1 chuck sc->sc_runt++;
677 1.1 chuck ifp->if_ierrors++;
678 1.1 chuck return;
679 1.1 chuck }
680 1.1 chuck
681 1.1 chuck /* Setup mbuf flags we'll need later */
682 1.1 chuck flags = 0;
683 1.1 chuck if (bcmp((caddr_t)etherbroadcastaddr,
684 1.1 chuck (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
685 1.1 chuck flags |= M_BCAST;
686 1.1 chuck if (et->ether_dhost[0] & 1)
687 1.1 chuck flags |= M_MCAST;
688 1.1 chuck
689 1.1 chuck #if NBPFILTER > 0
690 1.1 chuck /*
691 1.1 chuck * Check if there's a bpf filter listening on this interface.
692 1.1 chuck * If so, hand off the raw packet to enet, then discard things
693 1.1 chuck * not destined for us (but be sure to keep broadcast/multicast).
694 1.1 chuck */
695 1.1 chuck if (sc->sc_if.if_bpf) {
696 1.1 chuck bpf_tap(sc->sc_if.if_bpf, pkt,
697 1.1 chuck len + sizeof(struct ether_header));
698 1.1 chuck if ((flags & (M_BCAST | M_MCAST)) == 0 &&
699 1.1 chuck bcmp(et->ether_dhost, sc->sc_addr,
700 1.1 chuck sizeof(et->ether_dhost)) != 0)
701 1.1 chuck return;
702 1.1 chuck }
703 1.1 chuck #endif
704 1.1 chuck m = leget(pkt, len, 0, ifp);
705 1.1 chuck if (m == 0)
706 1.1 chuck return;
707 1.1 chuck ether_input(ifp, et, m);
708 1.1 chuck }
709 1.1 chuck
710 1.1 chuck /*
711 1.1 chuck * Routine to copy from mbuf chain to transmit
712 1.1 chuck * buffer in board local memory.
713 1.1 chuck *
714 1.1 chuck * ### this can be done by remapping in some cases
715 1.1 chuck */
716 1.1 chuck int
717 1.1 chuck leput(lebuf, m)
718 1.1 chuck register char *lebuf;
719 1.1 chuck register struct mbuf *m;
720 1.1 chuck {
721 1.1 chuck register struct mbuf *mp;
722 1.1 chuck register int len, tlen = 0;
723 1.1 chuck
724 1.1 chuck for (mp = m; mp; mp = mp->m_next) {
725 1.1 chuck len = mp->m_len;
726 1.1 chuck if (len == 0)
727 1.1 chuck continue;
728 1.1 chuck tlen += len;
729 1.1 chuck bcopy(mtod(mp, char *), lebuf, len);
730 1.1 chuck lebuf += len;
731 1.1 chuck }
732 1.1 chuck m_freem(m);
733 1.1 chuck if (tlen < LEMINSIZE) {
734 1.1 chuck bzero(lebuf, LEMINSIZE - tlen);
735 1.1 chuck tlen = LEMINSIZE;
736 1.1 chuck }
737 1.1 chuck return (tlen);
738 1.1 chuck }
739 1.1 chuck
740 1.1 chuck /*
741 1.1 chuck * Routine to copy from board local memory into mbufs.
742 1.1 chuck */
743 1.1 chuck struct mbuf *
744 1.1 chuck leget(lebuf, totlen, off0, ifp)
745 1.1 chuck char *lebuf;
746 1.1 chuck int totlen, off0;
747 1.1 chuck struct ifnet *ifp;
748 1.1 chuck {
749 1.1 chuck register struct mbuf *m;
750 1.1 chuck struct mbuf *top = 0, **mp = ⊤
751 1.1 chuck register int off = off0, len;
752 1.1 chuck register char *cp;
753 1.1 chuck char *epkt;
754 1.1 chuck
755 1.1 chuck lebuf += sizeof(struct ether_header);
756 1.1 chuck cp = lebuf;
757 1.1 chuck epkt = cp + totlen;
758 1.1 chuck if (off) {
759 1.1 chuck cp += off + 2 * sizeof(u_short);
760 1.1 chuck totlen -= 2 * sizeof(u_short);
761 1.1 chuck }
762 1.1 chuck
763 1.1 chuck MGETHDR(m, M_DONTWAIT, MT_DATA);
764 1.1 chuck if (m == 0)
765 1.1 chuck return (0);
766 1.1 chuck m->m_pkthdr.rcvif = ifp;
767 1.1 chuck m->m_pkthdr.len = totlen;
768 1.1 chuck m->m_len = MHLEN;
769 1.1 chuck
770 1.1 chuck while (totlen > 0) {
771 1.1 chuck if (top) {
772 1.1 chuck MGET(m, M_DONTWAIT, MT_DATA);
773 1.1 chuck if (m == 0) {
774 1.1 chuck m_freem(top);
775 1.1 chuck return (0);
776 1.1 chuck }
777 1.1 chuck m->m_len = MLEN;
778 1.1 chuck }
779 1.1 chuck len = min(totlen, epkt - cp);
780 1.1 chuck if (len >= MINCLSIZE) {
781 1.1 chuck MCLGET(m, M_DONTWAIT);
782 1.1 chuck if (m->m_flags & M_EXT)
783 1.1 chuck m->m_len = len = min(len, MCLBYTES);
784 1.1 chuck else
785 1.1 chuck len = m->m_len;
786 1.1 chuck } else {
787 1.1 chuck /*
788 1.1 chuck * Place initial small packet/header at end of mbuf.
789 1.1 chuck */
790 1.1 chuck if (len < m->m_len) {
791 1.1 chuck if (top == 0 && len + max_linkhdr <= m->m_len)
792 1.1 chuck m->m_data += max_linkhdr;
793 1.1 chuck m->m_len = len;
794 1.1 chuck } else
795 1.1 chuck len = m->m_len;
796 1.1 chuck }
797 1.1 chuck bcopy(cp, mtod(m, caddr_t), (unsigned)len);
798 1.1 chuck cp += len;
799 1.1 chuck *mp = m;
800 1.1 chuck mp = &m->m_next;
801 1.1 chuck totlen -= len;
802 1.1 chuck if (cp == epkt)
803 1.1 chuck cp = lebuf;
804 1.1 chuck }
805 1.1 chuck return (top);
806 1.1 chuck }
807 1.1 chuck
808 1.1 chuck /*
809 1.1 chuck * Process an ioctl request.
810 1.1 chuck */
811 1.1 chuck int
812 1.1 chuck leioctl(ifp, cmd, data)
813 1.1 chuck register struct ifnet *ifp;
814 1.1 chuck u_long cmd;
815 1.1 chuck caddr_t data;
816 1.1 chuck {
817 1.1 chuck register struct ifaddr *ifa;
818 1.1 chuck register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
819 1.1 chuck register struct lereg1 *ler1;
820 1.1 chuck int s = splimp(), error = 0;
821 1.1 chuck
822 1.1 chuck switch (cmd) {
823 1.1 chuck
824 1.1 chuck case SIOCSIFADDR:
825 1.1 chuck ifa = (struct ifaddr *)data;
826 1.1 chuck ifp->if_flags |= IFF_UP;
827 1.1 chuck switch (ifa->ifa_addr->sa_family) {
828 1.1 chuck #ifdef INET
829 1.1 chuck case AF_INET:
830 1.1 chuck (void)leinit(ifp->if_unit);
831 1.1 chuck arp_ifinit(&sc->sc_ac, ifa);
832 1.1 chuck break;
833 1.1 chuck #endif
834 1.1 chuck #ifdef NS
835 1.1 chuck case AF_NS:
836 1.1 chuck {
837 1.1 chuck register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
838 1.1 chuck
839 1.1 chuck if (ns_nullhost(*ina))
840 1.1 chuck ina->x_host = *(union ns_host *)(sc->sc_addr);
841 1.1 chuck else {
842 1.1 chuck /*
843 1.1 chuck * The manual says we can't change the address
844 1.1 chuck * while the receiver is armed,
845 1.1 chuck * so reset everything
846 1.1 chuck */
847 1.1 chuck ifp->if_flags &= ~IFF_RUNNING;
848 1.1 chuck bcopy((caddr_t)ina->x_host.c_host,
849 1.1 chuck (caddr_t)sc->sc_addr, sizeof(sc->sc_addr));
850 1.1 chuck }
851 1.1 chuck (void)leinit(ifp->if_unit); /* does le_setaddr() */
852 1.1 chuck break;
853 1.1 chuck }
854 1.1 chuck #endif
855 1.1 chuck default:
856 1.1 chuck (void)leinit(ifp->if_unit);
857 1.1 chuck break;
858 1.1 chuck }
859 1.1 chuck break;
860 1.1 chuck
861 1.1 chuck case SIOCSIFFLAGS:
862 1.1 chuck ler1 = sc->sc_r1;
863 1.1 chuck if ((ifp->if_flags & IFF_UP) == 0 &&
864 1.1 chuck ifp->if_flags & IFF_RUNNING) {
865 1.1 chuck ler1->ler1_rdp = LE_C0_STOP;
866 1.1 chuck ifp->if_flags &= ~IFF_RUNNING;
867 1.1 chuck } else if (ifp->if_flags & IFF_UP &&
868 1.1 chuck (ifp->if_flags & IFF_RUNNING) == 0)
869 1.1 chuck (void)leinit(ifp->if_unit);
870 1.1 chuck /*
871 1.1 chuck * If the state of the promiscuous bit changes, the interface
872 1.1 chuck * must be reset to effect the change.
873 1.1 chuck */
874 1.1 chuck if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
875 1.1 chuck (ifp->if_flags & IFF_RUNNING)) {
876 1.1 chuck sc->sc_iflags = ifp->if_flags;
877 1.1 chuck lereset(&sc->sc_dev);
878 1.1 chuck lestart(ifp);
879 1.1 chuck }
880 1.1 chuck break;
881 1.1 chuck
882 1.1 chuck case SIOCADDMULTI:
883 1.1 chuck error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
884 1.1 chuck goto update_multicast;
885 1.1 chuck
886 1.1 chuck case SIOCDELMULTI:
887 1.1 chuck error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
888 1.1 chuck update_multicast:
889 1.1 chuck if (error == ENETRESET) {
890 1.1 chuck /*
891 1.1 chuck * Multicast list has changed; set the hardware
892 1.1 chuck * filter accordingly.
893 1.1 chuck */
894 1.1 chuck lereset(&sc->sc_dev);
895 1.1 chuck error = 0;
896 1.1 chuck }
897 1.1 chuck break;
898 1.1 chuck
899 1.1 chuck default:
900 1.1 chuck error = EINVAL;
901 1.1 chuck }
902 1.1 chuck splx(s);
903 1.1 chuck return (error);
904 1.1 chuck }
905 1.1 chuck
906 1.1 chuck void
907 1.1 chuck leerror(sc, stat)
908 1.1 chuck register struct le_softc *sc;
909 1.1 chuck int stat;
910 1.1 chuck {
911 1.1 chuck if (!ledebug)
912 1.1 chuck return;
913 1.1 chuck
914 1.1 chuck /*
915 1.1 chuck * Not all transceivers implement heartbeat
916 1.1 chuck * so we only log CERR once.
917 1.1 chuck */
918 1.1 chuck if ((stat & LE_C0_CERR) && sc->sc_cerr)
919 1.1 chuck return;
920 1.1 chuck log(LOG_WARNING, "%s: error: stat=%b\n",
921 1.1 chuck sc->sc_dev.dv_xname, stat, LE_C0_BITS);
922 1.1 chuck }
923 1.1 chuck
924 1.1 chuck void
925 1.1 chuck lererror(sc, msg)
926 1.1 chuck register struct le_softc *sc;
927 1.1 chuck char *msg;
928 1.1 chuck {
929 1.1 chuck register struct lermd *rmd;
930 1.1 chuck int len;
931 1.1 chuck
932 1.1 chuck if (!ledebug)
933 1.1 chuck return;
934 1.1 chuck
935 1.1 chuck rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
936 1.1 chuck len = rmd->rmd3;
937 1.1 chuck log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
938 1.1 chuck sc->sc_dev.dv_xname, msg, len > 11 ?
939 1.1 chuck ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :
940 1.1 chuck "unknown",
941 1.1 chuck sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);
942 1.1 chuck }
943 1.1 chuck
944 1.1 chuck void
945 1.1 chuck lexerror(sc)
946 1.1 chuck register struct le_softc *sc;
947 1.1 chuck {
948 1.1 chuck register struct letmd *tmd;
949 1.1 chuck register int len, tmd3, tdr;
950 1.1 chuck
951 1.1 chuck if (!ledebug)
952 1.1 chuck return;
953 1.1 chuck
954 1.1 chuck tmd = sc->sc_r2->ler2_tmd;
955 1.1 chuck tmd3 = tmd->tmd3;
956 1.1 chuck tdr = tmd3 & LE_T3_TDR_MASK;
957 1.1 chuck len = -(tmd->tmd2 & ~LE_XMD2_ONES);
958 1.1 chuck log(LOG_WARNING,
959 1.1 chuck "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",
960 1.1 chuck sc->sc_dev.dv_xname, len > 5 ?
961 1.1 chuck ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
962 1.1 chuck 0, len,
963 1.1 chuck tmd->tmd1_bits, LE_T1_BITS,
964 1.1 chuck tmd3, LE_T3_BITS, tdr, tdr * 100);
965 1.1 chuck }
966