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