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