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