1 /* $NetBSD: lemac.c,v 1.12 1999/05/18 23:52:56 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1994, 1995, 1997 Matt Thomas <matt@3am-software.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software withough specific prior written permission 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* 28 * DEC EtherWORKS 3 Ethernet Controllers 29 * 30 * Written by Matt Thomas 31 * BPF support code stolen directly from if_ec.c 32 * 33 * This driver supports the LEMAC DE203/204/205 cards. 34 */ 35 36 #include "opt_inet.h" 37 #include "opt_ns.h" 38 #include "rnd.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/mbuf.h> 43 #include <sys/protosw.h> 44 #include <sys/socket.h> 45 #include <sys/sockio.h> 46 #include <sys/errno.h> 47 #include <sys/malloc.h> 48 #include <sys/device.h> 49 #if NRND > 0 50 #include <sys/rnd.h> 51 #endif 52 53 #include <net/if.h> 54 #include <net/if_types.h> 55 #include <net/if_dl.h> 56 #include <net/route.h> 57 #include <net/if_ether.h> 58 #include <net/if_media.h> 59 60 #ifdef INET 61 #include <netinet/in.h> 62 #include <netinet/in_systm.h> 63 #include <netinet/in_var.h> 64 #include <netinet/ip.h> 65 #include <netinet/if_inarp.h> 66 #endif 67 68 #ifdef NS 69 #include <netns/ns.h> 70 #include <netns/ns_if.h> 71 #endif 72 73 #include <machine/bus.h> 74 75 #include <dev/ic/lemacreg.h> 76 #include <dev/ic/lemacvar.h> 77 #if 0 78 #include <i386/isa/decether.h> 79 #endif 80 81 #include <vm/vm.h> 82 83 #include "bpfilter.h" 84 #if NBPFILTER > 0 85 #include <net/bpf.h> 86 #endif 87 88 static void lemac_init(lemac_softc_t *sc); 89 static void lemac_ifstart(struct ifnet *ifp); 90 static void lemac_reset(lemac_softc_t *sc); 91 static void lemac_rne_intr(lemac_softc_t *sc); 92 static void lemac_tne_intr(lemac_softc_t *sc); 93 static void lemac_txd_intr(lemac_softc_t *sc, unsigned cs_value); 94 static void lemac_rxd_intr(lemac_softc_t *sc, unsigned cs_value); 95 static int lemac_read_eeprom(lemac_softc_t *sc); 96 static void lemac_init_adapmem(lemac_softc_t *sc); 97 98 static const u_int16_t lemac_allmulti_mctbl[16] = { 99 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 100 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 101 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 102 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 103 }; 104 105 /* 106 * Some tuning/monitoring variables. 107 */ 108 unsigned lemac_txmax = 16; 109 110 static void 111 lemac_rxd_intr( 112 lemac_softc_t *sc, 113 unsigned cs_value) 114 { 115 /* 116 * Handle CS_RXD (Receiver disabled) here. 117 * 118 * Check Free Memory Queue Count. If not equal to zero 119 * then just turn Receiver back on. If it is equal to 120 * zero then check to see if transmitter is disabled. 121 * Process transmit TXD loop once more. If all else 122 * fails then do software init (0xC0 to EEPROM Init) 123 * and rebuild Free Memory Queue. 124 */ 125 126 sc->sc_cntrs.cntr_rxd_intrs++; 127 128 /* 129 * Re-enable Receiver. 130 */ 131 132 cs_value &= ~LEMAC_CS_RXD; 133 LEMAC_OUTB(sc, LEMAC_REG_CS, cs_value); 134 135 if (LEMAC_INB(sc, LEMAC_REG_FMC) > 0) 136 return; 137 138 if (cs_value & LEMAC_CS_TXD) 139 lemac_txd_intr(sc, cs_value); 140 141 if ((LEMAC_INB(sc, LEMAC_REG_CS) & LEMAC_CS_RXD) == 0) 142 return; 143 144 printf("%s: fatal RXD error, attempting recovery\n", sc->sc_if.if_xname); 145 146 lemac_reset(sc); 147 if (sc->sc_if.if_flags & IFF_UP) { 148 lemac_init(sc); 149 return; 150 } 151 152 /* 153 * Error during initializion. Mark card as disabled. 154 */ 155 printf("%s: recovery failed -- board disabled\n", sc->sc_if.if_xname); 156 } 157 158 static void 159 lemac_tne_intr( 160 lemac_softc_t *sc) 161 { 162 unsigned txcount = LEMAC_INB(sc, LEMAC_REG_TDC); 163 164 sc->sc_cntrs.cntr_tne_intrs++; 165 while (txcount-- > 0) { 166 unsigned txsts = LEMAC_INB(sc, LEMAC_REG_TDQ); 167 sc->sc_if.if_opackets++; /* another one done */ 168 if ((txsts & (LEMAC_TDQ_LCL|LEMAC_TDQ_NCL)) 169 || (txsts & LEMAC_TDQ_COL) == LEMAC_TDQ_EXCCOL) { 170 if (txsts & LEMAC_TDQ_NCL) 171 sc->sc_flags &= ~LEMAC_LINKUP; 172 sc->sc_if.if_oerrors++; 173 } else { 174 sc->sc_flags |= LEMAC_LINKUP; 175 if ((txsts & LEMAC_TDQ_COL) != LEMAC_TDQ_NOCOL) 176 sc->sc_if.if_collisions++; 177 } 178 } 179 sc->sc_if.if_flags &= ~IFF_OACTIVE; 180 lemac_ifstart(&sc->sc_if); 181 } 182 183 static void 184 lemac_txd_intr( 185 lemac_softc_t *sc, 186 unsigned cs_value) 187 { 188 /* 189 * Read transmit status, remove transmit buffer from 190 * transmit queue and place on free memory queue, 191 * then reset transmitter. 192 * Increment appropriate counters. 193 */ 194 195 sc->sc_cntrs.cntr_txd_intrs++; 196 if (sc->sc_txctl & LEMAC_TX_STP) { 197 sc->sc_if.if_oerrors++; 198 /* return page to free queue */ 199 LEMAC_OUTB(sc, LEMAC_REG_FMQ, LEMAC_INB(sc, LEMAC_REG_TDQ)); 200 } 201 202 /* Turn back on transmitter if disabled */ 203 LEMAC_OUTB(sc, LEMAC_REG_CS, cs_value & ~LEMAC_CS_TXD); 204 sc->sc_if.if_flags &= ~IFF_OACTIVE; 205 } 206 207 static int 208 lemac_read_eeprom( 209 lemac_softc_t *sc) 210 { 211 int word_off, cksum; 212 213 u_char *ep; 214 215 cksum = 0; 216 ep = sc->sc_eeprom; 217 for (word_off = 0; word_off < LEMAC_EEP_SIZE / 2; word_off++) { 218 LEMAC_OUTB(sc, LEMAC_REG_PI1, word_off); 219 LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEREAD); 220 221 DELAY(LEMAC_EEP_DELAY); 222 223 *ep = LEMAC_INB(sc, LEMAC_REG_EE1); cksum += *ep++; 224 *ep = LEMAC_INB(sc, LEMAC_REG_EE2); cksum += *ep++; 225 } 226 227 /* 228 * Set up Transmit Control Byte for use later during transmit. 229 */ 230 231 sc->sc_txctl |= LEMAC_TX_FLAGS; 232 233 if ((sc->sc_eeprom[LEMAC_EEP_SWFLAGS] & LEMAC_EEP_SW_SQE) == 0) 234 sc->sc_txctl &= ~LEMAC_TX_SQE; 235 236 if (sc->sc_eeprom[LEMAC_EEP_SWFLAGS] & LEMAC_EEP_SW_LAB) 237 sc->sc_txctl |= LEMAC_TX_LAB; 238 239 bcopy(&sc->sc_eeprom[LEMAC_EEP_PRDNM], sc->sc_prodname, LEMAC_EEP_PRDNMSZ); 240 sc->sc_prodname[LEMAC_EEP_PRDNMSZ] = '\0'; 241 242 return cksum % 256; 243 } 244 245 static void 246 lemac_init_adapmem( 247 lemac_softc_t *sc) 248 { 249 int pg, conf; 250 251 conf = LEMAC_INB(sc, LEMAC_REG_CNF); 252 253 if ((sc->sc_eeprom[LEMAC_EEP_SETUP] & LEMAC_EEP_ST_DRAM) == 0) { 254 sc->sc_lastpage = 63; 255 conf &= ~LEMAC_CNF_DRAM; 256 } else { 257 sc->sc_lastpage = 127; 258 conf |= LEMAC_CNF_DRAM; 259 } 260 261 LEMAC_OUTB(sc, LEMAC_REG_CNF, conf); 262 263 for (pg = 1; pg <= sc->sc_lastpage; pg++) 264 LEMAC_OUTB(sc, LEMAC_REG_FMQ, pg); 265 } 266 267 static void 268 lemac_input( 269 lemac_softc_t *sc, 270 bus_addr_t offset, 271 size_t length) 272 { 273 struct ether_header eh; 274 struct mbuf *m; 275 276 if (length - sizeof(eh) > ETHERMTU 277 || length - sizeof(eh) < ETHERMIN) { 278 sc->sc_if.if_ierrors++; 279 return; 280 } 281 if (LEMAC_USE_PIO_MODE(sc)) { 282 LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(eh), (void *) &eh); 283 } else { 284 LEMAC_GETBUF16(sc, offset, sizeof(eh) / 2, (void *) &eh); 285 } 286 287 /* 288 * If this is single cast but not to us 289 * drop it! 290 */ 291 if ((eh.ether_dhost[0] & 1) == 0 292 #if NBPFILTER > 0 293 && (sc->sc_if.if_flags & IFF_PROMISC) == 0 294 #endif 295 && !LEMAC_ADDREQUAL(eh.ether_dhost, sc->sc_enaddr)) 296 return; 297 298 MGETHDR(m, M_DONTWAIT, MT_DATA); 299 if (m == NULL) { 300 sc->sc_if.if_ierrors++; 301 return; 302 } 303 if (length + 2 > MHLEN) { 304 MCLGET(m, M_DONTWAIT); 305 if ((m->m_flags & M_EXT) == 0) { 306 m_free(m); 307 sc->sc_if.if_ierrors++; 308 return; 309 } 310 } 311 m->m_data += 2; 312 bcopy((caddr_t)&eh, m->m_data, sizeof(eh)); 313 if (LEMAC_USE_PIO_MODE(sc)) { 314 LEMAC_INSB(sc, LEMAC_REG_DAT, length - sizeof(eh), 315 mtod(m, caddr_t) + sizeof(eh)); 316 } else { 317 LEMAC_GETBUF16(sc, offset + sizeof(eh), (length - sizeof(eh)) / 2, 318 (void *) (mtod(m, caddr_t) + sizeof(eh))); 319 if (length & 1) 320 m->m_data[length - 1] = LEMAC_GET8(sc, offset + length - 1); 321 } 322 #if NBPFILTER > 0 323 if (sc->sc_if.if_bpf != NULL) { 324 m->m_pkthdr.len = m->m_len = length; 325 bpf_mtap(sc->sc_if.if_bpf, m); 326 } 327 /* 328 * If this is single cast but not to us 329 * drop it! 330 */ 331 if ((eh.ether_dhost[0] & 1) == 0 332 && !LEMAC_ADDREQUAL(eh.ether_dhost, sc->sc_enaddr)) { 333 m_freem(m); 334 return; 335 } 336 #endif 337 m->m_pkthdr.len = m->m_len = length; 338 m->m_pkthdr.rcvif = &sc->sc_if; 339 (*sc->sc_if.if_input)(&sc->sc_if, m); 340 } 341 342 static void 343 lemac_rne_intr( 344 lemac_softc_t *sc) 345 { 346 int rxcount; 347 348 sc->sc_cntrs.cntr_rne_intrs++; 349 rxcount = LEMAC_INB(sc, LEMAC_REG_RQC); 350 while (rxcount--) { 351 unsigned rxpg = LEMAC_INB(sc, LEMAC_REG_RQ); 352 u_int32_t rxlen; 353 354 sc->sc_if.if_ipackets++; 355 if (LEMAC_USE_PIO_MODE(sc)) { 356 LEMAC_OUTB(sc, LEMAC_REG_IOP, rxpg); 357 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0); 358 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0); 359 LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(rxlen), (void *) &rxlen); 360 } else { 361 LEMAC_OUTB(sc, LEMAC_REG_MPN, rxpg); 362 rxlen = LEMAC_GET32(sc, 0); 363 } 364 if (rxlen & LEMAC_RX_OK) { 365 sc->sc_flags |= LEMAC_LINKUP; 366 /* 367 * Get receive length - subtract out checksum. 368 */ 369 rxlen = ((rxlen >> 8) & 0x7FF) - 4; 370 lemac_input(sc, sizeof(rxlen), rxlen); 371 } else { 372 sc->sc_if.if_ierrors++; 373 } 374 LEMAC_OUTB(sc, LEMAC_REG_FMQ, rxpg); /* Return this page to Free Memory Queue */ 375 } /* end while (recv_count--) */ 376 377 return; 378 } 379 380 /* 381 * This is the standard method of reading the DEC Address ROMS. 382 * I don't understand it but it does work. 383 */ 384 static int 385 lemac_read_macaddr( 386 unsigned char *hwaddr, 387 const bus_space_tag_t iot, 388 const bus_space_handle_t ioh, 389 const bus_addr_t ioreg, 390 int skippat) 391 { 392 int cksum, rom_cksum; 393 unsigned char addrbuf[6]; 394 395 if (!skippat) { 396 int idx, idx2, found, octet; 397 static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; 398 idx2 = found = 0; 399 400 for (idx = 0; idx < 32; idx++) { 401 octet = bus_space_read_1(iot, ioh, ioreg); 402 403 if (octet == testpat[idx2]) { 404 if (++idx2 == sizeof(testpat)) { 405 ++found; 406 break; 407 } 408 } else { 409 idx2 = 0; 410 } 411 } 412 413 if (!found) 414 return -1; 415 } 416 417 if (hwaddr == NULL) 418 hwaddr = addrbuf; 419 420 cksum = 0; 421 hwaddr[0] = bus_space_read_1(iot, ioh, ioreg); 422 hwaddr[1] = bus_space_read_1(iot, ioh, ioreg); 423 424 /* hardware adddress can't be multicast */ 425 if (hwaddr[0] & 1) 426 return -1; 427 428 cksum = *(u_short *) &hwaddr[0]; 429 430 hwaddr[2] = bus_space_read_1(iot, ioh, ioreg); 431 hwaddr[3] = bus_space_read_1(iot, ioh, ioreg); 432 cksum *= 2; 433 if (cksum > 65535) cksum -= 65535; 434 cksum += *(u_short *) &hwaddr[2]; 435 if (cksum > 65535) cksum -= 65535; 436 437 hwaddr[4] = bus_space_read_1(iot, ioh, ioreg); 438 hwaddr[5] = bus_space_read_1(iot, ioh, ioreg); 439 cksum *= 2; 440 if (cksum > 65535) cksum -= 65535; 441 cksum += *(u_short *) &hwaddr[4]; 442 if (cksum >= 65535) cksum -= 65535; 443 444 /* 00-00-00 is an illegal OUI */ 445 if (hwaddr[0] == 0 && hwaddr[1] == 0 && hwaddr[2] == 0) 446 return -1; 447 448 rom_cksum = bus_space_read_1(iot, ioh, ioreg); 449 rom_cksum |= bus_space_read_1(iot, ioh, ioreg) << 8; 450 451 if (cksum != rom_cksum) 452 return -1; 453 return 0; 454 } 455 456 static void 457 lemac_multicast_op( 458 u_int16_t *mctbl, 459 const u_char *mca, 460 int enable) 461 { 462 u_int idx, bit, crc = 0xFFFFFFFFUL; 463 static const u_int crctab[] = { 464 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 465 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 466 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 467 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 468 }; 469 470 for (idx = 0; idx < 6; idx++) { 471 crc ^= *mca++; 472 crc = (crc >> 4) ^ crctab[crc & 0xf]; 473 crc = (crc >> 4) ^ crctab[crc & 0xf]; 474 } 475 /* 476 * The following two lines convert the N bit index into a longword index 477 * and a longword mask. 478 */ 479 #if LEMAC_MCTBL_BITS < 0 480 crc >>= (32 + LEMAC_MCTBL_BITS); 481 crc &= (1 << -LEMAC_MCTBL_BITS) - 1; 482 #else 483 crc &= (1 << LEMAC_MCTBL_BITS) - 1; 484 #endif 485 bit = 1 << (crc & 0x0F); 486 idx = crc >> 4; 487 488 /* 489 * Set or clear hash filter bit in our table. 490 */ 491 if (enable) { 492 mctbl[idx] |= bit; /* Set Bit */ 493 } else { 494 mctbl[idx] &= ~bit; /* Clear Bit */ 495 } 496 } 497 498 static void 499 lemac_multicast_filter( 500 lemac_softc_t *sc) 501 { 502 struct ether_multistep step; 503 struct ether_multi *enm; 504 505 bzero(sc->sc_mctbl, LEMAC_MCTBL_BITS / 8); 506 507 lemac_multicast_op(sc->sc_mctbl, etherbroadcastaddr, TRUE); 508 509 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm); 510 while (enm != NULL) { 511 if (!LEMAC_ADDREQUAL(enm->enm_addrlo, enm->enm_addrhi)) { 512 sc->sc_flags |= LEMAC_ALLMULTI; 513 sc->sc_if.if_flags |= IFF_ALLMULTI; 514 return; 515 } 516 lemac_multicast_op(sc->sc_mctbl, enm->enm_addrlo, TRUE); 517 ETHER_NEXT_MULTI(step, enm); 518 } 519 sc->sc_flags &= ~LEMAC_ALLMULTI; 520 sc->sc_if.if_flags &= ~IFF_ALLMULTI; 521 } 522 523 /* 524 * Do a hard reset of the board; 525 */ 526 static void 527 lemac_reset( 528 lemac_softc_t * const sc) 529 { 530 unsigned data; 531 532 /* 533 * Initialize board.. 534 */ 535 sc->sc_flags &= ~LEMAC_LINKUP; 536 sc->sc_if.if_flags &= ~IFF_OACTIVE; 537 LEMAC_INTR_DISABLE(sc); 538 539 LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEINIT); 540 DELAY(LEMAC_EEP_DELAY); 541 542 /* 543 * Read EEPROM information. NOTE - the placement of this function 544 * is important because functions hereafter may rely on information 545 * read from the EEPROM. 546 */ 547 if ((data = lemac_read_eeprom(sc)) != LEMAC_EEP_CKSUM) { 548 printf("%s: reset: EEPROM checksum failed (0x%x)\n", 549 sc->sc_if.if_xname, data); 550 return; 551 } 552 553 /* 554 * Update the control register to reflect the media choice 555 */ 556 data = LEMAC_INB(sc, LEMAC_REG_CTL); 557 if ((data & (LEMAC_CTL_APD|LEMAC_CTL_PSL)) != sc->sc_ctlmode) { 558 data &= ~(LEMAC_CTL_APD|LEMAC_CTL_PSL); 559 data |= sc->sc_ctlmode; 560 LEMAC_OUTB(sc, LEMAC_REG_CTL, data); 561 } 562 563 /* 564 * Force to 2K mode if not already configured. 565 */ 566 567 data = LEMAC_INB(sc, LEMAC_REG_MBR); 568 if (LEMAC_IS_2K_MODE(data)) { 569 sc->sc_flags |= LEMAC_2K_MODE; 570 } else if (LEMAC_IS_64K_MODE(data)) { 571 data = (((data * 2) & 0xF) << 4); 572 sc->sc_flags |= LEMAC_WAS_64K_MODE; 573 LEMAC_OUTB(sc, LEMAC_REG_MBR, data); 574 } else if (LEMAC_IS_32K_MODE(data)) { 575 data = ((data & 0xF) << 4); 576 sc->sc_flags |= LEMAC_WAS_32K_MODE; 577 LEMAC_OUTB(sc, LEMAC_REG_MBR, data); 578 } else { 579 sc->sc_flags |= LEMAC_PIO_MODE; 580 /* PIO mode */ 581 } 582 583 /* 584 * Initialize Free Memory Queue, Init mcast table with broadcast. 585 */ 586 587 lemac_init_adapmem(sc); 588 sc->sc_flags |= LEMAC_ALIVE; 589 } 590 591 static void 592 lemac_init( 593 lemac_softc_t * const sc) 594 { 595 if ((sc->sc_flags & LEMAC_ALIVE) == 0) 596 return; 597 598 /* 599 * If the interface has the up flag 600 */ 601 if (sc->sc_if.if_flags & IFF_UP) { 602 int saved_cs = LEMAC_INB(sc, LEMAC_REG_CS); 603 LEMAC_OUTB(sc, LEMAC_REG_CS, saved_cs | (LEMAC_CS_TXD | LEMAC_CS_RXD)); 604 LEMAC_OUTB(sc, LEMAC_REG_PA0, sc->sc_enaddr[0]); 605 LEMAC_OUTB(sc, LEMAC_REG_PA1, sc->sc_enaddr[1]); 606 LEMAC_OUTB(sc, LEMAC_REG_PA2, sc->sc_enaddr[2]); 607 LEMAC_OUTB(sc, LEMAC_REG_PA3, sc->sc_enaddr[3]); 608 LEMAC_OUTB(sc, LEMAC_REG_PA4, sc->sc_enaddr[4]); 609 LEMAC_OUTB(sc, LEMAC_REG_PA5, sc->sc_enaddr[5]); 610 611 LEMAC_OUTB(sc, LEMAC_REG_IC, LEMAC_INB(sc, LEMAC_REG_IC) | LEMAC_IC_IE); 612 613 if (sc->sc_if.if_flags & IFF_PROMISC) { 614 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE | LEMAC_CS_PME); 615 } else { 616 LEMAC_INTR_DISABLE(sc); 617 lemac_multicast_filter(sc); 618 if (sc->sc_flags & LEMAC_ALLMULTI) 619 bcopy(lemac_allmulti_mctbl, sc->sc_mctbl, sizeof(sc->sc_mctbl)); 620 if (LEMAC_USE_PIO_MODE(sc)) { 621 LEMAC_OUTB(sc, LEMAC_REG_IOP, 0); 622 LEMAC_OUTB(sc, LEMAC_REG_PI1, LEMAC_MCTBL_OFF & 0xFF); 623 LEMAC_OUTB(sc, LEMAC_REG_PI2, LEMAC_MCTBL_OFF >> 8); 624 LEMAC_OUTSB(sc, LEMAC_REG_DAT, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl); 625 } else { 626 LEMAC_OUTB(sc, LEMAC_REG_MPN, 0); 627 LEMAC_PUTBUF8(sc, LEMAC_MCTBL_OFF, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl); 628 } 629 630 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE); 631 } 632 633 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED); 634 635 LEMAC_INTR_ENABLE(sc); 636 sc->sc_if.if_flags |= IFF_RUNNING; 637 lemac_ifstart(&sc->sc_if); 638 } else { 639 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_RXD|LEMAC_CS_TXD); 640 641 LEMAC_INTR_DISABLE(sc); 642 sc->sc_if.if_flags &= ~IFF_RUNNING; 643 } 644 } 645 646 static void 647 lemac_ifstart( 648 struct ifnet *ifp) 649 { 650 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 651 struct ifqueue * const ifq = &ifp->if_snd; 652 653 if ((ifp->if_flags & IFF_RUNNING) == 0) 654 return; 655 656 LEMAC_INTR_DISABLE(sc); 657 658 while (ifq->ifq_head != NULL) { 659 struct mbuf *m; 660 struct mbuf *m0; 661 int tx_pg; 662 663 if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC)) >= lemac_txmax) { 664 sc->sc_cntrs.cntr_txfull++; 665 ifp->if_flags |= IFF_OACTIVE; 666 break; 667 } 668 669 /* 670 * get free memory page 671 */ 672 tx_pg = sc->sc_csr.csr_fmq = LEMAC_INB(sc, LEMAC_REG_FMQ); 673 /* 674 * Check for good transmit page. 675 */ 676 if (tx_pg == 0 || tx_pg > sc->sc_lastpage) { 677 sc->sc_cntrs.cntr_txnospc++; 678 ifp->if_flags |= IFF_OACTIVE; 679 break; 680 } 681 682 IF_DEQUEUE(ifq, m); 683 684 /* 685 * The first four bytes of each transmit buffer are for 686 * control information. The first byte is the control 687 * byte, then the length (why not word aligned??), then 688 * the offset to the buffer. 689 */ 690 691 if (LEMAC_USE_PIO_MODE(sc)) { 692 LEMAC_OUTB(sc, LEMAC_REG_IOP, tx_pg); /* Shift 2K window. */ 693 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0); 694 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0); 695 LEMAC_OUTB(sc, LEMAC_REG_DAT, sc->sc_txctl); 696 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 0) & 0xFF); 697 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 8) & 0xFF); 698 LEMAC_OUTB(sc, LEMAC_REG_DAT, LEMAC_TX_HDRSZ); 699 for (m0 = m; m0 != NULL; m0 = m0->m_next) 700 LEMAC_OUTSB(sc, LEMAC_REG_DAT, m0->m_len, m0->m_data); 701 } else { 702 bus_size_t txoff = /* (mtod(m, u_int32_t) & (sizeof(u_int32_t) - 1)) + */ LEMAC_TX_HDRSZ; 703 LEMAC_OUTB(sc, LEMAC_REG_MPN, tx_pg); /* Shift 2K window. */ 704 LEMAC_PUT8(sc, 0, sc->sc_txctl); 705 LEMAC_PUT8(sc, 1, (m->m_pkthdr.len >> 0) & 0xFF); 706 LEMAC_PUT8(sc, 2, (m->m_pkthdr.len >> 8) & 0xFF); 707 LEMAC_PUT8(sc, 3, txoff); 708 709 /* 710 * Copy the packet to the board 711 */ 712 for (m0 = m; m0 != NULL; m0 = m0->m_next) { 713 #if 0 714 LEMAC_PUTBUF8(sc, txoff, m0->m_len, m0->m_data); 715 txoff += m0->m_len; 716 #else 717 const u_int8_t *cp = m0->m_data; 718 int len = m0->m_len; 719 #if 0 720 if ((txoff & 3) == (((long)cp) & 3) && len >= 4) { 721 if (txoff & 3) { 722 int alen = (~txoff & 3); 723 LEMAC_PUTBUF8(sc, txoff, alen, cp); 724 cp += alen; txoff += alen; len -= alen; 725 } 726 if (len >= 4) { 727 LEMAC_PUTBUF32(sc, txoff, len / 4, cp); 728 cp += len & ~3; txoff += len & ~3; len &= 3; 729 } 730 } 731 #endif 732 if ((txoff & 1) == (((long)cp) & 1) && len >= 2) { 733 if (txoff & 1) { 734 int alen = (~txoff & 1); 735 LEMAC_PUTBUF8(sc, txoff, alen, cp); 736 cp += alen; txoff += alen; len -= alen; 737 } 738 if (len >= 2) { 739 LEMAC_PUTBUF16(sc, txoff, len / 2, (void *) cp); 740 cp += len & ~1; txoff += len & ~1; len &= 1; 741 } 742 } 743 if (len > 0) { 744 LEMAC_PUTBUF8(sc, txoff, len, cp); 745 txoff += len; 746 } 747 #endif 748 } 749 } 750 751 LEMAC_OUTB(sc, LEMAC_REG_TQ, tx_pg); /* tell chip to transmit this packet */ 752 #if NBPFILTER > 0 753 if (sc->sc_if.if_bpf != NULL) 754 bpf_mtap(sc->sc_if.if_bpf, m); 755 #endif 756 m_freem(m); /* free the mbuf */ 757 } 758 LEMAC_INTR_ENABLE(sc); 759 } 760 761 static int 762 lemac_ifioctl( 763 struct ifnet *ifp, 764 u_long cmd, 765 caddr_t data) 766 { 767 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 768 int s; 769 int error = 0; 770 771 s = splnet(); 772 773 switch (cmd) { 774 case SIOCSIFADDR: { 775 struct ifaddr *ifa = (struct ifaddr *)data; 776 777 ifp->if_flags |= IFF_UP; 778 lemac_init(sc); 779 switch (ifa->ifa_addr->sa_family) { 780 #ifdef INET 781 case AF_INET: { 782 arp_ifinit(&sc->sc_if, ifa); 783 break; 784 } 785 #endif /* INET */ 786 787 #ifdef NS 788 /* This magic copied from if_is.c; I don't use XNS, 789 * so I have no way of telling if this actually 790 * works or not. 791 */ 792 case AF_NS: { 793 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 794 if (ns_nullhost(*ina)) { 795 ina->x_host = *(union ns_host *)sc->sc_enaddr; 796 } else { 797 bcopy((caddr_t)ina->x_host.c_host, sc->sc_enaddr, 798 ifp->if_addrlen); 799 } 800 break; 801 } 802 #endif /* NS */ 803 804 default: { 805 break; 806 } 807 } 808 break; 809 } 810 811 case SIOCSIFFLAGS: { 812 lemac_init(sc); 813 break; 814 } 815 816 case SIOCADDMULTI: 817 case SIOCDELMULTI: { 818 /* 819 * Update multicast listeners 820 */ 821 if (cmd == SIOCADDMULTI) 822 error = ether_addmulti((struct ifreq *)data, &sc->sc_ec); 823 else 824 error = ether_delmulti((struct ifreq *)data, &sc->sc_ec); 825 826 if (error == ENETRESET) { 827 828 /* reset multicast filtering */ 829 lemac_init(sc); 830 error = 0; 831 } 832 break; 833 } 834 835 case SIOCSIFMEDIA: 836 case SIOCGIFMEDIA: { 837 error = ifmedia_ioctl(ifp, (struct ifreq *)data, 838 &sc->sc_ifmedia, cmd); 839 break; 840 } 841 842 default: { 843 error = EINVAL; 844 break; 845 } 846 } 847 848 splx(s); 849 return error; 850 } 851 852 static int 853 lemac_ifmedia_change( 854 struct ifnet * const ifp) 855 { 856 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 857 unsigned new_ctl; 858 859 switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) { 860 case IFM_10_T: new_ctl = LEMAC_CTL_APD; break; 861 case IFM_10_2: 862 case IFM_10_5: new_ctl = LEMAC_CTL_APD|LEMAC_CTL_PSL; break; 863 case IFM_AUTO: new_ctl = 0; break; 864 default: return EINVAL; 865 } 866 if (sc->sc_ctlmode != new_ctl) { 867 sc->sc_ctlmode = new_ctl; 868 lemac_reset(sc); 869 if (sc->sc_if.if_flags & IFF_UP) 870 lemac_init(sc); 871 } 872 return 0; 873 } 874 875 /* 876 * Media status callback 877 */ 878 static void 879 lemac_ifmedia_status( 880 struct ifnet * const ifp, 881 struct ifmediareq *req) 882 { 883 lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp); 884 unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF); 885 886 req->ifm_status = IFM_AVALID; 887 if (sc->sc_flags & LEMAC_LINKUP) 888 req->ifm_status |= IFM_ACTIVE; 889 890 if (sc->sc_ctlmode & LEMAC_CTL_APD) { 891 if (sc->sc_ctlmode & LEMAC_CTL_PSL) { 892 req->ifm_active = IFM_10_5; 893 } else { 894 req->ifm_active = IFM_10_T; 895 } 896 } else { 897 /* 898 * The link bit of the configuration register reflects the 899 * current media choice when auto-port is enabled. 900 */ 901 if (data & LEMAC_CNF_NOLINK) { 902 req->ifm_active = IFM_10_5; 903 } else { 904 req->ifm_active = IFM_10_T; 905 } 906 } 907 908 req->ifm_active |= IFM_ETHER; 909 } 910 911 int 912 lemac_port_check( 913 const bus_space_tag_t iot, 914 const bus_space_handle_t ioh) 915 { 916 unsigned char hwaddr[6]; 917 918 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0) 919 return 1; 920 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0) 921 return 1; 922 return 0; 923 } 924 925 void 926 lemac_info_get( 927 const bus_space_tag_t iot, 928 const bus_space_handle_t ioh, 929 bus_addr_t *maddr_p, 930 bus_size_t *msize_p, 931 int *irq_p) 932 { 933 unsigned data; 934 935 *irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC) & LEMAC_IC_IRQMSK); 936 937 data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR); 938 if (LEMAC_IS_2K_MODE(data)) { 939 *maddr_p = data * (2 * 1024) + (512 * 1024); 940 *msize_p = 2 * 1024; 941 } else if (LEMAC_IS_64K_MODE(data)) { 942 *maddr_p = data * 64 * 1024; 943 *msize_p = 64 * 1024; 944 } else if (LEMAC_IS_32K_MODE(data)) { 945 *maddr_p = data * 32 * 1024; 946 *msize_p = 32* 1024; 947 } else { 948 *maddr_p = 0; 949 *msize_p = 0; 950 } 951 } 952 953 /* 954 * What to do upon receipt of an interrupt. 955 */ 956 int 957 lemac_intr( 958 void *arg) 959 { 960 lemac_softc_t * const sc = arg; 961 int cs_value; 962 963 LEMAC_INTR_DISABLE(sc); /* Mask interrupts */ 964 965 /* 966 * Determine cause of interrupt. Receive events take 967 * priority over Transmit. 968 */ 969 970 cs_value = LEMAC_INB(sc, LEMAC_REG_CS); 971 972 /* 973 * Check for Receive Queue not being empty. 974 * Check for Transmit Done Queue not being empty. 975 */ 976 977 if (cs_value & LEMAC_CS_RNE) 978 lemac_rne_intr(sc); 979 if (cs_value & LEMAC_CS_TNE) 980 lemac_tne_intr(sc); 981 982 /* 983 * Check for Transmitter Disabled. 984 * Check for Receiver Disabled. 985 */ 986 987 if (cs_value & LEMAC_CS_TXD) 988 lemac_txd_intr(sc, cs_value); 989 if (cs_value & LEMAC_CS_RXD) 990 lemac_rxd_intr(sc, cs_value); 991 992 /* 993 * Toggle LED and unmask interrupts. 994 */ 995 996 sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS); 997 998 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED); 999 LEMAC_INTR_ENABLE(sc); /* Unmask interrupts */ 1000 1001 #if NRND > 0 1002 if (cs_value) 1003 rnd_add_uint32(&sc->rnd_source, cs_value); 1004 #endif 1005 1006 return 1; 1007 } 1008 1009 void 1010 lemac_shutdown( 1011 void *arg) 1012 { 1013 lemac_reset((lemac_softc_t *) arg); 1014 } 1015 1016 static const char * const lemac_modes[4] = { 1017 "PIO mode (internal 2KB window)", 1018 "2KB window", 1019 "changed 32KB window to 2KB", 1020 "changed 64KB window to 2KB", 1021 }; 1022 1023 void 1024 lemac_ifattach( 1025 lemac_softc_t *sc) 1026 { 1027 struct ifnet * const ifp = &sc->sc_if; 1028 1029 bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ); 1030 1031 lemac_reset(sc); 1032 1033 (void) lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh, 1034 LEMAC_REG_APD, 0); 1035 1036 printf(": %s\n", sc->sc_prodname); 1037 1038 printf("%s: address %s, %dKB RAM, %s\n", 1039 ifp->if_xname, 1040 ether_sprintf(sc->sc_enaddr), 1041 sc->sc_lastpage * 2 + 2, 1042 lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]); 1043 1044 ifp->if_baudrate = 10000000; 1045 ifp->if_softc = (void *) sc; 1046 ifp->if_start = lemac_ifstart; 1047 ifp->if_ioctl = lemac_ifioctl; 1048 1049 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX 1050 #ifdef IFF_NOTRAILERS 1051 | IFF_NOTRAILERS 1052 #endif 1053 | IFF_MULTICAST; 1054 1055 if (sc->sc_flags & LEMAC_ALIVE) { 1056 int media; 1057 1058 if_attach(ifp); 1059 ether_ifattach(ifp, sc->sc_enaddr); 1060 1061 #if NBPFILTER > 0 1062 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 1063 #endif 1064 1065 #if NRND > 0 1066 rnd_attach_source(&sc->rnd_source, sc->sc_dv.dv_xname, 1067 RND_TYPE_NET, 0); 1068 #endif 1069 1070 ifmedia_init(&sc->sc_ifmedia, 0, 1071 lemac_ifmedia_change, 1072 lemac_ifmedia_status); 1073 if (sc->sc_prodname[4] == '5') /* DE205 is UTP/AUI */ 1074 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); 1075 if (sc->sc_prodname[4] != '3') /* DE204 & 205 have UTP */ 1076 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, 0); 1077 if (sc->sc_prodname[4] != '4') /* DE203 & 205 have BNC */ 1078 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, 0); 1079 switch (sc->sc_prodname[4]) { 1080 case '3': media = IFM_10_5; break; 1081 case '4': media = IFM_10_T; break; 1082 default: media = IFM_AUTO; break; 1083 } 1084 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media); 1085 } else { 1086 printf("%s: disabled due to error\n", ifp->if_xname); 1087 } 1088 } 1089