if_eg.c revision 1.7 1 /* $NetBSD: if_eg.c,v 1.7 1994/11/04 21:32:23 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1993 Dean Huxley <dean (at) fsa.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Dean Huxley.
18 * 4. The name of Dean Huxley may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* To do:
34 * - multicast
35 * - promiscuous
36 */
37 #include "bpfilter.h"
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/mbuf.h>
42 #include <sys/socket.h>
43 #include <sys/ioctl.h>
44 #include <sys/errno.h>
45 #include <sys/syslog.h>
46 #include <sys/select.h>
47 #include <sys/device.h>
48
49 #include <net/if.h>
50 #include <net/netisr.h>
51 #include <net/if_dl.h>
52 #include <net/if_types.h>
53 #include <net/netisr.h>
54
55 #ifdef INET
56 #include <netinet/in.h>
57 #include <netinet/in_systm.h>
58 #include <netinet/in_var.h>
59 #include <netinet/ip.h>
60 #include <netinet/if_ether.h>
61 #endif
62
63 #ifdef NS
64 #include <netns/ns.h>
65 #include <netns/ns_if.h>
66 #endif
67
68 #if NBPFILTER > 0
69 #include <net/bpf.h>
70 #include <net/bpfdesc.h>
71 #endif
72
73 #include <machine/cpu.h>
74 #include <machine/pio.h>
75
76 #include <i386/isa/isavar.h>
77 #include <i386/isa/if_egreg.h>
78 #include <i386/isa/elink.h>
79
80 /* for debugging convenience */
81 #ifdef EGDEBUG
82 #define dprintf(x) printf x
83 #else
84 #define dprintf(x)
85 #endif
86
87 #define ETHER_MIN_LEN 64
88 #define ETHER_MAX_LEN 1518
89 #define ETHER_ADDR_LEN 6
90
91 #define EG_INLEN 10
92 #define EG_BUFLEN 0x0670
93
94 /*
95 * Ethernet software status per interface.
96 */
97 struct eg_softc {
98 struct device sc_dev;
99 struct intrhand sc_ih;
100 struct arpcom sc_arpcom; /* Ethernet common part */
101 u_short eg_cmd; /* Command register R/W */
102 u_short eg_ctl; /* Control register R/W (EG_CTL_*) */
103 u_short eg_stat; /* Status register R/O (EG_STAT_*) */
104 u_short eg_data; /* Data register R/W (16 bits) */
105 u_char eg_rom_major; /* Cards ROM version (major number) */
106 u_char eg_rom_minor; /* Cards ROM version (minor number) */
107 short eg_ram; /* Amount of RAM on the card */
108 u_char eg_pcb[64]; /* Primary Command Block buffer */
109 u_char eg_incount; /* Number of buffers currently used */
110 u_char *eg_inbuf; /* Incoming packet buffer */
111 u_char *eg_outbuf; /* Outgoing packet buffer */
112 };
113
114 int egprobe __P((struct device *, void *, void *));
115 void egattach __P((struct device *, struct device *, void *));
116
117 struct cfdriver egcd = {
118 NULL, "eg", egprobe, egattach, DV_IFNET, sizeof(struct eg_softc)
119 };
120
121 int egintr __P((struct eg_softc *));
122 static void eginit __P((struct eg_softc *));
123 static int egioctl __P((struct ifnet *, u_long, caddr_t));
124 static int egrecv __P((struct eg_softc *));
125 static int egstart __P((struct ifnet *));
126 static int egwatchdog __P((int));
127 static void egreset __P((struct eg_softc *));
128 static inline void egread __P((struct eg_softc *, caddr_t, int));
129 static struct mbuf *egget __P((caddr_t, int, struct ifnet *));
130 static void egstop __P((struct eg_softc *));
131
132 /*
133 * Support stuff
134 */
135
136 static inline void
137 egprintpcb(sc)
138 struct eg_softc *sc;
139 {
140 int i;
141
142 for (i = 0; i < sc->eg_pcb[1] + 2; i++)
143 dprintf(("pcb[%2d] = %x\n", i, sc->eg_pcb[i]));
144 }
145
146
147 static inline void
148 egprintstat(b)
149 u_char b;
150 {
151 dprintf(("%s %s %s %s %s %s %s\n",
152 (b & EG_STAT_HCRE)?"HCRE":"",
153 (b & EG_STAT_ACRF)?"ACRF":"",
154 (b & EG_STAT_DIR )?"DIR ":"",
155 (b & EG_STAT_DONE)?"DONE":"",
156 (b & EG_STAT_ASF3)?"ASF3":"",
157 (b & EG_STAT_ASF2)?"ASF2":"",
158 (b & EG_STAT_ASF1)?"ASF1":""));
159 }
160
161 static int
162 egoutPCB(sc, b)
163 struct eg_softc *sc;
164 u_char b;
165 {
166 int i;
167
168 for (i=0; i < 4000; i++) {
169 if (inb(sc->eg_stat) & EG_STAT_HCRE) {
170 outb(sc->eg_cmd, b);
171 return 0;
172 }
173 delay(10);
174 }
175 dprintf(("egoutPCB failed\n"));
176 return 1;
177 }
178
179 static int
180 egreadPCBstat(sc, statb)
181 struct eg_softc *sc;
182 u_char statb;
183 {
184 int i;
185
186 for (i=0; i < 5000; i++) {
187 if (EG_PCB_STAT(inb(sc->eg_stat)))
188 break;
189 delay(10);
190 }
191 if (EG_PCB_STAT(inb(sc->eg_stat)) == statb)
192 return 0;
193 return 1;
194 }
195
196 static int
197 egreadPCBready(sc)
198 struct eg_softc *sc;
199 {
200 int i;
201
202 for (i=0; i < 10000; i++) {
203 if (inb(sc->eg_stat) & EG_STAT_ACRF)
204 return 0;
205 delay(5);
206 }
207 dprintf(("PCB read not ready\n"));
208 return 1;
209 }
210
211 static int
212 egwritePCB(sc)
213 struct eg_softc *sc;
214 {
215 int i;
216 u_char len;
217
218 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)));
219
220 len = sc->eg_pcb[1] + 2;
221 for (i = 0; i < len; i++)
222 egoutPCB(sc, sc->eg_pcb[i]);
223
224 for (i=0; i < 4000; i++) {
225 if (inb(sc->eg_stat) & EG_STAT_HCRE)
226 break;
227 delay(10);
228 }
229 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)) | EG_PCB_DONE);
230 egoutPCB(sc, len);
231
232 if (egreadPCBstat(sc, EG_PCB_ACCEPT))
233 return 1;
234 return 0;
235 }
236
237 static int
238 egreadPCB(sc)
239 struct eg_softc *sc;
240 {
241 int i;
242 u_char b;
243
244 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)));
245
246 bzero(sc->eg_pcb, sizeof(sc->eg_pcb));
247
248 if (egreadPCBready(sc))
249 return 1;
250
251 sc->eg_pcb[0] = inb(sc->eg_cmd);
252
253 if (egreadPCBready(sc))
254 return 1;
255
256 sc->eg_pcb[1] = inb(sc->eg_cmd);
257
258 if (sc->eg_pcb[1] > 62) {
259 dprintf(("len %d too large\n", sc->eg_pcb[1]));
260 return 1;
261 }
262
263 for (i = 0; i < sc->eg_pcb[1]; i++) {
264 if (egreadPCBready(sc))
265 return 1;
266 sc->eg_pcb[2+i] = inb(sc->eg_cmd);
267 }
268 if (egreadPCBready(sc))
269 return 1;
270 if (egreadPCBstat(sc, EG_PCB_DONE))
271 return 1;
272 if ((b = inb(sc->eg_cmd)) != sc->eg_pcb[1] + 2) {
273 dprintf(("%d != %d\n", b, sc->eg_pcb[1] + 2));
274 return 1;
275 }
276 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)) | EG_PCB_ACCEPT);
277 return 0;
278 }
279
280 /*
281 * Real stuff
282 */
283
284 int
285 egprobe(parent, match, aux)
286 struct device *parent;
287 void *match, *aux;
288 {
289 struct eg_softc *sc = match;
290 struct isa_attach_args *ia = aux;
291 int i;
292
293 if (ia->ia_iobase & ~0x07f0 != 0) {
294 dprintf(("Weird iobase %x\n", ia->ia_iobase));
295 return 0;
296 }
297
298 sc->eg_cmd = ia->ia_iobase + EG_COMMAND;
299 sc->eg_ctl = ia->ia_iobase + EG_CONTROL;
300 sc->eg_stat = ia->ia_iobase + EG_STATUS;
301 sc->eg_data = ia->ia_iobase + EG_DATA;
302
303 /* hard reset card */
304 outb(sc->eg_ctl, EG_CTL_RESET);
305 outb(sc->eg_ctl, 0);
306 for (i = 0; i < 5000; i++) {
307 delay(1000);
308 if (EG_PCB_STAT(inb(sc->eg_stat)) == 0)
309 break;
310 }
311 if (EG_PCB_STAT(inb(sc->eg_stat)) != 0) {
312 dprintf(("eg: Reset failed\n"));
313 return 0;
314 }
315 sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
316 sc->eg_pcb[1] = 0;
317 if (egwritePCB(sc) != 0)
318 return 0;
319
320 if (egreadPCB(sc) != 0) {
321 egprintpcb(sc);
322 return 0;
323 }
324
325 if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
326 sc->eg_pcb[1] != 0x0a) {
327 egprintpcb(sc);
328 return 0;
329 }
330 sc->eg_rom_major = sc->eg_pcb[3];
331 sc->eg_rom_minor = sc->eg_pcb[2];
332 sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
333
334 ia->ia_iosize = 0x08;
335 ia->ia_msize = 0;
336 return 1;
337 }
338
339 static void
340 egattach(parent, self, aux)
341 struct device *parent, *self;
342 void *aux;
343 {
344 struct eg_softc *sc = (void *)self;
345 struct isa_attach_args *ia = aux;
346 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
347 int i;
348
349 egstop(sc);
350
351 sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
352 sc->eg_pcb[1] = 0;
353 if (egwritePCB(sc) != 0) {
354 dprintf(("write error\n"));
355 return;
356 }
357 if (egreadPCB(sc) != 0) {
358 dprintf(("read error\n"));
359 egprintpcb(sc);
360 return;
361 }
362
363 /* check Get station address response */
364 if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) {
365 dprintf(("parse error\n"));
366 egprintpcb(sc);
367 return;
368 }
369 bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
370
371 printf(": ROM v%d.%02d %dk address %s\n",
372 sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram,
373 ether_sprintf(sc->sc_arpcom.ac_enaddr));
374
375 sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
376 if (egwritePCB(sc) != 0) {
377 dprintf(("write error2\n"));
378 return;
379 }
380 if (egreadPCB(sc) != 0) {
381 dprintf(("read error2\n"));
382 egprintpcb(sc);
383 return;
384 }
385 if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
386 sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
387 dprintf(("parse error2\n"));
388 egprintpcb(sc);
389 return;
390 }
391
392 /* Initialize ifnet structure. */
393 ifp->if_unit = sc->sc_dev.dv_unit;
394 ifp->if_name = egcd.cd_name;
395 ifp->if_output = ether_output;
396 ifp->if_start = egstart;
397 ifp->if_ioctl = egioctl;
398 ifp->if_watchdog = egwatchdog;
399 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
400
401 /* Now we can attach the interface. */
402 if_attach(ifp);
403 ether_ifattach(ifp);
404
405 #if NBPFILTER > 0
406 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
407 #endif
408
409 sc->sc_ih.ih_fun = egintr;
410 sc->sc_ih.ih_arg = sc;
411 sc->sc_ih.ih_level = IPL_NET;
412 intr_establish(ia->ia_irq, &sc->sc_ih);
413 }
414
415 static void
416 eginit(sc)
417 register struct eg_softc *sc;
418 {
419 register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
420
421 /* Address not known. */
422 if (ifp->if_addrlist == 0)
423 return;
424
425 /* soft reset the board */
426 outb(sc->eg_ctl, EG_CTL_FLSH);
427 delay(100);
428 outb(sc->eg_ctl, EG_CTL_ATTN);
429 delay(100);
430 outb(sc->eg_ctl, 0);
431 delay(200);
432
433 sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
434 sc->eg_pcb[1] = 2;
435 sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
436 sc->eg_pcb[3] = 0;
437 if (egwritePCB(sc) != 0)
438 dprintf(("write error3\n"));
439
440 if (egreadPCB(sc) != 0) {
441 dprintf(("read error\n"));
442 egprintpcb(sc);
443 } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
444 printf("%s: configure card command failed\n",
445 sc->sc_dev.dv_xname);
446
447 if (sc->eg_inbuf == NULL)
448 sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
449 sc->eg_incount = 0;
450
451 if (sc->eg_outbuf == NULL)
452 sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
453
454 ifp->if_flags |= IFF_RUNNING;
455 ifp->if_flags &= ~IFF_OACTIVE;
456
457 outb(sc->eg_ctl, EG_CTL_CMDE);
458
459 egstart(ifp);
460 egrecv(sc);
461 }
462
463 static int
464 egrecv(sc)
465 struct eg_softc *sc;
466 {
467
468 while (sc->eg_incount < EG_INLEN) {
469 sc->eg_pcb[0] = EG_CMD_RECVPACKET;
470 sc->eg_pcb[1] = 0x08;
471 sc->eg_pcb[2] = 0; /* address not used.. we send zero */
472 sc->eg_pcb[3] = 0;
473 sc->eg_pcb[4] = 0;
474 sc->eg_pcb[5] = 0;
475 sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
476 sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
477 sc->eg_pcb[8] = 0; /* timeout, 0 == none */
478 sc->eg_pcb[9] = 0;
479 if (egwritePCB(sc) == 0)
480 sc->eg_incount++;
481 else
482 break;
483 }
484 }
485
486 static int
487 egstart(ifp)
488 struct ifnet *ifp;
489 {
490 register struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
491 struct mbuf *m0, *m;
492 int len;
493 short *ptr;
494
495 /* Don't transmit if interface is busy or not running */
496 if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
497 return 0;
498
499 /* Dequeue the next datagram. */
500 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
501 if (m0 == NULL)
502 return 0;
503
504 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
505
506 /* Copy the datagram to the buffer. */
507 len = 0;
508 for (m = m0; m; m = m->m_next) {
509 if (m->m_len == 0)
510 continue;
511 if (len + m->m_len > EG_BUFLEN) {
512 dprintf(("Packet too large to send\n"));
513 m_freem(m0);
514 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
515 sc->sc_arpcom.ac_if.if_oerrors++;
516 return 0;
517 }
518 bcopy(mtod(m, caddr_t), sc->eg_outbuf + len, m->m_len);
519 len += m->m_len;
520 }
521 #if NBPFILTER > 0
522 if (sc->sc_arpcom.ac_if.if_bpf)
523 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
524 #endif
525 m_freem(m0);
526
527 /* length must be a minimum of ETHER_MIN_LEN bytes */
528 len = max(len, ETHER_MIN_LEN);
529
530 /* set direction bit: host -> adapter */
531 outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR);
532
533 sc->eg_pcb[0] = EG_CMD_SENDPACKET;
534 sc->eg_pcb[1] = 0x06;
535 sc->eg_pcb[2] = 0; /* address not used, we send zero */
536 sc->eg_pcb[3] = 0;
537 sc->eg_pcb[4] = 0;
538 sc->eg_pcb[5] = 0;
539 sc->eg_pcb[6] = len & 0xff; /* length of packet */
540 sc->eg_pcb[7] = (len >> 8) & 0xff;
541 if (egwritePCB(sc) == 0) {
542 for (ptr = (short *) sc->eg_outbuf; len > 0; len -= 2) {
543 outw(sc->eg_data, *ptr++);
544 while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
545 ; /* XXX need timeout here */
546 }
547 } else {
548 dprintf(("egwritePCB in egstart failed\n"));
549 sc->sc_arpcom.ac_if.if_oerrors++;
550 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
551 }
552
553 /* Set direction bit : Adapter -> host */
554 outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR);
555
556 return 0;
557 }
558
559 int
560 egintr(sc)
561 register struct eg_softc *sc;
562 {
563 int i, len;
564 short *ptr;
565
566 while (inb(sc->eg_stat) & EG_STAT_ACRF) {
567 egreadPCB(sc);
568 switch (sc->eg_pcb[0]) {
569 case EG_RSP_RECVPACKET:
570 len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
571 for (ptr = (short *) sc->eg_inbuf; len > 0; len -= 2) {
572 while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
573 ;
574 *ptr++ = inw(sc->eg_data);
575 }
576 len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8);
577 egrecv(sc);
578 sc->sc_arpcom.ac_if.if_ipackets++;
579 egread(sc, sc->eg_inbuf, len);
580 sc->eg_incount--;
581 break;
582
583 case EG_RSP_SENDPACKET:
584 if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
585 dprintf(("packet dropped\n"));
586 sc->sc_arpcom.ac_if.if_oerrors++;
587 } else
588 sc->sc_arpcom.ac_if.if_opackets++;
589 sc->sc_arpcom.ac_if.if_collisions += sc->eg_pcb[8] & 0xf;
590 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
591 egstart(&sc->sc_arpcom.ac_if);
592 break;
593
594 case EG_RSP_GETSTATS:
595 dprintf(("Card Statistics\n"));
596 bcopy(&sc->eg_pcb[2], &i, sizeof(i));
597 dprintf(("Receive Packets %d\n", i));
598 bcopy(&sc->eg_pcb[6], &i, sizeof(i));
599 dprintf(("Transmit Packets %d\n", i));
600 dprintf(("CRC errors %d\n", *(short*) &sc->eg_pcb[10]));
601 dprintf(("alignment errors %d\n", *(short*) &sc->eg_pcb[12]));
602 dprintf(("no resources errors %d\n", *(short*) &sc->eg_pcb[14]));
603 dprintf(("overrun errors %d\n", *(short*) &sc->eg_pcb[16]));
604 break;
605
606 default:
607 dprintf(("egintr: Unknown response %x??\n",
608 sc->eg_pcb[0]));
609 egprintpcb(sc);
610 break;
611 }
612 }
613
614 return 0;
615 }
616
617 /*
618 * Pass a packet up to the higher levels.
619 */
620 static inline void
621 egread(sc, buf, len)
622 struct eg_softc *sc;
623 caddr_t buf;
624 int len;
625 {
626 struct ifnet *ifp;
627 struct mbuf *m;
628 struct ether_header *eh;
629
630 if (len <= sizeof(struct ether_header) ||
631 len > ETHER_MAX_LEN) {
632 dprintf(("Unacceptable packet size %d\n", len));
633 sc->sc_arpcom.ac_if.if_ierrors++;
634 return;
635 }
636
637 /* Pull packet off interface. */
638 ifp = &sc->sc_arpcom.ac_if;
639 m = egget(buf, len, ifp);
640 if (m == 0) {
641 dprintf(("egget returned 0\n"));
642 sc->sc_arpcom.ac_if.if_ierrors++;
643 return;
644 }
645
646 /* We assume the header fit entirely in one mbuf. */
647 eh = mtod(m, struct ether_header *);
648
649 #if NBPFILTER > 0
650 /*
651 * Check if there's a BPF listener on this interface.
652 * If so, hand off the raw packet to BPF.
653 */
654 if (ifp->if_bpf) {
655 bpf_mtap(ifp->if_bpf, m);
656
657 /*
658 * Note that the interface cannot be in promiscuous mode if
659 * there are no BPF listeners. And if we are in promiscuous
660 * mode, we have to check if this packet is really ours.
661 */
662 if ((ifp->if_flags & IFF_PROMISC) &&
663 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
664 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
665 sizeof(eh->ether_dhost)) != 0) {
666 m_freem(m);
667 return;
668 }
669 }
670 #endif
671
672 /* We assume the header fit entirely in one mbuf. */
673 m->m_pkthdr.len -= sizeof(*eh);
674 m->m_len -= sizeof(*eh);
675 m->m_data += sizeof(*eh);
676
677 ether_input(ifp, eh, m);
678 }
679
680 /*
681 * convert buf into mbufs
682 */
683 static struct mbuf *
684 egget(buf, totlen, ifp)
685 caddr_t buf;
686 int totlen;
687 struct ifnet *ifp;
688 {
689 struct mbuf *top, **mp, *m;
690 int len;
691
692 MGETHDR(m, M_DONTWAIT, MT_DATA);
693 if (m == 0) {
694 dprintf(("MGETHDR returns 0\n"));
695 return 0;
696 }
697 m->m_pkthdr.rcvif = ifp;
698 m->m_pkthdr.len = totlen;
699 len = MHLEN;
700 top = 0;
701 mp = ⊤
702
703 while (totlen > 0) {
704 if (top) {
705 MGET(m, M_DONTWAIT, MT_DATA);
706 if (m == 0) {
707 m_freem(top);
708 dprintf(("MGET returns 0\n"));
709 return 0;
710 }
711 len = MLEN;
712 }
713 if (totlen >= MINCLSIZE) {
714 MCLGET(m, M_DONTWAIT);
715 if (m->m_flags & M_EXT)
716 len = MCLBYTES;
717 }
718 m->m_len = len = min(totlen, len);
719 bcopy((caddr_t)buf, mtod(m, caddr_t), len);
720 buf += len;
721 totlen -= len;
722 *mp = m;
723 mp = &m->m_next;
724 }
725
726 return top;
727 }
728
729 static int
730 egioctl(ifp, command, data)
731 register struct ifnet *ifp;
732 u_long command;
733 caddr_t data;
734 {
735 struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
736 register struct ifaddr *ifa = (struct ifaddr *)data;
737 struct ifreq *ifr = (struct ifreq *)data;
738 int s, error = 0;
739
740 s = splimp();
741
742 switch (command) {
743
744 case SIOCSIFADDR:
745 ifp->if_flags |= IFF_UP;
746
747 switch (ifa->ifa_addr->sa_family) {
748 #ifdef INET
749 case AF_INET:
750 eginit(sc); /* before arpwhohas */
751 sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr;
752 arpwhohas(&sc->sc_arpcom, &IA_SIN(ifa)->sin_addr);
753 break;
754 #endif
755 #ifdef NS
756 case AF_NS:
757 {
758 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
759
760 if (ns_nullhost(*ina))
761 ina->x_host =
762 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
763 else
764 bcopy(ina->x_host.c_host,
765 sc->sc_arpcom.ac_enaddr,
766 sizeof(sc->sc_arpcom.ac_enaddr));
767 /* Set new address. */
768 eginit(sc);
769 break;
770 }
771 #endif
772 default:
773 eginit(sc);
774 break;
775 }
776 break;
777
778 case SIOCSIFFLAGS:
779 if ((ifp->if_flags & IFF_UP) == 0 &&
780 (ifp->if_flags & IFF_RUNNING) != 0) {
781 /*
782 * If interface is marked down and it is running, then
783 * stop it.
784 */
785 egstop(sc);
786 ifp->if_flags &= ~IFF_RUNNING;
787 } else if ((ifp->if_flags & IFF_UP) != 0 &&
788 (ifp->if_flags & IFF_RUNNING) == 0) {
789 /*
790 * If interface is marked up and it is stopped, then
791 * start it.
792 */
793 eginit(sc);
794 } else {
795 sc->eg_pcb[0] = EG_CMD_GETSTATS;
796 sc->eg_pcb[1] = 0;
797 if (egwritePCB(sc) != 0)
798 dprintf(("write error\n"));
799 /*
800 * XXX deal with flags changes:
801 * IFF_MULTICAST, IFF_PROMISC,
802 * IFF_LINK0, IFF_LINK1,
803 */
804 }
805 break;
806
807 default:
808 error = EINVAL;
809 }
810
811 splx(s);
812 return error;
813 }
814
815 static void
816 egreset(sc)
817 struct eg_softc *sc;
818 {
819 int s;
820
821 dprintf(("egreset()\n"));
822 s = splimp();
823 egstop(sc);
824 eginit(sc);
825 splx(s);
826 }
827
828 static int
829 egwatchdog(unit)
830 int unit;
831 {
832 struct eg_softc *sc = egcd.cd_devs[unit];
833
834 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
835 sc->sc_arpcom.ac_if.if_oerrors++;
836
837 egreset(sc);
838 return 0;
839 }
840
841 static void
842 egstop(sc)
843 register struct eg_softc *sc;
844 {
845
846 outb(sc->eg_ctl, 0);
847 }
848