1 /* $NetBSD: if_iy.c,v 1.87 2010/01/19 22:06:59 pooka 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.87 2010/01/19 22:06:59 pooka 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 if (ifp->if_bpf) 690 bpf_ops->bpf_mtap(ifp->if_bpf, m0); 691 692 avail = sc->tx_start - sc->tx_end; 693 if (avail <= 0) 694 avail += sc->tx_size; 695 696 #ifdef IYDEBUG 697 printf("%s: avail is %d.\n", device_xname(&sc->sc_dev), avail); 698 #endif 699 /* 700 * we MUST RUN at splnet here --- 701 * XXX todo: or even turn off the boards ints ??? hm... 702 */ 703 704 /* See if there is room to put another packet in the buffer. */ 705 706 if ((len+pad+2*I595_XMT_HDRLEN) > avail) { 707 #ifdef IYDEBUG 708 printf("%s: len = %d, avail = %d, setting OACTIVE\n", 709 device_xname(&sc->sc_dev), len, avail); 710 #endif 711 /* mark interface as full ... */ 712 ifp->if_flags |= IFF_OACTIVE; 713 714 /* and wait for any transmission result */ 715 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 716 717 temp = bus_space_read_1(iot, ioh, REG1); 718 bus_space_write_1(iot, ioh, REG1, 719 temp & ~XMT_CHAIN_INT); 720 721 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 722 723 return; 724 } 725 726 /* we know it fits in the hardware now, so dequeue it */ 727 IFQ_DEQUEUE(&ifp->if_snd, m0); 728 729 last = sc->tx_end; 730 end = last + pad + len + I595_XMT_HDRLEN; 731 732 if (end >= sc->sram) { 733 if ((sc->sram - last) <= I595_XMT_HDRLEN) { 734 /* keep header in one piece */ 735 last = sc->rx_size; 736 end = last + pad + len + I595_XMT_HDRLEN; 737 } else 738 end -= sc->tx_size; 739 } 740 741 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 742 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 743 htole16(XMT_CMD)); 744 745 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 746 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 747 748 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 749 htole16(len + pad)); 750 751 residual = resval = 0; 752 753 while ((m = m0)!=0) { 754 data = mtod(m, void *); 755 llen = m->m_len; 756 if (residual) { 757 #ifdef IYDEBUG 758 printf("%s: merging residual with next mbuf.\n", 759 device_xname(&sc->sc_dev)); 760 #endif 761 resval |= *data << 8; 762 bus_space_write_stream_2(iot, ioh, 763 MEM_PORT_REG, resval); 764 --llen; 765 ++data; 766 } 767 /* 768 * XXX ALIGNMENT LOSSAGE HERE. 769 */ 770 if (llen > 1) 771 bus_space_write_multi_stream_2(iot, ioh, 772 MEM_PORT_REG, (u_int16_t *) data, 773 llen>>1); 774 residual = llen & 1; 775 if (residual) { 776 resval = *(data + llen - 1); 777 #ifdef IYDEBUG 778 printf("%s: got odd mbuf to send.\n", 779 device_xname(&sc->sc_dev)); 780 #endif 781 } 782 783 MFREE(m, m0); 784 } 785 786 if (residual) 787 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 788 resval); 789 790 pad >>= 1; 791 while (pad-- > 0) 792 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 0); 793 794 #ifdef IYDEBUG 795 printf("%s: new last = 0x%x, end = 0x%x.\n", 796 device_xname(&sc->sc_dev), last, end); 797 printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n", 798 device_xname(&sc->sc_dev), sc->tx_start, sc->tx_end, sc->tx_last); 799 #endif 800 801 if (sc->tx_start != sc->tx_end) { 802 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 803 sc->tx_last + XMT_COUNT); 804 805 /* 806 * XXX We keep stat in le order, to potentially save 807 * a byte swap. 808 */ 809 stat = bus_space_read_stream_2(iot, ioh, MEM_PORT_REG); 810 811 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 812 sc->tx_last + XMT_CHAIN); 813 814 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 815 htole16(last)); 816 817 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 818 stat | htole16(CHAIN)); 819 #ifdef IYDEBUG 820 printf("%s: setting 0x%x to 0x%x\n", 821 device_xname(&sc->sc_dev), sc->tx_last + XMT_COUNT, 822 le16toh(stat) | CHAIN); 823 #endif 824 } 825 stat = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */ 826 827 /* XXX todo: enable ints here if disabled */ 828 829 ++ifp->if_opackets; 830 831 if (sc->tx_start == sc->tx_end) { 832 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 833 bus_space_write_1(iot, ioh, 0, XMT_CMD); 834 sc->tx_start = last; 835 #ifdef IYDEBUG 836 printf("%s: writing 0x%x to XAR and giving XCMD\n", 837 device_xname(&sc->sc_dev), last); 838 #endif 839 } else { 840 bus_space_write_1(iot, ioh, 0, RESUME_XMT_CMD); 841 #ifdef IYDEBUG 842 printf("%s: giving RESUME_XCMD\n", 843 device_xname(&sc->sc_dev)); 844 #endif 845 } 846 sc->tx_last = last; 847 sc->tx_end = end; 848 } 849 /* and wait only for end of transmission chain */ 850 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 851 852 temp = bus_space_read_1(iot, ioh, REG1); 853 bus_space_write_1(iot, ioh, REG1, temp | XMT_CHAIN_INT); 854 855 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 856 } 857 858 859 static inline void 860 eepromwritebit(bus_space_tag_t iot, bus_space_handle_t ioh, int what) 861 { 862 bus_space_write_1(iot, ioh, EEPROM_REG, what); 863 delay(1); 864 bus_space_write_1(iot, ioh, EEPROM_REG, what|EESK); 865 delay(1); 866 bus_space_write_1(iot, ioh, EEPROM_REG, what); 867 delay(1); 868 } 869 870 static inline int 871 eepromreadbit(bus_space_tag_t iot, bus_space_handle_t ioh) 872 { 873 int b; 874 875 bus_space_write_1(iot, ioh, EEPROM_REG, EECS|EESK); 876 delay(1); 877 b = bus_space_read_1(iot, ioh, EEPROM_REG); 878 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); 879 delay(1); 880 881 return ((b & EEDO) != 0); 882 } 883 884 static u_int16_t 885 eepromread(bus_space_tag_t iot, bus_space_handle_t ioh, int offset) 886 { 887 volatile int i; 888 volatile int j; 889 volatile u_int16_t readval; 890 891 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 892 delay(1); 893 bus_space_write_1(iot, ioh, EEPROM_REG, EECS); /* XXXX??? */ 894 delay(1); 895 896 eepromwritebit(iot, ioh, EECS|EEDI); 897 eepromwritebit(iot, ioh, EECS|EEDI); 898 eepromwritebit(iot, ioh, EECS); 899 900 for (j=5; j>=0; --j) { 901 if ((offset>>j) & 1) 902 eepromwritebit(iot, ioh, EECS|EEDI); 903 else 904 eepromwritebit(iot, ioh, EECS); 905 } 906 907 for (readval=0, i=0; i<16; ++i) { 908 readval<<=1; 909 readval |= eepromreadbit(iot, ioh); 910 } 911 912 bus_space_write_1(iot, ioh, EEPROM_REG, 0|EESK); 913 delay(1); 914 bus_space_write_1(iot, ioh, EEPROM_REG, 0); 915 916 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 917 918 return readval; 919 } 920 921 /* 922 * Device timeout/watchdog routine. Entered if the device neglects to generate 923 * an interrupt after a transmit has been started on it. 924 */ 925 void 926 iywatchdog(struct ifnet *ifp) 927 { 928 struct iy_softc *sc = ifp->if_softc; 929 930 log(LOG_ERR, "%s: device timeout\n", device_xname(&sc->sc_dev)); 931 ++sc->sc_ethercom.ec_if.if_oerrors; 932 iyreset(sc); 933 } 934 935 /* 936 * What to do upon receipt of an interrupt. 937 */ 938 int 939 iyintr(void *arg) 940 { 941 struct iy_softc *sc; 942 struct ifnet *ifp; 943 bus_space_tag_t iot; 944 bus_space_handle_t ioh; 945 946 u_short status; 947 948 sc = arg; 949 iot = sc->sc_iot; 950 ioh = sc->sc_ioh; 951 952 ifp = &sc->sc_ethercom.ec_if; 953 954 status = bus_space_read_1(iot, ioh, STATUS_REG); 955 #ifdef IYDEBUG 956 if (status & ALL_INTS) { 957 char sbuf[128]; 958 959 snprintb(sbuf, sizeof(sbuf), "\020\1RX_STP\2RX\3TX\4EXEC", 960 status); 961 printf("%s: got interrupt %s", device_xname(&sc->sc_dev), sbuf); 962 963 if (status & EXEC_INT) { 964 snprintb(sbuf, sizeof(sbuf), 965 "\020\6ABORT", bus_space_read_1(iot, ioh, 0)); 966 printf(" event %s\n", sbuf); 967 } else 968 printf("\n"); 969 } 970 #endif 971 if ((status & (RX_INT | TX_INT)) == 0) 972 return 0; 973 974 if (status & RX_INT) { 975 iy_intr_rx(sc); 976 bus_space_write_1(iot, ioh, STATUS_REG, RX_INT); 977 } 978 if (status & TX_INT) { 979 /* Tell feeders we may be able to accept more data... */ 980 ifp->if_flags &= ~IFF_OACTIVE; 981 /* and get more data. */ 982 iystart(ifp); 983 bus_space_write_1(iot, ioh, STATUS_REG, TX_INT); 984 } 985 986 #if NRND > 0 987 rnd_add_uint32(&sc->rnd_source, status); 988 #endif 989 990 return 1; 991 } 992 993 void 994 iyget(struct iy_softc *sc, bus_space_tag_t iot, bus_space_handle_t ioh, int rxlen) 995 { 996 struct mbuf *m, *top, **mp; 997 struct ifnet *ifp; 998 int len; 999 1000 ifp = &sc->sc_ethercom.ec_if; 1001 1002 MGETHDR(m, M_DONTWAIT, MT_DATA); 1003 if (m == 0) 1004 goto dropped; 1005 m->m_pkthdr.rcvif = ifp; 1006 m->m_pkthdr.len = rxlen; 1007 len = MHLEN; 1008 top = 0; 1009 mp = ⊤ 1010 1011 while (rxlen > 0) { 1012 if (top) { 1013 MGET(m, M_DONTWAIT, MT_DATA); 1014 if (m == 0) { 1015 m_freem(top); 1016 goto dropped; 1017 } 1018 len = MLEN; 1019 } 1020 if (rxlen >= MINCLSIZE) { 1021 MCLGET(m, M_DONTWAIT); 1022 if ((m->m_flags & M_EXT) == 0) { 1023 m_free(m); 1024 m_freem(top); 1025 goto dropped; 1026 } 1027 len = MCLBYTES; 1028 } 1029 len = min(rxlen, len); 1030 /* 1031 * XXX ALIGNMENT LOSSAGE HERE. 1032 */ 1033 if (len > 1) { 1034 len &= ~1; 1035 1036 bus_space_read_multi_stream_2(iot, ioh, MEM_PORT_REG, 1037 mtod(m, u_int16_t *), len/2); 1038 } else { 1039 #ifdef IYDEBUG 1040 printf("%s: received odd mbuf\n", device_xname(&sc->sc_dev)); 1041 #endif 1042 *(mtod(m, char *)) = bus_space_read_stream_2(iot, ioh, 1043 MEM_PORT_REG); 1044 } 1045 m->m_len = len; 1046 rxlen -= len; 1047 *mp = m; 1048 mp = &m->m_next; 1049 } 1050 1051 if (top == NULL) 1052 return; 1053 1054 /* XXX receive the top here */ 1055 ++ifp->if_ipackets; 1056 1057 1058 if (ifp->if_bpf) 1059 bpf_ops->bpf_mtap(ifp->if_bpf, top); 1060 (*ifp->if_input)(ifp, top); 1061 return; 1062 1063 dropped: 1064 ++ifp->if_ierrors; 1065 return; 1066 } 1067 1068 void 1069 iy_intr_rx(struct iy_softc *sc) 1070 { 1071 bus_space_tag_t iot; 1072 bus_space_handle_t ioh; 1073 1074 u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen; 1075 1076 iot = sc->sc_iot; 1077 ioh = sc->sc_ioh; 1078 1079 rxadrs = sc->rx_start; 1080 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxadrs); 1081 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG)); 1082 rxnext = 0; 1083 1084 while (rxevnt == RCV_DONE) { 1085 rxstatus = le16toh(bus_space_read_stream_2(iot, ioh, 1086 MEM_PORT_REG)); 1087 rxnext = le16toh(bus_space_read_stream_2(iot, ioh, 1088 MEM_PORT_REG)); 1089 rxlen = le16toh(bus_space_read_stream_2(iot, ioh, 1090 MEM_PORT_REG)); 1091 #ifdef IYDEBUG 1092 { 1093 char sbuf[128]; 1094 1095 snprintb(sbuf, sizeof(sbuf), 1096 "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR" 1097 "\014CRCERR\015LENERR\016RCVOK\020TYP", rxstatus); 1098 1099 printf("%s: pck at 0x%04x stat %s next 0x%x len 0x%x\n", 1100 device_xname(&sc->sc_dev), rxadrs, sbuf, rxnext, rxlen); 1101 } 1102 #endif 1103 iyget(sc, iot, ioh, rxlen); 1104 1105 /* move stop address */ 1106 bus_space_write_2(iot, ioh, RCV_STOP_LOW, 1107 rxnext == 0 ? sc->rx_size - 2 : rxnext - 2); 1108 1109 bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxnext); 1110 rxadrs = rxnext; 1111 rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, 1112 MEM_PORT_REG)); 1113 } 1114 sc->rx_start = rxnext; 1115 } 1116 1117 void 1118 iy_intr_tx(struct iy_softc *sc) 1119 { 1120 bus_space_tag_t iot; 1121 bus_space_handle_t ioh; 1122 struct ifnet *ifp; 1123 u_int txstatus, txstat2, txlen, txnext; 1124 1125 ifp = &sc->sc_ethercom.ec_if; 1126 iot = sc->sc_iot; 1127 ioh = sc->sc_ioh; 1128 1129 while (sc->tx_start != sc->tx_end) { 1130 bus_space_write_2(iot, ioh, HOST_ADDR_REG, sc->tx_start); 1131 txstatus = le16toh(bus_space_read_stream_2(iot, ioh, 1132 MEM_PORT_REG)); 1133 1134 if ((txstatus & (TX_DONE|CMD_MASK)) != (TX_DONE|XMT_CMD)) 1135 break; 1136 1137 txstat2 = le16toh(bus_space_read_stream_2(iot, ioh, 1138 MEM_PORT_REG)); 1139 txnext = le16toh(bus_space_read_stream_2(iot, ioh, 1140 MEM_PORT_REG)); 1141 txlen = le16toh(bus_space_read_stream_2(iot, ioh, 1142 MEM_PORT_REG)); 1143 #ifdef IYDEBUG 1144 { 1145 char sbuf[128]; 1146 1147 snprintb(sbuf, sizeof(sbuf), 1148 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF" 1149 "\011UND_RUN\012JERR\013LST_CRS" 1150 "\014LTCOL\016TX_OK\020COLL", txstat2); 1151 1152 printf("txstat 0x%x stat2 0x%s next 0x%x len 0x%x\n", 1153 txstatus, sbuf, txnext, txlen); 1154 } 1155 #endif 1156 if (txlen & CHAIN) 1157 sc->tx_start = txnext; 1158 else 1159 sc->tx_start = sc->tx_end; 1160 ifp->if_flags &= ~IFF_OACTIVE; 1161 1162 if (txstat2 & 0x0020) 1163 ifp->if_collisions += 16; 1164 else 1165 ifp->if_collisions += txstat2 & 0x000f; 1166 1167 if ((txstat2 & 0x2000) == 0) 1168 ++ifp->if_oerrors; 1169 } 1170 } 1171 1172 int 1173 iyioctl(struct ifnet *ifp, u_long cmd, void *data) 1174 { 1175 struct iy_softc *sc; 1176 struct ifaddr *ifa; 1177 struct ifreq *ifr; 1178 int s, error = 0; 1179 1180 sc = ifp->if_softc; 1181 ifa = (struct ifaddr *)data; 1182 ifr = (struct ifreq *)data; 1183 1184 #ifdef IYDEBUG 1185 printf("iyioctl called with ifp %p (%s) cmd 0x%lx data %p\n", 1186 ifp, ifp->if_xname, cmd, data); 1187 #endif 1188 1189 s = splnet(); 1190 1191 switch (cmd) { 1192 1193 case SIOCINITIFADDR: 1194 ifp->if_flags |= IFF_UP; 1195 1196 iyinit(sc); 1197 switch (ifa->ifa_addr->sa_family) { 1198 #ifdef INET 1199 case AF_INET: 1200 arp_ifinit(ifp, ifa); 1201 break; 1202 #endif 1203 default: 1204 break; 1205 } 1206 break; 1207 1208 case SIOCSIFFLAGS: 1209 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 1210 break; 1211 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI); 1212 /* XXX re-use ether_ioctl() */ 1213 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 1214 case IFF_RUNNING: 1215 /* 1216 * If interface is marked down and it is running, then 1217 * stop it. 1218 */ 1219 iystop(sc); 1220 ifp->if_flags &= ~IFF_RUNNING; 1221 break; 1222 case IFF_UP: 1223 /* 1224 * If interface is marked up and it is stopped, then 1225 * start it. 1226 */ 1227 iyinit(sc); 1228 break; 1229 default: 1230 /* 1231 * Reset the interface to pick up changes in any other 1232 * flags that affect hardware registers. 1233 */ 1234 iystop(sc); 1235 iyinit(sc); 1236 break; 1237 } 1238 #ifdef IYDEBUGX 1239 if (ifp->if_flags & IFF_DEBUG) 1240 sc->sc_debug = IFY_ALL; 1241 else 1242 sc->sc_debug = 0; 1243 #endif 1244 break; 1245 1246 case SIOCADDMULTI: 1247 case SIOCDELMULTI: 1248 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 1249 /* 1250 * Multicast list has changed; set the hardware filter 1251 * accordingly. 1252 */ 1253 if (ifp->if_flags & IFF_RUNNING) { 1254 /* XXX can't make it work otherwise */ 1255 iyreset(sc); 1256 iy_mc_reset(sc); 1257 } 1258 error = 0; 1259 } 1260 break; 1261 1262 case SIOCSIFMEDIA: 1263 case SIOCGIFMEDIA: 1264 error = ifmedia_ioctl(ifp, ifr, &sc->iy_ifmedia, cmd); 1265 break; 1266 default: 1267 error = ether_ioctl(ifp, cmd, data); 1268 } 1269 splx(s); 1270 return error; 1271 } 1272 1273 int 1274 iy_mediachange(struct ifnet *ifp) 1275 { 1276 struct iy_softc *sc = ifp->if_softc; 1277 1278 if (IFM_TYPE(sc->iy_ifmedia.ifm_media) != IFM_ETHER) 1279 return EINVAL; 1280 switch(IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) { 1281 case IFM_10_5: 1282 case IFM_10_2: 1283 case IFM_10_T: 1284 case IFM_AUTO: 1285 iystop(sc); 1286 iyinit(sc); 1287 return 0; 1288 default: 1289 return EINVAL; 1290 } 1291 } 1292 1293 void 1294 iy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1295 { 1296 struct iy_softc *sc = ifp->if_softc; 1297 1298 ifmr->ifm_active = sc->iy_media; 1299 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1300 } 1301 1302 1303 static void 1304 iy_mc_setup(struct iy_softc *sc) 1305 { 1306 struct ether_multi *enm; 1307 struct ether_multistep step; 1308 struct ethercom *ecp; 1309 struct ifnet *ifp; 1310 bus_space_tag_t iot; 1311 bus_space_handle_t ioh; 1312 int avail, last /*, end*/ , len; 1313 int timeout; 1314 volatile u_int16_t dum; 1315 u_int8_t temp; 1316 1317 1318 ecp = &sc->sc_ethercom; 1319 ifp = &ecp->ec_if; 1320 1321 iot = sc->sc_iot; 1322 ioh = sc->sc_ioh; 1323 1324 len = 6 * ecp->ec_multicnt; 1325 1326 avail = sc->tx_start - sc->tx_end; 1327 if (avail <= 0) 1328 avail += sc->tx_size; 1329 if (ifp->if_flags & IFF_DEBUG) 1330 printf("%s: iy_mc_setup called, %d addresses, " 1331 "%d/%d bytes needed/avail\n", ifp->if_xname, 1332 ecp->ec_multicnt, len + I595_XMT_HDRLEN, avail); 1333 1334 last = sc->rx_size; 1335 1336 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1337 bus_space_write_1(iot, ioh, RECV_MODES_REG, MATCH_BRDCST); 1338 /* XXX VOODOO */ 1339 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1340 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1341 /* XXX END OF VOODOO */ 1342 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1343 bus_space_write_2(iot, ioh, HOST_ADDR_REG, last); 1344 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(MC_SETUP_CMD)); 1345 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1346 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1347 bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(len)); 1348 1349 ETHER_FIRST_MULTI(step, ecp, enm); 1350 while(enm) { 1351 /* 1352 * XXX ALIGNMENT LOSSAGE HERE? 1353 */ 1354 bus_space_write_multi_stream_2(iot, ioh, MEM_PORT_REG, 1355 (u_int16_t *) enm->enm_addrlo, 3); 1356 1357 ETHER_NEXT_MULTI(step, enm); 1358 } 1359 dum = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */ 1360 bus_space_write_2(iot, ioh, XMT_ADDR_REG, last); 1361 bus_space_write_1(iot, ioh, 0, MC_SETUP_CMD); 1362 1363 1364 sc->tx_start = sc->rx_size; 1365 sc->tx_end = sc->rx_size + I595_XMT_HDRLEN + len; 1366 1367 for (timeout=0; timeout<100; timeout++) { 1368 DELAY(2); 1369 if ((bus_space_read_1(iot, ioh, STATUS_REG) & EXEC_INT) == 0) 1370 continue; 1371 1372 temp = bus_space_read_1(iot, ioh, 0); 1373 bus_space_write_1(iot, ioh, STATUS_REG, EXEC_INT); 1374 #ifdef DIAGNOSTIC 1375 if (temp & 0x20) { 1376 aprint_error_dev(&sc->sc_dev, "mc setup failed, %d usec\n", 1377 timeout * 2); 1378 } else if (((temp & 0x0f) == 0x03) && 1379 (ifp->if_flags & IFF_DEBUG)) { 1380 printf("%s: mc setup done, %d usec\n", 1381 device_xname(&sc->sc_dev), timeout * 2); 1382 } 1383 #endif 1384 break; 1385 } 1386 sc->tx_start = sc->tx_end; 1387 ifp->if_flags &= ~IFF_OACTIVE; 1388 1389 } 1390 1391 static void 1392 iy_mc_reset(struct iy_softc *sc) 1393 { 1394 struct ether_multi *enm; 1395 struct ether_multistep step; 1396 struct ethercom *ecp; 1397 struct ifnet *ifp; 1398 bus_space_tag_t iot; 1399 bus_space_handle_t ioh; 1400 u_int16_t temp; 1401 1402 ecp = &sc->sc_ethercom; 1403 ifp = &ecp->ec_if; 1404 1405 iot = sc->sc_iot; 1406 ioh = sc->sc_ioh; 1407 1408 if (ecp->ec_multicnt > 63) { 1409 ifp->if_flags |= IFF_ALLMULTI; 1410 1411 } else if (ecp->ec_multicnt > 0) { 1412 /* 1413 * Step through the list of addresses. 1414 */ 1415 ETHER_FIRST_MULTI(step, ecp, enm); 1416 while(enm) { 1417 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { 1418 ifp->if_flags |= IFF_ALLMULTI; 1419 goto setupmulti; 1420 } 1421 ETHER_NEXT_MULTI(step, enm); 1422 } 1423 /* OK, we really need to do it now: */ 1424 #if 0 1425 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) 1426 != IFF_RUNNING) { 1427 ifp->if_flags |= IFF_OACTIVE; 1428 sc->want_mc_setup = 1; 1429 return; 1430 } 1431 #endif 1432 iy_mc_setup(sc); 1433 } else { 1434 ifp->if_flags &= ~IFF_ALLMULTI; 1435 } 1436 1437 setupmulti: 1438 bus_space_write_1(iot, ioh, 0, BANK_SEL(2)); 1439 if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) { 1440 temp = MATCH_ALL; 1441 } else 1442 temp = MATCH_BRDCST; 1443 1444 bus_space_write_1(iot, ioh, RECV_MODES_REG, temp); 1445 /* XXX VOODOO */ 1446 temp = bus_space_read_1(iot, ioh, MEDIA_SELECT); 1447 bus_space_write_1(iot, ioh, MEDIA_SELECT, temp); 1448 /* XXX END OF VOODOO */ 1449 1450 /* XXX TBD: setup hardware for all multicasts */ 1451 bus_space_write_1(iot, ioh, 0, BANK_SEL(0)); 1452 return; 1453 } 1454 1455 #ifdef IYDEBUGX 1456 void 1457 print_rbd(volatile struct ie_recv_buf_desc *rbd) 1458 { 1459 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n" 1460 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual, 1461 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length, 1462 rbd->mbz); 1463 } 1464 #endif 1465 1466 void 1467 iyprobemem(struct iy_softc *sc) 1468 { 1469 bus_space_tag_t iot; 1470 bus_space_handle_t ioh; 1471 int testing; 1472 1473 iot = sc->sc_iot; 1474 ioh = sc->sc_ioh; 1475 1476 bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0)); 1477 delay(1); 1478 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 4096-2); 1479 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1480 1481 for (testing=65536; testing >= 4096; testing >>= 1) { 1482 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1483 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xdead); 1484 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1485 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xdead) { 1486 #ifdef IYMEMDEBUG 1487 printf("%s: Didn't keep 0xdead 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, testing-2); 1494 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xbeef); 1495 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2); 1496 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xbeef) { 1497 #ifdef IYMEMDEBUG 1498 printf("%s: Didn't keep 0xbeef at 0x%x\n", 1499 device_xname(&sc->sc_dev), testing-2); 1500 #endif 1501 continue; 1502 } 1503 1504 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1505 bus_space_write_2(iot, ioh, MEM_PORT_REG, 0); 1506 bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing >> 1); 1507 bus_space_write_2(iot, ioh, MEM_PORT_REG, testing >> 1); 1508 bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0); 1509 if (bus_space_read_2(iot, ioh, MEM_PORT_REG) == (testing >> 1)) { 1510 #ifdef IYMEMDEBUG 1511 printf("%s: 0x%x alias of 0x0\n", 1512 device_xname(&sc->sc_dev), testing >> 1); 1513 #endif 1514 continue; 1515 } 1516 1517 break; 1518 } 1519 1520 sc->sram = testing; 1521 1522 switch(testing) { 1523 case 65536: 1524 /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */ 1525 sc->rx_size = 44*1024; 1526 break; 1527 1528 case 32768: 1529 /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */ 1530 sc->rx_size = 22*1024; 1531 break; 1532 1533 case 16384: 1534 /* 1 NFS packet + overhead RX, 4 big packets TX */ 1535 sc->rx_size = 10*1024; 1536 break; 1537 default: 1538 sc->rx_size = testing/2; 1539 break; 1540 } 1541 sc->tx_size = testing - sc->rx_size; 1542 } 1543 1544 static int 1545 eepromreadall(bus_space_tag_t iot, bus_space_handle_t ioh, u_int16_t *wordp, int maxi) 1546 { 1547 int i; 1548 u_int16_t checksum, tmp; 1549 1550 checksum = 0; 1551 1552 for (i=0; i<EEPP_LENGTH; ++i) { 1553 tmp = eepromread(iot, ioh, i); 1554 checksum += tmp; 1555 if (i<maxi) 1556 wordp[i] = tmp; 1557 } 1558 1559 if (checksum != EEPP_CHKSUM) { 1560 #ifdef IYDEBUG 1561 printf("wrong EEPROM checksum 0x%x should be 0x%x\n", 1562 checksum, EEPP_CHKSUM); 1563 #endif 1564 return 1; 1565 } 1566 return 0; 1567 } 1568