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