1 /* $NetBSD: lemac.c,v 1.10 1998/07/05 06:49:11 jonathan 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 - sizeof(eh); 338 m->m_data += sizeof(eh); 339 m->m_pkthdr.rcvif = &sc->sc_if; 340 ether_input(&sc->sc_if, &eh, m); 341 } 342 343 static void 344 lemac_rne_intr( 345 lemac_softc_t *sc) 346 { 347 int rxcount; 348 349 sc->sc_cntrs.cntr_rne_intrs++; 350 rxcount = LEMAC_INB(sc, LEMAC_REG_RQC); 351 while (rxcount--) { 352 unsigned rxpg = LEMAC_INB(sc, LEMAC_REG_RQ); 353 u_int32_t rxlen; 354 355 sc->sc_if.if_ipackets++; 356 if (LEMAC_USE_PIO_MODE(sc)) { 357 LEMAC_OUTB(sc, LEMAC_REG_IOP, rxpg); 358 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0); 359 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0); 360 LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(rxlen), (void *) &rxlen); 361 } else { 362 LEMAC_OUTB(sc, LEMAC_REG_MPN, rxpg); 363 rxlen = LEMAC_GET32(sc, 0); 364 } 365 if (rxlen & LEMAC_RX_OK) { 366 sc->sc_flags |= LEMAC_LINKUP; 367 /* 368 * Get receive length - subtract out checksum. 369 */ 370 rxlen = ((rxlen >> 8) & 0x7FF) - 4; 371 lemac_input(sc, sizeof(rxlen), rxlen); 372 } else { 373 sc->sc_if.if_ierrors++; 374 } 375 LEMAC_OUTB(sc, LEMAC_REG_FMQ, rxpg); /* Return this page to Free Memory Queue */ 376 } /* end while (recv_count--) */ 377 378 return; 379 } 380 381 /* 382 * This is the standard method of reading the DEC Address ROMS. 383 * I don't understand it but it does work. 384 */ 385 static int 386 lemac_read_macaddr( 387 unsigned char *hwaddr, 388 const bus_space_tag_t iot, 389 const bus_space_handle_t ioh, 390 const bus_addr_t ioreg, 391 int skippat) 392 { 393 int cksum, rom_cksum; 394 unsigned char addrbuf[6]; 395 396 if (!skippat) { 397 int idx, idx2, found, octet; 398 static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; 399 idx2 = found = 0; 400 401 for (idx = 0; idx < 32; idx++) { 402 octet = bus_space_read_1(iot, ioh, ioreg); 403 404 if (octet == testpat[idx2]) { 405 if (++idx2 == sizeof(testpat)) { 406 ++found; 407 break; 408 } 409 } else { 410 idx2 = 0; 411 } 412 } 413 414 if (!found) 415 return -1; 416 } 417 418 if (hwaddr == NULL) 419 hwaddr = addrbuf; 420 421 cksum = 0; 422 hwaddr[0] = bus_space_read_1(iot, ioh, ioreg); 423 hwaddr[1] = bus_space_read_1(iot, ioh, ioreg); 424 425 /* hardware adddress can't be multicast */ 426 if (hwaddr[0] & 1) 427 return -1; 428 429 cksum = *(u_short *) &hwaddr[0]; 430 431 hwaddr[2] = bus_space_read_1(iot, ioh, ioreg); 432 hwaddr[3] = bus_space_read_1(iot, ioh, ioreg); 433 cksum *= 2; 434 if (cksum > 65535) cksum -= 65535; 435 cksum += *(u_short *) &hwaddr[2]; 436 if (cksum > 65535) cksum -= 65535; 437 438 hwaddr[4] = bus_space_read_1(iot, ioh, ioreg); 439 hwaddr[5] = bus_space_read_1(iot, ioh, ioreg); 440 cksum *= 2; 441 if (cksum > 65535) cksum -= 65535; 442 cksum += *(u_short *) &hwaddr[4]; 443 if (cksum >= 65535) cksum -= 65535; 444 445 /* 00-00-00 is an illegal OUI */ 446 if (hwaddr[0] == 0 && hwaddr[1] == 0 && hwaddr[2] == 0) 447 return -1; 448 449 rom_cksum = bus_space_read_1(iot, ioh, ioreg); 450 rom_cksum |= bus_space_read_1(iot, ioh, ioreg) << 8; 451 452 if (cksum != rom_cksum) 453 return -1; 454 return 0; 455 } 456 457 static void 458 lemac_multicast_op( 459 u_int16_t *mctbl, 460 const u_char *mca, 461 int enable) 462 { 463 u_int idx, bit, crc = 0xFFFFFFFFUL; 464 static const u_int crctab[] = { 465 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 466 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 467 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 468 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 469 }; 470 471 for (idx = 0; idx < 6; idx++) { 472 crc ^= *mca++; 473 crc = (crc >> 4) ^ crctab[crc & 0xf]; 474 crc = (crc >> 4) ^ crctab[crc & 0xf]; 475 } 476 /* 477 * The following two lines convert the N bit index into a longword index 478 * and a longword mask. 479 */ 480 #if LEMAC_MCTBL_BITS < 0 481 crc >>= (32 + LEMAC_MCTBL_BITS); 482 crc &= (1 << -LEMAC_MCTBL_BITS) - 1; 483 #else 484 crc &= (1 << LEMAC_MCTBL_BITS) - 1; 485 #endif 486 bit = 1 << (crc & 0x0F); 487 idx = crc >> 4; 488 489 /* 490 * Set or clear hash filter bit in our table. 491 */ 492 if (enable) { 493 mctbl[idx] |= bit; /* Set Bit */ 494 } else { 495 mctbl[idx] &= ~bit; /* Clear Bit */ 496 } 497 } 498 499 static void 500 lemac_multicast_filter( 501 lemac_softc_t *sc) 502 { 503 struct ether_multistep step; 504 struct ether_multi *enm; 505 506 bzero(sc->sc_mctbl, LEMAC_MCTBL_BITS / 8); 507 508 lemac_multicast_op(sc->sc_mctbl, etherbroadcastaddr, TRUE); 509 510 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm); 511 while (enm != NULL) { 512 if (!LEMAC_ADDREQUAL(enm->enm_addrlo, enm->enm_addrhi)) { 513 sc->sc_flags |= LEMAC_ALLMULTI; 514 sc->sc_if.if_flags |= IFF_ALLMULTI; 515 return; 516 } 517 lemac_multicast_op(sc->sc_mctbl, enm->enm_addrlo, TRUE); 518 ETHER_NEXT_MULTI(step, enm); 519 } 520 sc->sc_flags &= ~LEMAC_ALLMULTI; 521 sc->sc_if.if_flags &= ~IFF_ALLMULTI; 522 } 523 524 /* 525 * Do a hard reset of the board; 526 */ 527 static void 528 lemac_reset( 529 lemac_softc_t * const sc) 530 { 531 unsigned data; 532 533 /* 534 * Initialize board.. 535 */ 536 sc->sc_flags &= ~LEMAC_LINKUP; 537 sc->sc_if.if_flags &= ~IFF_OACTIVE; 538 LEMAC_INTR_DISABLE(sc); 539 540 LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEINIT); 541 DELAY(LEMAC_EEP_DELAY); 542 543 /* 544 * Read EEPROM information. NOTE - the placement of this function 545 * is important because functions hereafter may rely on information 546 * read from the EEPROM. 547 */ 548 if ((data = lemac_read_eeprom(sc)) != LEMAC_EEP_CKSUM) { 549 printf("%s: reset: EEPROM checksum failed (0x%x)\n", 550 sc->sc_if.if_xname, data); 551 return; 552 } 553 554 /* 555 * Update the control register to reflect the media choice 556 */ 557 data = LEMAC_INB(sc, LEMAC_REG_CTL); 558 if ((data & (LEMAC_CTL_APD|LEMAC_CTL_PSL)) != sc->sc_ctlmode) { 559 data &= ~(LEMAC_CTL_APD|LEMAC_CTL_PSL); 560 data |= sc->sc_ctlmode; 561 LEMAC_OUTB(sc, LEMAC_REG_CTL, data); 562 } 563 564 /* 565 * Force to 2K mode if not already configured. 566 */ 567 568 data = LEMAC_INB(sc, LEMAC_REG_MBR); 569 if (LEMAC_IS_2K_MODE(data)) { 570 sc->sc_flags |= LEMAC_2K_MODE; 571 } else if (LEMAC_IS_64K_MODE(data)) { 572 data = (((data * 2) & 0xF) << 4); 573 sc->sc_flags |= LEMAC_WAS_64K_MODE; 574 LEMAC_OUTB(sc, LEMAC_REG_MBR, data); 575 } else if (LEMAC_IS_32K_MODE(data)) { 576 data = ((data & 0xF) << 4); 577 sc->sc_flags |= LEMAC_WAS_32K_MODE; 578 LEMAC_OUTB(sc, LEMAC_REG_MBR, data); 579 } else { 580 sc->sc_flags |= LEMAC_PIO_MODE; 581 /* PIO mode */ 582 } 583 584 /* 585 * Initialize Free Memory Queue, Init mcast table with broadcast. 586 */ 587 588 lemac_init_adapmem(sc); 589 sc->sc_flags |= LEMAC_ALIVE; 590 } 591 592 static void 593 lemac_init( 594 lemac_softc_t * const sc) 595 { 596 if ((sc->sc_flags & LEMAC_ALIVE) == 0) 597 return; 598 599 /* 600 * If the interface has the up flag 601 */ 602 if (sc->sc_if.if_flags & IFF_UP) { 603 int saved_cs = LEMAC_INB(sc, LEMAC_REG_CS); 604 LEMAC_OUTB(sc, LEMAC_REG_CS, saved_cs | (LEMAC_CS_TXD | LEMAC_CS_RXD)); 605 LEMAC_OUTB(sc, LEMAC_REG_PA0, sc->sc_enaddr[0]); 606 LEMAC_OUTB(sc, LEMAC_REG_PA1, sc->sc_enaddr[1]); 607 LEMAC_OUTB(sc, LEMAC_REG_PA2, sc->sc_enaddr[2]); 608 LEMAC_OUTB(sc, LEMAC_REG_PA3, sc->sc_enaddr[3]); 609 LEMAC_OUTB(sc, LEMAC_REG_PA4, sc->sc_enaddr[4]); 610 LEMAC_OUTB(sc, LEMAC_REG_PA5, sc->sc_enaddr[5]); 611 612 LEMAC_OUTB(sc, LEMAC_REG_IC, LEMAC_INB(sc, LEMAC_REG_IC) | LEMAC_IC_IE); 613 614 if (sc->sc_if.if_flags & IFF_PROMISC) { 615 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE | LEMAC_CS_PME); 616 } else { 617 LEMAC_INTR_DISABLE(sc); 618 lemac_multicast_filter(sc); 619 if (sc->sc_flags & LEMAC_ALLMULTI) 620 bcopy(lemac_allmulti_mctbl, sc->sc_mctbl, sizeof(sc->sc_mctbl)); 621 if (LEMAC_USE_PIO_MODE(sc)) { 622 LEMAC_OUTB(sc, LEMAC_REG_IOP, 0); 623 LEMAC_OUTB(sc, LEMAC_REG_PI1, LEMAC_MCTBL_OFF & 0xFF); 624 LEMAC_OUTB(sc, LEMAC_REG_PI2, LEMAC_MCTBL_OFF >> 8); 625 LEMAC_OUTSB(sc, LEMAC_REG_DAT, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl); 626 } else { 627 LEMAC_OUTB(sc, LEMAC_REG_MPN, 0); 628 LEMAC_PUTBUF8(sc, LEMAC_MCTBL_OFF, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl); 629 } 630 631 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE); 632 } 633 634 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED); 635 636 LEMAC_INTR_ENABLE(sc); 637 sc->sc_if.if_flags |= IFF_RUNNING; 638 lemac_ifstart(&sc->sc_if); 639 } else { 640 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_RXD|LEMAC_CS_TXD); 641 642 LEMAC_INTR_DISABLE(sc); 643 sc->sc_if.if_flags &= ~IFF_RUNNING; 644 } 645 } 646 647 static void 648 lemac_ifstart( 649 struct ifnet *ifp) 650 { 651 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 652 struct ifqueue * const ifq = &ifp->if_snd; 653 654 if ((ifp->if_flags & IFF_RUNNING) == 0) 655 return; 656 657 LEMAC_INTR_DISABLE(sc); 658 659 while (ifq->ifq_head != NULL) { 660 struct mbuf *m; 661 struct mbuf *m0; 662 int tx_pg; 663 664 if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC)) >= lemac_txmax) { 665 sc->sc_cntrs.cntr_txfull++; 666 ifp->if_flags |= IFF_OACTIVE; 667 break; 668 } 669 670 /* 671 * get free memory page 672 */ 673 tx_pg = sc->sc_csr.csr_fmq = LEMAC_INB(sc, LEMAC_REG_FMQ); 674 /* 675 * Check for good transmit page. 676 */ 677 if (tx_pg == 0 || tx_pg > sc->sc_lastpage) { 678 sc->sc_cntrs.cntr_txnospc++; 679 ifp->if_flags |= IFF_OACTIVE; 680 break; 681 } 682 683 IF_DEQUEUE(ifq, m); 684 685 /* 686 * The first four bytes of each transmit buffer are for 687 * control information. The first byte is the control 688 * byte, then the length (why not word aligned??), then 689 * the offset to the buffer. 690 */ 691 692 if (LEMAC_USE_PIO_MODE(sc)) { 693 LEMAC_OUTB(sc, LEMAC_REG_IOP, tx_pg); /* Shift 2K window. */ 694 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0); 695 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0); 696 LEMAC_OUTB(sc, LEMAC_REG_DAT, sc->sc_txctl); 697 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 0) & 0xFF); 698 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 8) & 0xFF); 699 LEMAC_OUTB(sc, LEMAC_REG_DAT, LEMAC_TX_HDRSZ); 700 for (m0 = m; m0 != NULL; m0 = m0->m_next) 701 LEMAC_OUTSB(sc, LEMAC_REG_DAT, m0->m_len, m0->m_data); 702 } else { 703 bus_size_t txoff = /* (mtod(m, u_int32_t) & (sizeof(u_int32_t) - 1)) + */ LEMAC_TX_HDRSZ; 704 LEMAC_OUTB(sc, LEMAC_REG_MPN, tx_pg); /* Shift 2K window. */ 705 LEMAC_PUT8(sc, 0, sc->sc_txctl); 706 LEMAC_PUT8(sc, 1, (m->m_pkthdr.len >> 0) & 0xFF); 707 LEMAC_PUT8(sc, 2, (m->m_pkthdr.len >> 8) & 0xFF); 708 LEMAC_PUT8(sc, 3, txoff); 709 710 /* 711 * Copy the packet to the board 712 */ 713 for (m0 = m; m0 != NULL; m0 = m0->m_next) { 714 #if 0 715 LEMAC_PUTBUF8(sc, txoff, m0->m_len, m0->m_data); 716 txoff += m0->m_len; 717 #else 718 const u_int8_t *cp = m0->m_data; 719 int len = m0->m_len; 720 #if 0 721 if ((txoff & 3) == (((long)cp) & 3) && len >= 4) { 722 if (txoff & 3) { 723 int alen = (~txoff & 3); 724 LEMAC_PUTBUF8(sc, txoff, alen, cp); 725 cp += alen; txoff += alen; len -= alen; 726 } 727 if (len >= 4) { 728 LEMAC_PUTBUF32(sc, txoff, len / 4, cp); 729 cp += len & ~3; txoff += len & ~3; len &= 3; 730 } 731 } 732 #endif 733 if ((txoff & 1) == (((long)cp) & 1) && len >= 2) { 734 if (txoff & 1) { 735 int alen = (~txoff & 1); 736 LEMAC_PUTBUF8(sc, txoff, alen, cp); 737 cp += alen; txoff += alen; len -= alen; 738 } 739 if (len >= 2) { 740 LEMAC_PUTBUF16(sc, txoff, len / 2, (void *) cp); 741 cp += len & ~1; txoff += len & ~1; len &= 1; 742 } 743 } 744 if (len > 0) { 745 LEMAC_PUTBUF8(sc, txoff, len, cp); 746 txoff += len; 747 } 748 #endif 749 } 750 } 751 752 LEMAC_OUTB(sc, LEMAC_REG_TQ, tx_pg); /* tell chip to transmit this packet */ 753 #if NBPFILTER > 0 754 if (sc->sc_if.if_bpf != NULL) 755 bpf_mtap(sc->sc_if.if_bpf, m); 756 #endif 757 m_freem(m); /* free the mbuf */ 758 } 759 LEMAC_INTR_ENABLE(sc); 760 } 761 762 static int 763 lemac_ifioctl( 764 struct ifnet *ifp, 765 u_long cmd, 766 caddr_t data) 767 { 768 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 769 int s; 770 int error = 0; 771 772 s = splnet(); 773 774 switch (cmd) { 775 case SIOCSIFADDR: { 776 struct ifaddr *ifa = (struct ifaddr *)data; 777 778 ifp->if_flags |= IFF_UP; 779 lemac_init(sc); 780 switch (ifa->ifa_addr->sa_family) { 781 #ifdef INET 782 case AF_INET: { 783 arp_ifinit(&sc->sc_if, ifa); 784 break; 785 } 786 #endif /* INET */ 787 788 #ifdef NS 789 /* This magic copied from if_is.c; I don't use XNS, 790 * so I have no way of telling if this actually 791 * works or not. 792 */ 793 case AF_NS: { 794 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 795 if (ns_nullhost(*ina)) { 796 ina->x_host = *(union ns_host *)sc->sc_enaddr; 797 } else { 798 bcopy((caddr_t)ina->x_host.c_host, sc->sc_enaddr, 799 ifp->if_addrlen); 800 } 801 break; 802 } 803 #endif /* NS */ 804 805 default: { 806 break; 807 } 808 } 809 break; 810 } 811 812 case SIOCSIFFLAGS: { 813 lemac_init(sc); 814 break; 815 } 816 817 case SIOCADDMULTI: 818 case SIOCDELMULTI: { 819 /* 820 * Update multicast listeners 821 */ 822 if (cmd == SIOCADDMULTI) 823 error = ether_addmulti((struct ifreq *)data, &sc->sc_ec); 824 else 825 error = ether_delmulti((struct ifreq *)data, &sc->sc_ec); 826 827 if (error == ENETRESET) { 828 829 /* reset multicast filtering */ 830 lemac_init(sc); 831 error = 0; 832 } 833 break; 834 } 835 836 case SIOCSIFMEDIA: 837 case SIOCGIFMEDIA: { 838 error = ifmedia_ioctl(ifp, (struct ifreq *)data, 839 &sc->sc_ifmedia, cmd); 840 break; 841 } 842 843 default: { 844 error = EINVAL; 845 break; 846 } 847 } 848 849 splx(s); 850 return error; 851 } 852 853 static int 854 lemac_ifmedia_change( 855 struct ifnet * const ifp) 856 { 857 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 858 unsigned new_ctl; 859 860 switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) { 861 case IFM_10_T: new_ctl = LEMAC_CTL_APD; break; 862 case IFM_10_2: 863 case IFM_10_5: new_ctl = LEMAC_CTL_APD|LEMAC_CTL_PSL; break; 864 case IFM_AUTO: new_ctl = 0; break; 865 default: return EINVAL; 866 } 867 if (sc->sc_ctlmode != new_ctl) { 868 sc->sc_ctlmode = new_ctl; 869 lemac_reset(sc); 870 if (sc->sc_if.if_flags & IFF_UP) 871 lemac_init(sc); 872 } 873 return 0; 874 } 875 876 /* 877 * Media status callback 878 */ 879 static void 880 lemac_ifmedia_status( 881 struct ifnet * const ifp, 882 struct ifmediareq *req) 883 { 884 lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp); 885 unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF); 886 887 req->ifm_status = IFM_AVALID; 888 if (sc->sc_flags & LEMAC_LINKUP) 889 req->ifm_status |= IFM_ACTIVE; 890 891 if (sc->sc_ctlmode & LEMAC_CTL_APD) { 892 if (sc->sc_ctlmode & LEMAC_CTL_PSL) { 893 req->ifm_active = IFM_10_5; 894 } else { 895 req->ifm_active = IFM_10_T; 896 } 897 } else { 898 /* 899 * The link bit of the configuration register reflects the 900 * current media choice when auto-port is enabled. 901 */ 902 if (data & LEMAC_CNF_NOLINK) { 903 req->ifm_active = IFM_10_5; 904 } else { 905 req->ifm_active = IFM_10_T; 906 } 907 } 908 909 req->ifm_active |= IFM_ETHER; 910 } 911 912 int 913 lemac_port_check( 914 const bus_space_tag_t iot, 915 const bus_space_handle_t ioh) 916 { 917 unsigned char hwaddr[6]; 918 919 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0) 920 return 1; 921 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0) 922 return 1; 923 return 0; 924 } 925 926 void 927 lemac_info_get( 928 const bus_space_tag_t iot, 929 const bus_space_handle_t ioh, 930 bus_addr_t *maddr_p, 931 bus_size_t *msize_p, 932 int *irq_p) 933 { 934 unsigned data; 935 936 *irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC) & LEMAC_IC_IRQMSK); 937 938 data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR); 939 if (LEMAC_IS_2K_MODE(data)) { 940 *maddr_p = data * (2 * 1024) + (512 * 1024); 941 *msize_p = 2 * 1024; 942 } else if (LEMAC_IS_64K_MODE(data)) { 943 *maddr_p = data * 64 * 1024; 944 *msize_p = 64 * 1024; 945 } else if (LEMAC_IS_32K_MODE(data)) { 946 *maddr_p = data * 32 * 1024; 947 *msize_p = 32* 1024; 948 } else { 949 *maddr_p = 0; 950 *msize_p = 0; 951 } 952 } 953 954 /* 955 * What to do upon receipt of an interrupt. 956 */ 957 int 958 lemac_intr( 959 void *arg) 960 { 961 lemac_softc_t * const sc = arg; 962 int cs_value; 963 964 LEMAC_INTR_DISABLE(sc); /* Mask interrupts */ 965 966 /* 967 * Determine cause of interrupt. Receive events take 968 * priority over Transmit. 969 */ 970 971 cs_value = LEMAC_INB(sc, LEMAC_REG_CS); 972 973 /* 974 * Check for Receive Queue not being empty. 975 * Check for Transmit Done Queue not being empty. 976 */ 977 978 if (cs_value & LEMAC_CS_RNE) 979 lemac_rne_intr(sc); 980 if (cs_value & LEMAC_CS_TNE) 981 lemac_tne_intr(sc); 982 983 /* 984 * Check for Transmitter Disabled. 985 * Check for Receiver Disabled. 986 */ 987 988 if (cs_value & LEMAC_CS_TXD) 989 lemac_txd_intr(sc, cs_value); 990 if (cs_value & LEMAC_CS_RXD) 991 lemac_rxd_intr(sc, cs_value); 992 993 /* 994 * Toggle LED and unmask interrupts. 995 */ 996 997 sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS); 998 999 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED); 1000 LEMAC_INTR_ENABLE(sc); /* Unmask interrupts */ 1001 1002 #if NRND > 0 1003 if (cs_value) 1004 rnd_add_uint32(&sc->rnd_source, cs_value); 1005 #endif 1006 1007 return 1; 1008 } 1009 1010 void 1011 lemac_shutdown( 1012 void *arg) 1013 { 1014 lemac_reset((lemac_softc_t *) arg); 1015 } 1016 1017 static const char * const lemac_modes[4] = { 1018 "PIO mode (internal 2KB window)", 1019 "2KB window", 1020 "changed 32KB window to 2KB", 1021 "changed 64KB window to 2KB", 1022 }; 1023 1024 void 1025 lemac_ifattach( 1026 lemac_softc_t *sc) 1027 { 1028 struct ifnet * const ifp = &sc->sc_if; 1029 1030 bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ); 1031 1032 lemac_reset(sc); 1033 1034 (void) lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh, 1035 LEMAC_REG_APD, 0); 1036 1037 printf(": %s\n", sc->sc_prodname); 1038 1039 printf("%s: address %s, %dKB RAM, %s\n", 1040 ifp->if_xname, 1041 ether_sprintf(sc->sc_enaddr), 1042 sc->sc_lastpage * 2 + 2, 1043 lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]); 1044 1045 ifp->if_baudrate = 10000000; 1046 ifp->if_softc = (void *) sc; 1047 ifp->if_start = lemac_ifstart; 1048 ifp->if_output = ether_output; 1049 ifp->if_ioctl = lemac_ifioctl; 1050 1051 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX 1052 #ifdef IFF_NOTRAILERS 1053 | IFF_NOTRAILERS 1054 #endif 1055 | IFF_MULTICAST; 1056 1057 if (sc->sc_flags & LEMAC_ALIVE) { 1058 int media; 1059 1060 if_attach(ifp); 1061 ether_ifattach(ifp, sc->sc_enaddr); 1062 1063 #if NBPFILTER > 0 1064 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 1065 #endif 1066 1067 #if NRND > 0 1068 rnd_attach_source(&sc->rnd_source, sc->sc_dv.dv_xname, RND_TYPE_NET); 1069 #endif 1070 1071 ifmedia_init(&sc->sc_ifmedia, 0, 1072 lemac_ifmedia_change, 1073 lemac_ifmedia_status); 1074 if (sc->sc_prodname[4] == '5') /* DE205 is UTP/AUI */ 1075 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); 1076 if (sc->sc_prodname[4] != '3') /* DE204 & 205 have UTP */ 1077 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, 0); 1078 if (sc->sc_prodname[4] != '4') /* DE203 & 205 have BNC */ 1079 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, 0); 1080 switch (sc->sc_prodname[4]) { 1081 case '3': media = IFM_10_5; break; 1082 case '4': media = IFM_10_T; break; 1083 default: media = IFM_AUTO; break; 1084 } 1085 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media); 1086 } else { 1087 printf("%s: disabled due to error\n", ifp->if_xname); 1088 } 1089 } 1090