if_eg.c revision 1.1 1 /*
2 * Copyright (c) 1993 Dean Huxley <dean (at) fsa.ca>
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 Dean Huxley.
16 * 4. The name of Dean Huxley may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id: if_eg.c,v 1.1 1994/08/23 18:00:08 deraadt Exp $
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 dlog(x) log x
83 #else
84 #define dlog(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 short eg_cmd; /* Command register R/W */
102 short eg_ctl; /* Control register R/W (EG_CTL_*) */
103 short eg_stat; /* Status register R/O (EG_STAT_*) */
104 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 static int egprobe();
115 static void egattach();
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 *, int, 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 dlog((LOG_DEBUG, "pcb[%2d] = %x\n", sc->eg_pcb[i]));
144 }
145
146
147 static inline void
148 egprintstat(b)
149 u_char b;
150 {
151 dlog((LOG_DEBUG, "%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 dlog((LOG_DEBUG, "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 dlog((LOG_DEBUG, "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
219 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)));
220
221 len = sc->eg_pcb[1] + 2;
222 for (i = 0; i < len; i++)
223 egoutPCB(sc, sc->eg_pcb[i]);
224
225 for (i=0; i < 4000; i++) {
226 if (inb(sc->eg_stat) & EG_STAT_HCRE)
227 break;
228 delay(10);
229 }
230 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)) | EG_PCB_DONE);
231 egoutPCB(sc, len);
232
233 if (egreadPCBstat(sc, EG_PCB_ACCEPT))
234 return 1;
235 return 0;
236 }
237
238 static int
239 egreadPCB(sc)
240 struct eg_softc *sc;
241 {
242 int i;
243 u_char b;
244
245 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)));
246
247 bzero(sc->eg_pcb, sizeof(sc->eg_pcb));
248
249 if (egreadPCBready(sc))
250 return 1;
251
252 sc->eg_pcb[0] = inb(sc->eg_cmd);
253
254 if (egreadPCBready(sc))
255 return 1;
256
257 sc->eg_pcb[1] = inb(sc->eg_cmd);
258
259 if (sc->eg_pcb[1] > 62) {
260 dlog((LOG_DEBUG, "len %d too large\n", sc->eg_pcb[1]));
261 return 1;
262 }
263
264 for (i = 0; i < sc->eg_pcb[1]; i++) {
265 if (egreadPCBready(sc))
266 return 1;
267 sc->eg_pcb[2+i] = inb(sc->eg_cmd);
268 }
269 if (egreadPCBready(sc))
270 return 1;
271 if (egreadPCBstat(sc, EG_PCB_DONE))
272 return 1;
273 if ((b = inb(sc->eg_cmd)) != sc->eg_pcb[1]+2) {
274 dlog((LOG_DEBUG, "%d != %d\n", b, sc->eg_pcb[1]+2));
275 return 1;
276 }
277 outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)) | EG_PCB_ACCEPT);
278 return 0;
279 }
280
281 /*
282 * Real stuff
283 */
284
285 int
286 egprobe(parent, self, aux)
287 struct device *parent, *self;
288 void *aux;
289 {
290 struct eg_softc *sc = (void *)self;
291 struct isa_attach_args *ia = aux;
292 int i;
293
294 if (ia->ia_iobase & ~0x07f0 != 0) {
295 dlog((LOG_DEBUG, "Weird iobase %x\n", ia->ia_iobase));
296 return 0;
297 }
298
299 sc->eg_cmd = ia->ia_iobase + EG_COMMAND;
300 sc->eg_ctl = ia->ia_iobase + EG_CONTROL;
301 sc->eg_stat = ia->ia_iobase + EG_STATUS;
302 sc->eg_data = ia->ia_iobase + EG_DATA;
303
304 /* hard reset card */
305 outb(sc->eg_ctl, EG_CTL_RESET);
306 outb(sc->eg_ctl, 0);
307 for (i = 0; i < 5000; i++) {
308 delay(1000);
309 if (EG_PCB_STAT(inb(sc->eg_stat)) == 0)
310 break;
311 }
312 if (EG_PCB_STAT(inb(sc->eg_stat)) != 0) {
313 dlog((LOG_DEBUG, "eg: Reset failed\n"));
314 return 0;
315 }
316 sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
317 sc->eg_pcb[1] = 0;
318 if (egwritePCB(sc) != 0)
319 return 0;
320
321 if (egreadPCB(sc) != 0) {
322 egprintpcb(sc);
323 return 0;
324 }
325
326 if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
327 sc->eg_pcb[1] != 0x0a) {
328 egprintpcb(sc);
329 return 0;
330 }
331 sc->eg_rom_major = sc->eg_pcb[3];
332 sc->eg_rom_minor = sc->eg_pcb[2];
333 sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
334
335 ia->ia_iosize = 0x08;
336 ia->ia_msize = 0;
337 return 1;
338 }
339
340 static void
341 egattach(parent, self, aux)
342 struct device *parent, *self;
343 void *aux;
344 {
345 struct eg_softc *sc = (void *)self;
346 struct isa_attach_args *ia = aux;
347 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
348 int i;
349
350 outb(sc->eg_ctl, 0); /* make sure board is in a nice state */
351
352 sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
353 sc->eg_pcb[1] = 0;
354 if (egwritePCB(sc) != 0) {
355 dlog((LOG_DEBUG, "write error\n"));
356 return;
357 }
358 if (egreadPCB(sc) != 0) {
359 dlog((LOG_DEBUG, "read error\n"));
360 egprintpcb(sc);
361 return;
362 }
363
364 /* check Get station address response */
365 if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) {
366 dlog((LOG_DEBUG, "parse error\n"));
367 egprintpcb(sc);
368 return;
369 }
370 bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
371
372 printf(": ROM v%d.%02d %dk address %s\n",
373 sc->eg_rom_major,
374 sc->eg_rom_minor,
375 sc->eg_ram,
376 ether_sprintf(sc->sc_arpcom.ac_enaddr));
377
378 sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
379 if (egwritePCB(sc) != 0) {
380 dlog((LOG_DEBUG, "write error2\n"));
381 return;
382 }
383 if (egreadPCB(sc) != 0) {
384 dlog((LOG_DEBUG, "read error2\n"));
385 egprintpcb(sc);
386 return;
387 }
388 if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
389 sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
390 dlog((LOG_DEBUG, "parse error2\n"));
391 egprintpcb(sc);
392 return;
393 }
394
395 /* Initialize ifnet structure. */
396 ifp->if_unit = sc->sc_dev.dv_unit;
397 ifp->if_name = egcd.cd_name;
398 ifp->if_mtu = ETHERMTU;
399 ifp->if_output = ether_output;
400 ifp->if_start = egstart;
401 ifp->if_ioctl = egioctl;
402 ifp->if_watchdog = egwatchdog;
403 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
404
405 /* Now we can attach the interface. */
406 if_attach(ifp);
407 ether_ifattach(ifp);
408
409 #if NBPFILTER > 0
410 bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
411 #endif
412
413 sc->sc_ih.ih_fun = egintr;
414 sc->sc_ih.ih_arg = sc;
415 sc->sc_ih.ih_level = IPL_NET;
416 intr_establish(ia->ia_irq, &sc->sc_ih);
417 }
418
419 static void
420 eginit(sc)
421 register struct eg_softc *sc;
422 {
423 register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
424 int s;
425
426 if (ifp->if_addrlist == 0)
427 return;
428
429 s = splimp();
430
431 /* soft reset the board */
432 outb(sc->eg_ctl, EG_CTL_FLSH);
433 delay(100);
434 outb(sc->eg_ctl, EG_CTL_ATTN);
435 delay(100);
436 outb(sc->eg_ctl, 0);
437 delay(200);
438
439 sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
440 sc->eg_pcb[1] = 2;
441 sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
442 sc->eg_pcb[3] = 0;
443 if (egwritePCB(sc) != 0)
444 dlog((LOG_DEBUG, "write error3\n"));
445
446 if (egreadPCB(sc) != 0) {
447 dlog((LOG_DEBUG, "read error\n"));
448 egprintpcb(sc);
449 } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
450 printf("eg: configure card command failed.\n");
451
452 if(sc->eg_inbuf == NULL)
453 sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
454 sc->eg_incount = 0;
455
456 if(sc->eg_outbuf == NULL)
457 sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
458
459 ifp->if_flags |= IFF_RUNNING;
460 ifp->if_flags &= ~IFF_OACTIVE;
461
462 outb(sc->eg_ctl, EG_CTL_CMDE);
463
464 egstart(ifp);
465 egrecv(sc);
466
467 splx(s);
468 }
469
470 static int
471 egrecv(sc)
472 struct eg_softc *sc;
473 {
474 while (sc->eg_incount < EG_INLEN) {
475 sc->eg_pcb[0] = EG_CMD_RECVPACKET;
476 sc->eg_pcb[1] = 0x08;
477 sc->eg_pcb[2] = 0; /* address not used.. we send zero */
478 sc->eg_pcb[3] = 0;
479 sc->eg_pcb[4] = 0;
480 sc->eg_pcb[5] = 0;
481 sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
482 sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
483 sc->eg_pcb[8] = 0; /* timeout, 0 == none */
484 sc->eg_pcb[9] = 0;
485 if (egwritePCB(sc) == 0) {
486 sc->eg_incount++;
487 } else
488 break;
489 }
490 }
491
492 static int
493 egstart(ifp)
494 struct ifnet *ifp;
495 {
496 register struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
497 struct mbuf *m0, *m;
498 int len;
499 short *ptr;
500
501 /* Don't transmit if interface is busy or not running */
502 if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
503 return 0;
504
505 /* Dequeue the next datagram. */
506 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
507 if (m0 == NULL)
508 return 0;
509
510 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
511
512 /* Copy the datagram to the buffer. */
513 len = 0;
514 for (m = m0; m; m = m->m_next) {
515 if (m->m_len == 0)
516 continue;
517 if (len + m->m_len > EG_BUFLEN) {
518 dlog((LOG_DEBUG, "Packet too large to send\n"));
519 m_freem(m0);
520 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
521 sc->sc_arpcom.ac_if.if_oerrors++;
522 return 0;
523 }
524 bcopy(mtod(m, caddr_t), sc->eg_outbuf + len, m->m_len);
525 len += m->m_len;
526 }
527 #if NBPFILTER > 0
528 if (sc->sc_arpcom.ac_if.if_bpf)
529 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
530 #endif
531 m_freem(m0);
532
533 /* length must be a minimum of ETHER_MIN_LEN bytes */
534 len = max(len, ETHER_MIN_LEN);
535
536 /* set direction bit: host -> adapter */
537 outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR);
538
539 sc->eg_pcb[0] = EG_CMD_SENDPACKET;
540 sc->eg_pcb[1] = 0x06;
541 sc->eg_pcb[2] = 0; /* address not used, we send zero */
542 sc->eg_pcb[3] = 0;
543 sc->eg_pcb[4] = 0;
544 sc->eg_pcb[5] = 0;
545 sc->eg_pcb[6] = len & 0xff; /* length of packet */
546 sc->eg_pcb[7] = (len >> 8) & 0xff;
547 if (egwritePCB(sc) == 0) {
548 for (ptr = (short *) sc->eg_outbuf; len > 0; len -= 2) {
549 outw(sc->eg_data, *ptr++);
550 while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
551 ; /* XXX need timeout here */
552 }
553 } else {
554 dlog((LOG_DEBUG, "egwritePCB in egstart failed\n"));
555 sc->sc_arpcom.ac_if.if_oerrors++;
556 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
557 }
558
559 /* Set direction bit : Adapter -> host */
560 outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR);
561
562 return 0;
563 }
564
565 int
566 egintr(sc)
567 register struct eg_softc *sc;
568 {
569 int i, len;
570 short *ptr;
571
572 while (inb(sc->eg_stat) & EG_STAT_ACRF) {
573 egreadPCB(sc);
574 switch(sc->eg_pcb[0]) {
575 case EG_RSP_RECVPACKET:
576 len = sc->eg_pcb[6]+(sc->eg_pcb[7]<<8);
577 for (ptr = (short *) sc->eg_inbuf; len > 0; len -= 2) {
578 while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
579 ;
580 *ptr++ = inw(sc->eg_data);
581 }
582 len = sc->eg_pcb[8]+(sc->eg_pcb[9]<<8);
583 egrecv(sc);
584 sc->sc_arpcom.ac_if.if_ipackets++;
585 egread(sc, sc->eg_inbuf, len);
586 sc->eg_incount--;
587 break;
588
589 case EG_RSP_SENDPACKET:
590 if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
591 dlog((LOG_DEBUG, "packet dropped\n"));
592 sc->sc_arpcom.ac_if.if_oerrors++;
593 }
594 sc->sc_arpcom.ac_if.if_opackets++;
595 sc->sc_arpcom.ac_if.if_collisions += sc->eg_pcb[8] & 0xf;
596 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
597 egstart(&sc->sc_arpcom.ac_if);
598 break;
599
600 case EG_RSP_GETSTATS:
601 egprintpcb();
602 dlog((LOG_DEBUG, "Card Statistics\n"));
603 break;
604
605 default:
606 dlog((LOG_DEBUG, "egintr: Unknown response %x??\n",
607 sc->eg_pcb[0]));
608 break;
609 }
610 }
611
612 return 0;
613 }
614
615 /*
616 * Pass a packet up to the higher levels.
617 */
618 static inline void
619 egread(sc, buf, len)
620 struct eg_softc *sc;
621 caddr_t buf;
622 int len;
623 {
624 register struct ether_header *eh;
625 struct mbuf *m;
626 int i;
627
628 eh = (struct ether_header *)buf;
629 if (len <= sizeof(struct ether_header) ||
630 len > ETHER_MAX_LEN) {
631 dlog((LOG_DEBUG, "Unacceptable packet size %d\n", len));
632 sc->sc_arpcom.ac_if.if_ierrors++;
633 return;
634 }
635 len -= sizeof(struct ether_header);
636
637 m = egget(buf, len, &sc->sc_arpcom.ac_if);
638 if (m == 0) {
639 dlog((LOG_DEBUG, "egget returned 0\n"));
640 sc->sc_arpcom.ac_if.if_ierrors++;
641 return;
642 }
643
644 #if NBPFILTER > 0
645 /*
646 * Check if there's a BPF listener on this interface.
647 * If so, hand off the raw packet to bpf.
648 */
649 if (sc->sc_arpcom.ac_if.if_bpf) {
650 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);
651
652 /*
653 * Note that the interface cannot be in promiscuous mode if
654 * there are no BPF listeners. And if we are in promiscuous
655 * mode, we have to check if this packet is really ours.
656 */
657 if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
658 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
659 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
660 sizeof(eh->ether_dhost)) != 0) {
661 m_freem(m);
662 return;
663 }
664 }
665 #endif
666
667 ether_input(&sc->sc_arpcom.ac_if, eh, m);
668 }
669
670 /*
671 * convert buf into mbufs
672 */
673
674 static struct mbuf *
675 egget(buf, totlen, ifp)
676 caddr_t buf;
677 int totlen;
678 struct ifnet *ifp;
679 {
680 struct mbuf *top, **mp, *m, *p;
681 int len;
682 register caddr_t cp = buf;
683 char *epkt;
684
685 buf += sizeof(struct ether_header);
686 cp = buf;
687 epkt = cp + totlen;
688
689 MGETHDR(m, M_DONTWAIT, MT_DATA);
690 if (m == 0) {
691 dlog((LOG_DEBUG, "MGETHDR returns 0\n"));
692 return 0;
693 }
694 m->m_pkthdr.rcvif = ifp;
695 m->m_pkthdr.len = totlen;
696 m->m_len = MHLEN;
697 top = 0;
698 mp = ⊤
699
700 while (totlen > 0) {
701 if (top) {
702 MGET(m, M_DONTWAIT, MT_DATA);
703 if (m == 0) {
704 m_freem(top);
705 dlog((LOG_DEBUG, "MGET returns 0\n"));
706 return 0;
707 }
708 m->m_len = MLEN;
709 }
710 len = min(totlen, epkt - cp);
711 if (len >= MINCLSIZE) {
712 MCLGET(m, M_DONTWAIT);
713 if (m->m_flags & M_EXT)
714 m->m_len = len = min(len, MCLBYTES);
715 else
716 len = m->m_len;
717 } else {
718 /*
719 * Place initial small packet/header at end of mbuf.
720 */
721 if (len < m->m_len) {
722 if (top == 0 && len + max_linkhdr <= m->m_len)
723 m->m_data += max_linkhdr;
724 m->m_len = len;
725 } else
726 len = m->m_len;
727 }
728 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
729 cp += len;
730 *mp = m;
731 mp = &m->m_next;
732 totlen -= len;
733 if (cp == epkt)
734 cp = buf;
735 }
736
737 return top;
738 }
739
740 static int
741 egioctl(ifp, cmd, data)
742 register struct ifnet *ifp;
743 int cmd;
744 caddr_t data;
745 {
746 register struct ifaddr *ifa = (struct ifaddr *) data;
747 struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
748 struct ifreq *ifr = (struct ifreq *) data;
749 int error = 0;
750
751 switch (cmd) {
752 case SIOCSIFADDR:
753 ifp->if_flags |= IFF_UP;
754 switch (ifa->ifa_addr->sa_family) {
755 #ifdef INET
756 case AF_INET:
757 eginit(sc); /* before arpwhohas */
758 ((struct arpcom *) ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
759 arpwhohas((struct arpcom *) ifp, &IA_SIN(ifa)->sin_addr);
760 break;
761 #endif
762 #ifdef NS
763 case AF_NS:
764 {
765 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
766
767 if (ns_nullhost(*ina))
768 ina->x_host =
769 *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
770 else {
771 ifp->if_flags &= ~IFF_RUNNING;
772 bcopy(ina->x_host.c_host,
773 sc->sc_arpcom.ac_enaddr,
774 sizeof(sc->sc_arpcom.ac_enaddr));
775 }
776 eginit(sc);
777 break;
778 }
779 #endif
780 default:
781 eginit(sc);
782 break;
783 }
784 break;
785 case SIOCSIFFLAGS:
786 if ((ifp->if_flags & IFF_UP) == 0 &&
787 (ifp->if_flags & IFF_RUNNING) != 0) {
788 ifp->if_flags &= ~IFF_RUNNING;
789 egstop(sc);
790 break;
791 } else if ((ifp->if_flags & IFF_UP) != 0 &&
792 (ifp->if_flags & IFF_RUNNING) == 0) {
793 eginit(sc);
794 } else {
795 /*
796 * XXX deal with flags changes:
797 * IFF_MULTICAST, IFF_PROMISC,
798 * IFF_LINK0, IFF_LINK1,
799 */
800 }
801 break;
802 default:
803 error = EINVAL;
804 }
805 return (error);
806 }
807
808 static void
809 egreset(sc)
810 struct eg_softc *sc;
811 {
812 int s;
813
814 dlog((LOG_DEBUG, "egreset()\n"));
815 s = splimp();
816 egstop(sc);
817 eginit(sc);
818 splx(s);
819 }
820
821 static int
822 egwatchdog(unit)
823 int unit;
824 {
825 struct eg_softc *sc = egcd.cd_devs[unit];
826
827 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
828 sc->sc_arpcom.ac_if.if_oerrors++;
829
830 egreset(sc);
831 return 0;
832 }
833
834 static void
835 egstop(sc)
836 register struct eg_softc *sc;
837 {
838
839 outb(sc->eg_ctl, 0);
840 }
841