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