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