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