1 /* $OpenBSD: if_el.c,v 1.35 2020/07/10 13:22:20 patrick 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 m0 = ifq_dequeue(&ifp->if_snd); 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 break; 369 } 370 } 371 372 /* 373 * Now give the card a chance to receive. 374 * Gotta love 3c501s... 375 */ 376 (void)inb(iobase+EL_AS); 377 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 378 splx(s); 379 /* Interrupt here. */ 380 s = splnet(); 381 } 382 383 (void)inb(iobase+EL_AS); 384 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 385 ifq_clr_oactive(&ifp->if_snd); 386 splx(s); 387 } 388 389 /* 390 * This function actually attempts to transmit a datagram downloaded to the 391 * board. Call at splnet or interrupt, after downloading data! Returns 0 on 392 * success, non-0 on failure. 393 */ 394 static int 395 el_xmit(sc) 396 struct el_softc *sc; 397 { 398 int iobase = sc->sc_iobase; 399 int i; 400 401 /* 402 * XXX 403 * This busy-waits for the tx completion. Can we get an interrupt 404 * instead? 405 */ 406 407 dprintf(("el: xmit...")); 408 outb(iobase+EL_AC, EL_AC_TXFRX); 409 i = 20000; 410 while ((inb(iobase+EL_AS) & EL_AS_TXBUSY) && (i > 0)) 411 i--; 412 if (i == 0) { 413 dprintf(("tx not ready\n")); 414 return -1; 415 } 416 dprintf(("%d cycles.\n", 20000 - i)); 417 return 0; 418 } 419 420 /* 421 * Controller interrupt. 422 */ 423 int 424 elintr(arg) 425 void *arg; 426 { 427 register struct el_softc *sc = arg; 428 int iobase = sc->sc_iobase; 429 int rxstat, len; 430 431 dprintf(("elintr: ")); 432 433 /* Check board status. */ 434 if ((inb(iobase+EL_AS) & EL_AS_RXBUSY) != 0) { 435 (void)inb(iobase+EL_RXC); 436 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 437 return 0; 438 } 439 440 for (;;) { 441 rxstat = inb(iobase+EL_RXS); 442 if (rxstat & EL_RXS_STALE) 443 break; 444 445 /* If there's an overflow, reinit the board. */ 446 if ((rxstat & EL_RXS_NOFLOW) == 0) { 447 dprintf(("overflow.\n")); 448 el_hardreset(sc); 449 /* Put board back into receive mode. */ 450 if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) 451 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC); 452 else 453 outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD); 454 (void)inb(iobase+EL_AS); 455 outb(iobase+EL_RBC, 0); 456 break; 457 } 458 459 /* Incoming packet. */ 460 len = inb(iobase+EL_RBL); 461 len |= inb(iobase+EL_RBH) << 8; 462 dprintf(("receive len=%d rxstat=%x ", len, rxstat)); 463 outb(iobase+EL_AC, EL_AC_HOST); 464 465 /* Pass data up to upper levels. */ 466 elread(sc, len); 467 468 /* Is there another packet? */ 469 if ((inb(iobase+EL_AS) & EL_AS_RXBUSY) != 0) 470 break; 471 472 dprintf(("<rescan> ")); 473 } 474 475 (void)inb(iobase+EL_RXC); 476 outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX); 477 return 1; 478 } 479 480 /* 481 * Pass a packet to the higher levels. 482 */ 483 void 484 elread(sc, len) 485 register struct el_softc *sc; 486 int len; 487 { 488 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 489 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 490 struct mbuf *m; 491 492 if (len <= sizeof(struct ether_header) || 493 len > ETHER_MAX_LEN) { 494 printf("%s: invalid packet size %d; dropping\n", 495 sc->sc_dev.dv_xname, len); 496 ifp->if_ierrors++; 497 return; 498 } 499 500 /* Pull packet off interface. */ 501 m = elget(sc, len); 502 if (m == NULL) { 503 ifp->if_ierrors++; 504 return; 505 } 506 507 ml_enqueue(&ml, m); 508 if_input(ifp, &ml); 509 } 510 511 /* 512 * Pull read data off a interface. Len is length of data, with local net 513 * header stripped. We copy the data into mbufs. When full cluster sized 514 * units are present we copy into clusters. 515 */ 516 struct mbuf * 517 elget(sc, totlen) 518 struct el_softc *sc; 519 int totlen; 520 { 521 int iobase = sc->sc_iobase; 522 struct mbuf *top, **mp, *m; 523 int len; 524 525 MGETHDR(m, M_DONTWAIT, MT_DATA); 526 if (m == NULL) 527 return 0; 528 m->m_pkthdr.len = totlen; 529 len = MHLEN; 530 top = 0; 531 mp = ⊤ 532 533 outb(iobase+EL_GPBL, 0); 534 outb(iobase+EL_GPBH, 0); 535 536 while (totlen > 0) { 537 if (top) { 538 MGET(m, M_DONTWAIT, MT_DATA); 539 if (m == NULL) { 540 m_freem(top); 541 return 0; 542 } 543 len = MLEN; 544 } 545 if (totlen >= MINCLSIZE) { 546 MCLGET(m, M_DONTWAIT); 547 if (m->m_flags & M_EXT) 548 len = MCLBYTES; 549 } 550 m->m_len = len = min(totlen, len); 551 insb(iobase+EL_BUF, mtod(m, caddr_t), len); 552 totlen -= len; 553 *mp = m; 554 mp = &m->m_next; 555 } 556 557 outb(iobase+EL_RBC, 0); 558 outb(iobase+EL_AC, EL_AC_RX); 559 560 return top; 561 } 562 563 /* 564 * Process an ioctl request. This code needs some work - it looks pretty ugly. 565 */ 566 int 567 elioctl(ifp, cmd, data) 568 register struct ifnet *ifp; 569 u_long cmd; 570 caddr_t data; 571 { 572 struct el_softc *sc = ifp->if_softc; 573 int s, error = 0; 574 575 s = splnet(); 576 577 switch (cmd) { 578 case SIOCSIFADDR: 579 ifp->if_flags |= IFF_UP; 580 elinit(sc); 581 break; 582 583 case SIOCSIFFLAGS: 584 if ((ifp->if_flags & IFF_UP) == 0 && 585 (ifp->if_flags & IFF_RUNNING) != 0) { 586 /* 587 * If interface is marked down and it is running, then 588 * stop it. 589 */ 590 elstop(sc); 591 ifp->if_flags &= ~IFF_RUNNING; 592 } else if ((ifp->if_flags & IFF_UP) != 0 && 593 (ifp->if_flags & IFF_RUNNING) == 0) { 594 /* 595 * If interface is marked up and it is stopped, then 596 * start it. 597 */ 598 elinit(sc); 599 } else { 600 /* 601 * Some other important flag might have changed, so 602 * reset. 603 */ 604 elreset(sc); 605 } 606 break; 607 608 default: 609 error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data); 610 } 611 612 splx(s); 613 return error; 614 } 615 616 /* 617 * Device timeout routine. 618 */ 619 void 620 elwatchdog(ifp) 621 struct ifnet *ifp; 622 { 623 struct el_softc *sc = ifp->if_softc; 624 625 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 626 sc->sc_arpcom.ac_if.if_oerrors++; 627 628 elreset(sc); 629 } 630