1 /* $NetBSD: if_eg.c,v 1.28 1996/08/03 02:23:57 thorpej 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 * Support for 3Com 3c505 Etherlink+ card. 34 */ 35 36 /* To do: 37 * - multicast 38 * - promiscuous 39 * - get rid of isa indirect stuff 40 */ 41 #include "bpfilter.h" 42 43 #include <sys/types.h> 44 #include <sys/param.h> 45 #include <sys/mbuf.h> 46 #include <sys/socket.h> 47 #include <sys/ioctl.h> 48 #include <sys/errno.h> 49 #include <sys/syslog.h> 50 #include <sys/select.h> 51 #include <sys/device.h> 52 53 #include <net/if.h> 54 #include <net/netisr.h> 55 #include <net/if_dl.h> 56 #include <net/if_types.h> 57 #include <net/netisr.h> 58 59 #ifdef INET 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/in_var.h> 63 #include <netinet/ip.h> 64 #include <netinet/if_ether.h> 65 #endif 66 67 #ifdef NS 68 #include <netns/ns.h> 69 #include <netns/ns_if.h> 70 #endif 71 72 #if NBPFILTER > 0 73 #include <net/bpf.h> 74 #include <net/bpfdesc.h> 75 #endif 76 77 #include <machine/cpu.h> 78 #include <machine/intr.h> 79 #include <machine/bus.h> 80 81 #include <dev/isa/isavar.h> 82 #include <dev/isa/if_egreg.h> 83 #include <dev/isa/elink.h> 84 85 /* for debugging convenience */ 86 #ifdef EGDEBUG 87 #define dprintf(x) printf x 88 #else 89 #define dprintf(x) 90 #endif 91 92 #define ETHER_MIN_LEN 64 93 #define ETHER_MAX_LEN 1518 94 #define ETHER_ADDR_LEN 6 95 96 #define EG_INLEN 10 97 #define EG_BUFLEN 0x0670 98 99 /* 100 * Ethernet software status per interface. 101 */ 102 struct eg_softc { 103 struct device sc_dev; 104 void *sc_ih; 105 struct arpcom sc_arpcom; /* Ethernet common part */ 106 bus_chipset_tag_t sc_bc; /* bus chipset identifier */ 107 bus_io_handle_t sc_ioh; /* i/o handle */ 108 u_int8_t eg_rom_major; /* Cards ROM version (major number) */ 109 u_int8_t eg_rom_minor; /* Cards ROM version (minor number) */ 110 short eg_ram; /* Amount of RAM on the card */ 111 u_int8_t eg_pcb[64]; /* Primary Command Block buffer */ 112 u_int8_t eg_incount; /* Number of buffers currently used */ 113 caddr_t eg_inbuf; /* Incoming packet buffer */ 114 caddr_t eg_outbuf; /* Outgoing packet buffer */ 115 }; 116 117 int egprobe __P((struct device *, void *, void *)); 118 void egattach __P((struct device *, struct device *, void *)); 119 120 struct cfattach eg_ca = { 121 sizeof(struct eg_softc), egprobe, egattach 122 }; 123 124 struct cfdriver eg_cd = { 125 NULL, "eg", DV_IFNET 126 }; 127 128 int egintr __P((void *)); 129 void eginit __P((struct eg_softc *)); 130 int egioctl __P((struct ifnet *, u_long, caddr_t)); 131 void egrecv __P((struct eg_softc *)); 132 void egstart __P((struct ifnet *)); 133 void egwatchdog __P((struct ifnet *)); 134 void egreset __P((struct eg_softc *)); 135 void egread __P((struct eg_softc *, caddr_t, int)); 136 struct mbuf *egget __P((struct eg_softc *, caddr_t, int)); 137 void egstop __P((struct eg_softc *)); 138 139 /* 140 * Support stuff 141 */ 142 143 static inline void 144 egprintpcb(sc) 145 struct eg_softc *sc; 146 { 147 int i; 148 149 for (i = 0; i < sc->eg_pcb[1] + 2; i++) 150 dprintf(("pcb[%2d] = %x\n", i, sc->eg_pcb[i])); 151 } 152 153 154 static inline void 155 egprintstat(b) 156 u_char b; 157 { 158 dprintf(("%s %s %s %s %s %s %s\n", 159 (b & EG_STAT_HCRE)?"HCRE":"", 160 (b & EG_STAT_ACRF)?"ACRF":"", 161 (b & EG_STAT_DIR )?"DIR ":"", 162 (b & EG_STAT_DONE)?"DONE":"", 163 (b & EG_STAT_ASF3)?"ASF3":"", 164 (b & EG_STAT_ASF2)?"ASF2":"", 165 (b & EG_STAT_ASF1)?"ASF1":"")); 166 } 167 168 static int 169 egoutPCB(sc, b) 170 struct eg_softc *sc; 171 u_int8_t b; 172 { 173 bus_chipset_tag_t bc = sc->sc_bc; 174 bus_io_handle_t ioh = sc->sc_ioh; 175 int i; 176 177 for (i=0; i < 4000; i++) { 178 if (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_HCRE) { 179 bus_io_write_1(bc, ioh, EG_COMMAND, b); 180 return 0; 181 } 182 delay(10); 183 } 184 dprintf(("egoutPCB failed\n")); 185 return 1; 186 } 187 188 static int 189 egreadPCBstat(sc, statb) 190 struct eg_softc *sc; 191 u_int8_t statb; 192 { 193 bus_chipset_tag_t bc = sc->sc_bc; 194 bus_io_handle_t ioh = sc->sc_ioh; 195 int i; 196 197 for (i=0; i < 5000; i++) { 198 if ((bus_io_read_1(bc, ioh, EG_STATUS) & 199 EG_PCB_STAT) != EG_PCB_NULL) 200 break; 201 delay(10); 202 } 203 if ((bus_io_read_1(bc, ioh, EG_STATUS) & EG_PCB_STAT) == statb) 204 return 0; 205 return 1; 206 } 207 208 static int 209 egreadPCBready(sc) 210 struct eg_softc *sc; 211 { 212 bus_chipset_tag_t bc = sc->sc_bc; 213 bus_io_handle_t ioh = sc->sc_ioh; 214 int i; 215 216 for (i=0; i < 10000; i++) { 217 if (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_ACRF) 218 return 0; 219 delay(5); 220 } 221 dprintf(("PCB read not ready\n")); 222 return 1; 223 } 224 225 static int 226 egwritePCB(sc) 227 struct eg_softc *sc; 228 { 229 bus_chipset_tag_t bc = sc->sc_bc; 230 bus_io_handle_t ioh = sc->sc_ioh; 231 int i; 232 u_int8_t len; 233 234 bus_io_write_1(bc, ioh, EG_CONTROL, 235 (bus_io_read_1(bc, ioh, EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_NULL); 236 237 len = sc->eg_pcb[1] + 2; 238 for (i = 0; i < len; i++) 239 egoutPCB(sc, sc->eg_pcb[i]); 240 241 for (i=0; i < 4000; i++) { 242 if (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_HCRE) 243 break; 244 delay(10); 245 } 246 247 bus_io_write_1(bc, ioh, EG_CONTROL, 248 (bus_io_read_1(bc, ioh, EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_DONE); 249 250 egoutPCB(sc, len); 251 252 if (egreadPCBstat(sc, EG_PCB_ACCEPT)) 253 return 1; 254 return 0; 255 } 256 257 static int 258 egreadPCB(sc) 259 struct eg_softc *sc; 260 { 261 bus_chipset_tag_t bc = sc->sc_bc; 262 bus_io_handle_t ioh = sc->sc_ioh; 263 int i; 264 u_int8_t b; 265 266 bus_io_write_1(bc, ioh, EG_CONTROL, 267 (bus_io_read_1(bc, ioh, EG_CONTROL) & ~EG_PCB_STAT) | EG_PCB_NULL); 268 269 bzero(sc->eg_pcb, sizeof(sc->eg_pcb)); 270 271 if (egreadPCBready(sc)) 272 return 1; 273 274 sc->eg_pcb[0] = bus_io_read_1(bc, ioh, EG_COMMAND); 275 276 if (egreadPCBready(sc)) 277 return 1; 278 279 sc->eg_pcb[1] = bus_io_read_1(bc, ioh, EG_COMMAND); 280 281 if (sc->eg_pcb[1] > 62) { 282 dprintf(("len %d too large\n", sc->eg_pcb[1])); 283 return 1; 284 } 285 286 for (i = 0; i < sc->eg_pcb[1]; i++) { 287 if (egreadPCBready(sc)) 288 return 1; 289 sc->eg_pcb[2+i] = bus_io_read_1(bc, ioh, EG_COMMAND); 290 } 291 if (egreadPCBready(sc)) 292 return 1; 293 if (egreadPCBstat(sc, EG_PCB_DONE)) 294 return 1; 295 if ((b = bus_io_read_1(bc, ioh, EG_COMMAND)) != sc->eg_pcb[1] + 2) { 296 dprintf(("%d != %d\n", b, sc->eg_pcb[1] + 2)); 297 return 1; 298 } 299 300 bus_io_write_1(bc, ioh, EG_CONTROL, 301 (bus_io_read_1(bc, ioh, EG_CONTROL) & 302 ~EG_PCB_STAT) | EG_PCB_ACCEPT); 303 304 return 0; 305 } 306 307 /* 308 * Real stuff 309 */ 310 311 int 312 egprobe(parent, match, aux) 313 struct device *parent; 314 void *match, *aux; 315 { 316 struct eg_softc *sc = match; 317 struct isa_attach_args *ia = aux; 318 bus_chipset_tag_t bc = ia->ia_bc; 319 bus_io_handle_t ioh; 320 int i, rval; 321 322 rval = 0; 323 324 if (ia->ia_iobase & ~0x07f0 != 0) { 325 dprintf(("Weird iobase %x\n", ia->ia_iobase)); 326 return 0; 327 } 328 329 /* Map i/o space. */ 330 if (bus_io_map(bc, ia->ia_iobase, 0x08, &ioh)) { 331 dprintf(("egprobe: can't map i/o space in probe\n")); 332 return 0; 333 } 334 335 /* 336 * XXX Indirect brokenness. 337 */ 338 sc->sc_bc = bc; /* XXX */ 339 sc->sc_ioh = ioh; /* XXX */ 340 341 /* hard reset card */ 342 bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_RESET); 343 bus_io_write_1(bc, ioh, EG_CONTROL, 0); 344 for (i = 0; i < 5000; i++) { 345 delay(1000); 346 if ((bus_io_read_1(bc, ioh, EG_STATUS) & 347 EG_PCB_STAT) == EG_PCB_NULL) 348 break; 349 } 350 if ((bus_io_read_1(bc, ioh, EG_STATUS) & EG_PCB_STAT) != EG_PCB_NULL) { 351 dprintf(("egprobe: Reset failed\n")); 352 goto out; 353 } 354 sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */ 355 sc->eg_pcb[1] = 0; 356 if (egwritePCB(sc) != 0) 357 goto out; 358 359 if (egreadPCB(sc) != 0) { 360 egprintpcb(sc); 361 goto out; 362 } 363 364 if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */ 365 sc->eg_pcb[1] != 0x0a) { 366 egprintpcb(sc); 367 goto out; 368 } 369 sc->eg_rom_major = sc->eg_pcb[3]; 370 sc->eg_rom_minor = sc->eg_pcb[2]; 371 sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8); 372 373 ia->ia_iosize = 0x08; 374 ia->ia_msize = 0; 375 rval = 1; 376 377 out: 378 bus_io_unmap(bc, ioh, 0x08); 379 return rval; 380 } 381 382 void 383 egattach(parent, self, aux) 384 struct device *parent, *self; 385 void *aux; 386 { 387 struct eg_softc *sc = (void *)self; 388 struct isa_attach_args *ia = aux; 389 bus_chipset_tag_t bc = ia->ia_bc; 390 bus_io_handle_t ioh; 391 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 392 int i; 393 394 printf("\n"); 395 396 /* Map i/o space. */ 397 if (bus_io_map(bc, ia->ia_iobase, ia->ia_iosize, &ioh)) { 398 printf("%s: can't map i/o space\n", self->dv_xname); 399 return; 400 } 401 402 sc->sc_bc = bc; 403 sc->sc_ioh = ioh; 404 405 egstop(sc); 406 407 sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */ 408 sc->eg_pcb[1] = 0; 409 if (egwritePCB(sc) != 0) { 410 printf("%s: can't send Get Station Address\n", self->dv_xname); 411 return; 412 } 413 if (egreadPCB(sc) != 0) { 414 printf("%s: can't read station address\n", self->dv_xname); 415 egprintpcb(sc); 416 return; 417 } 418 419 /* check Get station address response */ 420 if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) { 421 printf("%s: card responded with garbage (1)\n", 422 self->dv_xname); 423 egprintpcb(sc); 424 return; 425 } 426 bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 427 428 printf("%s: ROM v%d.%02d %dk address %s\n", self->dv_xname, 429 sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram, 430 ether_sprintf(sc->sc_arpcom.ac_enaddr)); 431 432 sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */ 433 if (egwritePCB(sc) != 0) { 434 printf("%s: can't send Set Station Address\n", self->dv_xname); 435 return; 436 } 437 if (egreadPCB(sc) != 0) { 438 printf("%s: can't read Set Station Address status\n", 439 self->dv_xname); 440 egprintpcb(sc); 441 return; 442 } 443 if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 || 444 sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) { 445 printf("%s: card responded with garbage (2)\n", 446 self->dv_xname); 447 egprintpcb(sc); 448 return; 449 } 450 451 /* Initialize ifnet structure. */ 452 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 453 ifp->if_softc = sc; 454 ifp->if_start = egstart; 455 ifp->if_ioctl = egioctl; 456 ifp->if_watchdog = egwatchdog; 457 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 458 459 /* Now we can attach the interface. */ 460 if_attach(ifp); 461 ether_ifattach(ifp); 462 463 #if NBPFILTER > 0 464 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 465 #endif 466 467 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 468 IPL_NET, egintr, sc); 469 } 470 471 void 472 eginit(sc) 473 register struct eg_softc *sc; 474 { 475 register struct ifnet *ifp = &sc->sc_arpcom.ac_if; 476 bus_chipset_tag_t bc = sc->sc_bc; 477 bus_io_handle_t ioh = sc->sc_ioh; 478 479 /* soft reset the board */ 480 bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_FLSH); 481 delay(100); 482 bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_ATTN); 483 delay(100); 484 bus_io_write_1(bc, ioh, EG_CONTROL, 0); 485 delay(200); 486 487 sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */ 488 sc->eg_pcb[1] = 2; 489 sc->eg_pcb[2] = 3; /* receive broadcast & multicast */ 490 sc->eg_pcb[3] = 0; 491 if (egwritePCB(sc) != 0) 492 printf("%s: can't send Configure 82586\n", 493 sc->sc_dev.dv_xname); 494 495 if (egreadPCB(sc) != 0) { 496 printf("%s: can't read Configure 82586 status\n", 497 sc->sc_dev.dv_xname); 498 egprintpcb(sc); 499 } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) 500 printf("%s: configure card command failed\n", 501 sc->sc_dev.dv_xname); 502 503 if (sc->eg_inbuf == NULL) { 504 sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT); 505 if (sc->eg_inbuf == NULL) { 506 printf("%s: can't allocate inbuf\n", 507 sc->sc_dev.dv_xname); 508 panic("eginit"); 509 } 510 } 511 sc->eg_incount = 0; 512 513 if (sc->eg_outbuf == NULL) { 514 sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT); 515 if (sc->eg_outbuf == NULL) { 516 printf("%s: can't allocate outbuf\n", 517 sc->sc_dev.dv_xname); 518 panic("eginit"); 519 } 520 } 521 522 bus_io_write_1(bc, ioh, EG_CONTROL, EG_CTL_CMDE); 523 524 sc->eg_incount = 0; 525 egrecv(sc); 526 527 /* Interface is now `running', with no output active. */ 528 ifp->if_flags |= IFF_RUNNING; 529 ifp->if_flags &= ~IFF_OACTIVE; 530 531 /* Attempt to start output, if any. */ 532 egstart(ifp); 533 } 534 535 void 536 egrecv(sc) 537 struct eg_softc *sc; 538 { 539 540 while (sc->eg_incount < EG_INLEN) { 541 sc->eg_pcb[0] = EG_CMD_RECVPACKET; 542 sc->eg_pcb[1] = 0x08; 543 sc->eg_pcb[2] = 0; /* address not used.. we send zero */ 544 sc->eg_pcb[3] = 0; 545 sc->eg_pcb[4] = 0; 546 sc->eg_pcb[5] = 0; 547 sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */ 548 sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff; 549 sc->eg_pcb[8] = 0; /* timeout, 0 == none */ 550 sc->eg_pcb[9] = 0; 551 if (egwritePCB(sc) != 0) 552 break; 553 sc->eg_incount++; 554 } 555 } 556 557 void 558 egstart(ifp) 559 struct ifnet *ifp; 560 { 561 register struct eg_softc *sc = ifp->if_softc; 562 bus_chipset_tag_t bc = sc->sc_bc; 563 bus_io_handle_t ioh = sc->sc_ioh; 564 struct mbuf *m0, *m; 565 caddr_t buffer; 566 int len; 567 u_int16_t *ptr; 568 569 /* Don't transmit if interface is busy or not running */ 570 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) 571 return; 572 573 loop: 574 /* Dequeue the next datagram. */ 575 IF_DEQUEUE(&ifp->if_snd, m0); 576 if (m0 == 0) 577 return; 578 579 ifp->if_flags |= IFF_OACTIVE; 580 581 /* We need to use m->m_pkthdr.len, so require the header */ 582 if ((m0->m_flags & M_PKTHDR) == 0) { 583 printf("%s: no header mbuf\n", sc->sc_dev.dv_xname); 584 panic("egstart"); 585 } 586 len = max(m0->m_pkthdr.len, ETHER_MIN_LEN); 587 588 #if NBPFILTER > 0 589 if (ifp->if_bpf) 590 bpf_mtap(ifp->if_bpf, m0); 591 #endif 592 593 sc->eg_pcb[0] = EG_CMD_SENDPACKET; 594 sc->eg_pcb[1] = 0x06; 595 sc->eg_pcb[2] = 0; /* address not used, we send zero */ 596 sc->eg_pcb[3] = 0; 597 sc->eg_pcb[4] = 0; 598 sc->eg_pcb[5] = 0; 599 sc->eg_pcb[6] = len; /* length of packet */ 600 sc->eg_pcb[7] = len >> 8; 601 if (egwritePCB(sc) != 0) { 602 printf("%s: can't send Send Packet command\n", 603 sc->sc_dev.dv_xname); 604 ifp->if_oerrors++; 605 ifp->if_flags &= ~IFF_OACTIVE; 606 m_freem(m0); 607 goto loop; 608 } 609 610 buffer = sc->eg_outbuf; 611 for (m = m0; m != 0; m = m->m_next) { 612 bcopy(mtod(m, caddr_t), buffer, m->m_len); 613 buffer += m->m_len; 614 } 615 616 /* set direction bit: host -> adapter */ 617 bus_io_write_1(bc, ioh, EG_CONTROL, 618 bus_io_read_1(bc, ioh, EG_CONTROL) & ~EG_CTL_DIR); 619 620 for (ptr = (u_int16_t *) sc->eg_outbuf; len > 0; len -= 2) { 621 bus_io_write_2(bc, ioh, EG_DATA, *ptr++); 622 while (!(bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_HRDY)) 623 ; /* XXX need timeout here */ 624 } 625 626 m_freem(m0); 627 } 628 629 int 630 egintr(arg) 631 void *arg; 632 { 633 register struct eg_softc *sc = arg; 634 bus_chipset_tag_t bc = sc->sc_bc; 635 bus_io_handle_t ioh = sc->sc_ioh; 636 int i, len, serviced; 637 u_int16_t *ptr; 638 639 serviced = 0; 640 641 while (bus_io_read_1(bc, ioh, EG_STATUS) & EG_STAT_ACRF) { 642 egreadPCB(sc); 643 switch (sc->eg_pcb[0]) { 644 case EG_RSP_RECVPACKET: 645 len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8); 646 647 /* Set direction bit : Adapter -> host */ 648 bus_io_write_1(bc, ioh, EG_CONTROL, 649 bus_io_read_1(bc, ioh, EG_CONTROL) | EG_CTL_DIR); 650 651 for (ptr = (u_int16_t *) sc->eg_inbuf; 652 len > 0; len -= 2) { 653 while (!(bus_io_read_1(bc, ioh, EG_STATUS) & 654 EG_STAT_HRDY)) 655 ; 656 *ptr++ = bus_io_read_2(bc, ioh, EG_DATA); 657 } 658 659 len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8); 660 egread(sc, sc->eg_inbuf, len); 661 662 sc->eg_incount--; 663 egrecv(sc); 664 serviced = 1; 665 break; 666 667 case EG_RSP_SENDPACKET: 668 if (sc->eg_pcb[6] || sc->eg_pcb[7]) { 669 dprintf(("%s: packet dropped\n", 670 sc->sc_dev.dv_xname)); 671 sc->sc_arpcom.ac_if.if_oerrors++; 672 } else 673 sc->sc_arpcom.ac_if.if_opackets++; 674 sc->sc_arpcom.ac_if.if_collisions += 675 sc->eg_pcb[8] & 0xf; 676 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; 677 egstart(&sc->sc_arpcom.ac_if); 678 serviced = 1; 679 break; 680 681 /* XXX byte-order and type-size bugs here... */ 682 case EG_RSP_GETSTATS: 683 dprintf(("%s: Card Statistics\n", 684 sc->sc_dev.dv_xname)); 685 bcopy(&sc->eg_pcb[2], &i, sizeof(i)); 686 dprintf(("Receive Packets %d\n", i)); 687 bcopy(&sc->eg_pcb[6], &i, sizeof(i)); 688 dprintf(("Transmit Packets %d\n", i)); 689 dprintf(("CRC errors %d\n", 690 *(short *) &sc->eg_pcb[10])); 691 dprintf(("alignment errors %d\n", 692 *(short *) &sc->eg_pcb[12])); 693 dprintf(("no resources errors %d\n", 694 *(short *) &sc->eg_pcb[14])); 695 dprintf(("overrun errors %d\n", 696 *(short *) &sc->eg_pcb[16])); 697 serviced = 1; 698 break; 699 700 default: 701 printf("%s: egintr: Unknown response %x??\n", 702 sc->sc_dev.dv_xname, sc->eg_pcb[0]); 703 egprintpcb(sc); 704 break; 705 } 706 } 707 708 return serviced; 709 } 710 711 /* 712 * Pass a packet up to the higher levels. 713 */ 714 void 715 egread(sc, buf, len) 716 struct eg_softc *sc; 717 caddr_t buf; 718 int len; 719 { 720 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 721 struct mbuf *m; 722 struct ether_header *eh; 723 724 if (len <= sizeof(struct ether_header) || 725 len > ETHER_MAX_LEN) { 726 printf("%s: invalid packet size %d; dropping\n", 727 sc->sc_dev.dv_xname, len); 728 ifp->if_ierrors++; 729 return; 730 } 731 732 /* Pull packet off interface. */ 733 m = egget(sc, buf, len); 734 if (m == 0) { 735 ifp->if_ierrors++; 736 return; 737 } 738 739 ifp->if_ipackets++; 740 741 /* We assume the header fit entirely in one mbuf. */ 742 eh = mtod(m, struct ether_header *); 743 744 #if NBPFILTER > 0 745 /* 746 * Check if there's a BPF listener on this interface. 747 * If so, hand off the raw packet to BPF. 748 */ 749 if (ifp->if_bpf) { 750 bpf_mtap(ifp->if_bpf, m); 751 752 /* 753 * Note that the interface cannot be in promiscuous mode if 754 * there are no BPF listeners. And if we are in promiscuous 755 * mode, we have to check if this packet is really ours. 756 */ 757 if ((ifp->if_flags & IFF_PROMISC) && 758 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ 759 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, 760 sizeof(eh->ether_dhost)) != 0) { 761 m_freem(m); 762 return; 763 } 764 } 765 #endif 766 767 /* We assume the header fit entirely in one mbuf. */ 768 m_adj(m, sizeof(struct ether_header)); 769 ether_input(ifp, eh, m); 770 } 771 772 /* 773 * convert buf into mbufs 774 */ 775 struct mbuf * 776 egget(sc, buf, totlen) 777 struct eg_softc *sc; 778 caddr_t buf; 779 int totlen; 780 { 781 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 782 struct mbuf *top, **mp, *m; 783 int len; 784 785 MGETHDR(m, M_DONTWAIT, MT_DATA); 786 if (m == 0) 787 return 0; 788 m->m_pkthdr.rcvif = ifp; 789 m->m_pkthdr.len = totlen; 790 len = MHLEN; 791 top = 0; 792 mp = ⊤ 793 794 while (totlen > 0) { 795 if (top) { 796 MGET(m, M_DONTWAIT, MT_DATA); 797 if (m == 0) { 798 m_freem(top); 799 return 0; 800 } 801 len = MLEN; 802 } 803 if (totlen >= MINCLSIZE) { 804 MCLGET(m, M_DONTWAIT); 805 if (m->m_flags & M_EXT) 806 len = MCLBYTES; 807 } 808 m->m_len = len = min(totlen, len); 809 bcopy((caddr_t)buf, mtod(m, caddr_t), len); 810 buf += len; 811 totlen -= len; 812 *mp = m; 813 mp = &m->m_next; 814 } 815 816 return top; 817 } 818 819 int 820 egioctl(ifp, cmd, data) 821 register struct ifnet *ifp; 822 u_long cmd; 823 caddr_t data; 824 { 825 struct eg_softc *sc = ifp->if_softc; 826 struct ifaddr *ifa = (struct ifaddr *)data; 827 struct ifreq *ifr = (struct ifreq *)data; 828 int s, error = 0; 829 830 s = splnet(); 831 832 switch (cmd) { 833 834 case SIOCSIFADDR: 835 ifp->if_flags |= IFF_UP; 836 837 switch (ifa->ifa_addr->sa_family) { 838 #ifdef INET 839 case AF_INET: 840 eginit(sc); 841 arp_ifinit(&sc->sc_arpcom, ifa); 842 break; 843 #endif 844 #ifdef NS 845 case AF_NS: 846 { 847 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 848 849 if (ns_nullhost(*ina)) 850 ina->x_host = 851 *(union ns_host *)(sc->sc_arpcom.ac_enaddr); 852 else 853 bcopy(ina->x_host.c_host, 854 sc->sc_arpcom.ac_enaddr, 855 sizeof(sc->sc_arpcom.ac_enaddr)); 856 /* Set new address. */ 857 eginit(sc); 858 break; 859 } 860 #endif 861 default: 862 eginit(sc); 863 break; 864 } 865 break; 866 867 case SIOCSIFFLAGS: 868 if ((ifp->if_flags & IFF_UP) == 0 && 869 (ifp->if_flags & IFF_RUNNING) != 0) { 870 /* 871 * If interface is marked down and it is running, then 872 * stop it. 873 */ 874 egstop(sc); 875 ifp->if_flags &= ~IFF_RUNNING; 876 } else if ((ifp->if_flags & IFF_UP) != 0 && 877 (ifp->if_flags & IFF_RUNNING) == 0) { 878 /* 879 * If interface is marked up and it is stopped, then 880 * start it. 881 */ 882 eginit(sc); 883 } else { 884 sc->eg_pcb[0] = EG_CMD_GETSTATS; 885 sc->eg_pcb[1] = 0; 886 if (egwritePCB(sc) != 0) 887 dprintf(("write error\n")); 888 /* 889 * XXX deal with flags changes: 890 * IFF_MULTICAST, IFF_PROMISC, 891 * IFF_LINK0, IFF_LINK1, 892 */ 893 } 894 break; 895 896 default: 897 error = EINVAL; 898 break; 899 } 900 901 splx(s); 902 return error; 903 } 904 905 void 906 egreset(sc) 907 struct eg_softc *sc; 908 { 909 int s; 910 911 dprintf(("%s: egreset()\n", sc->sc_dev.dv_xname)); 912 s = splnet(); 913 egstop(sc); 914 eginit(sc); 915 splx(s); 916 } 917 918 void 919 egwatchdog(ifp) 920 struct ifnet *ifp; 921 { 922 struct eg_softc *sc = ifp->if_softc; 923 924 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 925 sc->sc_arpcom.ac_if.if_oerrors++; 926 927 egreset(sc); 928 } 929 930 void 931 egstop(sc) 932 register struct eg_softc *sc; 933 { 934 935 bus_io_write_1(sc->sc_bc, sc->sc_ioh, EG_CONTROL, 0); 936 } 937