1 /* $NetBSD: if_gm.c,v 1.19 2002/10/02 05:30:41 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Tsubai Masanari. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "opt_inet.h" 30 #include "opt_ns.h" 31 #include "rnd.h" 32 #include "bpfilter.h" 33 34 #include <sys/param.h> 35 #include <sys/device.h> 36 #include <sys/ioctl.h> 37 #include <sys/kernel.h> 38 #include <sys/mbuf.h> 39 #include <sys/socket.h> 40 #include <sys/systm.h> 41 #include <sys/callout.h> 42 43 #if NRND > 0 44 #include <sys/rnd.h> 45 #endif 46 47 #include <uvm/uvm_extern.h> 48 49 #include <net/if.h> 50 #include <net/if_ether.h> 51 #include <net/if_media.h> 52 53 #if NBPFILTER > 0 54 #include <net/bpf.h> 55 #endif 56 57 #ifdef INET 58 #include <netinet/in.h> 59 #include <netinet/if_inarp.h> 60 #endif 61 62 #include <dev/mii/mii.h> 63 #include <dev/mii/miivar.h> 64 65 #include <dev/pci/pcivar.h> 66 #include <dev/pci/pcireg.h> 67 #include <dev/pci/pcidevs.h> 68 69 #include <dev/ofw/openfirm.h> 70 #include <macppc/dev/if_gmreg.h> 71 #include <machine/pio.h> 72 73 #define NTXBUF 4 74 #define NRXBUF 32 75 76 struct gmac_softc { 77 struct device sc_dev; 78 struct ethercom sc_ethercom; 79 vaddr_t sc_reg; 80 struct gmac_dma *sc_txlist; 81 struct gmac_dma *sc_rxlist; 82 int sc_txnext; 83 int sc_rxlast; 84 caddr_t sc_txbuf[NTXBUF]; 85 caddr_t sc_rxbuf[NRXBUF]; 86 struct mii_data sc_mii; 87 struct callout sc_tick_ch; 88 char sc_laddr[6]; 89 90 #if NRND > 0 91 rndsource_element_t sc_rnd_source; /* random source */ 92 #endif 93 }; 94 95 #define sc_if sc_ethercom.ec_if 96 97 int gmac_match __P((struct device *, struct cfdata *, void *)); 98 void gmac_attach __P((struct device *, struct device *, void *)); 99 100 static __inline u_int gmac_read_reg __P((struct gmac_softc *, int)); 101 static __inline void gmac_write_reg __P((struct gmac_softc *, int, u_int)); 102 103 static __inline void gmac_start_txdma __P((struct gmac_softc *)); 104 static __inline void gmac_start_rxdma __P((struct gmac_softc *)); 105 static __inline void gmac_stop_txdma __P((struct gmac_softc *)); 106 static __inline void gmac_stop_rxdma __P((struct gmac_softc *)); 107 108 int gmac_intr __P((void *)); 109 void gmac_tint __P((struct gmac_softc *)); 110 void gmac_rint __P((struct gmac_softc *)); 111 struct mbuf * gmac_get __P((struct gmac_softc *, caddr_t, int)); 112 void gmac_start __P((struct ifnet *)); 113 int gmac_put __P((struct gmac_softc *, caddr_t, struct mbuf *)); 114 115 void gmac_stop __P((struct gmac_softc *)); 116 void gmac_reset __P((struct gmac_softc *)); 117 void gmac_init __P((struct gmac_softc *)); 118 void gmac_init_mac __P((struct gmac_softc *)); 119 void gmac_setladrf __P((struct gmac_softc *)); 120 121 int gmac_ioctl __P((struct ifnet *, u_long, caddr_t)); 122 void gmac_watchdog __P((struct ifnet *)); 123 124 int gmac_mediachange __P((struct ifnet *)); 125 void gmac_mediastatus __P((struct ifnet *, struct ifmediareq *)); 126 int gmac_mii_readreg __P((struct device *, int, int)); 127 void gmac_mii_writereg __P((struct device *, int, int, int)); 128 void gmac_mii_statchg __P((struct device *)); 129 void gmac_mii_tick __P((void *)); 130 131 CFATTACH_DECL(gm, sizeof(struct gmac_softc), 132 gmac_match, gmac_attach, NULL, NULL); 133 134 int 135 gmac_match(parent, match, aux) 136 struct device *parent; 137 struct cfdata *match; 138 void *aux; 139 { 140 struct pci_attach_args *pa = aux; 141 142 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE && 143 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_GMAC || 144 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_GMAC2)) 145 return 1; 146 147 return 0; 148 } 149 150 void 151 gmac_attach(parent, self, aux) 152 struct device *parent, *self; 153 void *aux; 154 { 155 struct gmac_softc *sc = (void *)self; 156 struct pci_attach_args *pa = aux; 157 struct ifnet *ifp = &sc->sc_if; 158 struct mii_data *mii = &sc->sc_mii; 159 pci_intr_handle_t ih; 160 const char *intrstr = NULL; 161 int node, i; 162 char *p; 163 struct gmac_dma *dp; 164 u_int32_t reg[10]; 165 u_char laddr[6]; 166 167 node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag); 168 if (node == 0) { 169 printf(": cannot find gmac node\n"); 170 return; 171 } 172 173 OF_getprop(node, "local-mac-address", laddr, sizeof laddr); 174 OF_getprop(node, "assigned-addresses", reg, sizeof reg); 175 176 memcpy(sc->sc_laddr, laddr, sizeof laddr); 177 sc->sc_reg = reg[2]; 178 179 if (pci_intr_map(pa, &ih)) { 180 printf(": unable to map interrupt\n"); 181 return; 182 } 183 intrstr = pci_intr_string(pa->pa_pc, ih); 184 185 if (pci_intr_establish(pa->pa_pc, ih, IPL_NET, gmac_intr, sc) == NULL) { 186 printf(": unable to establish interrupt"); 187 if (intrstr) 188 printf(" at %s", intrstr); 189 printf("\n"); 190 return; 191 } 192 193 /* Setup packet buffers and dma descriptors. */ 194 p = malloc((NRXBUF + NTXBUF) * 2048 + 3 * 0x800, M_DEVBUF, M_NOWAIT); 195 if (p == NULL) { 196 printf(": cannot malloc buffers\n"); 197 return; 198 } 199 p = (void *)roundup((vaddr_t)p, 0x800); 200 memset(p, 0, 2048 * (NRXBUF + NTXBUF) + 2 * 0x800); 201 202 sc->sc_rxlist = (void *)p; 203 p += 0x800; 204 sc->sc_txlist = (void *)p; 205 p += 0x800; 206 207 dp = sc->sc_rxlist; 208 for (i = 0; i < NRXBUF; i++) { 209 sc->sc_rxbuf[i] = p; 210 dp->address = htole32(vtophys((vaddr_t)p)); 211 dp->cmd = htole32(GMAC_OWN); 212 dp++; 213 p += 2048; 214 } 215 216 dp = sc->sc_txlist; 217 for (i = 0; i < NTXBUF; i++) { 218 sc->sc_txbuf[i] = p; 219 dp->address = htole32(vtophys((vaddr_t)p)); 220 dp++; 221 p += 2048; 222 } 223 224 printf(": Ethernet address %s\n", ether_sprintf(laddr)); 225 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 226 227 callout_init(&sc->sc_tick_ch); 228 229 gmac_reset(sc); 230 gmac_init_mac(sc); 231 232 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 233 ifp->if_softc = sc; 234 ifp->if_ioctl = gmac_ioctl; 235 ifp->if_start = gmac_start; 236 ifp->if_watchdog = gmac_watchdog; 237 ifp->if_flags = 238 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 239 IFQ_SET_READY(&ifp->if_snd); 240 241 mii->mii_ifp = ifp; 242 mii->mii_readreg = gmac_mii_readreg; 243 mii->mii_writereg = gmac_mii_writereg; 244 mii->mii_statchg = gmac_mii_statchg; 245 246 ifmedia_init(&mii->mii_media, 0, gmac_mediachange, gmac_mediastatus); 247 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); 248 249 /* Choose a default media. */ 250 if (LIST_FIRST(&mii->mii_phys) == NULL) { 251 ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL); 252 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE); 253 } else 254 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); 255 256 if_attach(ifp); 257 ether_ifattach(ifp, laddr); 258 #if NRND > 0 259 rnd_attach_source(&sc->sc_rnd_source, sc->sc_dev.dv_xname, 260 RND_TYPE_NET, 0); 261 #endif 262 } 263 264 u_int 265 gmac_read_reg(sc, reg) 266 struct gmac_softc *sc; 267 int reg; 268 { 269 return in32rb(sc->sc_reg + reg); 270 } 271 272 void 273 gmac_write_reg(sc, reg, val) 274 struct gmac_softc *sc; 275 int reg; 276 u_int val; 277 { 278 out32rb(sc->sc_reg + reg, val); 279 } 280 281 void 282 gmac_start_txdma(sc) 283 struct gmac_softc *sc; 284 { 285 u_int x; 286 287 x = gmac_read_reg(sc, GMAC_TXDMACONFIG); 288 x |= 1; 289 gmac_write_reg(sc, GMAC_TXDMACONFIG, x); 290 x = gmac_read_reg(sc, GMAC_TXMACCONFIG); 291 x |= 1; 292 gmac_write_reg(sc, GMAC_TXMACCONFIG, x); 293 } 294 295 void 296 gmac_start_rxdma(sc) 297 struct gmac_softc *sc; 298 { 299 u_int x; 300 301 x = gmac_read_reg(sc, GMAC_RXDMACONFIG); 302 x |= 1; 303 gmac_write_reg(sc, GMAC_RXDMACONFIG, x); 304 x = gmac_read_reg(sc, GMAC_RXMACCONFIG); 305 x |= 1; 306 gmac_write_reg(sc, GMAC_RXMACCONFIG, x); 307 } 308 309 void 310 gmac_stop_txdma(sc) 311 struct gmac_softc *sc; 312 { 313 u_int x; 314 315 x = gmac_read_reg(sc, GMAC_TXDMACONFIG); 316 x &= ~1; 317 gmac_write_reg(sc, GMAC_TXDMACONFIG, x); 318 x = gmac_read_reg(sc, GMAC_TXMACCONFIG); 319 x &= ~1; 320 gmac_write_reg(sc, GMAC_TXMACCONFIG, x); 321 } 322 323 void 324 gmac_stop_rxdma(sc) 325 struct gmac_softc *sc; 326 { 327 u_int x; 328 329 x = gmac_read_reg(sc, GMAC_RXDMACONFIG); 330 x &= ~1; 331 gmac_write_reg(sc, GMAC_RXDMACONFIG, x); 332 x = gmac_read_reg(sc, GMAC_RXMACCONFIG); 333 x &= ~1; 334 gmac_write_reg(sc, GMAC_RXMACCONFIG, x); 335 } 336 337 int 338 gmac_intr(v) 339 void *v; 340 { 341 struct gmac_softc *sc = v; 342 u_int status; 343 344 status = gmac_read_reg(sc, GMAC_STATUS) & 0xff; 345 if (status == 0) 346 return 0; 347 348 if (status & GMAC_INT_RXDONE) 349 gmac_rint(sc); 350 351 if (status & GMAC_INT_TXEMPTY) 352 gmac_tint(sc); 353 354 #if NRND > 0 355 rnd_add_uint32(&sc->sc_rnd_source, status); 356 #endif 357 return 1; 358 } 359 360 void 361 gmac_tint(sc) 362 struct gmac_softc *sc; 363 { 364 struct ifnet *ifp = &sc->sc_if; 365 366 ifp->if_flags &= ~IFF_OACTIVE; 367 ifp->if_timer = 0; 368 gmac_start(ifp); 369 } 370 371 void 372 gmac_rint(sc) 373 struct gmac_softc *sc; 374 { 375 struct ifnet *ifp = &sc->sc_if; 376 volatile struct gmac_dma *dp; 377 struct mbuf *m; 378 int i, j, len; 379 u_int cmd; 380 381 for (i = sc->sc_rxlast;; i++) { 382 if (i == NRXBUF) 383 i = 0; 384 385 dp = &sc->sc_rxlist[i]; 386 cmd = le32toh(dp->cmd); 387 if (cmd & GMAC_OWN) 388 break; 389 len = (cmd >> 16) & GMAC_LEN_MASK; 390 len -= 4; /* CRC */ 391 392 if (le32toh(dp->cmd_hi) & 0x40000000) { 393 ifp->if_ierrors++; 394 goto next; 395 } 396 397 m = gmac_get(sc, sc->sc_rxbuf[i], len); 398 if (m == NULL) { 399 ifp->if_ierrors++; 400 goto next; 401 } 402 403 #if NBPFILTER > 0 404 /* 405 * Check if there's a BPF listener on this interface. 406 * If so, hand off the raw packet to BPF. 407 */ 408 if (ifp->if_bpf) 409 bpf_mtap(ifp->if_bpf, m); 410 #endif 411 (*ifp->if_input)(ifp, m); 412 ifp->if_ipackets++; 413 414 next: 415 dp->cmd_hi = 0; 416 __asm __volatile ("sync"); 417 dp->cmd = htole32(GMAC_OWN); 418 } 419 sc->sc_rxlast = i; 420 421 /* XXX Make sure free buffers have GMAC_OWN. */ 422 i++; 423 for (j = 1; j < NRXBUF; j++) { 424 if (i == NRXBUF) 425 i = 0; 426 dp = &sc->sc_rxlist[i++]; 427 dp->cmd = htole32(GMAC_OWN); 428 } 429 } 430 431 struct mbuf * 432 gmac_get(sc, pkt, totlen) 433 struct gmac_softc *sc; 434 caddr_t pkt; 435 int totlen; 436 { 437 struct mbuf *m; 438 struct mbuf *top, **mp; 439 int len; 440 441 MGETHDR(m, M_DONTWAIT, MT_DATA); 442 if (m == 0) 443 return 0; 444 m->m_pkthdr.rcvif = &sc->sc_if; 445 m->m_pkthdr.len = totlen; 446 len = MHLEN; 447 top = 0; 448 mp = ⊤ 449 450 while (totlen > 0) { 451 if (top) { 452 MGET(m, M_DONTWAIT, MT_DATA); 453 if (m == 0) { 454 m_freem(top); 455 return 0; 456 } 457 len = MLEN; 458 } 459 if (totlen >= MINCLSIZE) { 460 MCLGET(m, M_DONTWAIT); 461 if ((m->m_flags & M_EXT) == 0) { 462 m_free(m); 463 m_freem(top); 464 return 0; 465 } 466 len = MCLBYTES; 467 } 468 m->m_len = len = min(totlen, len); 469 memcpy(mtod(m, caddr_t), pkt, len); 470 pkt += len; 471 totlen -= len; 472 *mp = m; 473 mp = &m->m_next; 474 } 475 476 return top; 477 } 478 479 void 480 gmac_start(ifp) 481 struct ifnet *ifp; 482 { 483 struct gmac_softc *sc = ifp->if_softc; 484 struct mbuf *m; 485 caddr_t buff; 486 int i, tlen; 487 volatile struct gmac_dma *dp; 488 489 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 490 return; 491 492 for (;;) { 493 if (ifp->if_flags & IFF_OACTIVE) 494 break; 495 496 IFQ_DEQUEUE(&ifp->if_snd, m); 497 if (m == 0) 498 break; 499 500 /* 5 seconds to watch for failing to transmit */ 501 ifp->if_timer = 5; 502 ifp->if_opackets++; /* # of pkts */ 503 504 i = sc->sc_txnext; 505 buff = sc->sc_txbuf[i]; 506 tlen = gmac_put(sc, buff, m); 507 508 dp = &sc->sc_txlist[i]; 509 dp->cmd_hi = 0; 510 dp->address_hi = 0; 511 dp->cmd = htole32(tlen | GMAC_OWN | GMAC_SOP); 512 513 i++; 514 if (i == NTXBUF) 515 i = 0; 516 __asm __volatile ("sync"); 517 518 gmac_write_reg(sc, GMAC_TXDMAKICK, i); 519 sc->sc_txnext = i; 520 521 #if NBPFILTER > 0 522 /* 523 * If BPF is listening on this interface, let it see the 524 * packet before we commit it to the wire. 525 */ 526 if (ifp->if_bpf) 527 bpf_mtap(ifp->if_bpf, m); 528 #endif 529 m_freem(m); 530 531 i++; 532 if (i == NTXBUF) 533 i = 0; 534 if (i == gmac_read_reg(sc, GMAC_TXDMACOMPLETE)) { 535 ifp->if_flags |= IFF_OACTIVE; 536 break; 537 } 538 } 539 } 540 541 int 542 gmac_put(sc, buff, m) 543 struct gmac_softc *sc; 544 caddr_t buff; 545 struct mbuf *m; 546 { 547 int len, tlen = 0; 548 549 for (; m; m = m->m_next) { 550 len = m->m_len; 551 if (len == 0) 552 continue; 553 memcpy(buff, mtod(m, caddr_t), len); 554 buff += len; 555 tlen += len; 556 } 557 if (tlen > 2048) 558 panic("%s: gmac_put packet overflow", sc->sc_dev.dv_xname); 559 560 return tlen; 561 } 562 563 void 564 gmac_reset(sc) 565 struct gmac_softc *sc; 566 { 567 int i, s; 568 569 s = splnet(); 570 571 gmac_stop_txdma(sc); 572 gmac_stop_rxdma(sc); 573 574 gmac_write_reg(sc, GMAC_SOFTWARERESET, 3); 575 for (i = 10; i > 0; i--) { 576 delay(300000); /* XXX long delay */ 577 if ((gmac_read_reg(sc, GMAC_SOFTWARERESET) & 3) == 0) 578 break; 579 } 580 if (i == 0) 581 printf("%s: reset timeout\n", sc->sc_dev.dv_xname); 582 583 sc->sc_txnext = 0; 584 sc->sc_rxlast = 0; 585 for (i = 0; i < NRXBUF; i++) 586 sc->sc_rxlist[i].cmd = htole32(GMAC_OWN); 587 __asm __volatile ("sync"); 588 589 gmac_write_reg(sc, GMAC_TXDMADESCBASEHI, 0); 590 gmac_write_reg(sc, GMAC_TXDMADESCBASELO, 591 vtophys((vaddr_t)sc->sc_txlist)); 592 gmac_write_reg(sc, GMAC_RXDMADESCBASEHI, 0); 593 gmac_write_reg(sc, GMAC_RXDMADESCBASELO, 594 vtophys((vaddr_t)sc->sc_rxlist)); 595 gmac_write_reg(sc, GMAC_RXDMAKICK, NRXBUF); 596 597 splx(s); 598 } 599 600 void 601 gmac_stop(sc) 602 struct gmac_softc *sc; 603 { 604 struct ifnet *ifp = &sc->sc_if; 605 int s; 606 607 s = splnet(); 608 609 callout_stop(&sc->sc_tick_ch); 610 mii_down(&sc->sc_mii); 611 612 gmac_stop_txdma(sc); 613 gmac_stop_rxdma(sc); 614 615 gmac_write_reg(sc, GMAC_INTMASK, 0xffffffff); 616 617 ifp->if_flags &= ~(IFF_UP | IFF_RUNNING); 618 ifp->if_timer = 0; 619 620 splx(s); 621 } 622 623 void 624 gmac_init_mac(sc) 625 struct gmac_softc *sc; 626 { 627 int i, tb; 628 char *laddr = sc->sc_laddr; 629 630 __asm ("mftb %0" : "=r"(tb)); 631 gmac_write_reg(sc, GMAC_RANDOMSEED, tb); 632 633 /* init-mii */ 634 gmac_write_reg(sc, GMAC_DATAPATHMODE, 4); 635 gmac_mii_writereg(&sc->sc_dev, 0, 0, 0x1000); 636 637 gmac_write_reg(sc, GMAC_TXDMACONFIG, 0xffc00); 638 gmac_write_reg(sc, GMAC_RXDMACONFIG, 0); 639 gmac_write_reg(sc, GMAC_MACPAUSE, 0x1bf0); 640 gmac_write_reg(sc, GMAC_INTERPACKETGAP0, 0); 641 gmac_write_reg(sc, GMAC_INTERPACKETGAP1, 8); 642 gmac_write_reg(sc, GMAC_INTERPACKETGAP2, 4); 643 gmac_write_reg(sc, GMAC_MINFRAMESIZE, ETHER_MIN_LEN); 644 gmac_write_reg(sc, GMAC_MAXFRAMESIZE, ETHER_MAX_LEN); 645 gmac_write_reg(sc, GMAC_PASIZE, 7); 646 gmac_write_reg(sc, GMAC_JAMSIZE, 4); 647 gmac_write_reg(sc, GMAC_ATTEMPTLIMIT,0x10); 648 gmac_write_reg(sc, GMAC_MACCNTLTYPE, 0x8808); 649 650 gmac_write_reg(sc, GMAC_MACADDRESS0, (laddr[4] << 8) | laddr[5]); 651 gmac_write_reg(sc, GMAC_MACADDRESS1, (laddr[2] << 8) | laddr[3]); 652 gmac_write_reg(sc, GMAC_MACADDRESS2, (laddr[0] << 8) | laddr[1]); 653 gmac_write_reg(sc, GMAC_MACADDRESS3, 0); 654 gmac_write_reg(sc, GMAC_MACADDRESS4, 0); 655 gmac_write_reg(sc, GMAC_MACADDRESS5, 0); 656 gmac_write_reg(sc, GMAC_MACADDRESS6, 1); 657 gmac_write_reg(sc, GMAC_MACADDRESS7, 0xc200); 658 gmac_write_reg(sc, GMAC_MACADDRESS8, 0x0180); 659 gmac_write_reg(sc, GMAC_MACADDRFILT0, 0); 660 gmac_write_reg(sc, GMAC_MACADDRFILT1, 0); 661 gmac_write_reg(sc, GMAC_MACADDRFILT2, 0); 662 gmac_write_reg(sc, GMAC_MACADDRFILT2_1MASK, 0); 663 gmac_write_reg(sc, GMAC_MACADDRFILT0MASK, 0); 664 665 for (i = 0; i < 0x6c; i += 4) 666 gmac_write_reg(sc, GMAC_HASHTABLE0 + i, 0); 667 668 gmac_write_reg(sc, GMAC_SLOTTIME, 0x40); 669 670 if (IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) { 671 gmac_write_reg(sc, GMAC_TXMACCONFIG, 6); 672 gmac_write_reg(sc, GMAC_XIFCONFIG, 1); 673 } else { 674 gmac_write_reg(sc, GMAC_TXMACCONFIG, 0); 675 gmac_write_reg(sc, GMAC_XIFCONFIG, 5); 676 } 677 678 if (0) /* g-bit? */ 679 gmac_write_reg(sc, GMAC_MACCTRLCONFIG, 3); 680 else 681 gmac_write_reg(sc, GMAC_MACCTRLCONFIG, 0); 682 } 683 684 void 685 gmac_setladrf(sc) 686 struct gmac_softc *sc; 687 { 688 struct ifnet *ifp = &sc->sc_if; 689 struct ether_multi *enm; 690 struct ether_multistep step; 691 struct ethercom *ec = &sc->sc_ethercom; 692 u_int32_t crc; 693 u_int32_t hash[16]; 694 u_int v; 695 int i; 696 697 /* Clear hash table */ 698 for (i = 0; i < 16; i++) 699 hash[i] = 0; 700 701 /* Get current RX configuration */ 702 v = gmac_read_reg(sc, GMAC_RXMACCONFIG); 703 704 if ((ifp->if_flags & IFF_PROMISC) != 0) { 705 /* Turn on promiscuous mode; turn off the hash filter */ 706 v |= GMAC_RXMAC_PR; 707 v &= ~GMAC_RXMAC_HEN; 708 ifp->if_flags |= IFF_ALLMULTI; 709 goto chipit; 710 } 711 712 /* Turn off promiscuous mode; turn on the hash filter */ 713 v &= ~GMAC_RXMAC_PR; 714 v |= GMAC_RXMAC_HEN; 715 716 /* 717 * Set up multicast address filter by passing all multicast addresses 718 * through a crc generator, and then using the high order 8 bits as an 719 * index into the 256 bit logical address filter. The high order bit 720 * selects the word, while the rest of the bits select the bit within 721 * the word. 722 */ 723 724 ETHER_FIRST_MULTI(step, ec, enm); 725 while (enm != NULL) { 726 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) { 727 /* 728 * We must listen to a range of multicast addresses. 729 * For now, just accept all multicasts, rather than 730 * trying to set only those filter bits needed to match 731 * the range. (At this time, the only use of address 732 * ranges is for IP multicast routing, for which the 733 * range is big enough to require all bits set.) 734 */ 735 for (i = 0; i < 16; i++) 736 hash[i] = 0xffff; 737 ifp->if_flags |= IFF_ALLMULTI; 738 goto chipit; 739 } 740 741 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); 742 743 /* Just want the 8 most significant bits. */ 744 crc >>= 24; 745 746 /* Set the corresponding bit in the filter. */ 747 hash[crc >> 4] |= 1 << (crc & 0xf); 748 749 ETHER_NEXT_MULTI(step, enm); 750 } 751 752 ifp->if_flags &= ~IFF_ALLMULTI; 753 754 chipit: 755 /* Now load the hash table into the chip */ 756 for (i = 0; i < 16; i++) 757 gmac_write_reg(sc, GMAC_HASHTABLE0 + i * 4, hash[i]); 758 759 gmac_write_reg(sc, GMAC_RXMACCONFIG, v); 760 } 761 762 void 763 gmac_init(sc) 764 struct gmac_softc *sc; 765 { 766 struct ifnet *ifp = &sc->sc_if; 767 768 gmac_stop_txdma(sc); 769 gmac_stop_rxdma(sc); 770 771 gmac_init_mac(sc); 772 gmac_setladrf(sc); 773 774 gmac_start_txdma(sc); 775 gmac_start_rxdma(sc); 776 777 gmac_write_reg(sc, GMAC_INTMASK, ~(GMAC_INT_TXEMPTY | GMAC_INT_RXDONE)); 778 779 ifp->if_flags |= IFF_RUNNING; 780 ifp->if_flags &= ~IFF_OACTIVE; 781 ifp->if_timer = 0; 782 783 callout_reset(&sc->sc_tick_ch, 1, gmac_mii_tick, sc); 784 785 gmac_start(ifp); 786 } 787 788 int 789 gmac_ioctl(ifp, cmd, data) 790 struct ifnet *ifp; 791 u_long cmd; 792 caddr_t data; 793 { 794 struct gmac_softc *sc = ifp->if_softc; 795 struct ifaddr *ifa = (struct ifaddr *)data; 796 struct ifreq *ifr = (struct ifreq *)data; 797 int s, error = 0; 798 799 s = splnet(); 800 801 switch (cmd) { 802 803 case SIOCSIFADDR: 804 ifp->if_flags |= IFF_UP; 805 806 switch (ifa->ifa_addr->sa_family) { 807 #ifdef INET 808 case AF_INET: 809 gmac_init(sc); 810 arp_ifinit(ifp, ifa); 811 break; 812 #endif 813 #ifdef NS 814 case AF_NS: 815 { 816 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 817 818 if (ns_nullhost(*ina)) 819 ina->x_host = 820 *(union ns_host *)LLADDR(ifp->if_sadl); 821 else { 822 memcpy(LLADDR(ifp->if_sadl), 823 ina->x_host.c_host, 824 sizeof(sc->sc_enaddr)); 825 } 826 /* Set new address. */ 827 gmac_init(sc); 828 break; 829 } 830 #endif 831 default: 832 gmac_init(sc); 833 break; 834 } 835 break; 836 837 case SIOCSIFFLAGS: 838 if ((ifp->if_flags & IFF_UP) == 0 && 839 (ifp->if_flags & IFF_RUNNING) != 0) { 840 /* 841 * If interface is marked down and it is running, then 842 * stop it. 843 */ 844 gmac_stop(sc); 845 ifp->if_flags &= ~IFF_RUNNING; 846 } else if ((ifp->if_flags & IFF_UP) != 0 && 847 (ifp->if_flags & IFF_RUNNING) == 0) { 848 /* 849 * If interface is marked up and it is stopped, then 850 * start it. 851 */ 852 gmac_init(sc); 853 } else { 854 /* 855 * Reset the interface to pick up changes in any other 856 * flags that affect hardware registers. 857 */ 858 gmac_reset(sc); 859 gmac_init(sc); 860 } 861 #ifdef GMAC_DEBUG 862 if (ifp->if_flags & IFF_DEBUG) 863 sc->sc_flags |= GMAC_DEBUGFLAG; 864 #endif 865 break; 866 867 case SIOCADDMULTI: 868 case SIOCDELMULTI: 869 error = (cmd == SIOCADDMULTI) ? 870 ether_addmulti(ifr, &sc->sc_ethercom) : 871 ether_delmulti(ifr, &sc->sc_ethercom); 872 873 if (error == ENETRESET) { 874 /* 875 * Multicast list has changed; set the hardware filter 876 * accordingly. 877 */ 878 gmac_init(sc); 879 /* gmac_setladrf(sc); */ 880 error = 0; 881 } 882 break; 883 884 case SIOCGIFMEDIA: 885 case SIOCSIFMEDIA: 886 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); 887 break; 888 889 default: 890 error = EINVAL; 891 } 892 893 splx(s); 894 return error; 895 } 896 897 void 898 gmac_watchdog(ifp) 899 struct ifnet *ifp; 900 { 901 struct gmac_softc *sc = ifp->if_softc; 902 903 printf("%s: device timeout\n", ifp->if_xname); 904 ifp->if_oerrors++; 905 906 gmac_reset(sc); 907 gmac_init(sc); 908 } 909 910 int 911 gmac_mediachange(ifp) 912 struct ifnet *ifp; 913 { 914 struct gmac_softc *sc = ifp->if_softc; 915 916 return mii_mediachg(&sc->sc_mii); 917 } 918 919 void 920 gmac_mediastatus(ifp, ifmr) 921 struct ifnet *ifp; 922 struct ifmediareq *ifmr; 923 { 924 struct gmac_softc *sc = ifp->if_softc; 925 926 mii_pollstat(&sc->sc_mii); 927 928 ifmr->ifm_status = sc->sc_mii.mii_media_status; 929 ifmr->ifm_active = sc->sc_mii.mii_media_active; 930 } 931 932 int 933 gmac_mii_readreg(dev, phy, reg) 934 struct device *dev; 935 int phy, reg; 936 { 937 struct gmac_softc *sc = (void *)dev; 938 int i; 939 940 gmac_write_reg(sc, GMAC_MIFFRAMEOUTPUT, 941 0x60020000 | (phy << 23) | (reg << 18)); 942 943 for (i = 1000; i >= 0; i -= 10) { 944 if (gmac_read_reg(sc, GMAC_MIFFRAMEOUTPUT) & 0x10000) 945 break; 946 delay(10); 947 } 948 if (i < 0) { 949 printf("%s: gmac_mii_readreg: timeout\n", sc->sc_dev.dv_xname); 950 return 0; 951 } 952 953 return gmac_read_reg(sc, GMAC_MIFFRAMEOUTPUT) & 0xffff; 954 } 955 956 void 957 gmac_mii_writereg(dev, phy, reg, val) 958 struct device *dev; 959 int phy, reg, val; 960 { 961 struct gmac_softc *sc = (void *)dev; 962 int i; 963 964 gmac_write_reg(sc, GMAC_MIFFRAMEOUTPUT, 965 0x50020000 | (phy << 23) | (reg << 18) | (val & 0xffff)); 966 967 for (i = 1000; i >= 0; i -= 10) { 968 if (gmac_read_reg(sc, GMAC_MIFFRAMEOUTPUT) & 0x10000) 969 break; 970 delay(10); 971 } 972 if (i < 0) 973 printf("%s: gmac_mii_writereg: timeout\n", sc->sc_dev.dv_xname); 974 } 975 976 void 977 gmac_mii_statchg(dev) 978 struct device *dev; 979 { 980 struct gmac_softc *sc = (void *)dev; 981 982 gmac_stop_txdma(sc); 983 gmac_stop_rxdma(sc); 984 985 if (IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) { 986 gmac_write_reg(sc, GMAC_TXMACCONFIG, 6); 987 gmac_write_reg(sc, GMAC_XIFCONFIG, 1); 988 } else { 989 gmac_write_reg(sc, GMAC_TXMACCONFIG, 0); 990 gmac_write_reg(sc, GMAC_XIFCONFIG, 5); 991 } 992 993 if (0) /* g-bit? */ 994 gmac_write_reg(sc, GMAC_MACCTRLCONFIG, 3); 995 else 996 gmac_write_reg(sc, GMAC_MACCTRLCONFIG, 0); 997 998 gmac_start_txdma(sc); 999 gmac_start_rxdma(sc); 1000 } 1001 1002 void 1003 gmac_mii_tick(v) 1004 void *v; 1005 { 1006 struct gmac_softc *sc = v; 1007 int s; 1008 1009 s = splnet(); 1010 mii_tick(&sc->sc_mii); 1011 splx(s); 1012 1013 callout_reset(&sc->sc_tick_ch, hz, gmac_mii_tick, sc); 1014 } 1015