1 /* $NetBSD: lemac.c,v 1.34 2007/10/19 11:59:55 ad 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.34 2007/10/19 11:59:55 ad 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 SIOCSIFADDR: { 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 lemac_init(sc); 783 break; 784 } 785 786 case SIOCADDMULTI: 787 case SIOCDELMULTI: { 788 /* 789 * Update multicast listeners 790 */ 791 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 792 /* reset multicast filtering */ 793 if (ifp->if_flags & IFF_RUNNING) 794 lemac_init(sc); 795 error = 0; 796 } 797 break; 798 } 799 800 case SIOCSIFMEDIA: 801 case SIOCGIFMEDIA: { 802 error = ifmedia_ioctl(ifp, (struct ifreq *)data, 803 &sc->sc_ifmedia, cmd); 804 break; 805 } 806 807 default: { 808 error = EINVAL; 809 break; 810 } 811 } 812 813 splx(s); 814 return error; 815 } 816 817 static int 818 lemac_ifmedia_change( 819 struct ifnet * const ifp) 820 { 821 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp); 822 unsigned new_ctl; 823 824 switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) { 825 case IFM_10_T: new_ctl = LEMAC_CTL_APD; break; 826 case IFM_10_2: 827 case IFM_10_5: new_ctl = LEMAC_CTL_APD|LEMAC_CTL_PSL; break; 828 case IFM_AUTO: new_ctl = 0; break; 829 default: return EINVAL; 830 } 831 if (sc->sc_ctlmode != new_ctl) { 832 sc->sc_ctlmode = new_ctl; 833 lemac_reset(sc); 834 if (sc->sc_if.if_flags & IFF_UP) 835 lemac_init(sc); 836 } 837 return 0; 838 } 839 840 /* 841 * Media status callback 842 */ 843 static void 844 lemac_ifmedia_status( 845 struct ifnet * const ifp, 846 struct ifmediareq *req) 847 { 848 lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp); 849 unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF); 850 851 req->ifm_status = IFM_AVALID; 852 if (sc->sc_flags & LEMAC_LINKUP) 853 req->ifm_status |= IFM_ACTIVE; 854 855 if (sc->sc_ctlmode & LEMAC_CTL_APD) { 856 if (sc->sc_ctlmode & LEMAC_CTL_PSL) { 857 req->ifm_active = IFM_10_5; 858 } else { 859 req->ifm_active = IFM_10_T; 860 } 861 } else { 862 /* 863 * The link bit of the configuration register reflects the 864 * current media choice when auto-port is enabled. 865 */ 866 if (data & LEMAC_CNF_NOLINK) { 867 req->ifm_active = IFM_10_5; 868 } else { 869 req->ifm_active = IFM_10_T; 870 } 871 } 872 873 req->ifm_active |= IFM_ETHER; 874 } 875 876 int 877 lemac_port_check( 878 const bus_space_tag_t iot, 879 const bus_space_handle_t ioh) 880 { 881 unsigned char hwaddr[6]; 882 883 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0) 884 return 1; 885 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0) 886 return 1; 887 return 0; 888 } 889 890 void 891 lemac_info_get( 892 const bus_space_tag_t iot, 893 const bus_space_handle_t ioh, 894 bus_addr_t *maddr_p, 895 bus_size_t *msize_p, 896 int *irq_p) 897 { 898 unsigned data; 899 900 *irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC) & LEMAC_IC_IRQMSK); 901 902 data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR); 903 if (LEMAC_IS_2K_MODE(data)) { 904 *maddr_p = data * (2 * 1024) + (512 * 1024); 905 *msize_p = 2 * 1024; 906 } else if (LEMAC_IS_64K_MODE(data)) { 907 *maddr_p = data * 64 * 1024; 908 *msize_p = 64 * 1024; 909 } else if (LEMAC_IS_32K_MODE(data)) { 910 *maddr_p = data * 32 * 1024; 911 *msize_p = 32* 1024; 912 } else { 913 *maddr_p = 0; 914 *msize_p = 0; 915 } 916 } 917 918 /* 919 * What to do upon receipt of an interrupt. 920 */ 921 int 922 lemac_intr( 923 void *arg) 924 { 925 lemac_softc_t * const sc = arg; 926 int cs_value; 927 928 LEMAC_INTR_DISABLE(sc); /* Mask interrupts */ 929 930 /* 931 * Determine cause of interrupt. Receive events take 932 * priority over Transmit. 933 */ 934 935 cs_value = LEMAC_INB(sc, LEMAC_REG_CS); 936 937 /* 938 * Check for Receive Queue not being empty. 939 * Check for Transmit Done Queue not being empty. 940 */ 941 942 if (cs_value & LEMAC_CS_RNE) 943 lemac_rne_intr(sc); 944 if (cs_value & LEMAC_CS_TNE) 945 lemac_tne_intr(sc); 946 947 /* 948 * Check for Transmitter Disabled. 949 * Check for Receiver Disabled. 950 */ 951 952 if (cs_value & LEMAC_CS_TXD) 953 lemac_txd_intr(sc, cs_value); 954 if (cs_value & LEMAC_CS_RXD) 955 lemac_rxd_intr(sc, cs_value); 956 957 /* 958 * Toggle LED and unmask interrupts. 959 */ 960 961 sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS); 962 963 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED); 964 LEMAC_INTR_ENABLE(sc); /* Unmask interrupts */ 965 966 #if NRND > 0 967 if (cs_value) 968 rnd_add_uint32(&sc->rnd_source, cs_value); 969 #endif 970 971 return 1; 972 } 973 974 void 975 lemac_shutdown( 976 void *arg) 977 { 978 lemac_reset((lemac_softc_t *) arg); 979 } 980 981 static const char * const lemac_modes[4] = { 982 "PIO mode (internal 2KB window)", 983 "2KB window", 984 "changed 32KB window to 2KB", 985 "changed 64KB window to 2KB", 986 }; 987 988 void 989 lemac_ifattach( 990 lemac_softc_t *sc) 991 { 992 struct ifnet * const ifp = &sc->sc_if; 993 994 strcpy(ifp->if_xname, sc->sc_dv.dv_xname); 995 996 lemac_reset(sc); 997 998 (void) lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh, 999 LEMAC_REG_APD, 0); 1000 1001 printf(": %s\n", sc->sc_prodname); 1002 1003 printf("%s: address %s, %dKB RAM, %s\n", 1004 ifp->if_xname, 1005 ether_sprintf(sc->sc_enaddr), 1006 sc->sc_lastpage * 2 + 2, 1007 lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]); 1008 1009 ifp->if_softc = (void *) sc; 1010 ifp->if_start = lemac_ifstart; 1011 ifp->if_ioctl = lemac_ifioctl; 1012 1013 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX 1014 #ifdef IFF_NOTRAILERS 1015 | IFF_NOTRAILERS 1016 #endif 1017 | IFF_MULTICAST; 1018 1019 if (sc->sc_flags & LEMAC_ALIVE) { 1020 int media; 1021 1022 IFQ_SET_READY(&ifp->if_snd); 1023 1024 if_attach(ifp); 1025 ether_ifattach(ifp, sc->sc_enaddr); 1026 1027 #if NRND > 0 1028 rnd_attach_source(&sc->rnd_source, sc->sc_dv.dv_xname, 1029 RND_TYPE_NET, 0); 1030 #endif 1031 1032 ifmedia_init(&sc->sc_ifmedia, 0, 1033 lemac_ifmedia_change, 1034 lemac_ifmedia_status); 1035 if (sc->sc_prodname[4] == '5') /* DE205 is UTP/AUI */ 1036 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); 1037 if (sc->sc_prodname[4] != '3') /* DE204 & 205 have UTP */ 1038 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, 0); 1039 if (sc->sc_prodname[4] != '4') /* DE203 & 205 have BNC */ 1040 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, 0); 1041 switch (sc->sc_prodname[4]) { 1042 case '3': media = IFM_10_5; break; 1043 case '4': media = IFM_10_T; break; 1044 default: media = IFM_AUTO; break; 1045 } 1046 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media); 1047 } else { 1048 printf("%s: disabled due to error\n", ifp->if_xname); 1049 } 1050 } 1051