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