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