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