1 /* $NetBSD: if_iy.c,v 1.109 2019/05/29 10:07:29 msaitoh 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.109 2019/05/29 10:07:29 msaitoh 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 int 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 iot = ia->ia_iot; 286 287 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) { 288 aprint_error(": can't map i/o space\n"); 289 return; 290 } 291 292 sc->sc_iot = iot; 293 sc->sc_ioh = ioh; 294 295 sc->mappedirq = eepro_revirqmap[ia->ia_irq[0].ir_irq]; 296 297 /* now let's reset the chip */ 298 299 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 300 delay(200); 301 302 iyprobemem(sc); 303 304 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 305 ifp->if_softc = sc; 306 ifp->if_start = iystart; 307 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 308 309 sc->doing_mc_setup = 0; 310 311 ifp->if_ioctl = iyioctl; 312 ifp->if_watchdog = iywatchdog; 313 314 IFQ_SET_READY(&ifp->if_snd); 315 316 (void)eepromreadall(iot, ioh, eaddr, 8); 317 sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev; 318 319 #ifdef DIAGNOSTICS 320 if ((eaddr[EEPPEther0] != 321 eepromread(iot, ioh, EEPPEther0a)) && 322 (eaddr[EEPPEther1] != 323 eepromread(iot, ioh, EEPPEther1a)) && 324 (eaddr[EEPPEther2] != 325 eepromread(iot, ioh, EEPPEther2a))) 326 327 aprint_error("EEPROM Ethernet address differs from copy\n"); 328 #endif 329 330 myaddr[1] = eaddr[EEPPEther0] & 0xFF; 331 myaddr[0] = eaddr[EEPPEther0] >> 8; 332 myaddr[3] = eaddr[EEPPEther1] & 0xFF; 333 myaddr[2] = eaddr[EEPPEther1] >> 8; 334 myaddr[5] = eaddr[EEPPEther2] & 0xFF; 335 myaddr[4] = eaddr[EEPPEther2] >> 8; 336 337 /* Initialize ifmedia structures. */ 338 sc->sc_ethercom.ec_ifmedia = &sc->iy_ifmedia; 339 ifmedia_init(&sc->iy_ifmedia, 0, iy_mediachange, iy_mediastatus); 340 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_2, 0, NULL); 341 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_5, 0, NULL); 342 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL); 343 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL); 344 ifmedia_set(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO); 345 /* Attach the interface. */ 346 if_attach(ifp); 347 ether_ifattach(ifp, myaddr); 348 aprint_normal(": address %s, rev. %d, %d kB\n", 349 ether_sprintf(myaddr), 350 sc->hard_vers, sc->sram/1024); 351 352 eirq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int]; 353 if (eirq != ia->ia_irq[0].ir_irq) 354 aprint_error("%s: EEPROM irq setting %d ignored\n", 355 device_xname(sc->sc_dev), eirq); 356 357 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 358 IST_EDGE, IPL_NET, iyintr, sc); 359 360 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 361 RND_TYPE_NET, RND_FLAG_DEFAULT); 362 363 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 364 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq); 365 } 366 367 void 368 iystop(struct iy_softc *sc) 369 { 370 bus_space_tag_t iot; 371 bus_space_handle_t ioh; 372 #ifdef IYDEBUG 373 u_int p, v; 374 #endif 375 376 iot = sc->sc_iot; 377 ioh = sc->sc_ioh; 378 379 bus_space_write_1(iot, ioh, COMMAND_REG, RCV_DISABLE_CMD); 380 381 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS); 382 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); 383 384 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 385 delay(200); 386 #ifdef IYDEBUG 387 printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n", 388 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, sc->tx_last); 389 p = sc->tx_last; 390 if (!p) 391 p = sc->tx_start; 392 do { 393 char sbuf[128]; 394 395 bus_space_write_2(iot, ioh, HOST_ADDR_REG, p); 396 397 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 398 snprintb(sbuf, sizeof(sbuf), "\020\006Ab\010Dn", v); 399 printf("0x%04x: %s ", p, sbuf); 400 401 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 402 snprintb(sbuf, sizeof(sbuf), 403 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN" 404 "\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL", v); 405 printf("%s", sbuf); 406 407 p = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 408 printf(" 0x%04x", p); 409 410 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 411 snprintb(sbuf, sizeof(sbuf), "\020\020Ch", v); 412 printf(" %s\n", sbuf); 413 414 } while (v & 0x8000); 415 #endif 416 sc->tx_start = sc->tx_end = sc->rx_size; 417 sc->tx_last = 0; 418 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 419 } 420 421 void 422 iyreset(struct iy_softc *sc) 423 { 424 int s; 425 s = splnet(); 426 iystop(sc); 427 iyinit(sc); 428 splx(s); 429 } 430 431 void 432 iyinit(struct iy_softc *sc) 433 { 434 int i; 435 unsigned temp; 436 struct ifnet *ifp; 437 bus_space_tag_t iot; 438 bus_space_handle_t ioh; 439 440 iot = sc->sc_iot; 441 ioh = sc->sc_ioh; 442 443 ifp = &sc->sc_ethercom.ec_if; 444 #ifdef IYDEBUG 445 printf("ifp is %p\n", ifp); 446 #endif 447 448 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 449 450 temp = bus_space_read_1(iot, ioh, EEPROM_REG); 451 if (temp & 0x10) 452 bus_space_write_1(iot, ioh, EEPROM_REG, temp & ~0x10); 453 454 for (i=0; i<6; ++i) { 455 bus_space_write_1(iot, ioh, I_ADD(i), CLLADDR(ifp->if_sadl)[i]); 456 } 457 458 temp = bus_space_read_1(iot, ioh, REG1); 459 bus_space_write_1(iot, ioh, REG1, 460 temp | /* XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | */ RCV_DISCARD_BAD); 461 462 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) 463 temp = MATCH_ALL; 464 else 465 temp = MATCH_BRDCST; 466 467 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 468 469 #ifdef IYDEBUG 470 { 471 char sbuf[128]; 472 473 snprintb(sbuf, sizeof(sbuf), 474 "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA", 475 temp); 476 477 printf("%s: RECV_MODES set to %s\n", device_xname(sc->sc_dev), 478 sbuf); 479 } 480 #endif 481 /* XXX VOODOO */ 482 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 483 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 484 /* XXX END OF VOODOO */ 485 486 487 delay(500000); /* for the hardware to test for the connector */ 488 489 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 490 #ifdef IYDEBUG 491 { 492 char sbuf[128]; 493 494 snprintb(sbuf, sizeof(sbuf), 495 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC", 496 temp); 497 printf("%s: media select was %s ", device_xname(sc->sc_dev), 498 sbuf); 499 } 500 #endif 501 temp = (temp & TEST_MODE_MASK); 502 503 switch (IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 504 case IFM_10_5: 505 temp &= ~ (BNC_BIT | TPE_BIT); 506 break; 507 508 case IFM_10_2: 509 temp = (temp & ~TPE_BIT) | BNC_BIT; 510 break; 511 512 case IFM_10_T: 513 temp = (temp & ~BNC_BIT) | TPE_BIT; 514 break; 515 default: 516 ; 517 /* nothing; leave as it is */ 518 } 519 switch (temp & (BNC_BIT | TPE_BIT)) { 520 case BNC_BIT: 521 sc->iy_media = IFM_ETHER | IFM_10_2; 522 break; 523 case TPE_BIT: 524 sc->iy_media = IFM_ETHER | IFM_10_T; 525 break; 526 default: 527 sc->iy_media = IFM_ETHER | IFM_10_5; 528 } 529 530 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 531 #ifdef IYDEBUG 532 { 533 char sbuf[128]; 534 535 snprintb(sbuf, sizeof(sbuf), 536 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC", 537 temp); 538 printf("changed to %s\n", sbuf); 539 } 540 #endif 541 542 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 543 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS); 544 bus_space_write_1(iot, ioh, 0, BANK_SEL(1)); 545 546 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 547 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq); 548 549 #ifdef IYDEBUG 550 { 551 char sbuf[128]; 552 553 snprintb(sbuf, sizeof(sbuf), 554 "\020\4bad_irq\010flash/boot present", temp); 555 556 printf("%s: int no was %s\n", device_xname(sc->sc_dev), sbuf); 557 558 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 559 snprintb(sbuf, sizeof(sbuf), 560 "\020\4bad_irq\010flash/boot present", temp); 561 printf("%s: int no now %s\n", device_xname(sc->sc_dev), sbuf); 562 } 563 #endif 564 565 bus_space_write_1(iot, ioh, RCV_LOWER_LIMIT_REG, 0); 566 bus_space_write_1(iot, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size -2) >>8); 567 bus_space_write_1(iot, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >>8); 568 bus_space_write_1(iot, ioh, XMT_UPPER_LIMIT_REG, (sc->sram - 2) >>8); 569 570 temp = bus_space_read_1(iot, ioh, REG1); 571 #ifdef IYDEBUG 572 { 573 char sbuf[128]; 574 575 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE", 576 temp); 577 578 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf); 579 } 580 #endif 581 bus_space_write_1(iot, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */ 582 583 #ifdef IYDEBUG 584 { 585 char sbuf[128]; 586 587 temp = bus_space_read_1(iot, ioh, REG1); 588 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE", 589 temp); 590 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf); 591 } 592 #endif 593 594 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 595 596 bus_space_write_1(iot, ioh, INT_MASK_REG, 597 ALL_INTS & ~(RX_BIT | TX_BIT)); 598 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); /* clear ints */ 599 600 bus_space_write_1(iot, ioh, RCV_COPY_THRESHOLD, 0); 601 602 bus_space_write_2(iot, ioh, RCV_START_LOW, 0); 603 bus_space_write_2(iot, ioh, RCV_STOP_LOW, sc->rx_size - 2); 604 sc->rx_start = 0; 605 606 bus_space_write_1(iot, ioh, 0, SEL_RESET_CMD); 607 delay(200); 608 609 bus_space_write_2(iot, ioh, XMT_ADDR_REG, sc->rx_size); 610 611 sc->tx_start = sc->tx_end = sc->rx_size; 612 sc->tx_last = 0; 613 614 bus_space_write_1(iot, ioh, 0, RCV_ENABLE_CMD); 615 616 ifp->if_flags |= IFF_RUNNING; 617 ifp->if_flags &= ~IFF_OACTIVE; 618 } 619 620 void 621 iystart(struct ifnet *ifp) 622 { 623 struct iy_softc *sc; 624 625 626 struct mbuf *m0, *m; 627 u_int len, pad, last, end; 628 u_int llen, residual; 629 int avail; 630 char *data; 631 unsigned temp; 632 uint16_t resval, stat; 633 bus_space_tag_t iot; 634 bus_space_handle_t ioh; 635 636 #ifdef IYDEBUG 637 printf("iystart called\n"); 638 #endif 639 sc = ifp->if_softc; 640 641 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 642 return; 643 644 iy_intr_tx(sc); 645 646 iot = sc->sc_iot; 647 ioh = sc->sc_ioh; 648 649 for (;;) { 650 IFQ_POLL(&ifp->if_snd, m0); 651 if (m0 == NULL) 652 break; 653 #ifdef IYDEBUG 654 printf("%s: trying to write another packet to the hardware\n", 655 device_xname(sc->sc_dev)); 656 #endif 657 658 /* We need to use m->m_pkthdr.len, so require the header */ 659 if ((m0->m_flags & M_PKTHDR) == 0) 660 panic("iystart: no header mbuf"); 661 662 len = m0->m_pkthdr.len; 663 pad = len & 1; 664 665 #ifdef IYDEBUG 666 printf("%s: length is %d.\n", device_xname(sc->sc_dev), len); 667 #endif 668 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 669 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len; 670 } 671 672 if (len + pad > ETHER_MAX_LEN) { 673 /* packet is obviously too large: toss it */ 674 ++ifp->if_oerrors; 675 IFQ_DEQUEUE(&ifp->if_snd, m0); 676 m_freem(m0); 677 continue; 678 } 679 680 bpf_mtap(ifp, m0, BPF_D_OUT); 681 682 avail = sc->tx_start - sc->tx_end; 683 if (avail <= 0) 684 avail += sc->tx_size; 685 686 #ifdef IYDEBUG 687 printf("%s: avail is %d.\n", device_xname(sc->sc_dev), avail); 688 #endif 689 /* 690 * we MUST RUN at splnet here --- 691 * XXX todo: or even turn off the boards ints ??? hm... 692 */ 693 694 /* See if there is room to put another packet in the buffer. */ 695 696 if ((len+pad+2*I595_XMT_HDRLEN) > avail) { 697 #ifdef IYDEBUG 698 printf("%s: len = %d, avail = %d, setting OACTIVE\n", 699 device_xname(sc->sc_dev), len, avail); 700 #endif 701 /* mark interface as full ... */ 702 ifp->if_flags |= IFF_OACTIVE; 703 704 /* and wait for any transmission result */ 705 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 706 707 temp = bus_space_read_1(iot, ioh, REG1); 708 bus_space_write_1(iot, ioh, REG1, 709 temp & ~XMT_CHAIN_INT); 710 711 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 712 713 return; 714 } 715 716 /* we know it fits in the hardware now, so dequeue it */ 717 IFQ_DEQUEUE(&ifp->if_snd, m0); 718 719 last = sc->tx_end; 720 end = last + pad + len + I595_XMT_HDRLEN; 721 722 if (end >= sc->sram) { 723 if ((sc->sram - last) <= I595_XMT_HDRLEN) { 724 /* keep header in one piece */ 725 last = sc->rx_size; 726 end = last + pad + len + I595_XMT_HDRLEN; 727 } else 728 end -= sc->tx_size; 729 } 730 731 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 732 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 733 htole16(XMT_CMD)); 734 735 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 736 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 737 738 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 739 htole16(len + pad)); 740 741 residual = resval = 0; 742 743 while ((m = m0)!=0) { 744 data = mtod(m, void *); 745 llen = m->m_len; 746 if (residual) { 747 #ifdef IYDEBUG 748 printf("%s: merging residual with next mbuf.\n", 749 device_xname(sc->sc_dev)); 750 #endif 751 resval |= *data << 8; 752 bus_space_write_stream_2(iot, ioh, 753 MEM_PORT_REG, resval); 754 --llen; 755 ++data; 756 } 757 /* 758 * XXX ALIGNMENT LOSSAGE HERE. 759 */ 760 if (llen > 1) 761 bus_space_write_multi_stream_2(iot, ioh, 762 MEM_PORT_REG, (uint16_t *) data, 763 llen>>1); 764 residual = llen & 1; 765 if (residual) { 766 resval = *(data + llen - 1); 767 #ifdef IYDEBUG 768 printf("%s: got odd mbuf to send.\n", 769 device_xname(sc->sc_dev)); 770 #endif 771 } 772 773 m0 = m_free(m); 774 } 775 776 if (residual) 777 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 778 resval); 779 780 pad >>= 1; 781 while (pad-- > 0) 782 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 0); 783 784 #ifdef IYDEBUG 785 printf("%s: new last = 0x%x, end = 0x%x.\n", 786 device_xname(sc->sc_dev), last, end); 787 printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n", 788 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, 789 sc->tx_last); 790 #endif 791 792 if (sc->tx_start != sc->tx_end) { 793 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 794 sc->tx_last + XMT_COUNT); 795 796 /* 797 * XXX We keep stat in le order, to potentially save 798 * a byte swap. 799 */ 800 stat = bus_space_read_stream_2(iot, ioh, MEM_PORT_REG); 801 802 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 803 sc->tx_last + XMT_CHAIN); 804 805 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 806 htole16(last)); 807 808 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 809 stat | htole16(CHAIN)); 810 #ifdef IYDEBUG 811 printf("%s: setting 0x%x to 0x%x\n", 812 device_xname(sc->sc_dev), sc->tx_last + XMT_COUNT, 813 le16toh(stat) | CHAIN); 814 #endif 815 } 816 /* dummy read */ 817 stat = bus_space_read_2(iot, ioh, MEM_PORT_REG); 818 819 /* XXX todo: enable ints here if disabled */ 820 821 ++ifp->if_opackets; 822 823 if (sc->tx_start == sc->tx_end) { 824 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 825 bus_space_write_1(iot, ioh, 0, XMT_CMD); 826 sc->tx_start = last; 827 #ifdef IYDEBUG 828 printf("%s: writing 0x%x to XAR and giving XCMD\n", 829 device_xname(sc->sc_dev), last); 830 #endif 831 } else { 832 bus_space_write_1(iot, ioh, 0, RESUME_XMT_CMD); 833 #ifdef IYDEBUG 834 printf("%s: giving RESUME_XCMD\n", 835 device_xname(sc->sc_dev)); 836 #endif 837 } 838 sc->tx_last = last; 839 sc->tx_end = end; 840 } 841 /* and wait only for end of transmission chain */ 842 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 843 844 temp = bus_space_read_1(iot, ioh, REG1); 845 bus_space_write_1(iot, ioh, REG1, temp | XMT_CHAIN_INT); 846 847 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 848 } 849 850 851 static inline void 852 eepromwritebit(bus_space_tag_t iot, bus_space_handle_t ioh, int what) 853 { 854 bus_space_write_1(iot, ioh, EEPROM_REG, what); 855 delay(1); 856 bus_space_write_1(iot, ioh, EEPROM_REG, what | EESK); 857 delay(1); 858 bus_space_write_1(iot, ioh, EEPROM_REG, what); 859 delay(1); 860 } 861 862 static inline int 863 eepromreadbit(bus_space_tag_t iot, bus_space_handle_t ioh) 864 { 865 int b; 866 867 bus_space_write_1(iot, ioh, EEPROM_REG, EECS | EESK); 868 delay(1); 869 b = bus_space_read_1(iot, ioh, EEPROM_REG); 870 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); 871 delay(1); 872 873 return ((b & EEDO) != 0); 874 } 875 876 static uint16_t 877 eepromread(bus_space_tag_t iot, bus_space_handle_t ioh, int offset) 878 { 879 volatile int i; 880 volatile int j; 881 volatile uint16_t readval; 882 883 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 884 delay(1); 885 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); /* XXXX??? */ 886 delay(1); 887 888 eepromwritebit(iot, ioh, EECS | EEDI); 889 eepromwritebit(iot, ioh, EECS | EEDI); 890 eepromwritebit(iot, ioh, EECS); 891 892 for (j=5; j>=0; --j) { 893 if ((offset>>j) & 1) 894 eepromwritebit(iot, ioh, EECS | EEDI); 895 else 896 eepromwritebit(iot, ioh, EECS); 897 } 898 899 for (readval=0, i=0; i<16; ++i) { 900 readval<<=1; 901 readval |= eepromreadbit(iot, ioh); 902 } 903 904 bus_space_write_1(iot, ioh, EEPROM_REG, 0 | EESK); 905 delay(1); 906 bus_space_write_1(iot, ioh, EEPROM_REG, 0); 907 908 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 909 910 return readval; 911 } 912 913 /* 914 * Device timeout/watchdog routine. Entered if the device neglects to generate 915 * an interrupt after a transmit has been started on it. 916 */ 917 void 918 iywatchdog(struct ifnet *ifp) 919 { 920 struct iy_softc *sc = ifp->if_softc; 921 922 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 923 ++sc->sc_ethercom.ec_if.if_oerrors; 924 iyreset(sc); 925 } 926 927 /* 928 * What to do upon receipt of an interrupt. 929 */ 930 int 931 iyintr(void *arg) 932 { 933 struct iy_softc *sc; 934 struct ifnet *ifp; 935 bus_space_tag_t iot; 936 bus_space_handle_t ioh; 937 938 u_short status; 939 940 sc = arg; 941 iot = sc->sc_iot; 942 ioh = sc->sc_ioh; 943 944 ifp = &sc->sc_ethercom.ec_if; 945 946 status = bus_space_read_1(iot, ioh, STATUS_REG); 947 #ifdef IYDEBUG 948 if (status & ALL_INTS) { 949 char sbuf[128]; 950 951 snprintb(sbuf, sizeof(sbuf), "\020\1RX_STP\2RX\3TX\4EXEC", 952 status); 953 printf("%s: got interrupt %s", device_xname(sc->sc_dev), sbuf); 954 955 if (status & EXEC_INT) { 956 snprintb(sbuf, sizeof(sbuf), 957 "\020\6ABORT", bus_space_read_1(iot, ioh, 0)); 958 printf(" event %s\n", sbuf); 959 } else 960 printf("\n"); 961 } 962 #endif 963 if ((status & (RX_INT | TX_INT)) == 0) 964 return 0; 965 966 if (status & RX_INT) { 967 iy_intr_rx(sc); 968 bus_space_write_1(iot, ioh, STATUS_REG, RX_INT); 969 } 970 if (status & TX_INT) { 971 /* Tell feeders we may be able to accept more data... */ 972 ifp->if_flags &= ~IFF_OACTIVE; 973 /* and get more data. */ 974 iystart(ifp); 975 bus_space_write_1(iot, ioh, STATUS_REG, TX_INT); 976 } 977 978 rnd_add_uint32(&sc->rnd_source, status); 979 980 return 1; 981 } 982 983 void 984 iyget(struct iy_softc *sc, bus_space_tag_t iot, bus_space_handle_t ioh, 985 int rxlen) 986 { 987 struct mbuf *m, *top, **mp; 988 struct ifnet *ifp; 989 int len; 990 991 ifp = &sc->sc_ethercom.ec_if; 992 993 MGETHDR(m, M_DONTWAIT, MT_DATA); 994 if (m == 0) 995 goto dropped; 996 m_set_rcvif(m, ifp); 997 m->m_pkthdr.len = rxlen; 998 len = MHLEN; 999 top = 0; 1000 mp = ⊤ 1001 1002 while (rxlen > 0) { 1003 if (top) { 1004 MGET(m, M_DONTWAIT, MT_DATA); 1005 if (m == 0) { 1006 m_freem(top); 1007 goto dropped; 1008 } 1009 len = MLEN; 1010 } 1011 if (rxlen >= MINCLSIZE) { 1012 MCLGET(m, M_DONTWAIT); 1013 if ((m->m_flags & M_EXT) == 0) { 1014 m_free(m); 1015 m_freem(top); 1016 goto dropped; 1017 } 1018 len = MCLBYTES; 1019 } 1020 len = uimin(rxlen, len); 1021 /* 1022 * XXX ALIGNMENT LOSSAGE HERE. 1023 */ 1024 if (len > 1) { 1025 len &= ~1; 1026 1027 bus_space_read_multi_stream_2(iot, ioh, MEM_PORT_REG, 1028 mtod(m, uint16_t *), len / 2); 1029 } else { 1030 #ifdef IYDEBUG 1031 printf("%s: received odd mbuf\n", 1032 device_xname(sc->sc_dev)); 1033 #endif 1034 *(mtod(m, char *)) = bus_space_read_stream_2(iot, ioh, 1035 MEM_PORT_REG); 1036 } 1037 m->m_len = len; 1038 rxlen -= len; 1039 *mp = m; 1040 mp = &m->m_next; 1041 } 1042 1043 if (top == NULL) 1044 return; 1045 1046 if_percpuq_enqueue(ifp->if_percpuq, top); 1047 return; 1048 1049 dropped: 1050 ++ifp->if_ierrors; 1051 return; 1052 } 1053 1054 void 1055 iy_intr_rx(struct iy_softc *sc) 1056 { 1057 bus_space_tag_t iot; 1058 bus_space_handle_t ioh; 1059 1060 u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen; 1061 1062 iot = sc->sc_iot; 1063 ioh = sc->sc_ioh; 1064 1065 rxadrs = sc->rx_start; 1066 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxadrs); 1067 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 1068 rxnext = 0; 1069 1070 while (rxevnt == RCV_DONE) { 1071 rxstatus = le16toh(bus_space_read_stream_2(iot, ioh, 1072 MEM_PORT_REG)); 1073 rxnext = le16toh(bus_space_read_stream_2(iot, ioh, 1074 MEM_PORT_REG)); 1075 rxlen = le16toh(bus_space_read_stream_2(iot, ioh, 1076 MEM_PORT_REG)); 1077 #ifdef IYDEBUG 1078 { 1079 char sbuf[128]; 1080 1081 snprintb(sbuf, sizeof(sbuf), 1082 "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR" 1083 "\014CRCERR\015LENERR\016RCVOK\020TYP", rxstatus); 1084 1085 printf("%s: pck at 0x%04x stat %s next 0x%x len 0x%x\n", 1086 device_xname(sc->sc_dev), rxadrs, sbuf, rxnext, 1087 rxlen); 1088 } 1089 #else 1090 __USE(rxstatus); 1091 #endif 1092 iyget(sc, iot, ioh, rxlen); 1093 1094 /* move stop address */ 1095 bus_space_write_2(iot, ioh, RCV_STOP_LOW, 1096 rxnext == 0 ? sc->rx_size - 2 : rxnext - 2); 1097 1098 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxnext); 1099 rxadrs = rxnext; 1100 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, 1101 MEM_PORT_REG)); 1102 } 1103 sc->rx_start = rxnext; 1104 } 1105 1106 void 1107 iy_intr_tx(struct iy_softc *sc) 1108 { 1109 bus_space_tag_t iot; 1110 bus_space_handle_t ioh; 1111 struct ifnet *ifp; 1112 u_int txstatus, txstat2, txlen, txnext; 1113 1114 ifp = &sc->sc_ethercom.ec_if; 1115 iot = sc->sc_iot; 1116 ioh = sc->sc_ioh; 1117 1118 while (sc->tx_start != sc->tx_end) { 1119 bus_space_write_2(iot, ioh, HOST_ADDR_REG, sc->tx_start); 1120 txstatus = le16toh(bus_space_read_stream_2(iot, ioh, 1121 MEM_PORT_REG)); 1122 1123 if ((txstatus & (TX_DONE | CMD_MASK)) != (TX_DONE | XMT_CMD)) 1124 break; 1125 1126 txstat2 = le16toh(bus_space_read_stream_2(iot, ioh, 1127 MEM_PORT_REG)); 1128 txnext = le16toh(bus_space_read_stream_2(iot, ioh, 1129 MEM_PORT_REG)); 1130 txlen = le16toh(bus_space_read_stream_2(iot, ioh, 1131 MEM_PORT_REG)); 1132 #ifdef IYDEBUG 1133 { 1134 char sbuf[128]; 1135 1136 snprintb(sbuf, sizeof(sbuf), 1137 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF" 1138 "\011UND_RUN\012JERR\013LST_CRS" 1139 "\014LTCOL\016TX_OK\020COLL", txstat2); 1140 1141 printf("txstat 0x%x stat2 %s next 0x%x len 0x%x\n", 1142 txstatus, sbuf, txnext, txlen); 1143 } 1144 #endif 1145 if (txlen & CHAIN) 1146 sc->tx_start = txnext; 1147 else 1148 sc->tx_start = sc->tx_end; 1149 ifp->if_flags &= ~IFF_OACTIVE; 1150 1151 if (txstat2 & 0x0020) 1152 ifp->if_collisions += 16; 1153 else 1154 ifp->if_collisions += txstat2 & 0x000f; 1155 1156 if ((txstat2 & 0x2000) == 0) 1157 ++ifp->if_oerrors; 1158 } 1159 } 1160 1161 int 1162 iyioctl(struct ifnet *ifp, u_long cmd, void *data) 1163 { 1164 struct iy_softc *sc; 1165 struct ifaddr *ifa; 1166 int s, error = 0; 1167 1168 sc = ifp->if_softc; 1169 ifa = (struct ifaddr *)data; 1170 1171 #ifdef IYDEBUG 1172 printf("iyioctl called with ifp %p (%s) cmd 0x%lx data %p\n", 1173 ifp, ifp->if_xname, cmd, data); 1174 #endif 1175 1176 s = splnet(); 1177 1178 switch (cmd) { 1179 1180 case SIOCINITIFADDR: 1181 ifp->if_flags |= IFF_UP; 1182 1183 iyinit(sc); 1184 switch (ifa->ifa_addr->sa_family) { 1185 #ifdef INET 1186 case AF_INET: 1187 arp_ifinit(ifp, ifa); 1188 break; 1189 #endif 1190 default: 1191 break; 1192 } 1193 break; 1194 1195 case SIOCSIFFLAGS: 1196 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 1197 break; 1198 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI); 1199 /* XXX re-use ether_ioctl() */ 1200 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 1201 case IFF_RUNNING: 1202 /* 1203 * If interface is marked down and it is running, then 1204 * stop it. 1205 */ 1206 iystop(sc); 1207 ifp->if_flags &= ~IFF_RUNNING; 1208 break; 1209 case IFF_UP: 1210 /* 1211 * If interface is marked up and it is stopped, then 1212 * start it. 1213 */ 1214 iyinit(sc); 1215 break; 1216 default: 1217 /* 1218 * Reset the interface to pick up changes in any other 1219 * flags that affect hardware registers. 1220 */ 1221 iystop(sc); 1222 iyinit(sc); 1223 break; 1224 } 1225 #ifdef IYDEBUGX 1226 if (ifp->if_flags & IFF_DEBUG) 1227 sc->sc_debug = IFY_ALL; 1228 else 1229 sc->sc_debug = 0; 1230 #endif 1231 break; 1232 1233 case SIOCADDMULTI: 1234 case SIOCDELMULTI: 1235 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 1236 /* 1237 * Multicast list has changed; set the hardware filter 1238 * accordingly. 1239 */ 1240 if (ifp->if_flags & IFF_RUNNING) { 1241 /* XXX can't make it work otherwise */ 1242 iyreset(sc); 1243 iy_mc_reset(sc); 1244 } 1245 error = 0; 1246 } 1247 break; 1248 1249 default: 1250 error = ether_ioctl(ifp, cmd, data); 1251 } 1252 splx(s); 1253 return error; 1254 } 1255 1256 int 1257 iy_mediachange(struct ifnet *ifp) 1258 { 1259 struct iy_softc *sc = ifp->if_softc; 1260 1261 if (IFM_TYPE(sc->iy_ifmedia.ifm_media) != IFM_ETHER) 1262 return EINVAL; 1263 switch (IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 1264 case IFM_10_5: 1265 case IFM_10_2: 1266 case IFM_10_T: 1267 case IFM_AUTO: 1268 iystop(sc); 1269 iyinit(sc); 1270 return 0; 1271 default: 1272 return EINVAL; 1273 } 1274 } 1275 1276 void 1277 iy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1278 { 1279 struct iy_softc *sc = ifp->if_softc; 1280 1281 ifmr->ifm_active = sc->iy_media; 1282 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1283 } 1284 1285 1286 static void 1287 iy_mc_setup(struct iy_softc *sc) 1288 { 1289 struct ether_multi *enm; 1290 struct ether_multistep step; 1291 struct ethercom *ecp; 1292 struct ifnet *ifp; 1293 bus_space_tag_t iot; 1294 bus_space_handle_t ioh; 1295 int avail, last /*, end*/ , len; 1296 int timeout; 1297 volatile uint16_t dum; 1298 uint8_t temp; 1299 1300 1301 ecp = &sc->sc_ethercom; 1302 ifp = &ecp->ec_if; 1303 1304 iot = sc->sc_iot; 1305 ioh = sc->sc_ioh; 1306 1307 len = 6 * ecp->ec_multicnt; 1308 1309 avail = sc->tx_start - sc->tx_end; 1310 if (avail <= 0) 1311 avail += sc->tx_size; 1312 if (ifp->if_flags & IFF_DEBUG) 1313 printf("%s: iy_mc_setup called, %d addresses, " 1314 "%d/%d bytes needed/avail\n", ifp->if_xname, 1315 ecp->ec_multicnt, len + I595_XMT_HDRLEN, avail); 1316 1317 last = sc->rx_size; 1318 1319 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1320 bus_space_write_1(iot, ioh, RECV_MODES_REG, MATCH_BRDCST); 1321 /* XXX VOODOO */ 1322 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1323 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1324 /* XXX END OF VOODOO */ 1325 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1326 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 1327 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(MC_SETUP_CMD)); 1328 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1329 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1330 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(len)); 1331 1332 ETHER_LOCK(ecp); 1333 ETHER_FIRST_MULTI(step, ecp, enm); 1334 while (enm) { 1335 /* 1336 * XXX ALIGNMENT LOSSAGE HERE? 1337 */ 1338 bus_space_write_multi_stream_2(iot, ioh, MEM_PORT_REG, 1339 (uint16_t *) enm->enm_addrlo, 3); 1340 1341 ETHER_NEXT_MULTI(step, enm); 1342 } 1343 ETHER_UNLOCK(ecp); 1344 dum = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */ 1345 __USE(dum); 1346 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 1347 bus_space_write_1(iot, ioh, 0, MC_SETUP_CMD); 1348 1349 1350 sc->tx_start = sc->rx_size; 1351 sc->tx_end = sc->rx_size + I595_XMT_HDRLEN + len; 1352 1353 for (timeout=0; timeout<100; timeout++) { 1354 DELAY(2); 1355 if ((bus_space_read_1(iot, ioh, STATUS_REG) & EXEC_INT) == 0) 1356 continue; 1357 1358 temp = bus_space_read_1(iot, ioh, 0); 1359 bus_space_write_1(iot, ioh, STATUS_REG, EXEC_INT); 1360 #ifdef DIAGNOSTIC 1361 if (temp & 0x20) { 1362 aprint_error_dev(sc->sc_dev, 1363 "mc setup failed, %d usec\n", timeout * 2); 1364 } else if (((temp & 0x0f) == 0x03) && 1365 (ifp->if_flags & IFF_DEBUG)) { 1366 printf("%s: mc setup done, %d usec\n", 1367 device_xname(sc->sc_dev), timeout * 2); 1368 } 1369 #endif 1370 break; 1371 } 1372 sc->tx_start = sc->tx_end; 1373 ifp->if_flags &= ~IFF_OACTIVE; 1374 1375 } 1376 1377 static void 1378 iy_mc_reset(struct iy_softc *sc) 1379 { 1380 struct ether_multi *enm; 1381 struct ether_multistep step; 1382 struct ethercom *ecp; 1383 struct ifnet *ifp; 1384 bus_space_tag_t iot; 1385 bus_space_handle_t ioh; 1386 uint16_t temp; 1387 1388 ecp = &sc->sc_ethercom; 1389 ifp = &ecp->ec_if; 1390 1391 iot = sc->sc_iot; 1392 ioh = sc->sc_ioh; 1393 1394 if (ecp->ec_multicnt > 63) { 1395 ifp->if_flags |= IFF_ALLMULTI; 1396 1397 } else if (ecp->ec_multicnt > 0) { 1398 /* 1399 * Step through the list of addresses. 1400 */ 1401 ETHER_LOCK(ecp); 1402 ETHER_FIRST_MULTI(step, ecp, enm); 1403 while (enm) { 1404 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { 1405 ifp->if_flags |= IFF_ALLMULTI; 1406 ETHER_UNLOCK(ecp); 1407 goto setupmulti; 1408 } 1409 ETHER_NEXT_MULTI(step, enm); 1410 } 1411 ETHER_UNLOCK(ecp); 1412 /* OK, we really need to do it now: */ 1413 #if 0 1414 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) 1415 != IFF_RUNNING) { 1416 ifp->if_flags |= IFF_OACTIVE; 1417 sc->want_mc_setup = 1; 1418 return; 1419 } 1420 #endif 1421 iy_mc_setup(sc); 1422 } else { 1423 ifp->if_flags &= ~IFF_ALLMULTI; 1424 } 1425 1426 setupmulti: 1427 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1428 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) 1429 temp = MATCH_ALL; 1430 else 1431 temp = MATCH_BRDCST; 1432 1433 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 1434 /* XXX VOODOO */ 1435 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1436 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1437 /* XXX END OF VOODOO */ 1438 1439 /* XXX TBD: setup hardware for all multicasts */ 1440 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1441 return; 1442 } 1443 1444 #ifdef IYDEBUGX 1445 void 1446 print_rbd(volatile struct ie_recv_buf_desc *rbd) 1447 { 1448 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n" 1449 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual, 1450 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length, 1451 rbd->mbz); 1452 } 1453 #endif 1454 1455 void 1456 iyprobemem(struct iy_softc *sc) 1457 { 1458 bus_space_tag_t iot; 1459 bus_space_handle_t ioh; 1460 int testing; 1461 1462 iot = sc->sc_iot; 1463 ioh = sc->sc_ioh; 1464 1465 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 1466 delay(1); 1467 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 4096-2); 1468 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1469 1470 for (testing=65536; testing >= 4096; testing >>= 1) { 1471 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1472 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xdead); 1473 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1474 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xdead) { 1475 #ifdef IYMEMDEBUG 1476 printf("%s: Didn't keep 0xdead at 0x%x\n", 1477 device_xname(sc->sc_dev), testing-2); 1478 #endif 1479 continue; 1480 } 1481 1482 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1483 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xbeef); 1484 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1485 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xbeef) { 1486 #ifdef IYMEMDEBUG 1487 printf("%s: Didn't keep 0xbeef at 0x%x\n", 1488 device_xname(sc->sc_dev), testing-2); 1489 #endif 1490 continue; 1491 } 1492 1493 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1494 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1495 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing >> 1); 1496 bus_space_write_2(iot, ioh, MEM_PORT_REG, testing >> 1); 1497 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1498 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) == (testing >> 1)) { 1499 #ifdef IYMEMDEBUG 1500 printf("%s: 0x%x alias of 0x0\n", 1501 device_xname(sc->sc_dev), testing >> 1); 1502 #endif 1503 continue; 1504 } 1505 1506 break; 1507 } 1508 1509 sc->sram = testing; 1510 1511 switch (testing) { 1512 case 65536: 1513 /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */ 1514 sc->rx_size = 44*1024; 1515 break; 1516 1517 case 32768: 1518 /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */ 1519 sc->rx_size = 22*1024; 1520 break; 1521 1522 case 16384: 1523 /* 1 NFS packet + overhead RX, 4 big packets TX */ 1524 sc->rx_size = 10*1024; 1525 break; 1526 default: 1527 sc->rx_size = testing/2; 1528 break; 1529 } 1530 sc->tx_size = testing - sc->rx_size; 1531 } 1532 1533 static int 1534 eepromreadall(bus_space_tag_t iot, bus_space_handle_t ioh, uint16_t *wordp, 1535 int maxi) 1536 { 1537 int i; 1538 uint16_t checksum, tmp; 1539 1540 checksum = 0; 1541 1542 for (i=0; i<EEPP_LENGTH; ++i) { 1543 tmp = eepromread(iot, ioh, i); 1544 checksum += tmp; 1545 if (i<maxi) 1546 wordp[i] = tmp; 1547 } 1548 1549 if (checksum != EEPP_CHKSUM) { 1550 #ifdef IYDEBUG 1551 printf("wrong EEPROM checksum 0x%x should be 0x%x\n", 1552 checksum, EEPP_CHKSUM); 1553 #endif 1554 return 1; 1555 } 1556 return 0; 1557 } 1558