1 /* $OpenBSD: if_el.c,v 1.21 2008/10/02 20:21:13 brad Exp $ */ 2 /* $NetBSD: if_el.c,v 1.39 1996/05/12 23:52:32 mycroft Exp $ */ 3 4 /* 5 * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted 6 * to use, copy, modify and distribute this software provided that both 7 * the copyright notice and this permission notice appear in all copies 8 * of the software, derivative works or modified versions, and any 9 * portions thereof. 10 */ 11 12 /* 13 * 3COM Etherlink 3C501 device driver 14 */ 15 16 /* 17 * Bugs/possible improvements: 18 * - Does not currently support DMA 19 * - Does not currently support multicasts 20 */ 21 22 #include "bpfilter.h" 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 #include <sys/errno.h> 27 #include <sys/ioctl.h> 28 #include <sys/mbuf.h> 29 #include <sys/socket.h> 30 #include <sys/syslog.h> 31 #include <sys/device.h> 32 33 #include <net/if.h> 34 #include <net/if_dl.h> 35 #include <net/if_types.h> 36 37 #ifdef INET 38 #include <netinet/in.h> 39 #include <netinet/in_systm.h> 40 #include <netinet/in_var.h> 41 #include <netinet/ip.h> 42 #include <netinet/if_ether.h> 43 #endif 44 45 #if NBPFILTER > 0 46 #include <net/bpf.h> 47 #endif 48 49 #include <machine/cpu.h> 50 #include <machine/intr.h> 51 #include <machine/pio.h> 52 53 #include <dev/isa/isavar.h> 54 #include <dev/isa/if_elreg.h> 55 56 /* for debugging convenience */ 57 #ifdef EL_DEBUG 58 #define dprintf(x) printf x 59 #else 60 #define dprintf(x) 61 #endif 62 63 /* 64 * per-line info and status 65 */ 66 struct el_softc { 67 struct device sc_dev; 68 void *sc_ih; 69 70 struct arpcom sc_arpcom; /* ethernet common */ 71 int sc_iobase; /* base I/O addr */ 72 }; 73 74 /* 75 * prototypes 76 */ 77 int elintr(void *); 78 void elinit(struct el_softc *); 79 int elioctl(struct ifnet *, u_long, caddr_t); 80 void elstart(struct ifnet *); 81 void elwatchdog(struct ifnet *); 82 void elreset(struct el_softc *); 83 void elstop(struct el_softc *); 84 static int el_xmit(struct el_softc *); 85 void elread(struct el_softc *, int); 86 struct mbuf *elget(struct el_softc *sc, int); 87 static inline void el_hardreset(struct el_softc *); 88 89 int elprobe(struct device *, void *, void *); 90 void elattach(struct device *, struct device *, void *); 91 92 struct cfattach el_ca = { 93 sizeof(struct el_softc), elprobe, elattach 94 }; 95 96 struct cfdriver el_cd = { 97 NULL, "el", DV_IFNET 98 }; 99 100 /* 101 * Probe routine. 102 * 103 * See if the card is there and at the right place. 104 * (XXX - cgd -- needs help) 105 */ 106 int 107 elprobe(parent, match, aux) 108 struct device *parent; 109 void *match, *aux; 110 { 111 struct el_softc *sc = match; 112 struct isa_attach_args *ia = aux; 113 int iobase = ia->ia_iobase; 114 u_char station_addr[ETHER_ADDR_LEN]; 115 int i; 116 117 /* First check the base. */ 118 if (iobase < 0x280 || iobase > 0x3f0) 119 return 0; 120 121 /* Grab some info for our structure. */ 122 sc->sc_iobase = iobase; 123 124 /* 125 * Now attempt to grab the station address from the PROM and see if it 126 * contains the 3com vendor code. 127 */ 128 dprintf(("Probing 3c501 at 0x%x...\n", iobase)); 129 130 /* Reset the board. */ 131 dprintf(("Resetting board...\n")); 132 outb(iobase+EL_AC, EL_AC_RESET); 133 delay(5); 134 outb(iobase+EL_AC, 0); 135 136 /* Now read the address. */ 137 dprintf(("Reading station address...\n")); 138 for (i = 0; i < ETHER_ADDR_LEN; i++) { 139 outb(iobase+EL_GPBL, i); 140 station_addr[i] = inb(iobase+EL_EAW); 141 } 142 dprintf(("Address is %s\n", ether_sprintf(station_addr))); 143 144 /* 145 * If the vendor code is ok, return a 1. We'll assume that whoever 146 * configured this system is right about the IRQ. 147 */ 148 if (station_addr[0] != 0x02 || station_addr[1] != 0x60 || 149 station_addr[2] != 0x8c) { 150 dprintf(("Bad vendor code.\n")); 151 return 0; 152 } 153 154 dprintf(("Vendor code ok.\n")); 155 /* Copy the station address into the arpcom structure. */ 156 bcopy(station_addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 157 158 ia->ia_iosize = 4; /* XXX */ 159 ia->ia_msize = 0; 160 return 1; 161 } 162 163 /* 164 * Attach the interface to the kernel data structures. By the time this is 165 * called, we know that the card exists at the given I/O address. We still 166 * assume that the IRQ given is correct. 167 */ 168 void 169 elattach(parent, self, aux) 170 struct device *parent, *self; 171 void *aux; 172 { 173 struct el_softc *sc = (void *)self; 174 struct isa_attach_args *ia = aux; 175 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 176 177 dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname)); 178 179 /* Stop the board. */ 180 elstop(sc); 181 182 /* Initialize ifnet structure. */ 183 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 184 ifp->if_softc = sc; 185 ifp->if_start = elstart; 186 ifp->if_ioctl = elioctl; 187 ifp->if_watchdog = elwatchdog; 188 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 189 IFQ_SET_READY(&ifp->if_snd); 190 191 /* Now we can attach the interface. */ 192 dprintf(("Attaching interface...\n")); 193 if_attach(ifp); 194 ether_ifattach(ifp); 195 196 /* Print out some information for the user. */ 197 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); 198 199 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 200 IPL_NET, elintr, sc, sc->sc_dev.dv_xname); 201 202 dprintf(("elattach() finished.\n")); 203 } 204 205 /* 206 * Reset interface. 207 */ 208 void 209 elreset(sc) 210 struct el_softc *sc; 211 { 212 int s; 213 214 dprintf(("elreset()\n")); 215 s = splnet(); 216 elstop(sc); 217 elinit(sc); 218 splx(s); 219 } 220 221 /* 222 * Stop interface. 223 */ 224 void 225 elstop(sc) 226 struct el_softc *sc; 227 { 228 229 outb(sc->sc_iobase+EL_AC, 0); 230 } 231 232 /* 233 * Do a hardware reset of the board, and upload the ethernet address again in 234 * case the board forgets. 235 */ 236 static inline void 237 el_hardreset(sc) 238 struct el_softc *sc; 239 { 240 int iobase = sc->sc_iobase; 241 int i; 242 243 outb(iobase+EL_AC, EL_AC_RESET); 244 delay(5); 245 outb(iobase+EL_AC, 0); 246 247 for (i = 0; i < ETHER_ADDR_LEN; i++) 248 outb(iobase+i, sc->sc_arpcom.ac_enaddr[i]); 249 } 250 251 /* 252 * Initialize interface. 253 */ 254 void 255 elinit(sc) 256 struct el_softc *sc; 257 { 258 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 259 int iobase = sc->sc_iobase; 260 261 /* First, reset the board. */ 262 el_hardreset(sc); 263 264 /* Configure rx. */ 265 dprintf(("Configuring rx...\n")); 266 if (ifp->if_flags & IFF_PROMISC) 267 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC); 268 else 269 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD); 270 outb(iobase+EL_RBC, 0); 271 272 /* Configure TX. */ 273 dprintf(("Configuring tx...\n")); 274 outb(iobase+EL_TXC, 0); 275 276 /* Start reception. */ 277 dprintf(("Starting reception...\n")); 278 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 279 280 /* Set flags appropriately. */ 281 ifp->if_flags |= IFF_RUNNING; 282 ifp->if_flags &= ~IFF_OACTIVE; 283 284 /* And start output. */ 285 elstart(ifp); 286 } 287 288 /* 289 * Start output on interface. Get datagrams from the queue and output them, 290 * giving the receiver a chance between datagrams. Call only from splnet or 291 * interrupt level! 292 */ 293 void 294 elstart(ifp) 295 struct ifnet *ifp; 296 { 297 struct el_softc *sc = ifp->if_softc; 298 int iobase = sc->sc_iobase; 299 struct mbuf *m, *m0; 300 int s, i, off, retries; 301 302 dprintf(("elstart()...\n")); 303 s = splnet(); 304 305 /* Don't do anything if output is active. */ 306 if ((ifp->if_flags & IFF_OACTIVE) != 0) { 307 splx(s); 308 return; 309 } 310 311 ifp->if_flags |= IFF_OACTIVE; 312 313 /* 314 * The main loop. They warned me against endless loops, but would I 315 * listen? NOOO.... 316 */ 317 for (;;) { 318 /* Dequeue the next datagram. */ 319 IFQ_DEQUEUE(&ifp->if_snd, m0); 320 321 /* If there's nothing to send, return. */ 322 if (m0 == 0) 323 break; 324 325 #if NBPFILTER > 0 326 /* Give the packet to the bpf, if any. */ 327 if (ifp->if_bpf) 328 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); 329 #endif 330 331 /* Disable the receiver. */ 332 outb(iobase+EL_AC, EL_AC_HOST); 333 outb(iobase+EL_RBC, 0); 334 335 /* Transfer datagram to board. */ 336 dprintf(("el: xfr pkt length=%d...\n", m0->m_pkthdr.len)); 337 off = EL_BUFSIZ - max(m0->m_pkthdr.len, ETHER_MIN_LEN); 338 outb(iobase+EL_GPBL, off); 339 outb(iobase+EL_GPBH, off >> 8); 340 341 /* Copy the datagram to the buffer. */ 342 for (m = m0; m != 0; m = m->m_next) 343 outsb(iobase+EL_BUF, mtod(m, caddr_t), m->m_len); 344 for (i = 0; 345 i < ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len; i++) 346 outb(iobase+EL_BUF, 0); 347 348 m_freem(m0); 349 350 /* Now transmit the datagram. */ 351 retries = 0; 352 for (;;) { 353 outb(iobase+EL_GPBL, off); 354 outb(iobase+EL_GPBH, off >> 8); 355 if (el_xmit(sc)) { 356 ifp->if_oerrors++; 357 break; 358 } 359 /* Check out status. */ 360 i = inb(iobase+EL_TXS); 361 dprintf(("tx status=0x%x\n", i)); 362 if ((i & EL_TXS_READY) == 0) { 363 dprintf(("el: err txs=%x\n", i)); 364 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) { 365 ifp->if_collisions++; 366 if ((i & EL_TXC_DCOLL16) == 0 && 367 retries < 15) { 368 retries++; 369 outb(iobase+EL_AC, EL_AC_HOST); 370 } 371 } else { 372 ifp->if_oerrors++; 373 break; 374 } 375 } else { 376 ifp->if_opackets++; 377 break; 378 } 379 } 380 381 /* 382 * Now give the card a chance to receive. 383 * Gotta love 3c501s... 384 */ 385 (void)inb(iobase+EL_AS); 386 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 387 splx(s); 388 /* Interrupt here. */ 389 s = splnet(); 390 } 391 392 (void)inb(iobase+EL_AS); 393 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 394 ifp->if_flags &= ~IFF_OACTIVE; 395 splx(s); 396 } 397 398 /* 399 * This function actually attempts to transmit a datagram downloaded to the 400 * board. Call at splnet or interrupt, after downloading data! Returns 0 on 401 * success, non-0 on failure. 402 */ 403 static int 404 el_xmit(sc) 405 struct el_softc *sc; 406 { 407 int iobase = sc->sc_iobase; 408 int i; 409 410 /* 411 * XXX 412 * This busy-waits for the tx completion. Can we get an interrupt 413 * instead? 414 */ 415 416 dprintf(("el: xmit...")); 417 outb(iobase+EL_AC, EL_AC_TXFRX); 418 i = 20000; 419 while ((inb(iobase+EL_AS) & EL_AS_TXBUSY) && (i > 0)) 420 i--; 421 if (i == 0) { 422 dprintf(("tx not ready\n")); 423 return -1; 424 } 425 dprintf(("%d cycles.\n", 20000 - i)); 426 return 0; 427 } 428 429 /* 430 * Controller interrupt. 431 */ 432 int 433 elintr(arg) 434 void *arg; 435 { 436 register struct el_softc *sc = arg; 437 int iobase = sc->sc_iobase; 438 int rxstat, len; 439 440 dprintf(("elintr: ")); 441 442 /* Check board status. */ 443 if ((inb(iobase+EL_AS) & EL_AS_RXBUSY) != 0) { 444 (void)inb(iobase+EL_RXC); 445 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 446 return 0; 447 } 448 449 for (;;) { 450 rxstat = inb(iobase+EL_RXS); 451 if (rxstat & EL_RXS_STALE) 452 break; 453 454 /* If there's an overflow, reinit the board. */ 455 if ((rxstat & EL_RXS_NOFLOW) == 0) { 456 dprintf(("overflow.\n")); 457 el_hardreset(sc); 458 /* Put board back into receive mode. */ 459 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) 460 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC); 461 else 462 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD); 463 (void)inb(iobase+EL_AS); 464 outb(iobase+EL_RBC, 0); 465 break; 466 } 467 468 /* Incoming packet. */ 469 len = inb(iobase+EL_RBL); 470 len |= inb(iobase+EL_RBH) << 8; 471 dprintf(("receive len=%d rxstat=%x ", len, rxstat)); 472 outb(iobase+EL_AC, EL_AC_HOST); 473 474 /* Pass data up to upper levels. */ 475 elread(sc, len); 476 477 /* Is there another packet? */ 478 if ((inb(iobase+EL_AS) & EL_AS_RXBUSY) != 0) 479 break; 480 481 dprintf(("<rescan> ")); 482 } 483 484 (void)inb(iobase+EL_RXC); 485 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 486 return 1; 487 } 488 489 /* 490 * Pass a packet to the higher levels. 491 */ 492 void 493 elread(sc, len) 494 register struct el_softc *sc; 495 int len; 496 { 497 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 498 struct mbuf *m; 499 500 if (len <= sizeof(struct ether_header) || 501 len > ETHER_MAX_LEN) { 502 printf("%s: invalid packet size %d; dropping\n", 503 sc->sc_dev.dv_xname, len); 504 ifp->if_ierrors++; 505 return; 506 } 507 508 /* Pull packet off interface. */ 509 m = elget(sc, len); 510 if (m == 0) { 511 ifp->if_ierrors++; 512 return; 513 } 514 515 ifp->if_ipackets++; 516 517 #if NBPFILTER > 0 518 /* 519 * Check if there's a BPF listener on this interface. 520 * If so, hand off the raw packet to BPF. 521 */ 522 if (ifp->if_bpf) 523 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 524 #endif 525 526 ether_input_mbuf(ifp, m); 527 } 528 529 /* 530 * Pull read data off a interface. Len is length of data, with local net 531 * header stripped. We copy the data into mbufs. When full cluster sized 532 * units are present we copy into clusters. 533 */ 534 struct mbuf * 535 elget(sc, totlen) 536 struct el_softc *sc; 537 int totlen; 538 { 539 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 540 int iobase = sc->sc_iobase; 541 struct mbuf *top, **mp, *m; 542 int len; 543 544 MGETHDR(m, M_DONTWAIT, MT_DATA); 545 if (m == 0) 546 return 0; 547 m->m_pkthdr.rcvif = ifp; 548 m->m_pkthdr.len = totlen; 549 len = MHLEN; 550 top = 0; 551 mp = ⊤ 552 553 outb(iobase+EL_GPBL, 0); 554 outb(iobase+EL_GPBH, 0); 555 556 while (totlen > 0) { 557 if (top) { 558 MGET(m, M_DONTWAIT, MT_DATA); 559 if (m == 0) { 560 m_freem(top); 561 return 0; 562 } 563 len = MLEN; 564 } 565 if (totlen >= MINCLSIZE) { 566 MCLGET(m, M_DONTWAIT); 567 if (m->m_flags & M_EXT) 568 len = MCLBYTES; 569 } 570 m->m_len = len = min(totlen, len); 571 insb(iobase+EL_BUF, mtod(m, caddr_t), len); 572 totlen -= len; 573 *mp = m; 574 mp = &m->m_next; 575 } 576 577 outb(iobase+EL_RBC, 0); 578 outb(iobase+EL_AC, EL_AC_RX); 579 580 return top; 581 } 582 583 /* 584 * Process an ioctl request. This code needs some work - it looks pretty ugly. 585 */ 586 int 587 elioctl(ifp, cmd, data) 588 register struct ifnet *ifp; 589 u_long cmd; 590 caddr_t data; 591 { 592 struct el_softc *sc = ifp->if_softc; 593 struct ifaddr *ifa = (struct ifaddr *)data; 594 int s, error = 0; 595 596 s = splnet(); 597 598 switch (cmd) { 599 case SIOCSIFADDR: 600 ifp->if_flags |= IFF_UP; 601 602 switch (ifa->ifa_addr->sa_family) { 603 #ifdef INET 604 case AF_INET: 605 elinit(sc); 606 arp_ifinit(&sc->sc_arpcom, ifa); 607 break; 608 #endif 609 default: 610 elinit(sc); 611 break; 612 } 613 break; 614 615 case SIOCSIFFLAGS: 616 if ((ifp->if_flags & IFF_UP) == 0 && 617 (ifp->if_flags & IFF_RUNNING) != 0) { 618 /* 619 * If interface is marked down and it is running, then 620 * stop it. 621 */ 622 elstop(sc); 623 ifp->if_flags &= ~IFF_RUNNING; 624 } else if ((ifp->if_flags & IFF_UP) != 0 && 625 (ifp->if_flags & IFF_RUNNING) == 0) { 626 /* 627 * If interface is marked up and it is stopped, then 628 * start it. 629 */ 630 elinit(sc); 631 } else { 632 /* 633 * Some other important flag might have changed, so 634 * reset. 635 */ 636 elreset(sc); 637 } 638 break; 639 640 default: 641 error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data); 642 } 643 644 splx(s); 645 return error; 646 } 647 648 /* 649 * Device timeout routine. 650 */ 651 void 652 elwatchdog(ifp) 653 struct ifnet *ifp; 654 { 655 struct el_softc *sc = ifp->if_softc; 656 657 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 658 sc->sc_arpcom.ac_if.if_oerrors++; 659 660 elreset(sc); 661 } 662