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