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