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