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