1 1.99 andvar /* $NetBSD: smc83c170.c,v 1.99 2024/09/07 06:17:37 andvar Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /*- 4 1.10 thorpej * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.1 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.1 thorpej * NASA Ames Research Center. 10 1.1 thorpej * 11 1.1 thorpej * Redistribution and use in source and binary forms, with or without 12 1.1 thorpej * modification, are permitted provided that the following conditions 13 1.1 thorpej * are met: 14 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.1 thorpej * notice, this list of conditions and the following disclaimer. 16 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.1 thorpej * documentation and/or other materials provided with the distribution. 19 1.1 thorpej * 20 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.1 thorpej */ 32 1.1 thorpej 33 1.1 thorpej /* 34 1.1 thorpej * Device driver for the Standard Microsystems Corp. 83C170 35 1.1 thorpej * Ethernet PCI Integrated Controller (EPIC/100). 36 1.1 thorpej */ 37 1.49 lukem 38 1.49 lukem #include <sys/cdefs.h> 39 1.99 andvar __KERNEL_RCSID(0, "$NetBSD: smc83c170.c,v 1.99 2024/09/07 06:17:37 andvar Exp $"); 40 1.1 thorpej 41 1.1 thorpej 42 1.1 thorpej #include <sys/param.h> 43 1.59 perry #include <sys/systm.h> 44 1.29 thorpej #include <sys/callout.h> 45 1.59 perry #include <sys/mbuf.h> 46 1.1 thorpej #include <sys/kernel.h> 47 1.1 thorpej #include <sys/socket.h> 48 1.1 thorpej #include <sys/ioctl.h> 49 1.1 thorpej #include <sys/errno.h> 50 1.1 thorpej #include <sys/device.h> 51 1.38 thorpej 52 1.1 thorpej #include <net/if.h> 53 1.1 thorpej #include <net/if_dl.h> 54 1.1 thorpej #include <net/if_media.h> 55 1.1 thorpej #include <net/if_ether.h> 56 1.1 thorpej 57 1.1 thorpej #include <net/bpf.h> 58 1.1 thorpej 59 1.67 ad #include <sys/bus.h> 60 1.67 ad #include <sys/intr.h> 61 1.1 thorpej 62 1.8 thorpej #include <dev/mii/miivar.h> 63 1.43 drochner #include <dev/mii/lxtphyreg.h> 64 1.8 thorpej 65 1.1 thorpej #include <dev/ic/smc83c170reg.h> 66 1.1 thorpej #include <dev/ic/smc83c170var.h> 67 1.1 thorpej 68 1.91 thorpej static void epic_start(struct ifnet *); 69 1.91 thorpej static void epic_watchdog(struct ifnet *); 70 1.91 thorpej static int epic_ioctl(struct ifnet *, u_long, void *); 71 1.91 thorpej static int epic_init(struct ifnet *); 72 1.91 thorpej static void epic_stop(struct ifnet *, int); 73 1.91 thorpej 74 1.91 thorpej static bool epic_shutdown(device_t, int); 75 1.91 thorpej 76 1.91 thorpej static void epic_reset(struct epic_softc *); 77 1.91 thorpej static void epic_rxdrain(struct epic_softc *); 78 1.91 thorpej static int epic_add_rxbuf(struct epic_softc *, int); 79 1.91 thorpej static void epic_read_eeprom(struct epic_softc *, int, int, uint16_t *); 80 1.91 thorpej static void epic_set_mchash(struct epic_softc *); 81 1.91 thorpej static void epic_fixup_clock_source(struct epic_softc *); 82 1.91 thorpej static int epic_mii_read(device_t, int, int, uint16_t *); 83 1.91 thorpej static int epic_mii_write(device_t, int, int, uint16_t); 84 1.91 thorpej static int epic_mii_wait(struct epic_softc *, uint32_t); 85 1.91 thorpej static void epic_tick(void *); 86 1.58 perry 87 1.91 thorpej static void epic_statchg(struct ifnet *); 88 1.91 thorpej static int epic_mediachange(struct ifnet *); 89 1.1 thorpej 90 1.1 thorpej #define INTMASK (INTSTAT_FATAL_INT | INTSTAT_TXU | \ 91 1.21 thorpej INTSTAT_TXC | INTSTAT_RXE | INTSTAT_RQE | INTSTAT_RCC) 92 1.1 thorpej 93 1.19 thorpej int epic_copy_small = 0; 94 1.19 thorpej 95 1.52 bouyer #define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) 96 1.52 bouyer 97 1.1 thorpej /* 98 1.1 thorpej * Attach an EPIC interface to the system. 99 1.1 thorpej */ 100 1.1 thorpej void 101 1.76 tsutsui epic_attach(struct epic_softc *sc) 102 1.1 thorpej { 103 1.1 thorpej bus_space_tag_t st = sc->sc_st; 104 1.1 thorpej bus_space_handle_t sh = sc->sc_sh; 105 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 106 1.88 msaitoh struct mii_data * const mii = &sc->sc_mii; 107 1.51 thorpej int rseg, error, miiflags; 108 1.51 thorpej u_int i; 109 1.1 thorpej bus_dma_segment_t seg; 110 1.63 tsutsui uint8_t enaddr[ETHER_ADDR_LEN], devname[12 + 1]; 111 1.63 tsutsui uint16_t myea[ETHER_ADDR_LEN / 2], mydevname[6]; 112 1.52 bouyer char *nullbuf; 113 1.1 thorpej 114 1.65 ad callout_init(&sc->sc_mii_callout, 0); 115 1.93 thorpej callout_setfunc(&sc->sc_mii_callout, epic_tick, sc); 116 1.29 thorpej 117 1.1 thorpej /* 118 1.1 thorpej * Allocate the control data structures, and create and load the 119 1.1 thorpej * DMA map for it. 120 1.1 thorpej */ 121 1.1 thorpej if ((error = bus_dmamem_alloc(sc->sc_dmat, 122 1.52 bouyer sizeof(struct epic_control_data) + ETHER_PAD_LEN, PAGE_SIZE, 0, 123 1.52 bouyer &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 124 1.88 msaitoh aprint_error_dev(sc->sc_dev, 125 1.76 tsutsui "unable to allocate control data, error = %d\n", error); 126 1.14 thorpej goto fail_0; 127 1.1 thorpej } 128 1.1 thorpej 129 1.1 thorpej if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 130 1.52 bouyer sizeof(struct epic_control_data) + ETHER_PAD_LEN, 131 1.64 christos (void **)&sc->sc_control_data, 132 1.88 msaitoh BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 133 1.76 tsutsui aprint_error_dev(sc->sc_dev, 134 1.76 tsutsui "unable to map control data, error = %d\n", error); 135 1.14 thorpej goto fail_1; 136 1.1 thorpej } 137 1.52 bouyer nullbuf = 138 1.52 bouyer (char *)sc->sc_control_data + sizeof(struct epic_control_data); 139 1.52 bouyer memset(nullbuf, 0, ETHER_PAD_LEN); 140 1.1 thorpej 141 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, 142 1.1 thorpej sizeof(struct epic_control_data), 1, 143 1.1 thorpej sizeof(struct epic_control_data), 0, BUS_DMA_NOWAIT, 144 1.1 thorpej &sc->sc_cddmamap)) != 0) { 145 1.76 tsutsui aprint_error_dev(sc->sc_dev, 146 1.76 tsutsui "unable to create control data DMA map, error = %d\n", 147 1.76 tsutsui error); 148 1.14 thorpej goto fail_2; 149 1.1 thorpej } 150 1.1 thorpej 151 1.1 thorpej if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, 152 1.1 thorpej sc->sc_control_data, sizeof(struct epic_control_data), NULL, 153 1.1 thorpej BUS_DMA_NOWAIT)) != 0) { 154 1.88 msaitoh aprint_error_dev(sc->sc_dev, 155 1.73 cegger "unable to load control data DMA map, error = %d\n", 156 1.73 cegger error); 157 1.14 thorpej goto fail_3; 158 1.1 thorpej } 159 1.1 thorpej 160 1.1 thorpej /* 161 1.1 thorpej * Create the transmit buffer DMA maps. 162 1.1 thorpej */ 163 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) { 164 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 165 1.1 thorpej EPIC_NFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT, 166 1.10 thorpej &EPIC_DSTX(sc, i)->ds_dmamap)) != 0) { 167 1.76 tsutsui aprint_error_dev(sc->sc_dev, 168 1.76 tsutsui "unable to create tx DMA map %d, error = %d\n", 169 1.76 tsutsui i, error); 170 1.14 thorpej goto fail_4; 171 1.1 thorpej } 172 1.1 thorpej } 173 1.1 thorpej 174 1.1 thorpej /* 175 1.42 tsutsui * Create the receive buffer DMA maps. 176 1.1 thorpej */ 177 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) { 178 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 179 1.1 thorpej MCLBYTES, 0, BUS_DMA_NOWAIT, 180 1.10 thorpej &EPIC_DSRX(sc, i)->ds_dmamap)) != 0) { 181 1.76 tsutsui aprint_error_dev(sc->sc_dev, 182 1.76 tsutsui "unable to create rx DMA map %d, error = %d\n", 183 1.76 tsutsui i, error); 184 1.14 thorpej goto fail_5; 185 1.1 thorpej } 186 1.19 thorpej EPIC_DSRX(sc, i)->ds_mbuf = NULL; 187 1.1 thorpej } 188 1.1 thorpej 189 1.52 bouyer /* 190 1.52 bouyer * create and map the pad buffer 191 1.52 bouyer */ 192 1.52 bouyer if ((error = bus_dmamap_create(sc->sc_dmat, ETHER_PAD_LEN, 1, 193 1.52 bouyer ETHER_PAD_LEN, 0, BUS_DMA_NOWAIT,&sc->sc_nulldmamap)) != 0) { 194 1.76 tsutsui aprint_error_dev(sc->sc_dev, 195 1.76 tsutsui "unable to create pad buffer DMA map, error = %d\n", error); 196 1.52 bouyer goto fail_5; 197 1.52 bouyer } 198 1.52 bouyer 199 1.52 bouyer if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_nulldmamap, 200 1.52 bouyer nullbuf, ETHER_PAD_LEN, NULL, BUS_DMA_NOWAIT)) != 0) { 201 1.76 tsutsui aprint_error_dev(sc->sc_dev, 202 1.76 tsutsui "unable to load pad buffer DMA map, error = %d\n", error); 203 1.52 bouyer goto fail_6; 204 1.52 bouyer } 205 1.52 bouyer bus_dmamap_sync(sc->sc_dmat, sc->sc_nulldmamap, 0, ETHER_PAD_LEN, 206 1.52 bouyer BUS_DMASYNC_PREWRITE); 207 1.1 thorpej 208 1.1 thorpej /* 209 1.1 thorpej * Bring the chip out of low-power mode and reset it to a known state. 210 1.1 thorpej */ 211 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, 0); 212 1.1 thorpej epic_reset(sc); 213 1.1 thorpej 214 1.1 thorpej /* 215 1.1 thorpej * Read the Ethernet address from the EEPROM. 216 1.1 thorpej */ 217 1.62 tsutsui epic_read_eeprom(sc, 0, __arraycount(myea), myea); 218 1.62 tsutsui for (i = 0; i < __arraycount(myea); i++) { 219 1.89 msaitoh enaddr[i * 2] = myea[i] & 0xff; 220 1.32 tsutsui enaddr[i * 2 + 1] = myea[i] >> 8; 221 1.32 tsutsui } 222 1.1 thorpej 223 1.1 thorpej /* 224 1.1 thorpej * ...and the device name. 225 1.1 thorpej */ 226 1.62 tsutsui epic_read_eeprom(sc, 0x2c, __arraycount(mydevname), mydevname); 227 1.62 tsutsui for (i = 0; i < __arraycount(mydevname); i++) { 228 1.89 msaitoh devname[i * 2] = mydevname[i] & 0xff; 229 1.32 tsutsui devname[i * 2 + 1] = mydevname[i] >> 8; 230 1.32 tsutsui } 231 1.32 tsutsui 232 1.1 thorpej devname[sizeof(mydevname)] = '\0'; 233 1.61 tsutsui for (i = sizeof(mydevname) ; i > 0; i--) { 234 1.61 tsutsui if (devname[i - 1] == ' ') 235 1.61 tsutsui devname[i - 1] = '\0'; 236 1.1 thorpej else 237 1.1 thorpej break; 238 1.1 thorpej } 239 1.1 thorpej 240 1.76 tsutsui aprint_normal_dev(sc->sc_dev, "%s, Ethernet address %s\n", 241 1.1 thorpej devname, ether_sprintf(enaddr)); 242 1.1 thorpej 243 1.43 drochner miiflags = 0; 244 1.43 drochner if (sc->sc_hwflags & EPIC_HAS_MII_FIBER) 245 1.43 drochner miiflags |= MIIF_HAVEFIBER; 246 1.43 drochner 247 1.8 thorpej /* 248 1.8 thorpej * Initialize our media structures and probe the MII. 249 1.8 thorpej */ 250 1.88 msaitoh mii->mii_ifp = ifp; 251 1.88 msaitoh mii->mii_readreg = epic_mii_read; 252 1.88 msaitoh mii->mii_writereg = epic_mii_write; 253 1.88 msaitoh mii->mii_statchg = epic_statchg; 254 1.71 dyoung 255 1.88 msaitoh sc->sc_ethercom.ec_mii = mii; 256 1.88 msaitoh ifmedia_init(&mii->mii_media, IFM_IMASK, epic_mediachange, 257 1.71 dyoung ether_mediastatus); 258 1.88 msaitoh mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, 259 1.43 drochner MII_OFFSET_ANY, miiflags); 260 1.88 msaitoh if (LIST_EMPTY(&mii->mii_phys)) { 261 1.88 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 262 1.88 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 263 1.8 thorpej } else 264 1.88 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 265 1.8 thorpej 266 1.43 drochner if (sc->sc_hwflags & EPIC_HAS_BNC) { 267 1.43 drochner /* use the next free media instance */ 268 1.88 msaitoh sc->sc_serinst = mii->mii_instance++; 269 1.88 msaitoh ifmedia_add(&mii->mii_media, 270 1.76 tsutsui IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc->sc_serinst), 271 1.76 tsutsui 0, NULL); 272 1.76 tsutsui aprint_normal_dev(sc->sc_dev, "10base2/BNC\n"); 273 1.43 drochner } else 274 1.43 drochner sc->sc_serinst = -1; 275 1.43 drochner 276 1.76 tsutsui strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 277 1.1 thorpej ifp->if_softc = sc; 278 1.1 thorpej ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 279 1.1 thorpej ifp->if_ioctl = epic_ioctl; 280 1.1 thorpej ifp->if_start = epic_start; 281 1.1 thorpej ifp->if_watchdog = epic_watchdog; 282 1.34 thorpej ifp->if_init = epic_init; 283 1.34 thorpej ifp->if_stop = epic_stop; 284 1.40 thorpej IFQ_SET_READY(&ifp->if_snd); 285 1.36 bouyer 286 1.36 bouyer /* 287 1.36 bouyer * We can support 802.1Q VLAN-sized frames. 288 1.36 bouyer */ 289 1.36 bouyer sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; 290 1.1 thorpej 291 1.1 thorpej /* 292 1.1 thorpej * Attach the interface. 293 1.1 thorpej */ 294 1.1 thorpej if_attach(ifp); 295 1.85 ozaki if_deferred_start_init(ifp, NULL); 296 1.1 thorpej ether_ifattach(ifp, enaddr); 297 1.1 thorpej 298 1.1 thorpej /* 299 1.1 thorpej * Make sure the interface is shutdown during reboot. 300 1.1 thorpej */ 301 1.77 tsutsui if (pmf_device_register1(sc->sc_dev, NULL, NULL, epic_shutdown)) 302 1.77 tsutsui pmf_class_network_register(sc->sc_dev, ifp); 303 1.77 tsutsui else 304 1.76 tsutsui aprint_error_dev(sc->sc_dev, 305 1.77 tsutsui "couldn't establish power handler\n"); 306 1.77 tsutsui 307 1.1 thorpej return; 308 1.1 thorpej 309 1.1 thorpej /* 310 1.1 thorpej * Free any resources we've allocated during the failed attach 311 1.1 thorpej * attempt. Do this in reverse order and fall through. 312 1.1 thorpej */ 313 1.52 bouyer fail_6: 314 1.52 bouyer bus_dmamap_destroy(sc->sc_dmat, sc->sc_nulldmamap); 315 1.14 thorpej fail_5: 316 1.14 thorpej for (i = 0; i < EPIC_NRXDESC; i++) { 317 1.14 thorpej if (EPIC_DSRX(sc, i)->ds_dmamap != NULL) 318 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, 319 1.10 thorpej EPIC_DSRX(sc, i)->ds_dmamap); 320 1.14 thorpej } 321 1.14 thorpej fail_4: 322 1.14 thorpej for (i = 0; i < EPIC_NTXDESC; i++) { 323 1.14 thorpej if (EPIC_DSTX(sc, i)->ds_dmamap != NULL) 324 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, 325 1.10 thorpej EPIC_DSTX(sc, i)->ds_dmamap); 326 1.1 thorpej } 327 1.14 thorpej bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); 328 1.14 thorpej fail_3: 329 1.14 thorpej bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); 330 1.14 thorpej fail_2: 331 1.64 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, 332 1.14 thorpej sizeof(struct epic_control_data)); 333 1.14 thorpej fail_1: 334 1.14 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg); 335 1.14 thorpej fail_0: 336 1.14 thorpej return; 337 1.1 thorpej } 338 1.1 thorpej 339 1.1 thorpej /* 340 1.1 thorpej * Shutdown hook. Make sure the interface is stopped at reboot. 341 1.1 thorpej */ 342 1.91 thorpej static bool 343 1.77 tsutsui epic_shutdown(device_t self, int howto) 344 1.1 thorpej { 345 1.77 tsutsui struct epic_softc *sc = device_private(self); 346 1.1 thorpej 347 1.34 thorpej epic_stop(&sc->sc_ethercom.ec_if, 1); 348 1.77 tsutsui 349 1.77 tsutsui return true; 350 1.1 thorpej } 351 1.1 thorpej 352 1.1 thorpej /* 353 1.1 thorpej * Start packet transmission on the interface. 354 1.1 thorpej * [ifnet interface function] 355 1.1 thorpej */ 356 1.91 thorpej static void 357 1.76 tsutsui epic_start(struct ifnet *ifp) 358 1.1 thorpej { 359 1.1 thorpej struct epic_softc *sc = ifp->if_softc; 360 1.10 thorpej struct mbuf *m0, *m; 361 1.1 thorpej struct epic_txdesc *txd; 362 1.1 thorpej struct epic_descsoft *ds; 363 1.1 thorpej struct epic_fraglist *fr; 364 1.1 thorpej bus_dmamap_t dmamap; 365 1.10 thorpej int error, firsttx, nexttx, opending, seg; 366 1.55 tsutsui u_int len; 367 1.1 thorpej 368 1.10 thorpej /* 369 1.10 thorpej * Remember the previous txpending and the first transmit 370 1.10 thorpej * descriptor we use. 371 1.10 thorpej */ 372 1.10 thorpej opending = sc->sc_txpending; 373 1.10 thorpej firsttx = EPIC_NEXTTX(sc->sc_txlast); 374 1.1 thorpej 375 1.1 thorpej /* 376 1.1 thorpej * Loop through the send queue, setting up transmit descriptors 377 1.1 thorpej * until we drain the queue, or use up all available transmit 378 1.1 thorpej * descriptors. 379 1.1 thorpej */ 380 1.10 thorpej while (sc->sc_txpending < EPIC_NTXDESC) { 381 1.1 thorpej /* 382 1.1 thorpej * Grab a packet off the queue. 383 1.1 thorpej */ 384 1.40 thorpej IFQ_POLL(&ifp->if_snd, m0); 385 1.10 thorpej if (m0 == NULL) 386 1.10 thorpej break; 387 1.41 thorpej m = NULL; 388 1.1 thorpej 389 1.1 thorpej /* 390 1.1 thorpej * Get the last and next available transmit descriptor. 391 1.1 thorpej */ 392 1.1 thorpej nexttx = EPIC_NEXTTX(sc->sc_txlast); 393 1.10 thorpej txd = EPIC_CDTX(sc, nexttx); 394 1.10 thorpej fr = EPIC_CDFL(sc, nexttx); 395 1.10 thorpej ds = EPIC_DSTX(sc, nexttx); 396 1.1 thorpej dmamap = ds->ds_dmamap; 397 1.1 thorpej 398 1.1 thorpej /* 399 1.10 thorpej * Load the DMA map. If this fails, the packet either 400 1.97 andvar * didn't fit in the allotted number of frags, or we were 401 1.89 msaitoh * short on resources. In this case, we'll copy and try 402 1.10 thorpej * again. 403 1.1 thorpej */ 404 1.52 bouyer if ((error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, 405 1.88 msaitoh BUS_DMA_WRITE | BUS_DMA_NOWAIT)) != 0 || 406 1.52 bouyer (m0->m_pkthdr.len < ETHER_PAD_LEN && 407 1.52 bouyer dmamap-> dm_nsegs == EPIC_NFRAGS)) { 408 1.52 bouyer if (error == 0) 409 1.52 bouyer bus_dmamap_unload(sc->sc_dmat, dmamap); 410 1.59 perry 411 1.10 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA); 412 1.10 thorpej if (m == NULL) { 413 1.76 tsutsui printf("%s: unable to allocate Tx mbuf\n", 414 1.76 tsutsui device_xname(sc->sc_dev)); 415 1.10 thorpej break; 416 1.1 thorpej } 417 1.94 thorpej MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); 418 1.1 thorpej if (m0->m_pkthdr.len > MHLEN) { 419 1.10 thorpej MCLGET(m, M_DONTWAIT); 420 1.10 thorpej if ((m->m_flags & M_EXT) == 0) { 421 1.76 tsutsui printf("%s: unable to allocate Tx " 422 1.76 tsutsui "cluster\n", 423 1.76 tsutsui device_xname(sc->sc_dev)); 424 1.10 thorpej m_freem(m); 425 1.10 thorpej break; 426 1.1 thorpej } 427 1.1 thorpej } 428 1.64 christos m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); 429 1.10 thorpej m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; 430 1.10 thorpej error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, 431 1.88 msaitoh m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); 432 1.10 thorpej if (error) { 433 1.76 tsutsui printf("%s: unable to load Tx buffer, " 434 1.76 tsutsui "error = %d\n", device_xname(sc->sc_dev), 435 1.76 tsutsui error); 436 1.10 thorpej break; 437 1.10 thorpej } 438 1.1 thorpej } 439 1.40 thorpej IFQ_DEQUEUE(&ifp->if_snd, m0); 440 1.41 thorpej if (m != NULL) { 441 1.41 thorpej m_freem(m0); 442 1.41 thorpej m0 = m; 443 1.41 thorpej } 444 1.1 thorpej 445 1.10 thorpej /* Initialize the fraglist. */ 446 1.1 thorpej for (seg = 0; seg < dmamap->dm_nsegs; seg++) { 447 1.1 thorpej fr->ef_frags[seg].ef_addr = 448 1.1 thorpej dmamap->dm_segs[seg].ds_addr; 449 1.1 thorpej fr->ef_frags[seg].ef_length = 450 1.1 thorpej dmamap->dm_segs[seg].ds_len; 451 1.1 thorpej } 452 1.55 tsutsui len = m0->m_pkthdr.len; 453 1.55 tsutsui if (len < ETHER_PAD_LEN) { 454 1.52 bouyer fr->ef_frags[seg].ef_addr = sc->sc_nulldma; 455 1.55 tsutsui fr->ef_frags[seg].ef_length = ETHER_PAD_LEN - len; 456 1.55 tsutsui len = ETHER_PAD_LEN; 457 1.52 bouyer seg++; 458 1.52 bouyer } 459 1.52 bouyer fr->ef_nfrags = seg; 460 1.1 thorpej 461 1.10 thorpej EPIC_CDFLSYNC(sc, nexttx, BUS_DMASYNC_PREWRITE); 462 1.10 thorpej 463 1.10 thorpej /* Sync the DMA map. */ 464 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, 465 1.1 thorpej BUS_DMASYNC_PREWRITE); 466 1.1 thorpej 467 1.1 thorpej /* 468 1.1 thorpej * Store a pointer to the packet so we can free it later. 469 1.1 thorpej */ 470 1.1 thorpej ds->ds_mbuf = m0; 471 1.1 thorpej 472 1.1 thorpej /* 473 1.52 bouyer * Fill in the transmit descriptor. 474 1.1 thorpej */ 475 1.10 thorpej txd->et_control = ET_TXCTL_LASTDESC | ET_TXCTL_FRAGLIST; 476 1.1 thorpej 477 1.1 thorpej /* 478 1.10 thorpej * If this is the first descriptor we're enqueueing, 479 1.10 thorpej * don't give it to the EPIC yet. That could cause 480 1.10 thorpej * a race condition. We'll do it below. 481 1.1 thorpej */ 482 1.10 thorpej if (nexttx == firsttx) 483 1.55 tsutsui txd->et_txstatus = TXSTAT_TXLENGTH(len); 484 1.10 thorpej else 485 1.55 tsutsui txd->et_txstatus = 486 1.55 tsutsui TXSTAT_TXLENGTH(len) | ET_TXSTAT_OWNER; 487 1.10 thorpej 488 1.10 thorpej EPIC_CDTXSYNC(sc, nexttx, 489 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 490 1.1 thorpej 491 1.10 thorpej /* Advance the tx pointer. */ 492 1.1 thorpej sc->sc_txpending++; 493 1.10 thorpej sc->sc_txlast = nexttx; 494 1.1 thorpej 495 1.1 thorpej /* 496 1.1 thorpej * Pass the packet to any BPF listeners. 497 1.1 thorpej */ 498 1.86 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 499 1.1 thorpej } 500 1.1 thorpej 501 1.10 thorpej if (sc->sc_txpending != opending) { 502 1.10 thorpej /* 503 1.89 msaitoh * We enqueued packets. If the transmitter was idle, 504 1.10 thorpej * reset the txdirty pointer. 505 1.10 thorpej */ 506 1.10 thorpej if (opending == 0) 507 1.10 thorpej sc->sc_txdirty = firsttx; 508 1.10 thorpej 509 1.10 thorpej /* 510 1.10 thorpej * Cause a transmit interrupt to happen on the 511 1.10 thorpej * last packet we enqueued. 512 1.10 thorpej */ 513 1.10 thorpej EPIC_CDTX(sc, sc->sc_txlast)->et_control |= ET_TXCTL_IAF; 514 1.10 thorpej EPIC_CDTXSYNC(sc, sc->sc_txlast, 515 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 516 1.10 thorpej 517 1.10 thorpej /* 518 1.10 thorpej * The entire packet chain is set up. Give the 519 1.10 thorpej * first descriptor to the EPIC now. 520 1.10 thorpej */ 521 1.55 tsutsui EPIC_CDTX(sc, firsttx)->et_txstatus |= ET_TXSTAT_OWNER; 522 1.10 thorpej EPIC_CDTXSYNC(sc, firsttx, 523 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 524 1.10 thorpej 525 1.10 thorpej /* Start the transmitter. */ 526 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND, 527 1.1 thorpej COMMAND_TXQUEUED); 528 1.1 thorpej 529 1.10 thorpej /* Set a watchdog timer in case the chip flakes out. */ 530 1.1 thorpej ifp->if_timer = 5; 531 1.1 thorpej } 532 1.1 thorpej } 533 1.1 thorpej 534 1.1 thorpej /* 535 1.1 thorpej * Watchdog timer handler. 536 1.1 thorpej * [ifnet interface function] 537 1.1 thorpej */ 538 1.91 thorpej static void 539 1.76 tsutsui epic_watchdog(struct ifnet *ifp) 540 1.1 thorpej { 541 1.1 thorpej struct epic_softc *sc = ifp->if_softc; 542 1.1 thorpej 543 1.76 tsutsui printf("%s: device timeout\n", device_xname(sc->sc_dev)); 544 1.92 thorpej if_statinc(ifp, if_oerrors); 545 1.1 thorpej 546 1.76 tsutsui (void)epic_init(ifp); 547 1.1 thorpej } 548 1.1 thorpej 549 1.1 thorpej /* 550 1.1 thorpej * Handle control requests from the operator. 551 1.1 thorpej * [ifnet interface function] 552 1.1 thorpej */ 553 1.91 thorpej static int 554 1.76 tsutsui epic_ioctl(struct ifnet *ifp, u_long cmd, void *data) 555 1.1 thorpej { 556 1.1 thorpej struct epic_softc *sc = ifp->if_softc; 557 1.34 thorpej int s, error; 558 1.1 thorpej 559 1.7 mycroft s = splnet(); 560 1.1 thorpej 561 1.71 dyoung error = ether_ioctl(ifp, cmd, data); 562 1.71 dyoung if (error == ENETRESET) { 563 1.71 dyoung /* 564 1.71 dyoung * Multicast list has changed; set the hardware filter 565 1.89 msaitoh * accordingly. Update our idea of the current media; 566 1.71 dyoung * epic_set_mchash() needs to know what it is. 567 1.71 dyoung */ 568 1.71 dyoung if (ifp->if_flags & IFF_RUNNING) { 569 1.71 dyoung mii_pollstat(&sc->sc_mii); 570 1.71 dyoung epic_set_mchash(sc); 571 1.1 thorpej } 572 1.71 dyoung error = 0; 573 1.1 thorpej } 574 1.1 thorpej 575 1.1 thorpej splx(s); 576 1.76 tsutsui return error; 577 1.1 thorpej } 578 1.1 thorpej 579 1.1 thorpej /* 580 1.1 thorpej * Interrupt handler. 581 1.1 thorpej */ 582 1.1 thorpej int 583 1.76 tsutsui epic_intr(void *arg) 584 1.1 thorpej { 585 1.1 thorpej struct epic_softc *sc = arg; 586 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 587 1.1 thorpej struct epic_rxdesc *rxd; 588 1.1 thorpej struct epic_txdesc *txd; 589 1.1 thorpej struct epic_descsoft *ds; 590 1.1 thorpej struct mbuf *m; 591 1.63 tsutsui uint32_t intstat, rxstatus, txstatus; 592 1.51 thorpej int i, claimed = 0; 593 1.51 thorpej u_int len; 594 1.1 thorpej 595 1.1 thorpej top: 596 1.1 thorpej /* 597 1.1 thorpej * Get the interrupt status from the EPIC. 598 1.1 thorpej */ 599 1.1 thorpej intstat = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT); 600 1.1 thorpej if ((intstat & INTSTAT_INT_ACTV) == 0) 601 1.76 tsutsui return claimed; 602 1.1 thorpej 603 1.1 thorpej claimed = 1; 604 1.1 thorpej 605 1.1 thorpej /* 606 1.1 thorpej * Acknowledge the interrupt. 607 1.1 thorpej */ 608 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT, 609 1.1 thorpej intstat & INTMASK); 610 1.1 thorpej 611 1.1 thorpej /* 612 1.1 thorpej * Check for receive interrupts. 613 1.1 thorpej */ 614 1.21 thorpej if (intstat & (INTSTAT_RCC | INTSTAT_RXE | INTSTAT_RQE)) { 615 1.1 thorpej for (i = sc->sc_rxptr;; i = EPIC_NEXTRX(i)) { 616 1.10 thorpej rxd = EPIC_CDRX(sc, i); 617 1.10 thorpej ds = EPIC_DSRX(sc, i); 618 1.10 thorpej 619 1.10 thorpej EPIC_CDRXSYNC(sc, i, 620 1.88 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 621 1.1 thorpej 622 1.55 tsutsui rxstatus = rxd->er_rxstatus; 623 1.55 tsutsui if (rxstatus & ER_RXSTAT_OWNER) { 624 1.1 thorpej /* 625 1.1 thorpej * We have processed all of the 626 1.1 thorpej * receive buffers. 627 1.1 thorpej */ 628 1.1 thorpej break; 629 1.1 thorpej } 630 1.1 thorpej 631 1.1 thorpej /* 632 1.89 msaitoh * Make sure the packet arrived intact. If an error 633 1.10 thorpej * occurred, update stats and reset the descriptor. 634 1.10 thorpej * The buffer will be reused the next time the 635 1.10 thorpej * descriptor comes up in the ring. 636 1.1 thorpej */ 637 1.55 tsutsui if ((rxstatus & ER_RXSTAT_PKTINTACT) == 0) { 638 1.55 tsutsui if (rxstatus & ER_RXSTAT_CRCERROR) 639 1.76 tsutsui printf("%s: CRC error\n", 640 1.76 tsutsui device_xname(sc->sc_dev)); 641 1.55 tsutsui if (rxstatus & ER_RXSTAT_ALIGNERROR) 642 1.76 tsutsui printf("%s: alignment error\n", 643 1.76 tsutsui device_xname(sc->sc_dev)); 644 1.92 thorpej if_statinc(ifp, if_ierrors); 645 1.10 thorpej EPIC_INIT_RXDESC(sc, i); 646 1.10 thorpej continue; 647 1.1 thorpej } 648 1.1 thorpej 649 1.10 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 650 1.10 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); 651 1.10 thorpej 652 1.21 thorpej /* 653 1.57 thorpej * The EPIC includes the CRC with every packet; 654 1.57 thorpej * trim it. 655 1.21 thorpej */ 656 1.57 thorpej len = RXSTAT_RXLENGTH(rxstatus) - ETHER_CRC_LEN; 657 1.21 thorpej 658 1.19 thorpej if (len < sizeof(struct ether_header)) { 659 1.19 thorpej /* 660 1.19 thorpej * Runt packet; drop it now. 661 1.19 thorpej */ 662 1.92 thorpej if_statinc(ifp, if_ierrors); 663 1.10 thorpej EPIC_INIT_RXDESC(sc, i); 664 1.10 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 665 1.10 thorpej ds->ds_dmamap->dm_mapsize, 666 1.10 thorpej BUS_DMASYNC_PREREAD); 667 1.10 thorpej continue; 668 1.10 thorpej } 669 1.10 thorpej 670 1.19 thorpej /* 671 1.19 thorpej * If the packet is small enough to fit in a 672 1.19 thorpej * single header mbuf, allocate one and copy 673 1.19 thorpej * the data into it. This greatly reduces 674 1.19 thorpej * memory consumption when we receive lots 675 1.19 thorpej * of small packets. 676 1.19 thorpej * 677 1.19 thorpej * Otherwise, we add a new buffer to the receive 678 1.19 thorpej * chain. If this fails, we drop the packet and 679 1.19 thorpej * recycle the old buffer. 680 1.19 thorpej */ 681 1.19 thorpej if (epic_copy_small != 0 && len <= MHLEN) { 682 1.19 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA); 683 1.19 thorpej if (m == NULL) 684 1.19 thorpej goto dropit; 685 1.94 thorpej MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 686 1.64 christos memcpy(mtod(m, void *), 687 1.64 christos mtod(ds->ds_mbuf, void *), len); 688 1.19 thorpej EPIC_INIT_RXDESC(sc, i); 689 1.19 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 690 1.19 thorpej ds->ds_dmamap->dm_mapsize, 691 1.19 thorpej BUS_DMASYNC_PREREAD); 692 1.19 thorpej } else { 693 1.19 thorpej m = ds->ds_mbuf; 694 1.19 thorpej if (epic_add_rxbuf(sc, i) != 0) { 695 1.19 thorpej dropit: 696 1.92 thorpej if_statinc(ifp, if_ierrors); 697 1.19 thorpej EPIC_INIT_RXDESC(sc, i); 698 1.19 thorpej bus_dmamap_sync(sc->sc_dmat, 699 1.19 thorpej ds->ds_dmamap, 0, 700 1.19 thorpej ds->ds_dmamap->dm_mapsize, 701 1.19 thorpej BUS_DMASYNC_PREREAD); 702 1.19 thorpej continue; 703 1.19 thorpej } 704 1.10 thorpej } 705 1.10 thorpej 706 1.83 ozaki m_set_rcvif(m, ifp); 707 1.10 thorpej m->m_pkthdr.len = m->m_len = len; 708 1.1 thorpej 709 1.16 thorpej /* Pass it on. */ 710 1.82 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 711 1.1 thorpej } 712 1.10 thorpej 713 1.42 tsutsui /* Update the receive pointer. */ 714 1.1 thorpej sc->sc_rxptr = i; 715 1.1 thorpej 716 1.1 thorpej /* 717 1.1 thorpej * Check for receive queue underflow. 718 1.1 thorpej */ 719 1.1 thorpej if (intstat & INTSTAT_RQE) { 720 1.76 tsutsui printf("%s: receiver queue empty\n", 721 1.76 tsutsui device_xname(sc->sc_dev)); 722 1.1 thorpej /* 723 1.1 thorpej * Ring is already built; just restart the 724 1.1 thorpej * receiver. 725 1.1 thorpej */ 726 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_PRCDAR, 727 1.10 thorpej EPIC_CDRXADDR(sc, sc->sc_rxptr)); 728 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND, 729 1.1 thorpej COMMAND_RXQUEUED | COMMAND_START_RX); 730 1.1 thorpej } 731 1.1 thorpej } 732 1.1 thorpej 733 1.1 thorpej /* 734 1.1 thorpej * Check for transmission complete interrupts. 735 1.1 thorpej */ 736 1.1 thorpej if (intstat & (INTSTAT_TXC | INTSTAT_TXU)) { 737 1.10 thorpej for (i = sc->sc_txdirty; sc->sc_txpending != 0; 738 1.10 thorpej i = EPIC_NEXTTX(i), sc->sc_txpending--) { 739 1.10 thorpej txd = EPIC_CDTX(sc, i); 740 1.10 thorpej ds = EPIC_DSTX(sc, i); 741 1.1 thorpej 742 1.10 thorpej EPIC_CDTXSYNC(sc, i, 743 1.88 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 744 1.10 thorpej 745 1.55 tsutsui txstatus = txd->et_txstatus; 746 1.55 tsutsui if (txstatus & ET_TXSTAT_OWNER) 747 1.1 thorpej break; 748 1.1 thorpej 749 1.10 thorpej EPIC_CDFLSYNC(sc, i, BUS_DMASYNC_POSTWRITE); 750 1.10 thorpej 751 1.10 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 752 1.10 thorpej 0, ds->ds_dmamap->dm_mapsize, 753 1.10 thorpej BUS_DMASYNC_POSTWRITE); 754 1.10 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 755 1.10 thorpej m_freem(ds->ds_mbuf); 756 1.10 thorpej ds->ds_mbuf = NULL; 757 1.1 thorpej 758 1.1 thorpej /* 759 1.1 thorpej * Check for errors and collisions. 760 1.1 thorpej */ 761 1.92 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(ifp); 762 1.55 tsutsui if ((txstatus & ET_TXSTAT_PACKETTX) == 0) 763 1.98 riastrad if_statinc_ref(ifp, nsr, if_oerrors); 764 1.10 thorpej else 765 1.98 riastrad if_statinc_ref(ifp, nsr, if_opackets); 766 1.92 thorpej if (TXSTAT_COLLISIONS(txstatus)) 767 1.98 riastrad if_statadd_ref(ifp, nsr, if_collisions, 768 1.92 thorpej TXSTAT_COLLISIONS(txstatus)); 769 1.55 tsutsui if (txstatus & ET_TXSTAT_CARSENSELOST) 770 1.76 tsutsui printf("%s: lost carrier\n", 771 1.76 tsutsui device_xname(sc->sc_dev)); 772 1.92 thorpej IF_STAT_PUTREF(ifp); 773 1.1 thorpej } 774 1.59 perry 775 1.10 thorpej /* Update the dirty transmit buffer pointer. */ 776 1.1 thorpej sc->sc_txdirty = i; 777 1.1 thorpej 778 1.1 thorpej /* 779 1.1 thorpej * Cancel the watchdog timer if there are no pending 780 1.1 thorpej * transmissions. 781 1.1 thorpej */ 782 1.1 thorpej if (sc->sc_txpending == 0) 783 1.1 thorpej ifp->if_timer = 0; 784 1.1 thorpej 785 1.1 thorpej /* 786 1.1 thorpej * Kick the transmitter after a DMA underrun. 787 1.1 thorpej */ 788 1.1 thorpej if (intstat & INTSTAT_TXU) { 789 1.76 tsutsui printf("%s: transmit underrun\n", 790 1.76 tsutsui device_xname(sc->sc_dev)); 791 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, 792 1.1 thorpej EPIC_COMMAND, COMMAND_TXUGO); 793 1.1 thorpej if (sc->sc_txpending) 794 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, 795 1.1 thorpej EPIC_COMMAND, COMMAND_TXQUEUED); 796 1.1 thorpej } 797 1.1 thorpej 798 1.1 thorpej /* 799 1.1 thorpej * Try to get more packets going. 800 1.1 thorpej */ 801 1.85 ozaki if_schedule_deferred_start(ifp); 802 1.1 thorpej } 803 1.1 thorpej 804 1.1 thorpej /* 805 1.1 thorpej * Check for fatal interrupts. 806 1.1 thorpej */ 807 1.1 thorpej if (intstat & INTSTAT_FATAL_INT) { 808 1.21 thorpej if (intstat & INTSTAT_PTA) 809 1.76 tsutsui printf("%s: PCI target abort error\n", 810 1.76 tsutsui device_xname(sc->sc_dev)); 811 1.21 thorpej else if (intstat & INTSTAT_PMA) 812 1.76 tsutsui printf("%s: PCI master abort error\n", 813 1.76 tsutsui device_xname(sc->sc_dev)); 814 1.21 thorpej else if (intstat & INTSTAT_APE) 815 1.76 tsutsui printf("%s: PCI address parity error\n", 816 1.76 tsutsui device_xname(sc->sc_dev)); 817 1.21 thorpej else if (intstat & INTSTAT_DPE) 818 1.76 tsutsui printf("%s: PCI data parity error\n", 819 1.76 tsutsui device_xname(sc->sc_dev)); 820 1.21 thorpej else 821 1.76 tsutsui printf("%s: unknown fatal error\n", 822 1.76 tsutsui device_xname(sc->sc_dev)); 823 1.76 tsutsui (void)epic_init(ifp); 824 1.1 thorpej } 825 1.1 thorpej 826 1.1 thorpej /* 827 1.1 thorpej * Check for more interrupts. 828 1.1 thorpej */ 829 1.1 thorpej goto top; 830 1.1 thorpej } 831 1.1 thorpej 832 1.1 thorpej /* 833 1.8 thorpej * One second timer, used to tick the MII. 834 1.8 thorpej */ 835 1.91 thorpej static void 836 1.76 tsutsui epic_tick(void *arg) 837 1.8 thorpej { 838 1.8 thorpej struct epic_softc *sc = arg; 839 1.8 thorpej int s; 840 1.8 thorpej 841 1.12 thorpej s = splnet(); 842 1.8 thorpej mii_tick(&sc->sc_mii); 843 1.8 thorpej splx(s); 844 1.8 thorpej 845 1.93 thorpej callout_schedule(&sc->sc_mii_callout, hz); 846 1.8 thorpej } 847 1.8 thorpej 848 1.8 thorpej /* 849 1.6 thorpej * Fixup the clock source on the EPIC. 850 1.6 thorpej */ 851 1.91 thorpej static void 852 1.76 tsutsui epic_fixup_clock_source(struct epic_softc *sc) 853 1.6 thorpej { 854 1.6 thorpej int i; 855 1.6 thorpej 856 1.6 thorpej /* 857 1.6 thorpej * According to SMC Application Note 7-15, the EPIC's clock 858 1.6 thorpej * source is incorrect following a reset. This manifests itself 859 1.6 thorpej * as failure to recognize when host software has written to 860 1.6 thorpej * a register on the EPIC. The appnote recommends issuing at 861 1.6 thorpej * least 16 consecutive writes to the CLOCK TEST bit to correctly 862 1.6 thorpej * configure the clock source. 863 1.6 thorpej */ 864 1.6 thorpej for (i = 0; i < 16; i++) 865 1.6 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_TEST, 866 1.6 thorpej TEST_CLOCKTEST); 867 1.6 thorpej } 868 1.6 thorpej 869 1.6 thorpej /* 870 1.1 thorpej * Perform a soft reset on the EPIC. 871 1.1 thorpej */ 872 1.91 thorpej static void 873 1.76 tsutsui epic_reset(struct epic_softc *sc) 874 1.1 thorpej { 875 1.1 thorpej 876 1.6 thorpej epic_fixup_clock_source(sc); 877 1.6 thorpej 878 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, 0); 879 1.1 thorpej delay(100); 880 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, GENCTL_SOFTRESET); 881 1.1 thorpej delay(100); 882 1.6 thorpej 883 1.6 thorpej epic_fixup_clock_source(sc); 884 1.1 thorpej } 885 1.1 thorpej 886 1.1 thorpej /* 887 1.7 mycroft * Initialize the interface. Must be called at splnet(). 888 1.1 thorpej */ 889 1.91 thorpej static int 890 1.76 tsutsui epic_init(struct ifnet *ifp) 891 1.1 thorpej { 892 1.34 thorpej struct epic_softc *sc = ifp->if_softc; 893 1.1 thorpej bus_space_tag_t st = sc->sc_st; 894 1.1 thorpej bus_space_handle_t sh = sc->sc_sh; 895 1.66 dyoung const uint8_t *enaddr = CLLADDR(ifp->if_sadl); 896 1.1 thorpej struct epic_txdesc *txd; 897 1.19 thorpej struct epic_descsoft *ds; 898 1.63 tsutsui uint32_t genctl, reg0; 899 1.19 thorpej int i, error = 0; 900 1.1 thorpej 901 1.1 thorpej /* 902 1.1 thorpej * Cancel any pending I/O. 903 1.1 thorpej */ 904 1.34 thorpej epic_stop(ifp, 0); 905 1.1 thorpej 906 1.1 thorpej /* 907 1.1 thorpej * Reset the EPIC to a known state. 908 1.1 thorpej */ 909 1.1 thorpej epic_reset(sc); 910 1.1 thorpej 911 1.1 thorpej /* 912 1.1 thorpej * Magical mystery initialization. 913 1.1 thorpej */ 914 1.1 thorpej bus_space_write_4(st, sh, EPIC_TXTEST, 0); 915 1.1 thorpej 916 1.1 thorpej /* 917 1.1 thorpej * Initialize the EPIC genctl register: 918 1.1 thorpej * 919 1.1 thorpej * - 64 byte receive FIFO threshold 920 1.1 thorpej * - automatic advance to next receive frame 921 1.1 thorpej */ 922 1.1 thorpej genctl = GENCTL_RX_FIFO_THRESH0 | GENCTL_ONECOPY; 923 1.18 thorpej #if BYTE_ORDER == BIG_ENDIAN 924 1.18 thorpej genctl |= GENCTL_BIG_ENDIAN; 925 1.18 thorpej #endif 926 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl); 927 1.1 thorpej 928 1.1 thorpej /* 929 1.1 thorpej * Reset the MII bus and PHY. 930 1.1 thorpej */ 931 1.1 thorpej reg0 = bus_space_read_4(st, sh, EPIC_NVCTL); 932 1.1 thorpej bus_space_write_4(st, sh, EPIC_NVCTL, reg0 | NVCTL_GPIO1 | NVCTL_GPOE1); 933 1.1 thorpej bus_space_write_4(st, sh, EPIC_MIICFG, MIICFG_ENASER); 934 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_RESET_PHY); 935 1.1 thorpej delay(100); 936 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl); 937 1.44 drochner delay(1000); 938 1.1 thorpej bus_space_write_4(st, sh, EPIC_NVCTL, reg0); 939 1.1 thorpej 940 1.1 thorpej /* 941 1.1 thorpej * Initialize Ethernet address. 942 1.1 thorpej */ 943 1.1 thorpej reg0 = enaddr[1] << 8 | enaddr[0]; 944 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN0, reg0); 945 1.1 thorpej reg0 = enaddr[3] << 8 | enaddr[2]; 946 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN1, reg0); 947 1.1 thorpej reg0 = enaddr[5] << 8 | enaddr[4]; 948 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN2, reg0); 949 1.1 thorpej 950 1.1 thorpej /* 951 1.89 msaitoh * Initialize receive control. Remember the external buffer 952 1.1 thorpej * size setting. 953 1.1 thorpej */ 954 1.1 thorpej reg0 = bus_space_read_4(st, sh, EPIC_RXCON) & 955 1.1 thorpej (RXCON_EXTBUFSIZESEL1 | RXCON_EXTBUFSIZESEL0); 956 1.1 thorpej reg0 |= (RXCON_RXMULTICAST | RXCON_RXBROADCAST); 957 1.1 thorpej if (ifp->if_flags & IFF_PROMISC) 958 1.1 thorpej reg0 |= RXCON_PROMISCMODE; 959 1.1 thorpej bus_space_write_4(st, sh, EPIC_RXCON, reg0); 960 1.1 thorpej 961 1.13 thorpej /* Set the current media. */ 962 1.71 dyoung if ((error = epic_mediachange(ifp)) != 0) 963 1.71 dyoung goto out; 964 1.1 thorpej 965 1.13 thorpej /* Set up the multicast hash table. */ 966 1.13 thorpej epic_set_mchash(sc); 967 1.13 thorpej 968 1.1 thorpej /* 969 1.10 thorpej * Initialize the transmit descriptor ring. txlast is initialized 970 1.10 thorpej * to the end of the list so that it will wrap around to the first 971 1.10 thorpej * descriptor when the first packet is transmitted. 972 1.1 thorpej */ 973 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) { 974 1.10 thorpej txd = EPIC_CDTX(sc, i); 975 1.10 thorpej memset(txd, 0, sizeof(struct epic_txdesc)); 976 1.10 thorpej txd->et_bufaddr = EPIC_CDFLADDR(sc, i); 977 1.10 thorpej txd->et_nextdesc = EPIC_CDTXADDR(sc, EPIC_NEXTTX(i)); 978 1.88 msaitoh EPIC_CDTXSYNC(sc, i, 979 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 980 1.1 thorpej } 981 1.10 thorpej sc->sc_txpending = 0; 982 1.10 thorpej sc->sc_txdirty = 0; 983 1.10 thorpej sc->sc_txlast = EPIC_NTXDESC - 1; 984 1.1 thorpej 985 1.1 thorpej /* 986 1.19 thorpej * Initialize the receive descriptor ring. 987 1.1 thorpej */ 988 1.19 thorpej for (i = 0; i < EPIC_NRXDESC; i++) { 989 1.19 thorpej ds = EPIC_DSRX(sc, i); 990 1.19 thorpej if (ds->ds_mbuf == NULL) { 991 1.19 thorpej if ((error = epic_add_rxbuf(sc, i)) != 0) { 992 1.76 tsutsui printf("%s: unable to allocate or map rx " 993 1.19 thorpej "buffer %d error = %d\n", 994 1.76 tsutsui device_xname(sc->sc_dev), i, error); 995 1.19 thorpej /* 996 1.19 thorpej * XXX Should attempt to run with fewer receive 997 1.19 thorpej * XXX buffers instead of just failing. 998 1.19 thorpej */ 999 1.19 thorpej epic_rxdrain(sc); 1000 1.19 thorpej goto out; 1001 1.19 thorpej } 1002 1.48 thorpej } else 1003 1.48 thorpej EPIC_INIT_RXDESC(sc, i); 1004 1.19 thorpej } 1005 1.10 thorpej sc->sc_rxptr = 0; 1006 1.1 thorpej 1007 1.1 thorpej /* 1008 1.1 thorpej * Initialize the interrupt mask and enable interrupts. 1009 1.1 thorpej */ 1010 1.1 thorpej bus_space_write_4(st, sh, EPIC_INTMASK, INTMASK); 1011 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_INTENA); 1012 1.1 thorpej 1013 1.1 thorpej /* 1014 1.1 thorpej * Give the transmit and receive rings to the EPIC. 1015 1.1 thorpej */ 1016 1.1 thorpej bus_space_write_4(st, sh, EPIC_PTCDAR, 1017 1.10 thorpej EPIC_CDTXADDR(sc, EPIC_NEXTTX(sc->sc_txlast))); 1018 1.1 thorpej bus_space_write_4(st, sh, EPIC_PRCDAR, 1019 1.10 thorpej EPIC_CDRXADDR(sc, sc->sc_rxptr)); 1020 1.1 thorpej 1021 1.1 thorpej /* 1022 1.1 thorpej * Set the EPIC in motion. 1023 1.1 thorpej */ 1024 1.1 thorpej bus_space_write_4(st, sh, EPIC_COMMAND, 1025 1.1 thorpej COMMAND_RXQUEUED | COMMAND_START_RX); 1026 1.1 thorpej 1027 1.1 thorpej /* 1028 1.1 thorpej * ...all done! 1029 1.1 thorpej */ 1030 1.1 thorpej ifp->if_flags |= IFF_RUNNING; 1031 1.8 thorpej 1032 1.8 thorpej /* 1033 1.8 thorpej * Start the one second clock. 1034 1.8 thorpej */ 1035 1.93 thorpej callout_schedule(&sc->sc_mii_callout, hz); 1036 1.9 thorpej 1037 1.9 thorpej /* 1038 1.9 thorpej * Attempt to start output on the interface. 1039 1.9 thorpej */ 1040 1.9 thorpej epic_start(ifp); 1041 1.19 thorpej 1042 1.19 thorpej out: 1043 1.19 thorpej if (error) 1044 1.76 tsutsui printf("%s: interface not running\n", device_xname(sc->sc_dev)); 1045 1.76 tsutsui return error; 1046 1.19 thorpej } 1047 1.19 thorpej 1048 1.19 thorpej /* 1049 1.19 thorpej * Drain the receive queue. 1050 1.19 thorpej */ 1051 1.91 thorpej static void 1052 1.76 tsutsui epic_rxdrain(struct epic_softc *sc) 1053 1.19 thorpej { 1054 1.19 thorpej struct epic_descsoft *ds; 1055 1.19 thorpej int i; 1056 1.19 thorpej 1057 1.19 thorpej for (i = 0; i < EPIC_NRXDESC; i++) { 1058 1.19 thorpej ds = EPIC_DSRX(sc, i); 1059 1.19 thorpej if (ds->ds_mbuf != NULL) { 1060 1.19 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1061 1.19 thorpej m_freem(ds->ds_mbuf); 1062 1.19 thorpej ds->ds_mbuf = NULL; 1063 1.19 thorpej } 1064 1.19 thorpej } 1065 1.1 thorpej } 1066 1.1 thorpej 1067 1.1 thorpej /* 1068 1.1 thorpej * Stop transmission on the interface. 1069 1.1 thorpej */ 1070 1.91 thorpej static void 1071 1.76 tsutsui epic_stop(struct ifnet *ifp, int disable) 1072 1.1 thorpej { 1073 1.34 thorpej struct epic_softc *sc = ifp->if_softc; 1074 1.1 thorpej bus_space_tag_t st = sc->sc_st; 1075 1.1 thorpej bus_space_handle_t sh = sc->sc_sh; 1076 1.1 thorpej struct epic_descsoft *ds; 1077 1.63 tsutsui uint32_t reg; 1078 1.1 thorpej int i; 1079 1.6 thorpej 1080 1.8 thorpej /* 1081 1.8 thorpej * Stop the one second clock. 1082 1.8 thorpej */ 1083 1.29 thorpej callout_stop(&sc->sc_mii_callout); 1084 1.23 thorpej 1085 1.23 thorpej /* Down the MII. */ 1086 1.23 thorpej mii_down(&sc->sc_mii); 1087 1.8 thorpej 1088 1.6 thorpej /* Paranoia... */ 1089 1.6 thorpej epic_fixup_clock_source(sc); 1090 1.1 thorpej 1091 1.1 thorpej /* 1092 1.1 thorpej * Disable interrupts. 1093 1.1 thorpej */ 1094 1.1 thorpej reg = bus_space_read_4(st, sh, EPIC_GENCTL); 1095 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, reg & ~GENCTL_INTENA); 1096 1.1 thorpej bus_space_write_4(st, sh, EPIC_INTMASK, 0); 1097 1.1 thorpej 1098 1.1 thorpej /* 1099 1.1 thorpej * Stop the DMA engine and take the receiver off-line. 1100 1.1 thorpej */ 1101 1.1 thorpej bus_space_write_4(st, sh, EPIC_COMMAND, COMMAND_STOP_RDMA | 1102 1.1 thorpej COMMAND_STOP_TDMA | COMMAND_STOP_RX); 1103 1.1 thorpej 1104 1.1 thorpej /* 1105 1.1 thorpej * Release any queued transmit buffers. 1106 1.1 thorpej */ 1107 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) { 1108 1.10 thorpej ds = EPIC_DSTX(sc, i); 1109 1.1 thorpej if (ds->ds_mbuf != NULL) { 1110 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1111 1.1 thorpej m_freem(ds->ds_mbuf); 1112 1.1 thorpej ds->ds_mbuf = NULL; 1113 1.1 thorpej } 1114 1.19 thorpej } 1115 1.19 thorpej 1116 1.1 thorpej /* 1117 1.1 thorpej * Mark the interface down and cancel the watchdog timer. 1118 1.1 thorpej */ 1119 1.95 thorpej ifp->if_flags &= ~IFF_RUNNING; 1120 1.1 thorpej ifp->if_timer = 0; 1121 1.72 dyoung 1122 1.72 dyoung if (disable) 1123 1.72 dyoung epic_rxdrain(sc); 1124 1.1 thorpej } 1125 1.1 thorpej 1126 1.1 thorpej /* 1127 1.1 thorpej * Read the EPIC Serial EEPROM. 1128 1.1 thorpej */ 1129 1.91 thorpej static void 1130 1.76 tsutsui epic_read_eeprom(struct epic_softc *sc, int word, int wordcnt, uint16_t *data) 1131 1.1 thorpej { 1132 1.1 thorpej bus_space_tag_t st = sc->sc_st; 1133 1.1 thorpej bus_space_handle_t sh = sc->sc_sh; 1134 1.63 tsutsui uint16_t reg; 1135 1.1 thorpej int i, x; 1136 1.1 thorpej 1137 1.1 thorpej #define EEPROM_WAIT_READY(st, sh) \ 1138 1.1 thorpej while ((bus_space_read_4((st), (sh), EPIC_EECTL) & EECTL_EERDY) == 0) \ 1139 1.1 thorpej /* nothing */ 1140 1.1 thorpej 1141 1.1 thorpej /* 1142 1.1 thorpej * Enable the EEPROM. 1143 1.1 thorpej */ 1144 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE); 1145 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1146 1.1 thorpej 1147 1.1 thorpej for (i = 0; i < wordcnt; i++) { 1148 1.1 thorpej /* Send CHIP SELECT for one clock tick. */ 1149 1.88 msaitoh bus_space_write_4(st, sh, EPIC_EECTL, 1150 1.88 msaitoh EECTL_ENABLE | EECTL_EECS); 1151 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1152 1.1 thorpej 1153 1.1 thorpej /* Shift in the READ opcode. */ 1154 1.1 thorpej for (x = 3; x > 0; x--) { 1155 1.88 msaitoh reg = EECTL_ENABLE | EECTL_EECS; 1156 1.1 thorpej if (EPIC_EEPROM_OPC_READ & (1 << (x - 1))) 1157 1.1 thorpej reg |= EECTL_EEDI; 1158 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg); 1159 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1160 1.88 msaitoh bus_space_write_4(st, sh, EPIC_EECTL, reg |EECTL_EESK); 1161 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1162 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg); 1163 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1164 1.1 thorpej } 1165 1.1 thorpej 1166 1.1 thorpej /* Shift in address. */ 1167 1.1 thorpej for (x = 6; x > 0; x--) { 1168 1.88 msaitoh reg = EECTL_ENABLE | EECTL_EECS; 1169 1.1 thorpej if ((word + i) & (1 << (x - 1))) 1170 1.59 perry reg |= EECTL_EEDI; 1171 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg); 1172 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1173 1.88 msaitoh bus_space_write_4(st, sh, EPIC_EECTL, reg |EECTL_EESK); 1174 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1175 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg); 1176 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1177 1.1 thorpej } 1178 1.1 thorpej 1179 1.1 thorpej /* Shift out data. */ 1180 1.88 msaitoh reg = EECTL_ENABLE | EECTL_EECS; 1181 1.1 thorpej data[i] = 0; 1182 1.1 thorpej for (x = 16; x > 0; x--) { 1183 1.88 msaitoh bus_space_write_4(st, sh, EPIC_EECTL, reg |EECTL_EESK); 1184 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1185 1.1 thorpej if (bus_space_read_4(st, sh, EPIC_EECTL) & EECTL_EEDO) 1186 1.1 thorpej data[i] |= (1 << (x - 1)); 1187 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg); 1188 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1189 1.1 thorpej } 1190 1.1 thorpej 1191 1.1 thorpej /* Clear CHIP SELECT. */ 1192 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE); 1193 1.1 thorpej EEPROM_WAIT_READY(st, sh); 1194 1.1 thorpej } 1195 1.1 thorpej 1196 1.1 thorpej /* 1197 1.1 thorpej * Disable the EEPROM. 1198 1.1 thorpej */ 1199 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, 0); 1200 1.1 thorpej 1201 1.1 thorpej #undef EEPROM_WAIT_READY 1202 1.1 thorpej } 1203 1.1 thorpej 1204 1.1 thorpej /* 1205 1.1 thorpej * Add a receive buffer to the indicated descriptor. 1206 1.1 thorpej */ 1207 1.91 thorpej static int 1208 1.76 tsutsui epic_add_rxbuf(struct epic_softc *sc, int idx) 1209 1.1 thorpej { 1210 1.10 thorpej struct epic_descsoft *ds = EPIC_DSRX(sc, idx); 1211 1.10 thorpej struct mbuf *m; 1212 1.10 thorpej int error; 1213 1.1 thorpej 1214 1.10 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA); 1215 1.10 thorpej if (m == NULL) 1216 1.76 tsutsui return ENOBUFS; 1217 1.94 thorpej MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 1218 1.1 thorpej 1219 1.10 thorpej MCLGET(m, M_DONTWAIT); 1220 1.10 thorpej if ((m->m_flags & M_EXT) == 0) { 1221 1.10 thorpej m_freem(m); 1222 1.76 tsutsui return ENOBUFS; 1223 1.1 thorpej } 1224 1.1 thorpej 1225 1.10 thorpej if (ds->ds_mbuf != NULL) 1226 1.10 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1227 1.10 thorpej 1228 1.1 thorpej ds->ds_mbuf = m; 1229 1.1 thorpej 1230 1.10 thorpej error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap, 1231 1.47 thorpej m->m_ext.ext_buf, m->m_ext.ext_size, NULL, 1232 1.88 msaitoh BUS_DMA_READ | BUS_DMA_NOWAIT); 1233 1.10 thorpej if (error) { 1234 1.76 tsutsui printf("%s: can't load rx DMA map %d, error = %d\n", 1235 1.76 tsutsui device_xname(sc->sc_dev), idx, error); 1236 1.76 tsutsui panic("%s", __func__); /* XXX */ 1237 1.1 thorpej } 1238 1.1 thorpej 1239 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 1240 1.1 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1241 1.1 thorpej 1242 1.10 thorpej EPIC_INIT_RXDESC(sc, idx); 1243 1.1 thorpej 1244 1.76 tsutsui return 0; 1245 1.1 thorpej } 1246 1.1 thorpej 1247 1.1 thorpej /* 1248 1.1 thorpej * Set the EPIC multicast hash table. 1249 1.13 thorpej * 1250 1.13 thorpej * NOTE: We rely on a recently-updated mii_media_active here! 1251 1.1 thorpej */ 1252 1.91 thorpej static void 1253 1.76 tsutsui epic_set_mchash(struct epic_softc *sc) 1254 1.1 thorpej { 1255 1.1 thorpej struct ethercom *ec = &sc->sc_ethercom; 1256 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1257 1.1 thorpej struct ether_multi *enm; 1258 1.1 thorpej struct ether_multistep step; 1259 1.63 tsutsui uint32_t hash, mchash[4]; 1260 1.1 thorpej 1261 1.1 thorpej /* 1262 1.1 thorpej * Set up the multicast address filter by passing all multicast 1263 1.31 thorpej * addresses through a CRC generator, and then using the low-order 1264 1.1 thorpej * 6 bits as an index into the 64 bit multicast hash table (only 1265 1.1 thorpej * the lower 16 bits of each 32 bit multicast hash register are 1266 1.31 thorpej * valid). The high order bits select the register, while the 1267 1.1 thorpej * rest of the bits select the bit within the register. 1268 1.1 thorpej */ 1269 1.1 thorpej 1270 1.1 thorpej if (ifp->if_flags & IFF_PROMISC) 1271 1.1 thorpej goto allmulti; 1272 1.1 thorpej 1273 1.13 thorpej if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_10_T) { 1274 1.13 thorpej /* XXX hardware bug in 10Mbps mode. */ 1275 1.13 thorpej goto allmulti; 1276 1.13 thorpej } 1277 1.1 thorpej 1278 1.1 thorpej mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0; 1279 1.1 thorpej 1280 1.90 msaitoh ETHER_LOCK(ec); 1281 1.1 thorpej ETHER_FIRST_MULTI(step, ec, enm); 1282 1.1 thorpej while (enm != NULL) { 1283 1.46 thorpej if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 1284 1.1 thorpej /* 1285 1.1 thorpej * We must listen to a range of multicast addresses. 1286 1.1 thorpej * For now, just accept all multicasts, rather than 1287 1.1 thorpej * trying to set only those filter bits needed to match 1288 1.1 thorpej * the range. (At this time, the only use of address 1289 1.1 thorpej * ranges is for IP multicast routing, for which the 1290 1.1 thorpej * range is big enough to require all bits set.) 1291 1.1 thorpej */ 1292 1.90 msaitoh ETHER_UNLOCK(ec); 1293 1.1 thorpej goto allmulti; 1294 1.1 thorpej } 1295 1.1 thorpej 1296 1.37 thorpej hash = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); 1297 1.37 thorpej hash >>= 26; 1298 1.1 thorpej 1299 1.1 thorpej /* Set the corresponding bit in the hash table. */ 1300 1.31 thorpej mchash[hash >> 4] |= 1 << (hash & 0xf); 1301 1.1 thorpej 1302 1.1 thorpej ETHER_NEXT_MULTI(step, enm); 1303 1.1 thorpej } 1304 1.90 msaitoh ETHER_UNLOCK(ec); 1305 1.1 thorpej 1306 1.1 thorpej ifp->if_flags &= ~IFF_ALLMULTI; 1307 1.1 thorpej goto sethash; 1308 1.1 thorpej 1309 1.1 thorpej allmulti: 1310 1.1 thorpej ifp->if_flags |= IFF_ALLMULTI; 1311 1.1 thorpej mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0xffff; 1312 1.1 thorpej 1313 1.1 thorpej sethash: 1314 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC0, mchash[0]); 1315 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC1, mchash[1]); 1316 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC2, mchash[2]); 1317 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC3, mchash[3]); 1318 1.8 thorpej } 1319 1.8 thorpej 1320 1.8 thorpej /* 1321 1.8 thorpej * Wait for the MII to become ready. 1322 1.8 thorpej */ 1323 1.91 thorpej static int 1324 1.76 tsutsui epic_mii_wait(struct epic_softc *sc, uint32_t rw) 1325 1.8 thorpej { 1326 1.8 thorpej int i; 1327 1.8 thorpej 1328 1.8 thorpej for (i = 0; i < 50; i++) { 1329 1.8 thorpej if ((bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MMCTL) & rw) 1330 1.8 thorpej == 0) 1331 1.8 thorpej break; 1332 1.8 thorpej delay(2); 1333 1.8 thorpej } 1334 1.8 thorpej if (i == 50) { 1335 1.76 tsutsui printf("%s: MII timed out\n", device_xname(sc->sc_dev)); 1336 1.87 msaitoh return ETIMEDOUT; 1337 1.8 thorpej } 1338 1.8 thorpej 1339 1.76 tsutsui return 0; 1340 1.8 thorpej } 1341 1.8 thorpej 1342 1.8 thorpej /* 1343 1.8 thorpej * Read from the MII. 1344 1.8 thorpej */ 1345 1.91 thorpej static int 1346 1.87 msaitoh epic_mii_read(device_t self, int phy, int reg, uint16_t *val) 1347 1.8 thorpej { 1348 1.76 tsutsui struct epic_softc *sc = device_private(self); 1349 1.87 msaitoh int rv; 1350 1.8 thorpej 1351 1.87 msaitoh if ((rv = epic_mii_wait(sc, MMCTL_WRITE)) != 0) 1352 1.87 msaitoh return rv; 1353 1.8 thorpej 1354 1.8 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MMCTL, 1355 1.8 thorpej MMCTL_ARG(phy, reg, MMCTL_READ)); 1356 1.8 thorpej 1357 1.87 msaitoh if ((rv = epic_mii_wait(sc, MMCTL_READ)) != 0) 1358 1.87 msaitoh return rv; 1359 1.8 thorpej 1360 1.87 msaitoh *val = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MMDATA) 1361 1.87 msaitoh & MMDATA_MASK; 1362 1.87 msaitoh return 0; 1363 1.8 thorpej } 1364 1.8 thorpej 1365 1.8 thorpej /* 1366 1.8 thorpej * Write to the MII. 1367 1.8 thorpej */ 1368 1.91 thorpej static int 1369 1.87 msaitoh epic_mii_write(device_t self, int phy, int reg, uint16_t val) 1370 1.8 thorpej { 1371 1.76 tsutsui struct epic_softc *sc = device_private(self); 1372 1.87 msaitoh int rv; 1373 1.8 thorpej 1374 1.87 msaitoh if ((rv = epic_mii_wait(sc, MMCTL_WRITE)) != 0) 1375 1.87 msaitoh return rv; 1376 1.8 thorpej 1377 1.8 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MMDATA, val); 1378 1.8 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MMCTL, 1379 1.8 thorpej MMCTL_ARG(phy, reg, MMCTL_WRITE)); 1380 1.87 msaitoh 1381 1.87 msaitoh return 0; 1382 1.8 thorpej } 1383 1.8 thorpej 1384 1.8 thorpej /* 1385 1.8 thorpej * Callback from PHY when media changes. 1386 1.8 thorpej */ 1387 1.91 thorpej static void 1388 1.81 matt epic_statchg(struct ifnet *ifp) 1389 1.8 thorpej { 1390 1.81 matt struct epic_softc *sc = ifp->if_softc; 1391 1.63 tsutsui uint32_t txcon, miicfg; 1392 1.11 thorpej 1393 1.11 thorpej /* 1394 1.11 thorpej * Update loopback bits in TXCON to reflect duplex mode. 1395 1.11 thorpej */ 1396 1.11 thorpej txcon = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_TXCON); 1397 1.11 thorpej if (sc->sc_mii.mii_media_active & IFM_FDX) 1398 1.88 msaitoh txcon |= (TXCON_LOOPBACK_D1 | TXCON_LOOPBACK_D2); 1399 1.11 thorpej else 1400 1.88 msaitoh txcon &= ~(TXCON_LOOPBACK_D1 | TXCON_LOOPBACK_D2); 1401 1.11 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_TXCON, txcon); 1402 1.13 thorpej 1403 1.99 andvar /* On some cards we need manually set fullduplex led */ 1404 1.43 drochner if (sc->sc_hwflags & EPIC_DUPLEXLED_ON_694) { 1405 1.43 drochner miicfg = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG); 1406 1.59 perry if (IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) 1407 1.43 drochner miicfg |= MIICFG_ENABLE; 1408 1.43 drochner else 1409 1.43 drochner miicfg &= ~MIICFG_ENABLE; 1410 1.43 drochner bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG, miicfg); 1411 1.43 drochner } 1412 1.43 drochner 1413 1.13 thorpej /* 1414 1.13 thorpej * There is a multicast filter bug in 10Mbps mode. Kick the 1415 1.13 thorpej * multicast filter in case the speed changed. 1416 1.13 thorpej */ 1417 1.13 thorpej epic_set_mchash(sc); 1418 1.8 thorpej } 1419 1.8 thorpej 1420 1.8 thorpej /* 1421 1.8 thorpej * Callback from ifmedia to request new media setting. 1422 1.70 dyoung * 1423 1.70 dyoung * XXX Looks to me like some of this complexity should move into 1424 1.70 dyoung * XXX one or two custom PHY drivers. --dyoung 1425 1.8 thorpej */ 1426 1.91 thorpej static int 1427 1.76 tsutsui epic_mediachange(struct ifnet *ifp) 1428 1.8 thorpej { 1429 1.11 thorpej struct epic_softc *sc = ifp->if_softc; 1430 1.43 drochner struct mii_data *mii = &sc->sc_mii; 1431 1.43 drochner struct ifmedia *ifm = &mii->mii_media; 1432 1.43 drochner int media = ifm->ifm_cur->ifm_media; 1433 1.63 tsutsui uint32_t miicfg; 1434 1.43 drochner struct mii_softc *miisc; 1435 1.87 msaitoh int rc; 1436 1.87 msaitoh uint16_t cfg; 1437 1.43 drochner 1438 1.70 dyoung if ((ifp->if_flags & IFF_UP) == 0) 1439 1.76 tsutsui return 0; 1440 1.43 drochner 1441 1.43 drochner if (IFM_INST(media) != sc->sc_serinst) { 1442 1.43 drochner /* If we're not selecting serial interface, select MII mode */ 1443 1.43 drochner #ifdef EPICMEDIADEBUG 1444 1.43 drochner printf("%s: parallel mode\n", ifp->if_xname); 1445 1.59 perry #endif 1446 1.43 drochner miicfg = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG); 1447 1.43 drochner miicfg &= ~MIICFG_SERMODEENA; 1448 1.43 drochner bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG, miicfg); 1449 1.43 drochner } 1450 1.43 drochner 1451 1.71 dyoung if ((rc = mii_mediachg(mii)) == ENXIO) 1452 1.71 dyoung rc = 0; 1453 1.43 drochner 1454 1.43 drochner if (IFM_INST(media) == sc->sc_serinst) { 1455 1.43 drochner /* select serial interface */ 1456 1.43 drochner #ifdef EPICMEDIADEBUG 1457 1.43 drochner printf("%s: serial mode\n", ifp->if_xname); 1458 1.43 drochner #endif 1459 1.43 drochner miicfg = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG); 1460 1.43 drochner miicfg |= (MIICFG_SERMODEENA | MIICFG_ENABLE); 1461 1.43 drochner bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MIICFG, miicfg); 1462 1.43 drochner 1463 1.43 drochner /* There is no driver to fill this */ 1464 1.43 drochner mii->mii_media_active = media; 1465 1.43 drochner mii->mii_media_status = 0; 1466 1.43 drochner 1467 1.81 matt epic_statchg(mii->mii_ifp); 1468 1.76 tsutsui return 0; 1469 1.43 drochner } 1470 1.43 drochner 1471 1.43 drochner /* Lookup selected PHY */ 1472 1.69 dyoung LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 1473 1.43 drochner if (IFM_INST(media) == miisc->mii_inst) 1474 1.43 drochner break; 1475 1.43 drochner } 1476 1.43 drochner if (!miisc) { 1477 1.76 tsutsui printf("%s: can't happen\n", __func__); /* ??? panic */ 1478 1.76 tsutsui return 0; 1479 1.43 drochner } 1480 1.43 drochner #ifdef EPICMEDIADEBUG 1481 1.43 drochner printf("%s: using phy %s\n", ifp->if_xname, 1482 1.75 xtraeme device_xname(miisc->mii_dev)); 1483 1.43 drochner #endif 1484 1.43 drochner 1485 1.43 drochner if (miisc->mii_flags & MIIF_HAVEFIBER) { 1486 1.43 drochner /* XXX XXX assume it's a Level1 - should check */ 1487 1.43 drochner 1488 1.54 wiz /* We have to powerup fiber transceivers */ 1489 1.87 msaitoh PHY_READ(miisc, MII_LXTPHY_CONFIG, &cfg); 1490 1.43 drochner if (IFM_SUBTYPE(media) == IFM_100_FX) { 1491 1.43 drochner #ifdef EPICMEDIADEBUG 1492 1.43 drochner printf("%s: power up fiber\n", ifp->if_xname); 1493 1.43 drochner #endif 1494 1.43 drochner cfg |= (CONFIG_LEDC1 | CONFIG_LEDC0); 1495 1.43 drochner } else { 1496 1.43 drochner #ifdef EPICMEDIADEBUG 1497 1.43 drochner printf("%s: power down fiber\n", ifp->if_xname); 1498 1.43 drochner #endif 1499 1.43 drochner cfg &= ~(CONFIG_LEDC1 | CONFIG_LEDC0); 1500 1.43 drochner } 1501 1.43 drochner PHY_WRITE(miisc, MII_LXTPHY_CONFIG, cfg); 1502 1.43 drochner } 1503 1.8 thorpej 1504 1.71 dyoung return rc; 1505 1.1 thorpej } 1506