if_le.c revision 1.3 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 * $Id: if_le.c,v 1.3 1994/01/24 00:25:21 deraadt Exp $
35 */
36
37 #include "le.h"
38 #if NLE > 0
39
40 #include "bpfilter.h"
41
42 /*
43 * AMD 7990 LANCE
44 *
45 * This driver will generate and accept tailer encapsulated packets even
46 * though it buys us nothing. The motivation was to avoid incompatibilities
47 * with VAXen, SUNs, and others that handle and benefit from them.
48 * This reasoning is dubious.
49 */
50 #include "sys/param.h"
51 #include "sys/systm.h"
52 #include "sys/mbuf.h"
53 #include "sys/buf.h"
54 #include "sys/protosw.h"
55 #include "sys/socket.h"
56 #include "sys/syslog.h"
57 #include "sys/ioctl.h"
58 #include "sys/errno.h"
59
60 #include "net/if.h"
61 #include "net/netisr.h"
62 #include "net/route.h"
63
64 #ifdef INET
65 #include "netinet/in.h"
66 #include "netinet/in_systm.h"
67 #include "netinet/in_var.h"
68 #include "netinet/ip.h"
69 #include "netinet/if_ether.h"
70 #endif
71
72 #ifdef NS
73 #include "netns/ns.h"
74 #include "netns/ns_if.h"
75 #endif
76
77 #include "../include/cpu.h"
78 #include "../hp300/isr.h"
79 #include "../include/mtpr.h"
80 #include "device.h"
81 #include "if_lereg.h"
82
83 #if NBPFILTER > 0
84 #include "../net/bpf.h"
85 #include "../net/bpfdesc.h"
86 #endif
87
88 /* offsets for: ID, REGS, MEM, NVRAM */
89 int lestd[] = { 0, 0x4000, 0x8000, 0xC008 };
90
91 int leattach();
92 struct driver ledriver = {
93 leattach, "le",
94 };
95
96 struct isr le_isr[NLE];
97 int ledebug = 0; /* console error messages */
98
99 int leintr(), leinit(), leioctl(), lestart(), ether_output();
100 struct mbuf *leget();
101 extern struct ifnet loif;
102
103 /*
104 * Ethernet software status per interface.
105 *
106 * Each interface is referenced by a network interface structure,
107 * le_if, which the routing code uses to locate the interface.
108 * This structure contains the output queue for the interface, its address, ...
109 */
110 struct le_softc {
111 struct arpcom sc_ac; /* common Ethernet structures */
112 #define sc_if sc_ac.ac_if /* network-visible interface */
113 #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
114 struct lereg0 *sc_r0; /* DIO registers */
115 struct lereg1 *sc_r1; /* LANCE registers */
116 struct lereg2 *sc_r2; /* dual-port RAM */
117 int sc_rmd; /* predicted next rmd to process */
118 int sc_runt;
119 int sc_jab;
120 int sc_merr;
121 int sc_babl;
122 int sc_cerr;
123 int sc_miss;
124 int sc_xint;
125 int sc_xown;
126 int sc_uflo;
127 int sc_rxlen;
128 int sc_rxoff;
129 int sc_txoff;
130 int sc_busy;
131 short sc_iflags;
132 #if NBPFILTER > 0
133 caddr_t sc_bpf;
134 #endif
135 } le_softc[NLE];
136
137 /* access LANCE registers */
138 #define LERDWR(cntl, src, dst) \
139 do { \
140 (dst) = (src); \
141 } while (((cntl)->ler0_status & LE_ACK) == 0);
142
143 /*
144 * Interface exists: make available by filling in network interface
145 * record. System will initialize the interface when it is ready
146 * to accept packets.
147 */
148 leattach(hd)
149 struct hp_device *hd;
150 {
151 register struct lereg0 *ler0;
152 register struct lereg2 *ler2;
153 struct lereg2 *lemem = 0;
154 struct le_softc *le = &le_softc[hd->hp_unit];
155 struct ifnet *ifp = &le->sc_if;
156 char *cp;
157 int i;
158
159 ler0 = le->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
160 le->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr);
161 ler2 = le->sc_r2 = (struct lereg2 *)(lestd[2] + (int)hd->hp_addr);
162 if (ler0->ler0_id != LEID)
163 return(0);
164 le_isr[hd->hp_unit].isr_intr = leintr;
165 hd->hp_ipl = le_isr[hd->hp_unit].isr_ipl = LE_IPL(ler0->ler0_status);
166 le_isr[hd->hp_unit].isr_arg = hd->hp_unit;
167 ler0->ler0_id = 0xFF;
168 DELAY(100);
169
170 /*
171 * Read the ethernet address off the board, one nibble at a time.
172 */
173 cp = (char *)(lestd[3] + (int)hd->hp_addr);
174 for (i = 0; i < sizeof(le->sc_addr); i++) {
175 le->sc_addr[i] = (*++cp & 0xF) << 4;
176 cp++;
177 le->sc_addr[i] |= *++cp & 0xF;
178 cp++;
179 }
180 printf("le%d: hardware address %s\n", hd->hp_unit,
181 ether_sprintf(le->sc_addr));
182
183 /*
184 * Setup for transmit/receive
185 */
186 ler2->ler2_mode = LE_MODE;
187 ler2->ler2_padr[0] = le->sc_addr[1];
188 ler2->ler2_padr[1] = le->sc_addr[0];
189 ler2->ler2_padr[2] = le->sc_addr[3];
190 ler2->ler2_padr[3] = le->sc_addr[2];
191 ler2->ler2_padr[4] = le->sc_addr[5];
192 ler2->ler2_padr[5] = le->sc_addr[4];
193 ler2->ler2_ladrf0 = 0;
194 ler2->ler2_ladrf1 = 0;
195 ler2->ler2_rlen = LE_RLEN;
196 ler2->ler2_rdra = (int)lemem->ler2_rmd;
197 ler2->ler2_tlen = LE_TLEN;
198 ler2->ler2_tdra = (int)lemem->ler2_tmd;
199 isrlink(&le_isr[hd->hp_unit]);
200 ler0->ler0_status = LE_IE;
201
202 ifp->if_unit = hd->hp_unit;
203 ifp->if_name = "le";
204 ifp->if_mtu = ETHERMTU;
205 ifp->if_init = leinit;
206 ifp->if_ioctl = leioctl;
207 ifp->if_output = ether_output;
208 ifp->if_start = lestart;
209 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
210 #if NBPFILTER > 0
211 bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
212 #endif
213 if_attach(ifp);
214 return (1);
215 }
216
217 ledrinit(ler2)
218 register struct lereg2 *ler2;
219 {
220 register struct lereg2 *lemem = 0;
221 register int i;
222
223 for (i = 0; i < LERBUF; i++) {
224 ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
225 ler2->ler2_rmd[i].rmd1 = LE_OWN;
226 ler2->ler2_rmd[i].rmd2 = -LEMTU;
227 ler2->ler2_rmd[i].rmd3 = 0;
228 }
229 for (i = 0; i < LETBUF; i++) {
230 ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
231 ler2->ler2_tmd[i].tmd1 = 0;
232 ler2->ler2_tmd[i].tmd2 = 0;
233 ler2->ler2_tmd[i].tmd3 = 0;
234 }
235 }
236
237 lereset(unit)
238 register int unit;
239 {
240 register struct le_softc *le = &le_softc[unit];
241 register struct lereg0 *ler0 = le->sc_r0;
242 register struct lereg1 *ler1 = le->sc_r1;
243 register struct lereg2 *lemem = 0;
244 register int timo = 100000;
245 register int stat;
246
247 #ifdef lint
248 stat = unit;
249 #endif
250 #if NBPFILTER > 0
251 if (le->sc_if.if_flags & IFF_PROMISC)
252 /* set the promiscuous bit */
253 le->sc_r2->ler2_mode = LE_MODE|0x8000;
254 else
255 le->sc_r2->ler2_mode = LE_MODE;
256 #endif
257 LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
258 LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
259 ledrinit(le->sc_r2);
260 le->sc_rmd = 0;
261 LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
262 LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
263 LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
264 LERDWR(ler0, 0, ler1->ler1_rdp);
265 LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
266 LERDWR(ler0, LE_INIT, ler1->ler1_rdp);
267 do {
268 if (--timo == 0) {
269 printf("le%d: init timeout, stat = 0x%x\n",
270 unit, stat);
271 break;
272 }
273 LERDWR(ler0, ler1->ler1_rdp, stat);
274 } while ((stat & LE_IDON) == 0);
275 LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
276 LERDWR(ler0, LE_CSR3, ler1->ler1_rap);
277 LERDWR(ler0, LE_BSWP, ler1->ler1_rdp);
278 LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
279 LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
280 le->sc_if.if_flags &= ~IFF_OACTIVE;
281 }
282
283 /*
284 * Initialization of interface
285 */
286 leinit(unit)
287 int unit;
288 {
289 struct le_softc *le = &le_softc[unit];
290 register struct ifnet *ifp = &le->sc_if;
291 int s;
292
293 /* not yet, if address still unknown */
294 if (ifp->if_addrlist == (struct ifaddr *)0)
295 return;
296 if ((ifp->if_flags & IFF_RUNNING) == 0) {
297 s = splimp();
298 ifp->if_flags |= IFF_RUNNING;
299 lereset(unit);
300 (void) lestart(ifp);
301 splx(s);
302 }
303 }
304
305 /*
306 * Start output on interface. Get another datagram to send
307 * off of the interface queue, and copy it to the interface
308 * before starting the output.
309 */
310 lestart(ifp)
311 struct ifnet *ifp;
312 {
313 register struct le_softc *le = &le_softc[ifp->if_unit];
314 register struct letmd *tmd;
315 register struct mbuf *m;
316 int len;
317
318 if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
319 return (0);
320 IF_DEQUEUE(&le->sc_if.if_snd, m);
321 if (m == 0)
322 return (0);
323 len = leput(le->sc_r2->ler2_tbuf[0], m);
324 #if NBPFILTER > 0
325 /*
326 * If bpf is listening on this interface, let it
327 * see the packet before we commit it to the wire.
328 */
329 if (le->sc_bpf)
330 bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len);
331 #endif
332 tmd = le->sc_r2->ler2_tmd;
333 tmd->tmd3 = 0;
334 tmd->tmd2 = -len;
335 tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
336 le->sc_if.if_flags |= IFF_OACTIVE;
337 return (0);
338 }
339
340 leintr(unit)
341 register int unit;
342 {
343 register struct le_softc *le = &le_softc[unit];
344 register struct lereg0 *ler0 = le->sc_r0;
345 register struct lereg1 *ler1;
346 register int stat;
347
348 if ((ler0->ler0_status & LE_IR) == 0)
349 return(0);
350 if (ler0->ler0_status & LE_JAB) {
351 le->sc_jab++;
352 lereset(unit);
353 return(1);
354 }
355 ler1 = le->sc_r1;
356 LERDWR(ler0, ler1->ler1_rdp, stat);
357 if (stat & LE_SERR) {
358 leerror(unit, stat);
359 if (stat & LE_MERR) {
360 le->sc_merr++;
361 lereset(unit);
362 return(1);
363 }
364 if (stat & LE_BABL)
365 le->sc_babl++;
366 if (stat & LE_CERR)
367 le->sc_cerr++;
368 if (stat & LE_MISS)
369 le->sc_miss++;
370 LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
371 }
372 if ((stat & LE_RXON) == 0) {
373 le->sc_rxoff++;
374 lereset(unit);
375 return(1);
376 }
377 if ((stat & LE_TXON) == 0) {
378 le->sc_txoff++;
379 lereset(unit);
380 return(1);
381 }
382 if (stat & LE_RINT) {
383 /* interrupt is cleared in lerint */
384 lerint(unit);
385 }
386 if (stat & LE_TINT) {
387 LERDWR(ler0, LE_TINT|LE_INEA, ler1->ler1_rdp);
388 lexint(unit);
389 }
390 return(1);
391 }
392
393 /*
394 * Ethernet interface transmitter interrupt.
395 * Start another output if more data to send.
396 */
397 lexint(unit)
398 register int unit;
399 {
400 register struct le_softc *le = &le_softc[unit];
401 register struct letmd *tmd = le->sc_r2->ler2_tmd;
402
403 if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) {
404 le->sc_xint++;
405 return;
406 }
407 if (tmd->tmd1 & LE_OWN) {
408 le->sc_xown++;
409 return;
410 }
411 if (tmd->tmd1 & LE_ERR) {
412 err:
413 lexerror(unit);
414 le->sc_if.if_oerrors++;
415 if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
416 le->sc_uflo++;
417 lereset(unit);
418 }
419 else if (tmd->tmd3 & LE_LCOL)
420 le->sc_if.if_collisions++;
421 else if (tmd->tmd3 & LE_RTRY)
422 le->sc_if.if_collisions += 16;
423 }
424 else if (tmd->tmd3 & LE_TBUFF)
425 /* XXX documentation says BUFF not included in ERR */
426 goto err;
427 else if (tmd->tmd1 & LE_ONE)
428 le->sc_if.if_collisions++;
429 else if (tmd->tmd1 & LE_MORE)
430 /* what is the real number? */
431 le->sc_if.if_collisions += 2;
432 else
433 le->sc_if.if_opackets++;
434 le->sc_if.if_flags &= ~IFF_OACTIVE;
435 (void) lestart(&le->sc_if);
436 }
437
438 #define LENEXTRMP \
439 if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
440
441 /*
442 * Ethernet interface receiver interrupt.
443 * If input error just drop packet.
444 * Decapsulate packet based on type and pass to type specific
445 * higher-level input routine.
446 */
447 lerint(unit)
448 int unit;
449 {
450 register struct le_softc *le = &le_softc[unit];
451 register int bix = le->sc_rmd;
452 register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
453
454 /*
455 * Out of sync with hardware, should never happen?
456 */
457 if (rmd->rmd1 & LE_OWN) {
458 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
459 return;
460 }
461
462 /*
463 * Process all buffers with valid data
464 */
465 while ((rmd->rmd1 & LE_OWN) == 0) {
466 int len = rmd->rmd3;
467
468 /* Clear interrupt to avoid race condition */
469 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
470
471 if (rmd->rmd1 & LE_ERR) {
472 le->sc_rmd = bix;
473 lererror(unit, "bad packet");
474 le->sc_if.if_ierrors++;
475 } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
476 /*
477 * Find the end of the packet so we can see how long
478 * it was. We still throw it away.
479 */
480 do {
481 LERDWR(le->sc_r0, LE_RINT|LE_INEA,
482 le->sc_r1->ler1_rdp);
483 rmd->rmd3 = 0;
484 rmd->rmd1 = LE_OWN;
485 LENEXTRMP;
486 } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
487 le->sc_rmd = bix;
488 lererror(unit, "chained buffer");
489 le->sc_rxlen++;
490 /*
491 * If search terminated without successful completion
492 * we reset the hardware (conservative).
493 */
494 if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
495 LE_ENP) {
496 lereset(unit);
497 return;
498 }
499 } else
500 leread(unit, le->sc_r2->ler2_rbuf[bix], len);
501 rmd->rmd3 = 0;
502 rmd->rmd1 = LE_OWN;
503 LENEXTRMP;
504 }
505 le->sc_rmd = bix;
506 }
507
508 leread(unit, buf, len)
509 int unit;
510 char *buf;
511 int len;
512 {
513 register struct le_softc *le = &le_softc[unit];
514 register struct ether_header *et;
515 struct mbuf *m;
516 int off, resid;
517 u_short etype;
518
519 le->sc_if.if_ipackets++;
520 et = (struct ether_header *)buf;
521 /* adjust input length to account for header and CRC */
522 len = len - sizeof(struct ether_header) - 4;
523
524 #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
525 etype = ntohs(et->ether_type);
526 if (etype) >= ETHERTYPE_TRAIL &&
527 etype) < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
528 off = (etype - ETHERTYPE_TRAIL) * 512;
529 if (off >= ETHERMTU)
530 return; /* sanity */
531 et->ether_type = *ledataaddr(et, off, u_short *);
532 resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
533 if (off + resid > len)
534 return; /* sanity */
535 len = off + resid;
536 } else
537 off = 0;
538
539 if (len <= 0) {
540 if (ledebug)
541 log(LOG_WARNING,
542 "le%d: ierror(runt packet): from %s: len=%d\n",
543 unit, ether_sprintf(et->ether_shost), len);
544 le->sc_runt++;
545 le->sc_if.if_ierrors++;
546 return;
547 }
548 #if NBPFILTER > 0
549 /*
550 * Check if there's a bpf filter listening on this interface.
551 * If so, hand off the raw packet to bpf, which must deal with
552 * trailers in its own way.
553 */
554 if (le->sc_bpf) {
555 bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
556
557 /*
558 * Note that the interface cannot be in promiscuous mode if
559 * there are no bpf listeners. And if we are in promiscuous
560 * mode, we have to check if this packet is really ours.
561 *
562 * XXX This test does not support multicasts.
563 */
564 if ((le->sc_if.if_flags & IFF_PROMISC)
565 && bcmp(et->ether_dhost, le->sc_addr,
566 sizeof(et->ether_dhost)) != 0
567 && bcmp(et->ether_dhost, etherbroadcastaddr,
568 sizeof(et->ether_dhost)) != 0)
569 return;
570 }
571 #endif
572 /*
573 * Pull packet off interface. Off is nonzero if packet
574 * has trailing header; leget will then force this header
575 * information to be at the front, but we still have to drop
576 * the type and length which are at the front of any trailer data.
577 */
578 m = leget(buf, len, off, &le->sc_if);
579 if (m == 0)
580 return;
581 ether_input(&le->sc_if, et, m);
582 }
583
584 /*
585 * Routine to copy from mbuf chain to transmit
586 * buffer in board local memory.
587 */
588 leput(lebuf, m)
589 register char *lebuf;
590 register struct mbuf *m;
591 {
592 register struct mbuf *mp;
593 register int len, tlen = 0;
594
595 for (mp = m; mp; mp = mp->m_next) {
596 len = mp->m_len;
597 if (len == 0)
598 continue;
599 tlen += len;
600 bcopy(mtod(mp, char *), lebuf, len);
601 lebuf += len;
602 }
603 m_freem(m);
604 if (tlen < LEMINSIZE) {
605 bzero(lebuf, LEMINSIZE - tlen);
606 tlen = LEMINSIZE;
607 }
608 return(tlen);
609 }
610
611 /*
612 * Routine to copy from board local memory into mbufs.
613 */
614 struct mbuf *
615 leget(lebuf, totlen, off0, ifp)
616 char *lebuf;
617 int totlen, off0;
618 struct ifnet *ifp;
619 {
620 register struct mbuf *m;
621 struct mbuf *top = 0, **mp = ⊤
622 register int off = off0, len;
623 register char *cp;
624 char *epkt;
625
626 lebuf += sizeof (struct ether_header);
627 cp = lebuf;
628 epkt = cp + totlen;
629 if (off) {
630 cp += off + 2 * sizeof(u_short);
631 totlen -= 2 * sizeof(u_short);
632 }
633
634 MGETHDR(m, M_DONTWAIT, MT_DATA);
635 if (m == 0)
636 return (0);
637 m->m_pkthdr.rcvif = ifp;
638 m->m_pkthdr.len = totlen;
639 m->m_len = MHLEN;
640
641 while (totlen > 0) {
642 if (top) {
643 MGET(m, M_DONTWAIT, MT_DATA);
644 if (m == 0) {
645 m_freem(top);
646 return (0);
647 }
648 m->m_len = MLEN;
649 }
650 len = min(totlen, epkt - cp);
651 if (len >= MINCLSIZE) {
652 MCLGET(m, M_DONTWAIT);
653 if (m->m_flags & M_EXT)
654 m->m_len = len = min(len, MCLBYTES);
655 else
656 len = m->m_len;
657 } else {
658 /*
659 * Place initial small packet/header at end of mbuf.
660 */
661 if (len < m->m_len) {
662 if (top == 0 && len + max_linkhdr <= m->m_len)
663 m->m_data += max_linkhdr;
664 m->m_len = len;
665 } else
666 len = m->m_len;
667 }
668 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
669 cp += len;
670 *mp = m;
671 mp = &m->m_next;
672 totlen -= len;
673 if (cp == epkt)
674 cp = lebuf;
675 }
676 return (top);
677 }
678
679 /*
680 * Process an ioctl request.
681 */
682 leioctl(ifp, cmd, data)
683 register struct ifnet *ifp;
684 int cmd;
685 caddr_t data;
686 {
687 register struct ifaddr *ifa = (struct ifaddr *)data;
688 struct le_softc *le = &le_softc[ifp->if_unit];
689 struct lereg1 *ler1 = le->sc_r1;
690 int s = splimp(), error = 0;
691
692 switch (cmd) {
693
694 case SIOCSIFADDR:
695 ifp->if_flags |= IFF_UP;
696 switch (ifa->ifa_addr->sa_family) {
697 #ifdef INET
698 case AF_INET:
699 leinit(ifp->if_unit); /* before arpwhohas */
700 ((struct arpcom *)ifp)->ac_ipaddr =
701 IA_SIN(ifa)->sin_addr;
702 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
703 break;
704 #endif
705 #ifdef NS
706 case AF_NS:
707 {
708 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
709
710 if (ns_nullhost(*ina))
711 ina->x_host = *(union ns_host *)(le->sc_addr);
712 else {
713 /*
714 * The manual says we can't change the address
715 * while the receiver is armed,
716 * so reset everything
717 */
718 ifp->if_flags &= ~IFF_RUNNING;
719 bcopy((caddr_t)ina->x_host.c_host,
720 (caddr_t)le->sc_addr, sizeof(le->sc_addr));
721 }
722 leinit(ifp->if_unit); /* does le_setaddr() */
723 break;
724 }
725 #endif
726 default:
727 leinit(ifp->if_unit);
728 break;
729 }
730 break;
731
732 case SIOCSIFFLAGS:
733 if ((ifp->if_flags & IFF_UP) == 0 &&
734 ifp->if_flags & IFF_RUNNING) {
735 LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
736 ifp->if_flags &= ~IFF_RUNNING;
737 } else if (ifp->if_flags & IFF_UP &&
738 (ifp->if_flags & IFF_RUNNING) == 0)
739 leinit(ifp->if_unit);
740 /*
741 * If the state of the promiscuous bit changes, the interface
742 * must be reset to effect the change.
743 */
744 if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&
745 (ifp->if_flags & IFF_RUNNING)) {
746 le->sc_iflags = ifp->if_flags;
747 lereset(ifp->if_unit);
748 lestart(ifp);
749 }
750 break;
751
752 default:
753 error = EINVAL;
754 }
755 splx(s);
756 return (error);
757 }
758
759 leerror(unit, stat)
760 int unit;
761 int stat;
762 {
763 if (!ledebug)
764 return;
765
766 /*
767 * Not all transceivers implement heartbeat
768 * so we only log CERR once.
769 */
770 if ((stat & LE_CERR) && le_softc[unit].sc_cerr)
771 return;
772 log(LOG_WARNING,
773 "le%d: error: stat=%b\n", unit,
774 stat,
775 "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
776 }
777
778 lererror(unit, msg)
779 int unit;
780 char *msg;
781 {
782 register struct le_softc *le = &le_softc[unit];
783 register struct lermd *rmd;
784 int len;
785
786 if (!ledebug)
787 return;
788
789 rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
790 len = rmd->rmd3;
791 log(LOG_WARNING,
792 "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
793 unit, msg,
794 len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown",
795 le->sc_rmd, len,
796 rmd->rmd1,
797 "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
798 }
799
800 lexerror(unit)
801 int unit;
802 {
803 register struct le_softc *le = &le_softc[unit];
804 register struct letmd *tmd;
805 int len;
806
807 if (!ledebug)
808 return;
809
810 tmd = le->sc_r2->ler2_tmd;
811 len = -tmd->tmd2;
812 log(LOG_WARNING,
813 "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
814 unit,
815 len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown",
816 0, len,
817 tmd->tmd1,
818 "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
819 tmd->tmd3,
820 "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
821 }
822 #endif
823