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