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