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