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