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