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