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