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