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