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