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