if_le.c revision 1.5 1 /*
2 * Copyright (c) 1982, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * from: @(#)if_le.c 7.6 (Berkeley) 5/8/91
34 * if_le.c,v 1.2 1993/05/22 07:56:23 cgd Exp
35 */
36
37 #include "bpfilter.h"
38
39 /*
40 * AMD 7990 LANCE
41 *
42 * This driver will generate and accept tailer encapsulated packets even
43 * though it buys us nothing. The motivation was to avoid incompatibilities
44 * with VAXen, SUNs, and others that handle and benefit from them.
45 * This reasoning is dubious.
46 */
47 #include "sys/param.h"
48 #include "sys/systm.h"
49 #include "sys/mbuf.h"
50 #include "sys/buf.h"
51 #include "sys/protosw.h"
52 #include "sys/socket.h"
53 #include "sys/syslog.h"
54 #include "sys/ioctl.h"
55 #include "sys/errno.h"
56 #include "sys/device.h"
57
58 #include "net/if.h"
59 #include "net/netisr.h"
60 #include "net/route.h"
61
62 #ifdef INET
63 #include "netinet/in.h"
64 #include "netinet/in_systm.h"
65 #include "netinet/in_var.h"
66 #include "netinet/ip.h"
67 #include "netinet/if_ether.h"
68 #endif
69
70 #ifdef NS
71 #include "netns/ns.h"
72 #include "netns/ns_if.h"
73 #endif
74
75 #ifdef RMP
76 #include "netrmp/rmp.h"
77 #include "netrmp/rmp_var.h"
78 #endif
79
80 #include "machine/autoconf.h"
81
82 #include "if_lereg.h"
83
84 #if NBPFILTER > 0
85 #include "../net/bpf.h"
86 #include "../net/bpfdesc.h"
87 #endif
88
89 #include "if_le.h"
90 #include "if_le_subr.h"
91
92 int ledebug = 1; /* console error messages */
93
94 int leintr(), leinit(), leioctl(), lestart(), ether_output();
95 struct mbuf *leget();
96 extern struct ifnet loif;
97
98 /* access LANCE registers */
99
100 void leattach __P((struct device *, struct device *, void *));
101 int lematch __P((struct device *, struct cfdata *, void *args));
102
103 struct cfdriver lecd =
104 { NULL, "le", lematch, leattach, DV_DULL, sizeof(struct le_softc), 0};
105
106 #define ISQUADALIGN(a) ((a & 0x3) == 0)
107
108 int lematch(parent, cf, args)
109 struct device *parent;
110 struct cfdata *cf;
111 void *args;
112 {
113 return le_machdep_match(parent, cf, args);
114 }
115 /*
116 * Interface exists: make available by filling in network interface
117 * record. System will initialize the interface when it is ready
118 * to accept packets.
119 */
120 void leattach(parent, self, args)
121 struct device *parent;
122 struct device *self;
123 void *args;
124 {
125 register struct lereg2 *ler2;
126 unsigned int a;
127 struct le_softc *le = (struct le_softc *) self;
128 struct ifnet *ifp = &le->sc_if;
129 char *cp;
130 int i, unit;
131
132 unit = le->sc_dev.dv_unit;
133 if (le_machdep_attach(parent, self, args)) {
134 printf(": bad attach??\n");
135 return;
136 }
137 ler2 = le->sc_r2;
138 printf(": ether address %s\n", ether_sprintf(le->sc_addr));
139
140 /*
141 * Setup for transmit/receive
142 */
143 ler2->ler2_mode = LE_MODE;
144 ler2->ler2_padr[0] = le->sc_addr[1];
145 ler2->ler2_padr[1] = le->sc_addr[0];
146 ler2->ler2_padr[2] = le->sc_addr[3];
147 ler2->ler2_padr[3] = le->sc_addr[2];
148 ler2->ler2_padr[4] = le->sc_addr[5];
149 ler2->ler2_padr[5] = le->sc_addr[4];
150 #ifdef RMP
151 /*
152 * Set up logical addr filter to accept multicast 9:0:9:0:0:4
153 * This should be an ioctl() to the driver. (XXX)
154 */
155 ler2->ler2_ladrf0 = 0x00100000;
156 ler2->ler2_ladrf1 = 0x0;
157 #else
158 ler2->ler2_ladrf0 = 0;
159 ler2->ler2_ladrf1 = 0;
160 #endif
161 a = LANCE_ADDR(ler2->ler2_rmd);
162 if (!ISQUADALIGN(a))
163 panic("rdra not quad aligned");
164 ler2->ler2_rlen = LE_RLEN | (a >> 16);
165 ler2->ler2_rdra = a & LE_ADDR_LOW_MASK;
166 a = LANCE_ADDR(ler2->ler2_tmd);
167 if (!ISQUADALIGN(a))
168 panic("tdra not quad aligned");
169 ler2->ler2_tlen = LE_TLEN | (a >> 16);
170 ler2->ler2_tdra = a & LE_ADDR_LOW_MASK;
171
172 ifp->if_unit = unit;
173 ifp->if_name = "le";
174 ifp->if_mtu = ETHERMTU;
175 ifp->if_init = leinit;
176 ifp->if_ioctl = leioctl;
177 ifp->if_output = ether_output;
178 ifp->if_start = lestart;
179 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
180 #if NBPFILTER > 0
181 bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
182 #endif
183 if_attach(ifp);
184 }
185
186 ledrinit(ler2)
187 register struct lereg2 *ler2;
188 {
189 unsigned int a;
190 register int i;
191
192 for (i = 0; i < LERBUF; i++) {
193 a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
194 #if 0
195 if (!ISQUADALIGN(a))
196 panic("rbuf not quad aligned");
197 #endif
198 ler2->ler2_rmd[i].rmd0 = a & LE_ADDR_LOW_MASK;
199 ler2->ler2_rmd[i].rmd1_bits = LE_OWN;
200 ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
201 ler2->ler2_rmd[i].rmd2 = -LEMTU;
202 ler2->ler2_rmd[i].rmd3 = 0;
203 }
204 for (i = 0; i < LETBUF; i++) {
205 a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
206 #if 0
207 if (!ISQUADALIGN(a))
208 panic("rbuf not quad aligned");
209 #endif
210 ler2->ler2_tmd[i].tmd0 = a & LE_ADDR_LOW_MASK;
211 ler2->ler2_tmd[i].tmd1_bits = 0;
212 ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
213 ler2->ler2_tmd[i].tmd2 = 0;
214 ler2->ler2_tmd[i].tmd3 = 0;
215 }
216 }
217
218 lereset(unit)
219 register int unit;
220 {
221 register struct le_softc *le = (struct le_softc *) lecd.cd_devs[unit];
222 register struct lereg1 *ler1 = le->sc_r1;
223 register struct lereg2 *ler2 = le->sc_r2;
224 unsigned int a;
225 register int timo = 100000;
226 register int stat;
227
228 #ifdef lint
229 stat = unit;
230 #endif
231 #if NBPFILTER > 0
232 if (le->sc_if.if_flags & IFF_PROMISC)
233 /* set the promiscuous bit */
234 le->sc_r2->ler2_mode = LE_MODE|0x8000;
235 else
236 le->sc_r2->ler2_mode = LE_MODE;
237 #endif
238 if (ledebug)
239 printf("le: resetting unit %d, reg %x, ram %x\n",
240 unit, le->sc_r1, le->sc_r2);
241 LERDWR(le, LE_CSR0, ler1->ler1_rap);
242 LERDWR(le, LE_STOP, ler1->ler1_rdp);
243 ledrinit(le->sc_r2);
244 le->sc_rmd = 0;
245 LERDWR(le, LE_CSR1, ler1->ler1_rap);
246 a = LANCE_ADDR(ler2);
247 LERDWR(le, a & LE_ADDR_LOW_MASK, ler1->ler1_rdp);
248 LERDWR(le, LE_CSR2, ler1->ler1_rap);
249 LERDWR(le, a >> 16, ler1->ler1_rdp);
250 LERDWR(le, LE_CSR0, ler1->ler1_rap);
251 LERDWR(le, LE_INIT, ler1->ler1_rdp);
252 do {
253 if (--timo == 0) {
254 printf("le%d: init timeout, stat = 0x%x\n",
255 unit, stat);
256 break;
257 }
258 LERDWR(le, ler1->ler1_rdp, stat);
259 } while ((stat & LE_IDON) == 0);
260 LERDWR(le, LE_STOP, ler1->ler1_rdp);
261 LERDWR(le, LE_CSR3, ler1->ler1_rap);
262 LERDWR(le, LE_BSWP, ler1->ler1_rdp);
263 LERDWR(le, LE_CSR0, ler1->ler1_rap);
264 LERDWR(le, LE_STRT | LE_INEA, ler1->ler1_rdp);
265 le->sc_if.if_flags &= ~IFF_OACTIVE;
266 }
267
268 /*
269 * Initialization of interface
270 */
271 leinit(unit)
272 int unit;
273 {
274 struct le_softc *le = lecd.cd_devs[unit];
275 register struct ifnet *ifp = &le->sc_if;
276 int s;
277
278 /* not yet, if address still unknown */
279 if (ifp->if_addrlist == (struct ifaddr *)0)
280 return;
281 if ((ifp->if_flags & IFF_RUNNING) == 0) {
282 s = splimp();
283 if (ledebug)
284 printf("le: initializing unit %d, reg %x, ram %x\n",
285 unit, le->sc_r1, le->sc_r2);
286 ifp->if_flags |= IFF_RUNNING;
287 lereset(unit);
288 (void) lestart(ifp);
289 splx(s);
290 }
291 }
292
293 /*
294 * Start output on interface. Get another datagram to send
295 * off of the interface queue, and copy it to the interface
296 * before starting the output.
297 */
298 lestart(ifp)
299 struct ifnet *ifp;
300 {
301 register struct le_softc *le = lecd.cd_devs[ifp->if_unit];
302 register struct letmd *tmd;
303 register struct mbuf *m;
304 int len;
305
306 if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
307 return (0);
308 IF_DEQUEUE(&le->sc_if.if_snd, m);
309 if (m == 0)
310 return (0);
311 len = leput(le->sc_r2->ler2_tbuf[0], m);
312 #if NBPFILTER > 0
313 /*
314 * If bpf is listening on this interface, let it
315 * see the packet before we commit it to the wire.
316 */
317 if (le->sc_bpf)
318 bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len);
319 #endif
320 tmd = le->sc_r2->ler2_tmd;
321 tmd->tmd3 = 0;
322 tmd->tmd2 = -len;
323 tmd->tmd1_bits = LE_OWN | LE_STP | LE_ENP;
324 le->sc_if.if_flags |= IFF_OACTIVE;
325 return (0);
326 }
327
328 leintr(unit)
329 register int unit;
330 {
331 register struct le_softc *le = lecd.cd_devs[unit];
332 register struct lereg1 *ler1;
333 register int stat;
334
335 le_machdep_intrcheck(le, unit);
336 ler1 = le->sc_r1;
337 LERDWR(le, ler1->ler1_rdp, stat);
338 if (ledebug)
339 printf("[le%d: stat %b]", unit, stat, LE_STATUS_BITS);
340 if (stat & LE_SERR) {
341 leerror(unit, stat);
342 if (stat & LE_MERR) {
343 le->sc_merr++;
344 lereset(unit);
345 return(1);
346 }
347 if (stat & LE_BABL)
348 le->sc_babl++;
349 if (stat & LE_CERR)
350 le->sc_cerr++;
351 if (stat & LE_MISS)
352 le->sc_miss++;
353 LERDWR(le, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
354 }
355 if ((stat & LE_RXON) == 0) {
356 le->sc_rxoff++;
357 lereset(unit);
358 return(1);
359 }
360 if ((stat & LE_TXON) == 0) {
361 le->sc_txoff++;
362 lereset(unit);
363 return(1);
364 }
365 if (stat & LE_RINT) {
366 /* interrupt is cleared in lerint */
367 lerint(unit);
368 }
369 if (stat & LE_TINT) {
370 LERDWR(le, LE_TINT|LE_INEA, ler1->ler1_rdp);
371 lexint(unit);
372 }
373 return(1);
374 }
375
376 /*
377 * Ethernet interface transmitter interrupt.
378 * Start another output if more data to send.
379 */
380 lexint(unit)
381 register int unit;
382 {
383 register struct le_softc *le = lecd.cd_devs[unit];
384 register struct letmd *tmd = le->sc_r2->ler2_tmd;
385
386 if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) {
387 le->sc_xint++;
388 return;
389 }
390 if (tmd->tmd1_bits & LE_OWN) {
391 le->sc_xown++;
392 return;
393 }
394 if (tmd->tmd1_bits & LE_ERR) {
395 err:
396 lexerror(unit);
397 le->sc_if.if_oerrors++;
398 if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
399 le->sc_uflo++;
400 lereset(unit);
401 }
402 else if (tmd->tmd3 & LE_LCOL)
403 le->sc_if.if_collisions++;
404 else if (tmd->tmd3 & LE_RTRY)
405 le->sc_if.if_collisions += 16;
406 }
407 else if (tmd->tmd3 & LE_TBUFF)
408 /* XXX documentation says BUFF not included in ERR */
409 goto err;
410 else if (tmd->tmd1_bits & LE_ONE)
411 le->sc_if.if_collisions++;
412 else if (tmd->tmd1_bits & LE_MORE)
413 /* what is the real number? */
414 le->sc_if.if_collisions += 2;
415 else
416 le->sc_if.if_opackets++;
417 le->sc_if.if_flags &= ~IFF_OACTIVE;
418 (void) lestart(&le->sc_if);
419 }
420
421 #define LENEXTRMP \
422 if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
423
424 /*
425 * Ethernet interface receiver interrupt.
426 * If input error just drop packet.
427 * Decapsulate packet based on type and pass to type specific
428 * higher-level input routine.
429 */
430 lerint(unit)
431 int unit;
432 {
433 register struct le_softc *le = lecd.cd_devs[unit];
434 register int bix = le->sc_rmd;
435 register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
436
437 /*
438 * Out of sync with hardware, should never happen?
439 */
440 if (rmd->rmd1_bits & LE_OWN) {
441 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
442 return;
443 }
444
445 /*
446 * Process all buffers with valid data
447 */
448 while ((rmd->rmd1_bits & LE_OWN) == 0) {
449 int len = rmd->rmd3;
450
451 /* Clear interrupt to avoid race condition */
452 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
453
454 if (rmd->rmd1_bits & LE_ERR) {
455 le->sc_rmd = bix;
456 lererror(unit, "bad packet");
457 le->sc_if.if_ierrors++;
458 } else if ((rmd->rmd1_bits & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
459 /*
460 * Find the end of the packet so we can see how long
461 * it was. We still throw it away.
462 */
463 do {
464 LERDWR(le->sc_r0, LE_RINT|LE_INEA,
465 le->sc_r1->ler1_rdp);
466 rmd->rmd3 = 0;
467 rmd->rmd1_bits = LE_OWN;
468 LENEXTRMP;
469 } while (!(rmd->rmd1_bits & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
470 le->sc_rmd = bix;
471 lererror(unit, "chained buffer");
472 le->sc_rxlen++;
473 /*
474 * If search terminated without successful completion
475 * we reset the hardware (conservative).
476 */
477 if ((rmd->rmd1_bits & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
478 LE_ENP) {
479 lereset(unit);
480 return;
481 }
482 } else
483 leread(unit, le->sc_r2->ler2_rbuf[bix], len);
484 rmd->rmd3 = 0;
485 rmd->rmd1_bits = LE_OWN;
486 LENEXTRMP;
487 }
488 le->sc_rmd = bix;
489 }
490
491 leread(unit, buf, len)
492 int unit;
493 char *buf;
494 int len;
495 {
496 register struct le_softc *le = lecd.cd_devs[unit];
497 register struct ether_header *et;
498 struct mbuf *m;
499 int off, resid;
500
501 le->sc_if.if_ipackets++;
502 et = (struct ether_header *)buf;
503 et->ether_type = ntohs((u_short)et->ether_type);
504 /* adjust input length to account for header and CRC */
505 len = len - sizeof(struct ether_header) - 4;
506
507 #ifdef RMP
508 /* (XXX)
509 *
510 * If Ethernet Type field is < MaxPacketSize, we probably have
511 * a IEEE802 packet here. Make sure that the size is at least
512 * that of the HP LLC. Also do sanity checks on length of LLC
513 * (old Ethernet Type field) and packet length.
514 *
515 * Provided the above checks succeed, change `len' to reflect
516 * the length of the LLC (i.e. et->ether_type) and change the
517 * type field to ETHERTYPE_IEEE so we can switch() on it later.
518 * Yes, this is a hack and will eventually be done "right".
519 */
520 if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) &&
521 len >= et->ether_type && len >= IEEE802LEN_MIN) {
522 len = et->ether_type;
523 et->ether_type = ETHERTYPE_IEEE; /* hack! */
524 }
525 #endif
526
527 #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
528 if (et->ether_type >= ETHERTYPE_TRAIL &&
529 et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
530 off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
531 if (off >= ETHERMTU)
532 return; /* sanity */
533 et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
534 resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
535 if (off + resid > len)
536 return; /* sanity */
537 len = off + resid;
538 } else
539 off = 0;
540
541 if (len <= 0) {
542 if (ledebug)
543 log(LOG_WARNING,
544 "le%d: ierror(runt packet): from %s: len=%d\n",
545 unit, ether_sprintf(et->ether_shost), len);
546 le->sc_runt++;
547 le->sc_if.if_ierrors++;
548 return;
549 }
550 #if NBPFILTER > 0
551 /*
552 * Check if there's a bpf filter listening on this interface.
553 * If so, hand off the raw packet to bpf, which must deal with
554 * trailers in its own way.
555 */
556 if (le->sc_bpf) {
557 bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
558
559 /*
560 * Note that the interface cannot be in promiscuous mode if
561 * there are no bpf listeners. And if we are in promiscuous
562 * mode, we have to check if this packet is really ours.
563 *
564 * XXX This test does not support multicasts.
565 */
566 if ((le->sc_if.if_flags & IFF_PROMISC)
567 && bcmp(et->ether_dhost, le->sc_addr,
568 sizeof(et->ether_dhost)) != 0
569 && bcmp(et->ether_dhost, etherbroadcastaddr,
570 sizeof(et->ether_dhost)) != 0)
571 return;
572 }
573 #endif
574 /*
575 * Pull packet off interface. Off is nonzero if packet
576 * has trailing header; leget will then force this header
577 * information to be at the front, but we still have to drop
578 * the type and length which are at the front of any trailer data.
579 */
580 m = leget(buf, len, off, &le->sc_if);
581 if (m == 0)
582 return;
583 #ifdef RMP
584 /*
585 * (XXX)
586 * This needs to be integrated with the ISO stuff in ether_input()
587 */
588 if (et->ether_type == ETHERTYPE_IEEE) {
589 /*
590 * Snag the Logical Link Control header (IEEE 802.2).
591 */
592 struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc);
593
594 /*
595 * If the DSAP (and HP's extended DXSAP) indicate this
596 * is an RMP packet, hand it to the raw input routine.
597 */
598 if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) {
599 static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT};
600 static struct sockaddr rmp_src = {AF_RMP};
601 static struct sockaddr rmp_dst = {AF_RMP};
602
603 bcopy(et->ether_shost, rmp_src.sa_data,
604 sizeof(et->ether_shost));
605 bcopy(et->ether_dhost, rmp_dst.sa_data,
606 sizeof(et->ether_dhost));
607
608 raw_input(m, &rmp_sp, &rmp_src, &rmp_dst);
609 return;
610 }
611 }
612 #endif
613 ether_input(&le->sc_if, et, m);
614 }
615
616 /*
617 * Routine to copy from mbuf chain to transmit
618 * buffer in board local memory.
619 */
620 leput(lebuf, m)
621 register char *lebuf;
622 register struct mbuf *m;
623 {
624 register struct mbuf *mp;
625 register int len, tlen = 0;
626
627 for (mp = m; mp; mp = mp->m_next) {
628 len = mp->m_len;
629 if (len == 0)
630 continue;
631 tlen += len;
632 bcopy(mtod(mp, char *), lebuf, len);
633 lebuf += len;
634 }
635 m_freem(m);
636 if (tlen < LEMINSIZE) {
637 bzero(lebuf, LEMINSIZE - tlen);
638 tlen = LEMINSIZE;
639 }
640 return(tlen);
641 }
642
643 /*
644 * Routine to copy from board local memory into mbufs.
645 */
646 struct mbuf *
647 leget(lebuf, totlen, off0, ifp)
648 char *lebuf;
649 int totlen, off0;
650 struct ifnet *ifp;
651 {
652 register struct mbuf *m;
653 struct mbuf *top = 0, **mp = ⊤
654 register int off = off0, len;
655 register char *cp;
656 char *epkt;
657
658 lebuf += sizeof (struct ether_header);
659 cp = lebuf;
660 epkt = cp + totlen;
661 if (off) {
662 cp += off + 2 * sizeof(u_short);
663 totlen -= 2 * sizeof(u_short);
664 }
665
666 MGETHDR(m, M_DONTWAIT, MT_DATA);
667 if (m == 0)
668 return (0);
669 m->m_pkthdr.rcvif = ifp;
670 m->m_pkthdr.len = totlen;
671 m->m_len = MHLEN;
672
673 while (totlen > 0) {
674 if (top) {
675 MGET(m, M_DONTWAIT, MT_DATA);
676 if (m == 0) {
677 m_freem(top);
678 return (0);
679 }
680 m->m_len = MLEN;
681 }
682 len = min(totlen, epkt - cp);
683 if (len >= MINCLSIZE) {
684 MCLGET(m, M_DONTWAIT);
685 if (m->m_flags & M_EXT)
686 m->m_len = len = min(len, MCLBYTES);
687 else
688 len = m->m_len;
689 } else {
690 /*
691 * Place initial small packet/header at end of mbuf.
692 */
693 if (len < m->m_len) {
694 if (top == 0 && len + max_linkhdr <= m->m_len)
695 m->m_data += max_linkhdr;
696 m->m_len = len;
697 } else
698 len = m->m_len;
699 }
700 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
701 cp += len;
702 *mp = m;
703 mp = &m->m_next;
704 totlen -= len;
705 if (cp == epkt)
706 cp = lebuf;
707 }
708 return (top);
709 }
710
711 /*
712 * Process an ioctl request.
713 */
714 leioctl(ifp, cmd, data)
715 register struct ifnet *ifp;
716 int cmd;
717 caddr_t data;
718 {
719 register struct ifaddr *ifa = (struct ifaddr *)data;
720 struct le_softc *le = (struct le_softc *) lecd.cd_devs[ifp->if_unit];
721 struct lereg1 *ler1 = le->sc_r1;
722 int s = splimp(), error = 0;
723
724 switch (cmd) {
725
726 case SIOCSIFADDR:
727 ifp->if_flags |= IFF_UP;
728 switch (ifa->ifa_addr->sa_family) {
729 #ifdef INET
730 case AF_INET:
731 leinit(ifp->if_unit); /* before arpwhohas */
732 ((struct arpcom *)ifp)->ac_ipaddr =
733 IA_SIN(ifa)->sin_addr;
734 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
735 break;
736 #endif
737 #ifdef NS
738 case AF_NS:
739 {
740 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
741
742 if (ns_nullhost(*ina))
743 ina->x_host = *(union ns_host *)(le->sc_addr);
744 else {
745 /*
746 * The manual says we can't change the address
747 * while the receiver is armed,
748 * so reset everything
749 */
750 ifp->if_flags &= ~IFF_RUNNING;
751 bcopy((caddr_t)ina->x_host.c_host,
752 (caddr_t)le->sc_addr, sizeof(le->sc_addr));
753 }
754 leinit(ifp->if_unit); /* does le_setaddr() */
755 break;
756 }
757 #endif
758 default:
759 leinit(ifp->if_unit);
760 break;
761 }
762 break;
763
764 case SIOCSIFFLAGS:
765 if ((ifp->if_flags & IFF_UP) == 0 &&
766 ifp->if_flags & IFF_RUNNING) {
767 LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
768 ifp->if_flags &= ~IFF_RUNNING;
769 } else if (ifp->if_flags & IFF_UP &&
770 (ifp->if_flags & IFF_RUNNING) == 0)
771 leinit(ifp->if_unit);
772 /*
773 * If the state of the promiscuous bit changes, the interface
774 * must be reset to effect the change.
775 */
776 if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&
777 (ifp->if_flags & IFF_RUNNING)) {
778 le->sc_iflags = ifp->if_flags;
779 lereset(ifp->if_unit);
780 lestart(ifp);
781 }
782 break;
783
784 default:
785 error = EINVAL;
786 }
787 splx(s);
788 return (error);
789 }
790
791 leerror(unit, stat)
792 int unit;
793 int stat;
794 {
795 struct le_softc *le = NULL;
796
797
798 if (!ledebug)
799 return;
800
801 le = (struct le_softc *) lecd.cd_devs[unit];
802 /*
803 * Not all transceivers implement heartbeat
804 * so we only log CERR once.
805 */
806 if ((stat & LE_CERR) && le->sc_cerr)
807 return;
808 log(LOG_WARNING,
809 "le%d: error: stat=%b\n", unit,
810 stat,
811 LE_STATUS_BITS);
812 }
813
814 lererror(unit, msg)
815 int unit;
816 char *msg;
817 {
818 register struct le_softc *le = lecd.cd_devs[unit];
819 register struct lermd *rmd;
820 int len;
821
822 if (!ledebug)
823 return;
824
825 rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
826 len = rmd->rmd3;
827 log(LOG_WARNING,
828 "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1_bits=%b\n",
829 unit, msg,
830 len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown",
831 le->sc_rmd, len,
832 rmd->rmd1_bits,
833 "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3RBUF\2STP\1ENP");
834 }
835
836 lexerror(unit)
837 int unit;
838 {
839 register struct le_softc *le = lecd.cd_devs[unit];
840 register struct letmd *tmd;
841 int len;
842
843 if (!ledebug)
844 return;
845
846 tmd = le->sc_r2->ler2_tmd;
847 len = -tmd->tmd2;
848 log(LOG_WARNING,
849 "le%d: oerror: to %s: buf=%d, len=%d, tmd1_bits=%b, tmd3=%b\n",
850 unit,
851 len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown",
852 0, len,
853 tmd->tmd1_bits,
854 "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP",
855 tmd->tmd3,
856 "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
857 }
858