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