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