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