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