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