1 /* $NetBSD: if_eg.c,v 1.8 1994/11/18 22:03:15 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Dean Huxley <dean@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 int eg_cmd; /* Command register R/W */ 102 int eg_ctl; /* Control register R/W (EG_CTL_*) */ 103 int eg_stat; /* Status register R/O (EG_STAT_*) */ 104 int 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