1 /* $NetBSD: if_iy.c,v 1.102 2018/06/26 06:48:01 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.102 2018/06/26 06:48:01 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 64 #include <net/if_ether.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 #if defined(SIOCSIFMEDIA) 76 #include <net/if_media.h> 77 #endif 78 79 #include <sys/cpu.h> 80 #include <sys/bus.h> 81 #include <sys/intr.h> 82 83 #include <dev/isa/isareg.h> 84 #include <dev/isa/isavar.h> 85 #include <dev/ic/i82595reg.h> 86 87 /* XXX why isn't this centralized? */ 88 #ifndef __BUS_SPACE_HAS_STREAM_METHODS 89 #define bus_space_write_stream_2 bus_space_write_2 90 #define bus_space_write_multi_stream_2 bus_space_write_multi_2 91 #define bus_space_read_stream_2 bus_space_read_2 92 #define bus_space_read_multi_stream_2 bus_space_read_multi_2 93 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */ 94 95 /* 96 * Ethernet status, per interface. 97 */ 98 struct iy_softc { 99 device_t sc_dev; 100 void *sc_ih; 101 102 bus_space_tag_t sc_iot; 103 bus_space_handle_t sc_ioh; 104 105 struct ethercom sc_ethercom; 106 107 struct ifmedia iy_ifmedia; 108 int iy_media; 109 110 int mappedirq; 111 112 int hard_vers; 113 114 int promisc; 115 116 int sram, tx_size, rx_size; 117 118 int tx_start, tx_end, tx_last; 119 int rx_start; 120 121 int doing_mc_setup; 122 #ifdef IYDEBUG 123 int sc_debug; 124 #endif 125 126 krndsource_t rnd_source; 127 }; 128 129 void iywatchdog(struct ifnet *); 130 int iyioctl(struct ifnet *, u_long, void *); 131 int iyintr(void *); 132 void iyinit(struct iy_softc *); 133 void iystop(struct iy_softc *); 134 void iystart(struct ifnet *); 135 136 void iy_intr_rx(struct iy_softc *); 137 void iy_intr_tx(struct iy_softc *); 138 139 void iyreset(struct iy_softc *); 140 void iy_readframe(struct iy_softc *, int); 141 void iy_drop_packet_buffer(struct iy_softc *); 142 void iy_find_mem_size(struct iy_softc *); 143 void iyrint(struct iy_softc *); 144 void iytint(struct iy_softc *); 145 void iyxmit(struct iy_softc *); 146 static void iy_mc_setup(struct iy_softc *); 147 static void iy_mc_reset(struct iy_softc *); 148 void iyget(struct iy_softc *, bus_space_tag_t, bus_space_handle_t, int); 149 void iyprobemem(struct iy_softc *); 150 static inline void eepromwritebit(bus_space_tag_t, bus_space_handle_t, int); 151 static inline int eepromreadbit(bus_space_tag_t, bus_space_handle_t); 152 153 #ifdef IYDEBUGX 154 void print_rbd(volatile struct iy_recv_buf_desc *); 155 156 int in_ifrint = 0; 157 int in_iftint = 0; 158 #endif 159 160 int iy_mediachange(struct ifnet *); 161 void iy_mediastatus(struct ifnet *, struct ifmediareq *); 162 163 int iyprobe(device_t, cfdata_t, void *); 164 void iyattach(device_t, device_t, void *); 165 166 static u_int16_t eepromread(bus_space_tag_t, bus_space_handle_t, int); 167 168 static int eepromreadall(bus_space_tag_t, bus_space_handle_t, u_int16_t *, 169 int); 170 171 CFATTACH_DECL_NEW(iy, sizeof(struct iy_softc), 172 iyprobe, iyattach, NULL, NULL); 173 174 static u_int8_t eepro_irqmap[] = EEPP_INTMAP; 175 static u_int8_t eepro_revirqmap[] = EEPP_RINTMAP; 176 177 int 178 iyprobe(device_t parent, cfdata_t match, void *aux) 179 { 180 struct isa_attach_args *ia = aux; 181 u_int16_t eaddr[8]; 182 bus_space_tag_t iot; 183 bus_space_handle_t ioh; 184 u_int8_t c, d; 185 int irq; 186 187 if (ia->ia_nio < 1) 188 return (0); 189 if (ia->ia_nirq < 1) 190 return (0); 191 192 if (ISA_DIRECT_CONFIG(ia)) 193 return (0); 194 195 iot = ia->ia_iot; 196 197 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 198 return 0; 199 200 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) 201 return 0; 202 203 /* try to find the round robin sig: */ 204 205 c = bus_space_read_1(iot, ioh, ID_REG); 206 if ((c & ID_REG_MASK) != ID_REG_SIG) 207 goto out; 208 209 d = bus_space_read_1(iot, ioh, ID_REG); 210 if ((d & ID_REG_MASK) != ID_REG_SIG) 211 goto out; 212 213 if (((d-c) & R_ROBIN_BITS) != 0x40) 214 goto out; 215 216 d = bus_space_read_1(iot, ioh, ID_REG); 217 if ((d & ID_REG_MASK) != ID_REG_SIG) 218 goto out; 219 220 if (((d-c) & R_ROBIN_BITS) != 0x80) 221 goto out; 222 223 d = bus_space_read_1(iot, ioh, ID_REG); 224 if ((d & ID_REG_MASK) != ID_REG_SIG) 225 goto out; 226 227 if (((d-c) & R_ROBIN_BITS) != 0xC0) 228 goto out; 229 230 d = bus_space_read_1(iot, ioh, ID_REG); 231 if ((d & ID_REG_MASK) != ID_REG_SIG) 232 goto out; 233 234 if (((d-c) & R_ROBIN_BITS) != 0x00) 235 goto out; 236 237 #ifdef IYDEBUG 238 printf("iyprobe verified working ID reg.\n"); 239 #endif 240 241 if (eepromreadall(iot, ioh, eaddr, 8)) 242 goto out; 243 244 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 245 irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int]; 246 else 247 irq = ia->ia_irq[0].ir_irq; 248 249 if (irq >= sizeof(eepro_revirqmap)) 250 goto out; 251 252 if (eepro_revirqmap[irq] == 0xff) 253 goto out; 254 255 /* now lets reset the chip */ 256 257 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 258 delay(200); 259 260 ia->ia_nio = 1; 261 ia->ia_io[0].ir_size = 16; 262 263 ia->ia_nirq = 1; 264 ia->ia_irq[0].ir_irq = irq; 265 266 ia->ia_niomem = 0; 267 ia->ia_ndrq = 0; 268 269 bus_space_unmap(iot, ioh, 16); 270 return 1; /* found */ 271 out: 272 bus_space_unmap(iot, ioh, 16); 273 return 0; 274 } 275 276 void 277 iyattach(device_t parent, device_t self, void *aux) 278 { 279 struct iy_softc *sc = device_private(self); 280 struct isa_attach_args *ia = aux; 281 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 282 bus_space_tag_t iot; 283 bus_space_handle_t ioh; 284 unsigned temp; 285 u_int16_t eaddr[8]; 286 u_int8_t myaddr[ETHER_ADDR_LEN]; 287 int eirq; 288 289 iot = ia->ia_iot; 290 291 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) { 292 aprint_error(": can't map i/o space\n"); 293 return; 294 } 295 296 sc->sc_iot = iot; 297 sc->sc_ioh = ioh; 298 299 sc->mappedirq = eepro_revirqmap[ia->ia_irq[0].ir_irq]; 300 301 /* now let's reset the chip */ 302 303 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 304 delay(200); 305 306 iyprobemem(sc); 307 308 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 309 ifp->if_softc = sc; 310 ifp->if_start = iystart; 311 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS 312 | IFF_MULTICAST; 313 314 sc->doing_mc_setup = 0; 315 316 ifp->if_ioctl = iyioctl; 317 ifp->if_watchdog = iywatchdog; 318 319 IFQ_SET_READY(&ifp->if_snd); 320 321 (void)eepromreadall(iot, ioh, eaddr, 8); 322 sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev; 323 324 #ifdef DIAGNOSTICS 325 if ((eaddr[EEPPEther0] != 326 eepromread(iot, ioh, EEPPEther0a)) && 327 (eaddr[EEPPEther1] != 328 eepromread(iot, ioh, EEPPEther1a)) && 329 (eaddr[EEPPEther2] != 330 eepromread(iot, ioh, EEPPEther2a))) 331 332 aprint_error("EEPROM Ethernet address differs from copy\n"); 333 #endif 334 335 myaddr[1] = eaddr[EEPPEther0] & 0xFF; 336 myaddr[0] = eaddr[EEPPEther0] >> 8; 337 myaddr[3] = eaddr[EEPPEther1] & 0xFF; 338 myaddr[2] = eaddr[EEPPEther1] >> 8; 339 myaddr[5] = eaddr[EEPPEther2] & 0xFF; 340 myaddr[4] = eaddr[EEPPEther2] >> 8; 341 342 ifmedia_init(&sc->iy_ifmedia, 0, iy_mediachange, iy_mediastatus); 343 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_2, 0, NULL); 344 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_5, 0, NULL); 345 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL); 346 ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL); 347 ifmedia_set(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO); 348 /* Attach the interface. */ 349 if_attach(ifp); 350 ether_ifattach(ifp, myaddr); 351 aprint_normal(": address %s, rev. %d, %d kB\n", 352 ether_sprintf(myaddr), 353 sc->hard_vers, sc->sram/1024); 354 355 eirq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int]; 356 if (eirq != ia->ia_irq[0].ir_irq) 357 aprint_error("%s: EEPROM irq setting %d ignored\n", 358 device_xname(sc->sc_dev), eirq); 359 360 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 361 IST_EDGE, IPL_NET, iyintr, sc); 362 363 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 364 RND_TYPE_NET, RND_FLAG_DEFAULT); 365 366 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 367 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq); 368 } 369 370 void 371 iystop(struct iy_softc *sc) 372 { 373 bus_space_tag_t iot; 374 bus_space_handle_t ioh; 375 #ifdef IYDEBUG 376 u_int p, v; 377 #endif 378 379 iot = sc->sc_iot; 380 ioh = sc->sc_ioh; 381 382 bus_space_write_1(iot, ioh, COMMAND_REG, RCV_DISABLE_CMD); 383 384 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS); 385 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); 386 387 bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD); 388 delay(200); 389 #ifdef IYDEBUG 390 printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n", 391 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, sc->tx_last); 392 p = sc->tx_last; 393 if (!p) 394 p = sc->tx_start; 395 do { 396 char sbuf[128]; 397 398 bus_space_write_2(iot, ioh, HOST_ADDR_REG, p); 399 400 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 401 snprintb(sbuf, sizeof(sbuf), "\020\006Ab\010Dn", v); 402 printf("0x%04x: %s ", p, sbuf); 403 404 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 405 snprintb(sbuf, sizeof(sbuf), 406 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN" 407 "\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL", v); 408 printf("%s", sbuf); 409 410 p = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 411 printf(" 0x%04x", p); 412 413 v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 414 snprintb(sbuf, sizeof(sbuf), "\020\020Ch", v); 415 printf(" %s\n", sbuf); 416 417 } while (v & 0x8000); 418 #endif 419 sc->tx_start = sc->tx_end = sc->rx_size; 420 sc->tx_last = 0; 421 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 422 } 423 424 void 425 iyreset(struct iy_softc *sc) 426 { 427 int s; 428 s = splnet(); 429 iystop(sc); 430 iyinit(sc); 431 splx(s); 432 } 433 434 void 435 iyinit(struct iy_softc *sc) 436 { 437 int i; 438 unsigned temp; 439 struct ifnet *ifp; 440 bus_space_tag_t iot; 441 bus_space_handle_t ioh; 442 443 iot = sc->sc_iot; 444 ioh = sc->sc_ioh; 445 446 ifp = &sc->sc_ethercom.ec_if; 447 #ifdef IYDEBUG 448 printf("ifp is %p\n", ifp); 449 #endif 450 451 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 452 453 temp = bus_space_read_1(iot, ioh, EEPROM_REG); 454 if (temp & 0x10) 455 bus_space_write_1(iot, ioh, EEPROM_REG, temp & ~0x10); 456 457 for (i=0; i<6; ++i) { 458 bus_space_write_1(iot, ioh, I_ADD(i), CLLADDR(ifp->if_sadl)[i]); 459 } 460 461 temp = bus_space_read_1(iot, ioh, REG1); 462 bus_space_write_1(iot, ioh, REG1, 463 temp | /* XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | */ RCV_DISCARD_BAD); 464 465 if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) { 466 temp = MATCH_ALL; 467 } else 468 temp = MATCH_BRDCST; 469 470 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 471 472 #ifdef IYDEBUG 473 { 474 char sbuf[128]; 475 476 snprintb(sbuf, sizeof(sbuf), 477 "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA", 478 temp); 479 480 printf("%s: RECV_MODES set to %s\n", device_xname(sc->sc_dev), 481 sbuf); 482 } 483 #endif 484 /* XXX VOODOO */ 485 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 486 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 487 /* XXX END OF VOODOO */ 488 489 490 delay(500000); /* for the hardware to test for the connector */ 491 492 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 493 #ifdef IYDEBUG 494 { 495 char sbuf[128]; 496 497 snprintb(sbuf, sizeof(sbuf), 498 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC", 499 temp); 500 printf("%s: media select was %s ", device_xname(sc->sc_dev), 501 sbuf); 502 } 503 #endif 504 temp = (temp & TEST_MODE_MASK); 505 506 switch(IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 507 case IFM_10_5: 508 temp &= ~ (BNC_BIT | TPE_BIT); 509 break; 510 511 case IFM_10_2: 512 temp = (temp & ~TPE_BIT) | BNC_BIT; 513 break; 514 515 case IFM_10_T: 516 temp = (temp & ~BNC_BIT) | TPE_BIT; 517 break; 518 default: 519 ; 520 /* nothing; leave as it is */ 521 } 522 switch (temp & (BNC_BIT | TPE_BIT)) { 523 case BNC_BIT: 524 sc->iy_media = IFM_ETHER | IFM_10_2; 525 break; 526 case TPE_BIT: 527 sc->iy_media = IFM_ETHER | IFM_10_T; 528 break; 529 default: 530 sc->iy_media = IFM_ETHER | IFM_10_5; 531 } 532 533 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 534 #ifdef IYDEBUG 535 { 536 char sbuf[128]; 537 538 snprintb(sbuf, sizeof(sbuf), 539 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC", 540 temp); 541 printf("changed to %s\n", sbuf); 542 } 543 #endif 544 545 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 546 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS); 547 bus_space_write_1(iot, ioh, 0, BANK_SEL(1)); 548 549 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 550 bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq); 551 552 #ifdef IYDEBUG 553 { 554 char sbuf[128]; 555 556 snprintb(sbuf, sizeof(sbuf), 557 "\020\4bad_irq\010flash/boot present", temp); 558 559 printf("%s: int no was %s\n", device_xname(sc->sc_dev), sbuf); 560 561 temp = bus_space_read_1(iot, ioh, INT_NO_REG); 562 snprintb(sbuf, sizeof(sbuf), 563 "\020\4bad_irq\010flash/boot present", temp); 564 printf("%s: int no now %s\n", device_xname(sc->sc_dev), sbuf); 565 } 566 #endif 567 568 bus_space_write_1(iot, ioh, RCV_LOWER_LIMIT_REG, 0); 569 bus_space_write_1(iot, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size -2) >>8); 570 bus_space_write_1(iot, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >>8); 571 bus_space_write_1(iot, ioh, XMT_UPPER_LIMIT_REG, (sc->sram - 2) >>8); 572 573 temp = bus_space_read_1(iot, ioh, REG1); 574 #ifdef IYDEBUG 575 { 576 char sbuf[128]; 577 578 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE", 579 temp); 580 581 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf); 582 } 583 #endif 584 bus_space_write_1(iot, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */ 585 586 #ifdef IYDEBUG 587 { 588 char sbuf[128]; 589 590 temp = bus_space_read_1(iot, ioh, REG1); 591 snprintb(sbuf, sizeof(sbuf), "\020\2WORD_WIDTH\010INT_ENABLE", 592 temp); 593 printf("%s: HW access is %s\n", device_xname(sc->sc_dev), sbuf); 594 } 595 #endif 596 597 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 598 599 bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS & ~(RX_BIT|TX_BIT)); 600 bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); /* clear ints */ 601 602 bus_space_write_1(iot, ioh, RCV_COPY_THRESHOLD, 0); 603 604 bus_space_write_2(iot, ioh, RCV_START_LOW, 0); 605 bus_space_write_2(iot, ioh, RCV_STOP_LOW, sc->rx_size - 2); 606 sc->rx_start = 0; 607 608 bus_space_write_1(iot, ioh, 0, SEL_RESET_CMD); 609 delay(200); 610 611 bus_space_write_2(iot, ioh, XMT_ADDR_REG, sc->rx_size); 612 613 sc->tx_start = sc->tx_end = sc->rx_size; 614 sc->tx_last = 0; 615 616 bus_space_write_1(iot, ioh, 0, RCV_ENABLE_CMD); 617 618 ifp->if_flags |= IFF_RUNNING; 619 ifp->if_flags &= ~IFF_OACTIVE; 620 } 621 622 void 623 iystart(struct ifnet *ifp) 624 { 625 struct iy_softc *sc; 626 627 628 struct mbuf *m0, *m; 629 u_int len, pad, last, end; 630 u_int llen, residual; 631 int avail; 632 char *data; 633 unsigned temp; 634 u_int16_t resval, stat; 635 bus_space_tag_t iot; 636 bus_space_handle_t ioh; 637 638 #ifdef IYDEBUG 639 printf("iystart called\n"); 640 #endif 641 sc = ifp->if_softc; 642 643 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 644 return; 645 646 iy_intr_tx(sc); 647 648 iot = sc->sc_iot; 649 ioh = sc->sc_ioh; 650 651 for (;;) { 652 IFQ_POLL(&ifp->if_snd, m0); 653 if (m0 == NULL) 654 break; 655 #ifdef IYDEBUG 656 printf("%s: trying to write another packet to the hardware\n", 657 device_xname(sc->sc_dev)); 658 #endif 659 660 /* We need to use m->m_pkthdr.len, so require the header */ 661 if ((m0->m_flags & M_PKTHDR) == 0) 662 panic("iystart: no header mbuf"); 663 664 len = m0->m_pkthdr.len; 665 pad = len & 1; 666 667 #ifdef IYDEBUG 668 printf("%s: length is %d.\n", device_xname(sc->sc_dev), len); 669 #endif 670 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 671 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len; 672 } 673 674 if (len + pad > ETHER_MAX_LEN) { 675 /* packet is obviously too large: toss it */ 676 ++ifp->if_oerrors; 677 IFQ_DEQUEUE(&ifp->if_snd, m0); 678 m_freem(m0); 679 continue; 680 } 681 682 bpf_mtap(ifp, m0, BPF_D_OUT); 683 684 avail = sc->tx_start - sc->tx_end; 685 if (avail <= 0) 686 avail += sc->tx_size; 687 688 #ifdef IYDEBUG 689 printf("%s: avail is %d.\n", device_xname(sc->sc_dev), avail); 690 #endif 691 /* 692 * we MUST RUN at splnet here --- 693 * XXX todo: or even turn off the boards ints ??? hm... 694 */ 695 696 /* See if there is room to put another packet in the buffer. */ 697 698 if ((len+pad+2*I595_XMT_HDRLEN) > avail) { 699 #ifdef IYDEBUG 700 printf("%s: len = %d, avail = %d, setting OACTIVE\n", 701 device_xname(sc->sc_dev), len, avail); 702 #endif 703 /* mark interface as full ... */ 704 ifp->if_flags |= IFF_OACTIVE; 705 706 /* and wait for any transmission result */ 707 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 708 709 temp = bus_space_read_1(iot, ioh, REG1); 710 bus_space_write_1(iot, ioh, REG1, 711 temp & ~XMT_CHAIN_INT); 712 713 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 714 715 return; 716 } 717 718 /* we know it fits in the hardware now, so dequeue it */ 719 IFQ_DEQUEUE(&ifp->if_snd, m0); 720 721 last = sc->tx_end; 722 end = last + pad + len + I595_XMT_HDRLEN; 723 724 if (end >= sc->sram) { 725 if ((sc->sram - last) <= I595_XMT_HDRLEN) { 726 /* keep header in one piece */ 727 last = sc->rx_size; 728 end = last + pad + len + I595_XMT_HDRLEN; 729 } else 730 end -= sc->tx_size; 731 } 732 733 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 734 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 735 htole16(XMT_CMD)); 736 737 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 738 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 739 740 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 741 htole16(len + pad)); 742 743 residual = resval = 0; 744 745 while ((m = m0)!=0) { 746 data = mtod(m, void *); 747 llen = m->m_len; 748 if (residual) { 749 #ifdef IYDEBUG 750 printf("%s: merging residual with next mbuf.\n", 751 device_xname(sc->sc_dev)); 752 #endif 753 resval |= *data << 8; 754 bus_space_write_stream_2(iot, ioh, 755 MEM_PORT_REG, resval); 756 --llen; 757 ++data; 758 } 759 /* 760 * XXX ALIGNMENT LOSSAGE HERE. 761 */ 762 if (llen > 1) 763 bus_space_write_multi_stream_2(iot, ioh, 764 MEM_PORT_REG, (u_int16_t *) data, 765 llen>>1); 766 residual = llen & 1; 767 if (residual) { 768 resval = *(data + llen - 1); 769 #ifdef IYDEBUG 770 printf("%s: got odd mbuf to send.\n", 771 device_xname(sc->sc_dev)); 772 #endif 773 } 774 775 m0 = m_free(m); 776 } 777 778 if (residual) 779 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 780 resval); 781 782 pad >>= 1; 783 while (pad-- > 0) 784 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 0); 785 786 #ifdef IYDEBUG 787 printf("%s: new last = 0x%x, end = 0x%x.\n", 788 device_xname(sc->sc_dev), last, end); 789 printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n", 790 device_xname(sc->sc_dev), sc->tx_start, sc->tx_end, 791 sc->tx_last); 792 #endif 793 794 if (sc->tx_start != sc->tx_end) { 795 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 796 sc->tx_last + XMT_COUNT); 797 798 /* 799 * XXX We keep stat in le order, to potentially save 800 * a byte swap. 801 */ 802 stat = bus_space_read_stream_2(iot, ioh, MEM_PORT_REG); 803 804 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 805 sc->tx_last + XMT_CHAIN); 806 807 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 808 htole16(last)); 809 810 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 811 stat | htole16(CHAIN)); 812 #ifdef IYDEBUG 813 printf("%s: setting 0x%x to 0x%x\n", 814 device_xname(sc->sc_dev), sc->tx_last + XMT_COUNT, 815 le16toh(stat) | CHAIN); 816 #endif 817 } 818 stat = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */ 819 820 /* XXX todo: enable ints here if disabled */ 821 822 ++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 u_int16_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 u_int16_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 ++sc->sc_ethercom.ec_if.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 = min(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, u_int16_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 ++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 ifp->if_collisions += 16; 1154 else 1155 ifp->if_collisions += txstat2 & 0x000f; 1156 1157 if ((txstat2 & 0x2000) == 0) 1158 ++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 struct ifreq *ifr; 1168 int s, error = 0; 1169 1170 sc = ifp->if_softc; 1171 ifa = (struct ifaddr *)data; 1172 ifr = (struct ifreq *)data; 1173 1174 #ifdef IYDEBUG 1175 printf("iyioctl called with ifp %p (%s) cmd 0x%lx data %p\n", 1176 ifp, ifp->if_xname, cmd, data); 1177 #endif 1178 1179 s = splnet(); 1180 1181 switch (cmd) { 1182 1183 case SIOCINITIFADDR: 1184 ifp->if_flags |= IFF_UP; 1185 1186 iyinit(sc); 1187 switch (ifa->ifa_addr->sa_family) { 1188 #ifdef INET 1189 case AF_INET: 1190 arp_ifinit(ifp, ifa); 1191 break; 1192 #endif 1193 default: 1194 break; 1195 } 1196 break; 1197 1198 case SIOCSIFFLAGS: 1199 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 1200 break; 1201 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI); 1202 /* XXX re-use ether_ioctl() */ 1203 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 1204 case IFF_RUNNING: 1205 /* 1206 * If interface is marked down and it is running, then 1207 * stop it. 1208 */ 1209 iystop(sc); 1210 ifp->if_flags &= ~IFF_RUNNING; 1211 break; 1212 case IFF_UP: 1213 /* 1214 * If interface is marked up and it is stopped, then 1215 * start it. 1216 */ 1217 iyinit(sc); 1218 break; 1219 default: 1220 /* 1221 * Reset the interface to pick up changes in any other 1222 * flags that affect hardware registers. 1223 */ 1224 iystop(sc); 1225 iyinit(sc); 1226 break; 1227 } 1228 #ifdef IYDEBUGX 1229 if (ifp->if_flags & IFF_DEBUG) 1230 sc->sc_debug = IFY_ALL; 1231 else 1232 sc->sc_debug = 0; 1233 #endif 1234 break; 1235 1236 case SIOCADDMULTI: 1237 case SIOCDELMULTI: 1238 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 1239 /* 1240 * Multicast list has changed; set the hardware filter 1241 * accordingly. 1242 */ 1243 if (ifp->if_flags & IFF_RUNNING) { 1244 /* XXX can't make it work otherwise */ 1245 iyreset(sc); 1246 iy_mc_reset(sc); 1247 } 1248 error = 0; 1249 } 1250 break; 1251 1252 case SIOCSIFMEDIA: 1253 case SIOCGIFMEDIA: 1254 error = ifmedia_ioctl(ifp, ifr, &sc->iy_ifmedia, cmd); 1255 break; 1256 default: 1257 error = ether_ioctl(ifp, cmd, data); 1258 } 1259 splx(s); 1260 return error; 1261 } 1262 1263 int 1264 iy_mediachange(struct ifnet *ifp) 1265 { 1266 struct iy_softc *sc = ifp->if_softc; 1267 1268 if (IFM_TYPE(sc->iy_ifmedia.ifm_media) != IFM_ETHER) 1269 return EINVAL; 1270 switch(IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 1271 case IFM_10_5: 1272 case IFM_10_2: 1273 case IFM_10_T: 1274 case IFM_AUTO: 1275 iystop(sc); 1276 iyinit(sc); 1277 return 0; 1278 default: 1279 return EINVAL; 1280 } 1281 } 1282 1283 void 1284 iy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1285 { 1286 struct iy_softc *sc = ifp->if_softc; 1287 1288 ifmr->ifm_active = sc->iy_media; 1289 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1290 } 1291 1292 1293 static void 1294 iy_mc_setup(struct iy_softc *sc) 1295 { 1296 struct ether_multi *enm; 1297 struct ether_multistep step; 1298 struct ethercom *ecp; 1299 struct ifnet *ifp; 1300 bus_space_tag_t iot; 1301 bus_space_handle_t ioh; 1302 int avail, last /*, end*/ , len; 1303 int timeout; 1304 volatile u_int16_t dum; 1305 u_int8_t temp; 1306 1307 1308 ecp = &sc->sc_ethercom; 1309 ifp = &ecp->ec_if; 1310 1311 iot = sc->sc_iot; 1312 ioh = sc->sc_ioh; 1313 1314 len = 6 * ecp->ec_multicnt; 1315 1316 avail = sc->tx_start - sc->tx_end; 1317 if (avail <= 0) 1318 avail += sc->tx_size; 1319 if (ifp->if_flags & IFF_DEBUG) 1320 printf("%s: iy_mc_setup called, %d addresses, " 1321 "%d/%d bytes needed/avail\n", ifp->if_xname, 1322 ecp->ec_multicnt, len + I595_XMT_HDRLEN, avail); 1323 1324 last = sc->rx_size; 1325 1326 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1327 bus_space_write_1(iot, ioh, RECV_MODES_REG, MATCH_BRDCST); 1328 /* XXX VOODOO */ 1329 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1330 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1331 /* XXX END OF VOODOO */ 1332 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1333 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 1334 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(MC_SETUP_CMD)); 1335 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1336 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1337 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(len)); 1338 1339 ETHER_FIRST_MULTI(step, ecp, enm); 1340 while(enm) { 1341 /* 1342 * XXX ALIGNMENT LOSSAGE HERE? 1343 */ 1344 bus_space_write_multi_stream_2(iot, ioh, MEM_PORT_REG, 1345 (u_int16_t *) enm->enm_addrlo, 3); 1346 1347 ETHER_NEXT_MULTI(step, enm); 1348 } 1349 dum = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */ 1350 __USE(dum); 1351 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 1352 bus_space_write_1(iot, ioh, 0, MC_SETUP_CMD); 1353 1354 1355 sc->tx_start = sc->rx_size; 1356 sc->tx_end = sc->rx_size + I595_XMT_HDRLEN + len; 1357 1358 for (timeout=0; timeout<100; timeout++) { 1359 DELAY(2); 1360 if ((bus_space_read_1(iot, ioh, STATUS_REG) & EXEC_INT) == 0) 1361 continue; 1362 1363 temp = bus_space_read_1(iot, ioh, 0); 1364 bus_space_write_1(iot, ioh, STATUS_REG, EXEC_INT); 1365 #ifdef DIAGNOSTIC 1366 if (temp & 0x20) { 1367 aprint_error_dev(sc->sc_dev, 1368 "mc setup failed, %d usec\n", timeout * 2); 1369 } else if (((temp & 0x0f) == 0x03) && 1370 (ifp->if_flags & IFF_DEBUG)) { 1371 printf("%s: mc setup done, %d usec\n", 1372 device_xname(sc->sc_dev), timeout * 2); 1373 } 1374 #endif 1375 break; 1376 } 1377 sc->tx_start = sc->tx_end; 1378 ifp->if_flags &= ~IFF_OACTIVE; 1379 1380 } 1381 1382 static void 1383 iy_mc_reset(struct iy_softc *sc) 1384 { 1385 struct ether_multi *enm; 1386 struct ether_multistep step; 1387 struct ethercom *ecp; 1388 struct ifnet *ifp; 1389 bus_space_tag_t iot; 1390 bus_space_handle_t ioh; 1391 u_int16_t temp; 1392 1393 ecp = &sc->sc_ethercom; 1394 ifp = &ecp->ec_if; 1395 1396 iot = sc->sc_iot; 1397 ioh = sc->sc_ioh; 1398 1399 if (ecp->ec_multicnt > 63) { 1400 ifp->if_flags |= IFF_ALLMULTI; 1401 1402 } else if (ecp->ec_multicnt > 0) { 1403 /* 1404 * Step through the list of addresses. 1405 */ 1406 ETHER_FIRST_MULTI(step, ecp, enm); 1407 while(enm) { 1408 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { 1409 ifp->if_flags |= IFF_ALLMULTI; 1410 goto setupmulti; 1411 } 1412 ETHER_NEXT_MULTI(step, enm); 1413 } 1414 /* OK, we really need to do it now: */ 1415 #if 0 1416 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) 1417 != IFF_RUNNING) { 1418 ifp->if_flags |= IFF_OACTIVE; 1419 sc->want_mc_setup = 1; 1420 return; 1421 } 1422 #endif 1423 iy_mc_setup(sc); 1424 } else { 1425 ifp->if_flags &= ~IFF_ALLMULTI; 1426 } 1427 1428 setupmulti: 1429 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1430 if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) { 1431 temp = MATCH_ALL; 1432 } else 1433 temp = MATCH_BRDCST; 1434 1435 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 1436 /* XXX VOODOO */ 1437 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1438 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1439 /* XXX END OF VOODOO */ 1440 1441 /* XXX TBD: setup hardware for all multicasts */ 1442 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1443 return; 1444 } 1445 1446 #ifdef IYDEBUGX 1447 void 1448 print_rbd(volatile struct ie_recv_buf_desc *rbd) 1449 { 1450 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n" 1451 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual, 1452 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length, 1453 rbd->mbz); 1454 } 1455 #endif 1456 1457 void 1458 iyprobemem(struct iy_softc *sc) 1459 { 1460 bus_space_tag_t iot; 1461 bus_space_handle_t ioh; 1462 int testing; 1463 1464 iot = sc->sc_iot; 1465 ioh = sc->sc_ioh; 1466 1467 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 1468 delay(1); 1469 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 4096-2); 1470 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1471 1472 for (testing=65536; testing >= 4096; testing >>= 1) { 1473 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1474 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xdead); 1475 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1476 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xdead) { 1477 #ifdef IYMEMDEBUG 1478 printf("%s: Didn't keep 0xdead at 0x%x\n", 1479 device_xname(sc->sc_dev), testing-2); 1480 #endif 1481 continue; 1482 } 1483 1484 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1485 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xbeef); 1486 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1487 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xbeef) { 1488 #ifdef IYMEMDEBUG 1489 printf("%s: Didn't keep 0xbeef at 0x%x\n", 1490 device_xname(sc->sc_dev), testing-2); 1491 #endif 1492 continue; 1493 } 1494 1495 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1496 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1497 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing >> 1); 1498 bus_space_write_2(iot, ioh, MEM_PORT_REG, testing >> 1); 1499 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1500 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) == (testing >> 1)) { 1501 #ifdef IYMEMDEBUG 1502 printf("%s: 0x%x alias of 0x0\n", 1503 device_xname(sc->sc_dev), testing >> 1); 1504 #endif 1505 continue; 1506 } 1507 1508 break; 1509 } 1510 1511 sc->sram = testing; 1512 1513 switch(testing) { 1514 case 65536: 1515 /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */ 1516 sc->rx_size = 44*1024; 1517 break; 1518 1519 case 32768: 1520 /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */ 1521 sc->rx_size = 22*1024; 1522 break; 1523 1524 case 16384: 1525 /* 1 NFS packet + overhead RX, 4 big packets TX */ 1526 sc->rx_size = 10*1024; 1527 break; 1528 default: 1529 sc->rx_size = testing/2; 1530 break; 1531 } 1532 sc->tx_size = testing - sc->rx_size; 1533 } 1534 1535 static int 1536 eepromreadall(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t *wordp, 1537 int maxi) 1538 { 1539 int i; 1540 u_int16_t checksum, tmp; 1541 1542 checksum = 0; 1543 1544 for (i=0; i<EEPP_LENGTH; ++i) { 1545 tmp = eepromread(iot, ioh, i); 1546 checksum += tmp; 1547 if (i<maxi) 1548 wordp[i] = tmp; 1549 } 1550 1551 if (checksum != EEPP_CHKSUM) { 1552 #ifdef IYDEBUG 1553 printf("wrong EEPROM checksum 0x%x should be 0x%x\n", 1554 checksum, EEPP_CHKSUM); 1555 #endif 1556 return 1; 1557 } 1558 return 0; 1559 } 1560