1 /* $NetBSD: if_iy.c,v 1.113 2020/01/29 06:21:40 thorpej Exp $ */ 2 /* #define IYDEBUG */ 3 /* #define IYMEMDEBUG */ 4 5 /*- 6 * Copyright (c) 1996,2001 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Ignatios Souvatzis. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Supported hardware: 36 * 37 * - Intel EtherExpress Pro/10. 38 * - possibly other boards using the i82595 chip and no special tweaks. 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: if_iy.c,v 1.113 2020/01/29 06:21:40 thorpej Exp $"); 43 44 #include "opt_inet.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/mbuf.h> 49 #include <sys/buf.h> 50 #include <sys/protosw.h> 51 #include <sys/socket.h> 52 #include <sys/ioctl.h> 53 #include <sys/errno.h> 54 #include <sys/syslog.h> 55 #include <sys/device.h> 56 #include <sys/endian.h> 57 #include <sys/rndsource.h> 58 59 #include <net/if.h> 60 #include <net/if_types.h> 61 #include <net/if_dl.h> 62 #include <net/bpf.h> 63 #include <net/if_ether.h> 64 #include <net/if_media.h> 65 66 #ifdef INET 67 #include <netinet/in.h> 68 #include <netinet/in_systm.h> 69 #include <netinet/in_var.h> 70 #include <netinet/ip.h> 71 #include <netinet/if_inarp.h> 72 #endif 73 74 75 #include <sys/cpu.h> 76 #include <sys/bus.h> 77 #include <sys/intr.h> 78 79 #include <dev/isa/isareg.h> 80 #include <dev/isa/isavar.h> 81 #include <dev/ic/i82595reg.h> 82 83 /* XXX why isn't this centralized? */ 84 #ifndef __BUS_SPACE_HAS_STREAM_METHODS 85 #define bus_space_write_stream_2 bus_space_write_2 86 #define bus_space_write_multi_stream_2 bus_space_write_multi_2 87 #define bus_space_read_stream_2 bus_space_read_2 88 #define bus_space_read_multi_stream_2 bus_space_read_multi_2 89 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */ 90 91 /* 92 * Ethernet status, per interface. 93 */ 94 struct iy_softc { 95 device_t sc_dev; 96 void *sc_ih; 97 98 bus_space_tag_t sc_iot; 99 bus_space_handle_t sc_ioh; 100 101 struct ethercom sc_ethercom; 102 103 struct ifmedia iy_ifmedia; 104 int iy_media; 105 106 int mappedirq; 107 108 int hard_vers; 109 110 u_short promisc; 111 112 int sram, tx_size, rx_size; 113 114 int tx_start, tx_end, tx_last; 115 int rx_start; 116 117 int doing_mc_setup; 118 #ifdef IYDEBUG 119 int sc_debug; 120 #endif 121 122 krndsource_t rnd_source; 123 }; 124 125 void iywatchdog(struct ifnet *); 126 int iyioctl(struct ifnet *, u_long, void *); 127 int iyintr(void *); 128 void iyinit(struct iy_softc *); 129 void iystop(struct iy_softc *); 130 void iystart(struct ifnet *); 131 132 void iy_intr_rx(struct iy_softc *); 133 void iy_intr_tx(struct iy_softc *); 134 135 void iyreset(struct iy_softc *); 136 void iy_readframe(struct iy_softc *, int); 137 void iy_drop_packet_buffer(struct iy_softc *); 138 void iy_find_mem_size(struct iy_softc *); 139 void iyrint(struct iy_softc *); 140 void iytint(struct iy_softc *); 141 void iyxmit(struct iy_softc *); 142 static void iy_mc_setup(struct iy_softc *); 143 static void iy_mc_reset(struct iy_softc *); 144 void iyget(struct iy_softc *, bus_space_tag_t, bus_space_handle_t, int); 145 void iyprobemem(struct iy_softc *); 146 static inline void eepromwritebit(bus_space_tag_t, bus_space_handle_t, int); 147 static inline int eepromreadbit(bus_space_tag_t, bus_space_handle_t); 148 149 #ifdef IYDEBUGX 150 void print_rbd(volatile struct iy_recv_buf_desc *); 151 152 int in_ifrint = 0; 153 int in_iftint = 0; 154 #endif 155 156 int iy_mediachange(struct ifnet *); 157 void iy_mediastatus(struct ifnet *, struct ifmediareq *); 158 159 int iyprobe(device_t, cfdata_t, void *); 160 void iyattach(device_t, device_t, void *); 161 162 static uint16_t eepromread(bus_space_tag_t, bus_space_handle_t, int); 163 164 static int eepromreadall(bus_space_tag_t, bus_space_handle_t, uint16_t *, 165 int); 166 167 CFATTACH_DECL_NEW(iy, sizeof(struct iy_softc), 168 iyprobe, iyattach, NULL, NULL); 169 170 static uint8_t eepro_irqmap[] = EEPP_INTMAP; 171 static uint8_t eepro_revirqmap[] = EEPP_RINTMAP; 172 173 int 174 iyprobe(device_t parent, cfdata_t match, void *aux) 175 { 176 struct isa_attach_args *ia = aux; 177 uint16_t eaddr[8]; 178 bus_space_tag_t iot; 179 bus_space_handle_t ioh; 180 uint8_t c, d; 181 int irq; 182 183 if (ia->ia_nio < 1) 184 return 0; 185 if (ia->ia_nirq < 1) 186 return 0; 187 188 if (ISA_DIRECT_CONFIG(ia)) 189 return 0; 190 191 iot = ia->ia_iot; 192 193 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 194 return 0; 195 196 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) 197 return 0; 198 199 /* try to find the round robin sig: */ 200 201 c = bus_space_read_1(iot, ioh, ID_REG); 202 if ((c & ID_REG_MASK) != ID_REG_SIG) 203 goto out; 204 205 d = bus_space_read_1(iot, ioh, ID_REG); 206 if ((d & ID_REG_MASK) != ID_REG_SIG) 207 goto out; 208 209 if (((d-c) & R_ROBIN_BITS) != 0x40) 210 goto out; 211 212 d = bus_space_read_1(iot, ioh, ID_REG); 213 if ((d & ID_REG_MASK) != ID_REG_SIG) 214 goto out; 215 216 if (((d-c) & R_ROBIN_BITS) != 0x80) 217 goto out; 218 219 d = bus_space_read_1(iot, ioh, ID_REG); 220 if ((d & ID_REG_MASK) != ID_REG_SIG) 221 goto out; 222 223 if (((d-c) & R_ROBIN_BITS) != 0xC0) 224 goto out; 225 226 d = bus_space_read_1(iot, ioh, ID_REG); 227 if ((d & ID_REG_MASK) != ID_REG_SIG) 228 goto out; 229 230 if (((d-c) & R_ROBIN_BITS) != 0x00) 231 goto out; 232 233 #ifdef IYDEBUG 234 printf("iyprobe verified working ID reg.\n"); 235 #endif 236 237 if (eepromreadall(iot, ioh, eaddr, 8)) 238 goto out; 239 240 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 241 irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int]; 242 else 243 irq = ia->ia_irq[0].ir_irq; 244 245 if (irq >= sizeof(eepro_revirqmap)) 246 goto out; 247 248 if (eepro_revirqmap[irq] == 0xff) 249 goto out; 250 251 /* now lets reset the chip */ 252 253 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 254 delay(200); 255 256 ia->ia_nio = 1; 257 ia->ia_io[0].ir_size = 16; 258 259 ia->ia_nirq = 1; 260 ia->ia_irq[0].ir_irq = irq; 261 262 ia->ia_niomem = 0; 263 ia->ia_ndrq = 0; 264 265 bus_space_unmap(iot, ioh, 16); 266 return 1; /* found */ 267 out: 268 bus_space_unmap(iot, ioh, 16); 269 return 0; 270 } 271 272 void 273 iyattach(device_t parent, device_t self, void *aux) 274 { 275 struct iy_softc *sc = device_private(self); 276 struct isa_attach_args *ia = aux; 277 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 278 bus_space_tag_t iot; 279 bus_space_handle_t ioh; 280 unsigned temp; 281 uint16_t eaddr[8]; 282 uint8_t myaddr[ETHER_ADDR_LEN]; 283 int eirq; 284 285 sc->sc_dev = self; 286 iot = ia->ia_iot; 287 288 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) { 289 aprint_error(": can't map i/o space\n"); 290 return; 291 } 292 293 sc->sc_iot = iot; 294 sc->sc_ioh = ioh; 295 296 sc->mappedirq = eepro_revirqmap[ia->ia_irq[0].ir_irq]; 297 298 /* now let's reset the chip */ 299 300 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 301 delay(200); 302 303 iyprobemem(sc); 304 305 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 306 ifp->if_softc = sc; 307 ifp->if_start = iystart; 308 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 309 310 sc->doing_mc_setup = 0; 311 312 ifp->if_ioctl = iyioctl; 313 ifp->if_watchdog = iywatchdog; 314 315 IFQ_SET_READY(&ifp->if_snd); 316 317 (void)eepromreadall(iot, ioh, eaddr, 8); 318 sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev; 319 320 #ifdef DIAGNOSTICS 321 if ((eaddr[EEPPEther0] != 322 eepromread(iot, ioh, EEPPEther0a)) && 323 (eaddr[EEPPEther1] != 324 eepromread(iot, ioh, EEPPEther1a)) && 325 (eaddr[EEPPEther2] != 326 eepromread(iot, ioh, EEPPEther2a))) 327 328 aprint_error("EEPROM Ethernet address differs from copy\n"); 329 #endif 330 331 myaddr[1] = eaddr[EEPPEther0] & 0xFF; 332 myaddr[0] = eaddr[EEPPEther0] >> 8; 333 myaddr[3] = eaddr[EEPPEther1] & 0xFF; 334 myaddr[2] = eaddr[EEPPEther1] >> 8; 335 myaddr[5] = eaddr[EEPPEther2] & 0xFF; 336 myaddr[4] = eaddr[EEPPEther2] >> 8; 337 338 /* Initialize ifmedia structures. */ 339 sc->sc_ethercom.ec_ifmedia = &sc->iy_ifmedia; 340 ifmedia_init(&sc->iy_ifmedia, 0, iy_mediachange, iy_mediastatus); 341 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_2, 0, NULL); 342 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_5, 0, NULL); 343 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL); 344 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL); 345 ifmedia_set(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO); 346 /* Attach the interface. */ 347 if_attach(ifp); 348 ether_ifattach(ifp, myaddr); 349 aprint_normal(": address %s, rev. %d, %d kB\n", 350 ether_sprintf(myaddr), 351 sc->hard_vers, sc->sram/1024); 352 353 eirq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int]; 354 if (eirq != ia->ia_irq[0].ir_irq) 355 aprint_error("%s: EEPROM irq setting %d ignored\n", 356 device_xname(sc->sc_dev), eirq); 357 358 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 359 IST_EDGE, IPL_NET, iyintr, sc); 360 361 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 362 RND_TYPE_NET, RND_FLAG_DEFAULT); 363 364 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 365 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq); 366 } 367 368 void 369 iystop(struct iy_softc *sc) 370 { 371 bus_space_tag_t iot; 372 bus_space_handle_t ioh; 373 #ifdef IYDEBUG 374 u_int p, v; 375 #endif 376 377 iot = sc->sc_iot; 378 ioh = sc->sc_ioh; 379 380 bus_space_write_1(iot, ioh, COMMAND_REG, RCV_DISABLE_CMD); 381 382 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS); 383 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); 384 385 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 386 delay(200); 387 #ifdef IYDEBUG 388 printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n", 389 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, sc->tx_last); 390 p = sc->tx_last; 391 if (!p) 392 p = sc->tx_start; 393 do { 394 char sbuf[128]; 395 396 bus_space_write_2(iot, ioh, HOST_ADDR_REG, p); 397 398 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 399 snprintb(sbuf, sizeof(sbuf), "\020\006Ab\010Dn", v); 400 printf("0x%04x: %s ", p, sbuf); 401 402 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 403 snprintb(sbuf, sizeof(sbuf), 404 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN" 405 "\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL", v); 406 printf("%s", sbuf); 407 408 p = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 409 printf(" 0x%04x", p); 410 411 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 412 snprintb(sbuf, sizeof(sbuf), "\020\020Ch", v); 413 printf(" %s\n", sbuf); 414 415 } while (v & 0x8000); 416 #endif 417 sc->tx_start = sc->tx_end = sc->rx_size; 418 sc->tx_last = 0; 419 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 420 } 421 422 void 423 iyreset(struct iy_softc *sc) 424 { 425 int s; 426 s = splnet(); 427 iystop(sc); 428 iyinit(sc); 429 splx(s); 430 } 431 432 void 433 iyinit(struct iy_softc *sc) 434 { 435 int i; 436 unsigned temp; 437 struct ifnet *ifp; 438 bus_space_tag_t iot; 439 bus_space_handle_t ioh; 440 441 iot = sc->sc_iot; 442 ioh = sc->sc_ioh; 443 444 ifp = &sc->sc_ethercom.ec_if; 445 #ifdef IYDEBUG 446 printf("ifp is %p\n", ifp); 447 #endif 448 449 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 450 451 temp = bus_space_read_1(iot, ioh, EEPROM_REG); 452 if (temp & 0x10) 453 bus_space_write_1(iot, ioh, EEPROM_REG, temp & ~0x10); 454 455 for (i=0; i<6; ++i) { 456 bus_space_write_1(iot, ioh, I_ADD(i), CLLADDR(ifp->if_sadl)[i]); 457 } 458 459 temp = bus_space_read_1(iot, ioh, REG1); 460 bus_space_write_1(iot, ioh, REG1, 461 temp | /* XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | */ RCV_DISCARD_BAD); 462 463 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) 464 temp = MATCH_ALL; 465 else 466 temp = MATCH_BRDCST; 467 468 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 469 470 #ifdef IYDEBUG 471 { 472 char sbuf[128]; 473 474 snprintb(sbuf, sizeof(sbuf), 475 "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA", 476 temp); 477 478 printf("%s: RECV_MODES set to %s\n", device_xname(sc->sc_dev), 479 sbuf); 480 } 481 #endif 482 /* XXX VOODOO */ 483 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 484 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 485 /* XXX END OF VOODOO */ 486 487 488 delay(500000); /* for the hardware to test for the connector */ 489 490 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 491 #ifdef IYDEBUG 492 { 493 char sbuf[128]; 494 495 snprintb(sbuf, sizeof(sbuf), 496 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC", 497 temp); 498 printf("%s: media select was %s ", device_xname(sc->sc_dev), 499 sbuf); 500 } 501 #endif 502 temp = (temp & TEST_MODE_MASK); 503 504 switch (IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 505 case IFM_10_5: 506 temp &= ~ (BNC_BIT | TPE_BIT); 507 break; 508 509 case IFM_10_2: 510 temp = (temp & ~TPE_BIT) | BNC_BIT; 511 break; 512 513 case IFM_10_T: 514 temp = (temp & ~BNC_BIT) | TPE_BIT; 515 break; 516 default: 517 ; 518 /* nothing; leave as it is */ 519 } 520 switch (temp & (BNC_BIT | TPE_BIT)) { 521 case BNC_BIT: 522 sc->iy_media = IFM_ETHER | IFM_10_2; 523 break; 524 case TPE_BIT: 525 sc->iy_media = IFM_ETHER | IFM_10_T; 526 break; 527 default: 528 sc->iy_media = IFM_ETHER | IFM_10_5; 529 } 530 531 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 532 #ifdef IYDEBUG 533 { 534 char sbuf[128]; 535 536 snprintb(sbuf, sizeof(sbuf), 537 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC", 538 temp); 539 printf("changed to %s\n", sbuf); 540 } 541 #endif 542 543 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 544 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS); 545 bus_space_write_1(iot, ioh, 0, BANK_SEL(1)); 546 547 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 548 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq); 549 550 #ifdef IYDEBUG 551 { 552 char sbuf[128]; 553 554 snprintb(sbuf, sizeof(sbuf), 555 "\020\4bad_irq\010flash/boot present", temp); 556 557 printf("%s: int no was %s\n", device_xname(sc->sc_dev), sbuf); 558 559 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 560 snprintb(sbuf, sizeof(sbuf), 561 "\020\4bad_irq\010flash/boot present", temp); 562 printf("%s: int no now %s\n", device_xname(sc->sc_dev), sbuf); 563 } 564 #endif 565 566 bus_space_write_1(iot, ioh, RCV_LOWER_LIMIT_REG, 0); 567 bus_space_write_1(iot, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size -2) >>8); 568 bus_space_write_1(iot, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >>8); 569 bus_space_write_1(iot, ioh, XMT_UPPER_LIMIT_REG, (sc->sram - 2) >>8); 570 571 temp = bus_space_read_1(iot, ioh, REG1); 572 #ifdef IYDEBUG 573 { 574 char sbuf[128]; 575 576 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE", 577 temp); 578 579 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf); 580 } 581 #endif 582 bus_space_write_1(iot, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */ 583 584 #ifdef IYDEBUG 585 { 586 char sbuf[128]; 587 588 temp = bus_space_read_1(iot, ioh, REG1); 589 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE", 590 temp); 591 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf); 592 } 593 #endif 594 595 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 596 597 bus_space_write_1(iot, ioh, INT_MASK_REG, 598 ALL_INTS & ~(RX_BIT | TX_BIT)); 599 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); /* clear ints */ 600 601 bus_space_write_1(iot, ioh, RCV_COPY_THRESHOLD, 0); 602 603 bus_space_write_2(iot, ioh, RCV_START_LOW, 0); 604 bus_space_write_2(iot, ioh, RCV_STOP_LOW, sc->rx_size - 2); 605 sc->rx_start = 0; 606 607 bus_space_write_1(iot, ioh, 0, SEL_RESET_CMD); 608 delay(200); 609 610 bus_space_write_2(iot, ioh, XMT_ADDR_REG, sc->rx_size); 611 612 sc->tx_start = sc->tx_end = sc->rx_size; 613 sc->tx_last = 0; 614 615 bus_space_write_1(iot, ioh, 0, RCV_ENABLE_CMD); 616 617 ifp->if_flags |= IFF_RUNNING; 618 ifp->if_flags &= ~IFF_OACTIVE; 619 } 620 621 void 622 iystart(struct ifnet *ifp) 623 { 624 struct iy_softc *sc; 625 626 627 struct mbuf *m0, *m; 628 u_int len, pad, last, end; 629 u_int llen, residual; 630 int avail; 631 char *data; 632 unsigned temp; 633 uint16_t resval, stat; 634 bus_space_tag_t iot; 635 bus_space_handle_t ioh; 636 637 #ifdef IYDEBUG 638 printf("iystart called\n"); 639 #endif 640 sc = ifp->if_softc; 641 642 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 643 return; 644 645 iy_intr_tx(sc); 646 647 iot = sc->sc_iot; 648 ioh = sc->sc_ioh; 649 650 for (;;) { 651 IFQ_POLL(&ifp->if_snd, m0); 652 if (m0 == NULL) 653 break; 654 #ifdef IYDEBUG 655 printf("%s: trying to write another packet to the hardware\n", 656 device_xname(sc->sc_dev)); 657 #endif 658 659 /* We need to use m->m_pkthdr.len, so require the header */ 660 if ((m0->m_flags & M_PKTHDR) == 0) 661 panic("iystart: no header mbuf"); 662 663 len = m0->m_pkthdr.len; 664 pad = len & 1; 665 666 #ifdef IYDEBUG 667 printf("%s: length is %d.\n", device_xname(sc->sc_dev), len); 668 #endif 669 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 670 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len; 671 } 672 673 if (len + pad > ETHER_MAX_LEN) { 674 /* packet is obviously too large: toss it */ 675 if_statinc(ifp, if_oerrors); 676 IFQ_DEQUEUE(&ifp->if_snd, m0); 677 m_freem(m0); 678 continue; 679 } 680 681 bpf_mtap(ifp, m0, BPF_D_OUT); 682 683 avail = sc->tx_start - sc->tx_end; 684 if (avail <= 0) 685 avail += sc->tx_size; 686 687 #ifdef IYDEBUG 688 printf("%s: avail is %d.\n", device_xname(sc->sc_dev), avail); 689 #endif 690 /* 691 * we MUST RUN at splnet here --- 692 * XXX todo: or even turn off the boards ints ??? hm... 693 */ 694 695 /* See if there is room to put another packet in the buffer. */ 696 697 if ((len+pad+2*I595_XMT_HDRLEN) > avail) { 698 #ifdef IYDEBUG 699 printf("%s: len = %d, avail = %d, setting OACTIVE\n", 700 device_xname(sc->sc_dev), len, avail); 701 #endif 702 /* mark interface as full ... */ 703 ifp->if_flags |= IFF_OACTIVE; 704 705 /* and wait for any transmission result */ 706 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 707 708 temp = bus_space_read_1(iot, ioh, REG1); 709 bus_space_write_1(iot, ioh, REG1, 710 temp & ~XMT_CHAIN_INT); 711 712 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 713 714 return; 715 } 716 717 /* we know it fits in the hardware now, so dequeue it */ 718 IFQ_DEQUEUE(&ifp->if_snd, m0); 719 720 last = sc->tx_end; 721 end = last + pad + len + I595_XMT_HDRLEN; 722 723 if (end >= sc->sram) { 724 if ((sc->sram - last) <= I595_XMT_HDRLEN) { 725 /* keep header in one piece */ 726 last = sc->rx_size; 727 end = last + pad + len + I595_XMT_HDRLEN; 728 } else 729 end -= sc->tx_size; 730 } 731 732 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 733 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 734 htole16(XMT_CMD)); 735 736 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 737 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 738 739 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 740 htole16(len + pad)); 741 742 residual = resval = 0; 743 744 while ((m = m0)!=0) { 745 data = mtod(m, void *); 746 llen = m->m_len; 747 if (residual) { 748 #ifdef IYDEBUG 749 printf("%s: merging residual with next mbuf.\n", 750 device_xname(sc->sc_dev)); 751 #endif 752 resval |= *data << 8; 753 bus_space_write_stream_2(iot, ioh, 754 MEM_PORT_REG, resval); 755 --llen; 756 ++data; 757 } 758 /* 759 * XXX ALIGNMENT LOSSAGE HERE. 760 */ 761 if (llen > 1) 762 bus_space_write_multi_stream_2(iot, ioh, 763 MEM_PORT_REG, (uint16_t *) data, 764 llen>>1); 765 residual = llen & 1; 766 if (residual) { 767 resval = *(data + llen - 1); 768 #ifdef IYDEBUG 769 printf("%s: got odd mbuf to send.\n", 770 device_xname(sc->sc_dev)); 771 #endif 772 } 773 774 m0 = m_free(m); 775 } 776 777 if (residual) 778 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 779 resval); 780 781 pad >>= 1; 782 while (pad-- > 0) 783 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 0); 784 785 #ifdef IYDEBUG 786 printf("%s: new last = 0x%x, end = 0x%x.\n", 787 device_xname(sc->sc_dev), last, end); 788 printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n", 789 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, 790 sc->tx_last); 791 #endif 792 793 if (sc->tx_start != sc->tx_end) { 794 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 795 sc->tx_last + XMT_COUNT); 796 797 /* 798 * XXX We keep stat in le order, to potentially save 799 * a byte swap. 800 */ 801 stat = bus_space_read_stream_2(iot, ioh, MEM_PORT_REG); 802 803 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 804 sc->tx_last + XMT_CHAIN); 805 806 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 807 htole16(last)); 808 809 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 810 stat | htole16(CHAIN)); 811 #ifdef IYDEBUG 812 printf("%s: setting 0x%x to 0x%x\n", 813 device_xname(sc->sc_dev), sc->tx_last + XMT_COUNT, 814 le16toh(stat) | CHAIN); 815 #endif 816 } 817 /* dummy read */ 818 stat = bus_space_read_2(iot, ioh, MEM_PORT_REG); 819 820 /* XXX todo: enable ints here if disabled */ 821 822 if_statinc(ifp, if_opackets); 823 824 if (sc->tx_start == sc->tx_end) { 825 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 826 bus_space_write_1(iot, ioh, 0, XMT_CMD); 827 sc->tx_start = last; 828 #ifdef IYDEBUG 829 printf("%s: writing 0x%x to XAR and giving XCMD\n", 830 device_xname(sc->sc_dev), last); 831 #endif 832 } else { 833 bus_space_write_1(iot, ioh, 0, RESUME_XMT_CMD); 834 #ifdef IYDEBUG 835 printf("%s: giving RESUME_XCMD\n", 836 device_xname(sc->sc_dev)); 837 #endif 838 } 839 sc->tx_last = last; 840 sc->tx_end = end; 841 } 842 /* and wait only for end of transmission chain */ 843 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 844 845 temp = bus_space_read_1(iot, ioh, REG1); 846 bus_space_write_1(iot, ioh, REG1, temp | XMT_CHAIN_INT); 847 848 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 849 } 850 851 852 static inline void 853 eepromwritebit(bus_space_tag_t iot, bus_space_handle_t ioh, int what) 854 { 855 bus_space_write_1(iot, ioh, EEPROM_REG, what); 856 delay(1); 857 bus_space_write_1(iot, ioh, EEPROM_REG, what | EESK); 858 delay(1); 859 bus_space_write_1(iot, ioh, EEPROM_REG, what); 860 delay(1); 861 } 862 863 static inline int 864 eepromreadbit(bus_space_tag_t iot, bus_space_handle_t ioh) 865 { 866 int b; 867 868 bus_space_write_1(iot, ioh, EEPROM_REG, EECS | EESK); 869 delay(1); 870 b = bus_space_read_1(iot, ioh, EEPROM_REG); 871 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); 872 delay(1); 873 874 return ((b & EEDO) != 0); 875 } 876 877 static uint16_t 878 eepromread(bus_space_tag_t iot, bus_space_handle_t ioh, int offset) 879 { 880 volatile int i; 881 volatile int j; 882 volatile uint16_t readval; 883 884 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 885 delay(1); 886 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); /* XXXX??? */ 887 delay(1); 888 889 eepromwritebit(iot, ioh, EECS | EEDI); 890 eepromwritebit(iot, ioh, EECS | EEDI); 891 eepromwritebit(iot, ioh, EECS); 892 893 for (j=5; j>=0; --j) { 894 if ((offset>>j) & 1) 895 eepromwritebit(iot, ioh, EECS | EEDI); 896 else 897 eepromwritebit(iot, ioh, EECS); 898 } 899 900 for (readval=0, i=0; i<16; ++i) { 901 readval<<=1; 902 readval |= eepromreadbit(iot, ioh); 903 } 904 905 bus_space_write_1(iot, ioh, EEPROM_REG, 0 | EESK); 906 delay(1); 907 bus_space_write_1(iot, ioh, EEPROM_REG, 0); 908 909 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 910 911 return readval; 912 } 913 914 /* 915 * Device timeout/watchdog routine. Entered if the device neglects to generate 916 * an interrupt after a transmit has been started on it. 917 */ 918 void 919 iywatchdog(struct ifnet *ifp) 920 { 921 struct iy_softc *sc = ifp->if_softc; 922 923 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 924 if_statinc(ifp, if_oerrors); 925 iyreset(sc); 926 } 927 928 /* 929 * What to do upon receipt of an interrupt. 930 */ 931 int 932 iyintr(void *arg) 933 { 934 struct iy_softc *sc; 935 struct ifnet *ifp; 936 bus_space_tag_t iot; 937 bus_space_handle_t ioh; 938 939 u_short status; 940 941 sc = arg; 942 iot = sc->sc_iot; 943 ioh = sc->sc_ioh; 944 945 ifp = &sc->sc_ethercom.ec_if; 946 947 status = bus_space_read_1(iot, ioh, STATUS_REG); 948 #ifdef IYDEBUG 949 if (status & ALL_INTS) { 950 char sbuf[128]; 951 952 snprintb(sbuf, sizeof(sbuf), "\020\1RX_STP\2RX\3TX\4EXEC", 953 status); 954 printf("%s: got interrupt %s", device_xname(sc->sc_dev), sbuf); 955 956 if (status & EXEC_INT) { 957 snprintb(sbuf, sizeof(sbuf), 958 "\020\6ABORT", bus_space_read_1(iot, ioh, 0)); 959 printf(" event %s\n", sbuf); 960 } else 961 printf("\n"); 962 } 963 #endif 964 if ((status & (RX_INT | TX_INT)) == 0) 965 return 0; 966 967 if (status & RX_INT) { 968 iy_intr_rx(sc); 969 bus_space_write_1(iot, ioh, STATUS_REG, RX_INT); 970 } 971 if (status & TX_INT) { 972 /* Tell feeders we may be able to accept more data... */ 973 ifp->if_flags &= ~IFF_OACTIVE; 974 /* and get more data. */ 975 iystart(ifp); 976 bus_space_write_1(iot, ioh, STATUS_REG, TX_INT); 977 } 978 979 rnd_add_uint32(&sc->rnd_source, status); 980 981 return 1; 982 } 983 984 void 985 iyget(struct iy_softc *sc, bus_space_tag_t iot, bus_space_handle_t ioh, 986 int rxlen) 987 { 988 struct mbuf *m, *top, **mp; 989 struct ifnet *ifp; 990 int len; 991 992 ifp = &sc->sc_ethercom.ec_if; 993 994 MGETHDR(m, M_DONTWAIT, MT_DATA); 995 if (m == 0) 996 goto dropped; 997 m_set_rcvif(m, ifp); 998 m->m_pkthdr.len = rxlen; 999 len = MHLEN; 1000 top = 0; 1001 mp = ⊤ 1002 1003 while (rxlen > 0) { 1004 if (top) { 1005 MGET(m, M_DONTWAIT, MT_DATA); 1006 if (m == 0) { 1007 m_freem(top); 1008 goto dropped; 1009 } 1010 len = MLEN; 1011 } 1012 if (rxlen >= MINCLSIZE) { 1013 MCLGET(m, M_DONTWAIT); 1014 if ((m->m_flags & M_EXT) == 0) { 1015 m_free(m); 1016 m_freem(top); 1017 goto dropped; 1018 } 1019 len = MCLBYTES; 1020 } 1021 len = uimin(rxlen, len); 1022 /* 1023 * XXX ALIGNMENT LOSSAGE HERE. 1024 */ 1025 if (len > 1) { 1026 len &= ~1; 1027 1028 bus_space_read_multi_stream_2(iot, ioh, MEM_PORT_REG, 1029 mtod(m, uint16_t *), len / 2); 1030 } else { 1031 #ifdef IYDEBUG 1032 printf("%s: received odd mbuf\n", 1033 device_xname(sc->sc_dev)); 1034 #endif 1035 *(mtod(m, char *)) = bus_space_read_stream_2(iot, ioh, 1036 MEM_PORT_REG); 1037 } 1038 m->m_len = len; 1039 rxlen -= len; 1040 *mp = m; 1041 mp = &m->m_next; 1042 } 1043 1044 if (top == NULL) 1045 return; 1046 1047 if_percpuq_enqueue(ifp->if_percpuq, top); 1048 return; 1049 1050 dropped: 1051 if_statinc(ifp, if_ierrors); 1052 return; 1053 } 1054 1055 void 1056 iy_intr_rx(struct iy_softc *sc) 1057 { 1058 bus_space_tag_t iot; 1059 bus_space_handle_t ioh; 1060 1061 u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen; 1062 1063 iot = sc->sc_iot; 1064 ioh = sc->sc_ioh; 1065 1066 rxadrs = sc->rx_start; 1067 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxadrs); 1068 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 1069 rxnext = 0; 1070 1071 while (rxevnt == RCV_DONE) { 1072 rxstatus = le16toh(bus_space_read_stream_2(iot, ioh, 1073 MEM_PORT_REG)); 1074 rxnext = le16toh(bus_space_read_stream_2(iot, ioh, 1075 MEM_PORT_REG)); 1076 rxlen = le16toh(bus_space_read_stream_2(iot, ioh, 1077 MEM_PORT_REG)); 1078 #ifdef IYDEBUG 1079 { 1080 char sbuf[128]; 1081 1082 snprintb(sbuf, sizeof(sbuf), 1083 "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR" 1084 "\014CRCERR\015LENERR\016RCVOK\020TYP", rxstatus); 1085 1086 printf("%s: pck at 0x%04x stat %s next 0x%x len 0x%x\n", 1087 device_xname(sc->sc_dev), rxadrs, sbuf, rxnext, 1088 rxlen); 1089 } 1090 #else 1091 __USE(rxstatus); 1092 #endif 1093 iyget(sc, iot, ioh, rxlen); 1094 1095 /* move stop address */ 1096 bus_space_write_2(iot, ioh, RCV_STOP_LOW, 1097 rxnext == 0 ? sc->rx_size - 2 : rxnext - 2); 1098 1099 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxnext); 1100 rxadrs = rxnext; 1101 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, 1102 MEM_PORT_REG)); 1103 } 1104 sc->rx_start = rxnext; 1105 } 1106 1107 void 1108 iy_intr_tx(struct iy_softc *sc) 1109 { 1110 bus_space_tag_t iot; 1111 bus_space_handle_t ioh; 1112 struct ifnet *ifp; 1113 u_int txstatus, txstat2, txlen, txnext; 1114 1115 ifp = &sc->sc_ethercom.ec_if; 1116 iot = sc->sc_iot; 1117 ioh = sc->sc_ioh; 1118 1119 while (sc->tx_start != sc->tx_end) { 1120 bus_space_write_2(iot, ioh, HOST_ADDR_REG, sc->tx_start); 1121 txstatus = le16toh(bus_space_read_stream_2(iot, ioh, 1122 MEM_PORT_REG)); 1123 1124 if ((txstatus & (TX_DONE | CMD_MASK)) != (TX_DONE | XMT_CMD)) 1125 break; 1126 1127 txstat2 = le16toh(bus_space_read_stream_2(iot, ioh, 1128 MEM_PORT_REG)); 1129 txnext = le16toh(bus_space_read_stream_2(iot, ioh, 1130 MEM_PORT_REG)); 1131 txlen = le16toh(bus_space_read_stream_2(iot, ioh, 1132 MEM_PORT_REG)); 1133 #ifdef IYDEBUG 1134 { 1135 char sbuf[128]; 1136 1137 snprintb(sbuf, sizeof(sbuf), 1138 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF" 1139 "\011UND_RUN\012JERR\013LST_CRS" 1140 "\014LTCOL\016TX_OK\020COLL", txstat2); 1141 1142 printf("txstat 0x%x stat2 %s next 0x%x len 0x%x\n", 1143 txstatus, sbuf, txnext, txlen); 1144 } 1145 #endif 1146 if (txlen & CHAIN) 1147 sc->tx_start = txnext; 1148 else 1149 sc->tx_start = sc->tx_end; 1150 ifp->if_flags &= ~IFF_OACTIVE; 1151 1152 if (txstat2 & 0x0020) 1153 if_statadd(ifp, if_collisions, 16); 1154 else 1155 if_statadd(ifp, if_collisions, txstat2 & 0x000f); 1156 1157 if ((txstat2 & 0x2000) == 0) 1158 if_statinc(ifp, if_oerrors); 1159 } 1160 } 1161 1162 int 1163 iyioctl(struct ifnet *ifp, u_long cmd, void *data) 1164 { 1165 struct iy_softc *sc; 1166 struct ifaddr *ifa; 1167 int s, error = 0; 1168 1169 sc = ifp->if_softc; 1170 ifa = (struct ifaddr *)data; 1171 1172 #ifdef IYDEBUG 1173 printf("iyioctl called with ifp %p (%s) cmd 0x%lx data %p\n", 1174 ifp, ifp->if_xname, cmd, data); 1175 #endif 1176 1177 s = splnet(); 1178 1179 switch (cmd) { 1180 1181 case SIOCINITIFADDR: 1182 ifp->if_flags |= IFF_UP; 1183 1184 iyinit(sc); 1185 switch (ifa->ifa_addr->sa_family) { 1186 #ifdef INET 1187 case AF_INET: 1188 arp_ifinit(ifp, ifa); 1189 break; 1190 #endif 1191 default: 1192 break; 1193 } 1194 break; 1195 1196 case SIOCSIFFLAGS: 1197 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 1198 break; 1199 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI); 1200 /* XXX re-use ether_ioctl() */ 1201 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 1202 case IFF_RUNNING: 1203 /* 1204 * If interface is marked down and it is running, then 1205 * stop it. 1206 */ 1207 iystop(sc); 1208 ifp->if_flags &= ~IFF_RUNNING; 1209 break; 1210 case IFF_UP: 1211 /* 1212 * If interface is marked up and it is stopped, then 1213 * start it. 1214 */ 1215 iyinit(sc); 1216 break; 1217 default: 1218 /* 1219 * Reset the interface to pick up changes in any other 1220 * flags that affect hardware registers. 1221 */ 1222 iystop(sc); 1223 iyinit(sc); 1224 break; 1225 } 1226 #ifdef IYDEBUGX 1227 if (ifp->if_flags & IFF_DEBUG) 1228 sc->sc_debug = IFY_ALL; 1229 else 1230 sc->sc_debug = 0; 1231 #endif 1232 break; 1233 1234 case SIOCADDMULTI: 1235 case SIOCDELMULTI: 1236 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 1237 /* 1238 * Multicast list has changed; set the hardware filter 1239 * accordingly. 1240 */ 1241 if (ifp->if_flags & IFF_RUNNING) { 1242 /* XXX can't make it work otherwise */ 1243 iyreset(sc); 1244 iy_mc_reset(sc); 1245 } 1246 error = 0; 1247 } 1248 break; 1249 1250 default: 1251 error = ether_ioctl(ifp, cmd, data); 1252 } 1253 splx(s); 1254 return error; 1255 } 1256 1257 int 1258 iy_mediachange(struct ifnet *ifp) 1259 { 1260 struct iy_softc *sc = ifp->if_softc; 1261 1262 if (IFM_TYPE(sc->iy_ifmedia.ifm_media) != IFM_ETHER) 1263 return EINVAL; 1264 switch (IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 1265 case IFM_10_5: 1266 case IFM_10_2: 1267 case IFM_10_T: 1268 case IFM_AUTO: 1269 iystop(sc); 1270 iyinit(sc); 1271 return 0; 1272 default: 1273 return EINVAL; 1274 } 1275 } 1276 1277 void 1278 iy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1279 { 1280 struct iy_softc *sc = ifp->if_softc; 1281 1282 ifmr->ifm_active = sc->iy_media; 1283 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1284 } 1285 1286 1287 static void 1288 iy_mc_setup(struct iy_softc *sc) 1289 { 1290 struct ether_multi *enm; 1291 struct ether_multistep step; 1292 struct ethercom *ecp; 1293 struct ifnet *ifp; 1294 bus_space_tag_t iot; 1295 bus_space_handle_t ioh; 1296 int avail, last /*, end*/ , len; 1297 int timeout; 1298 volatile uint16_t dum; 1299 uint8_t temp; 1300 1301 1302 ecp = &sc->sc_ethercom; 1303 ifp = &ecp->ec_if; 1304 1305 iot = sc->sc_iot; 1306 ioh = sc->sc_ioh; 1307 1308 ETHER_LOCK(ecp); 1309 len = 6 * ecp->ec_multicnt; 1310 1311 avail = sc->tx_start - sc->tx_end; 1312 if (avail <= 0) 1313 avail += sc->tx_size; 1314 if (ifp->if_flags & IFF_DEBUG) 1315 printf("%s: iy_mc_setup called, %d addresses, " 1316 "%d/%d bytes needed/avail\n", ifp->if_xname, 1317 ecp->ec_multicnt, len + I595_XMT_HDRLEN, avail); 1318 1319 last = sc->rx_size; 1320 1321 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1322 bus_space_write_1(iot, ioh, RECV_MODES_REG, MATCH_BRDCST); 1323 /* XXX VOODOO */ 1324 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1325 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1326 /* XXX END OF VOODOO */ 1327 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1328 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 1329 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(MC_SETUP_CMD)); 1330 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1331 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1332 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(len)); 1333 1334 ETHER_FIRST_MULTI(step, ecp, enm); 1335 while (enm) { 1336 /* 1337 * XXX ALIGNMENT LOSSAGE HERE? 1338 */ 1339 bus_space_write_multi_stream_2(iot, ioh, MEM_PORT_REG, 1340 (uint16_t *) enm->enm_addrlo, 3); 1341 1342 ETHER_NEXT_MULTI(step, enm); 1343 } 1344 ETHER_UNLOCK(ecp); 1345 dum = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */ 1346 __USE(dum); 1347 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 1348 bus_space_write_1(iot, ioh, 0, MC_SETUP_CMD); 1349 1350 1351 sc->tx_start = sc->rx_size; 1352 sc->tx_end = sc->rx_size + I595_XMT_HDRLEN + len; 1353 1354 for (timeout=0; timeout<100; timeout++) { 1355 DELAY(2); 1356 if ((bus_space_read_1(iot, ioh, STATUS_REG) & EXEC_INT) == 0) 1357 continue; 1358 1359 temp = bus_space_read_1(iot, ioh, 0); 1360 bus_space_write_1(iot, ioh, STATUS_REG, EXEC_INT); 1361 #ifdef DIAGNOSTIC 1362 if (temp & 0x20) { 1363 aprint_error_dev(sc->sc_dev, 1364 "mc setup failed, %d usec\n", timeout * 2); 1365 } else if (((temp & 0x0f) == 0x03) && 1366 (ifp->if_flags & IFF_DEBUG)) { 1367 printf("%s: mc setup done, %d usec\n", 1368 device_xname(sc->sc_dev), timeout * 2); 1369 } 1370 #endif 1371 break; 1372 } 1373 sc->tx_start = sc->tx_end; 1374 ifp->if_flags &= ~IFF_OACTIVE; 1375 1376 } 1377 1378 static void 1379 iy_mc_reset(struct iy_softc *sc) 1380 { 1381 struct ether_multi *enm; 1382 struct ether_multistep step; 1383 struct ethercom *ecp; 1384 struct ifnet *ifp; 1385 bus_space_tag_t iot; 1386 bus_space_handle_t ioh; 1387 uint16_t temp; 1388 1389 ecp = &sc->sc_ethercom; 1390 ifp = &ecp->ec_if; 1391 1392 iot = sc->sc_iot; 1393 ioh = sc->sc_ioh; 1394 1395 if (ecp->ec_multicnt > 63) { 1396 ifp->if_flags |= IFF_ALLMULTI; 1397 1398 } else if (ecp->ec_multicnt > 0) { 1399 /* 1400 * Step through the list of addresses. 1401 */ 1402 ETHER_LOCK(ecp); 1403 ETHER_FIRST_MULTI(step, ecp, enm); 1404 while (enm) { 1405 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { 1406 ifp->if_flags |= IFF_ALLMULTI; 1407 ETHER_UNLOCK(ecp); 1408 goto setupmulti; 1409 } 1410 ETHER_NEXT_MULTI(step, enm); 1411 } 1412 ETHER_UNLOCK(ecp); 1413 /* OK, we really need to do it now: */ 1414 #if 0 1415 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) 1416 != IFF_RUNNING) { 1417 ifp->if_flags |= IFF_OACTIVE; 1418 sc->want_mc_setup = 1; 1419 return; 1420 } 1421 #endif 1422 iy_mc_setup(sc); 1423 } else { 1424 ifp->if_flags &= ~IFF_ALLMULTI; 1425 } 1426 1427 setupmulti: 1428 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1429 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) 1430 temp = MATCH_ALL; 1431 else 1432 temp = MATCH_BRDCST; 1433 1434 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 1435 /* XXX VOODOO */ 1436 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1437 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1438 /* XXX END OF VOODOO */ 1439 1440 /* XXX TBD: setup hardware for all multicasts */ 1441 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1442 return; 1443 } 1444 1445 #ifdef IYDEBUGX 1446 void 1447 print_rbd(volatile struct ie_recv_buf_desc *rbd) 1448 { 1449 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n" 1450 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual, 1451 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length, 1452 rbd->mbz); 1453 } 1454 #endif 1455 1456 void 1457 iyprobemem(struct iy_softc *sc) 1458 { 1459 bus_space_tag_t iot; 1460 bus_space_handle_t ioh; 1461 int testing; 1462 1463 iot = sc->sc_iot; 1464 ioh = sc->sc_ioh; 1465 1466 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 1467 delay(1); 1468 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 4096-2); 1469 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1470 1471 for (testing=65536; testing >= 4096; testing >>= 1) { 1472 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1473 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xdead); 1474 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1475 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xdead) { 1476 #ifdef IYMEMDEBUG 1477 printf("%s: Didn't keep 0xdead at 0x%x\n", 1478 device_xname(sc->sc_dev), testing-2); 1479 #endif 1480 continue; 1481 } 1482 1483 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1484 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xbeef); 1485 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1486 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xbeef) { 1487 #ifdef IYMEMDEBUG 1488 printf("%s: Didn't keep 0xbeef at 0x%x\n", 1489 device_xname(sc->sc_dev), testing-2); 1490 #endif 1491 continue; 1492 } 1493 1494 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1495 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1496 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing >> 1); 1497 bus_space_write_2(iot, ioh, MEM_PORT_REG, testing >> 1); 1498 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1499 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) == (testing >> 1)) { 1500 #ifdef IYMEMDEBUG 1501 printf("%s: 0x%x alias of 0x0\n", 1502 device_xname(sc->sc_dev), testing >> 1); 1503 #endif 1504 continue; 1505 } 1506 1507 break; 1508 } 1509 1510 sc->sram = testing; 1511 1512 switch (testing) { 1513 case 65536: 1514 /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */ 1515 sc->rx_size = 44*1024; 1516 break; 1517 1518 case 32768: 1519 /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */ 1520 sc->rx_size = 22*1024; 1521 break; 1522 1523 case 16384: 1524 /* 1 NFS packet + overhead RX, 4 big packets TX */ 1525 sc->rx_size = 10*1024; 1526 break; 1527 default: 1528 sc->rx_size = testing/2; 1529 break; 1530 } 1531 sc->tx_size = testing - sc->rx_size; 1532 } 1533 1534 static int 1535 eepromreadall(bus_space_tag_t iot, bus_space_handle_t ioh, uint16_t *wordp, 1536 int maxi) 1537 { 1538 int i; 1539 uint16_t checksum, tmp; 1540 1541 checksum = 0; 1542 1543 for (i=0; i<EEPP_LENGTH; ++i) { 1544 tmp = eepromread(iot, ioh, i); 1545 checksum += tmp; 1546 if (i<maxi) 1547 wordp[i] = tmp; 1548 } 1549 1550 if (checksum != EEPP_CHKSUM) { 1551 #ifdef IYDEBUG 1552 printf("wrong EEPROM checksum 0x%x should be 0x%x\n", 1553 checksum, EEPP_CHKSUM); 1554 #endif 1555 return 1; 1556 } 1557 return 0; 1558 } 1559