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