1 1.45 rin /* $NetBSD: if_ae.c,v 1.45 2024/07/05 04:31:49 rin Exp $ */ 2 1.1 gdamore /*- 3 1.1 gdamore * Copyright (c) 2006 Urbana-Champaign Independent Media Center. 4 1.1 gdamore * Copyright (c) 2006 Garrett D'Amore. 5 1.1 gdamore * All rights reserved. 6 1.1 gdamore * 7 1.1 gdamore * This code was written by Garrett D'Amore for the Champaign-Urbana 8 1.1 gdamore * Community Wireless Network Project. 9 1.1 gdamore * 10 1.1 gdamore * Redistribution and use in source and binary forms, with or 11 1.1 gdamore * without modification, are permitted provided that the following 12 1.1 gdamore * conditions are met: 13 1.1 gdamore * 1. Redistributions of source code must retain the above copyright 14 1.1 gdamore * notice, this list of conditions and the following disclaimer. 15 1.1 gdamore * 2. Redistributions in binary form must reproduce the above 16 1.1 gdamore * copyright notice, this list of conditions and the following 17 1.1 gdamore * disclaimer in the documentation and/or other materials provided 18 1.1 gdamore * with the distribution. 19 1.1 gdamore * 3. All advertising materials mentioning features or use of this 20 1.1 gdamore * software must display the following acknowledgements: 21 1.1 gdamore * This product includes software developed by the Urbana-Champaign 22 1.1 gdamore * Independent Media Center. 23 1.1 gdamore * This product includes software developed by Garrett D'Amore. 24 1.1 gdamore * 4. Urbana-Champaign Independent Media Center's name and Garrett 25 1.1 gdamore * D'Amore's name may not be used to endorse or promote products 26 1.1 gdamore * derived from this software without specific prior written permission. 27 1.1 gdamore * 28 1.1 gdamore * THIS SOFTWARE IS PROVIDED BY THE URBANA-CHAMPAIGN INDEPENDENT 29 1.1 gdamore * MEDIA CENTER AND GARRETT D'AMORE ``AS IS'' AND ANY EXPRESS OR 30 1.1 gdamore * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 1.1 gdamore * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 1.1 gdamore * ARE DISCLAIMED. IN NO EVENT SHALL THE URBANA-CHAMPAIGN INDEPENDENT 33 1.1 gdamore * MEDIA CENTER OR GARRETT D'AMORE BE LIABLE FOR ANY DIRECT, INDIRECT, 34 1.1 gdamore * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 1.1 gdamore * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 36 1.1 gdamore * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 37 1.1 gdamore * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 38 1.1 gdamore * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 1.1 gdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 40 1.1 gdamore * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 1.1 gdamore */ 42 1.1 gdamore /*- 43 1.1 gdamore * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc. 44 1.1 gdamore * All rights reserved. 45 1.1 gdamore * 46 1.1 gdamore * This code is derived from software contributed to The NetBSD Foundation 47 1.1 gdamore * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 48 1.1 gdamore * NASA Ames Research Center; and by Charles M. Hannum. 49 1.1 gdamore * 50 1.1 gdamore * Redistribution and use in source and binary forms, with or without 51 1.1 gdamore * modification, are permitted provided that the following conditions 52 1.1 gdamore * are met: 53 1.1 gdamore * 1. Redistributions of source code must retain the above copyright 54 1.1 gdamore * notice, this list of conditions and the following disclaimer. 55 1.1 gdamore * 2. Redistributions in binary form must reproduce the above copyright 56 1.1 gdamore * notice, this list of conditions and the following disclaimer in the 57 1.1 gdamore * documentation and/or other materials provided with the distribution. 58 1.1 gdamore * 59 1.1 gdamore * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 60 1.1 gdamore * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 61 1.1 gdamore * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 62 1.1 gdamore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 63 1.1 gdamore * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 64 1.1 gdamore * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 65 1.1 gdamore * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 66 1.1 gdamore * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 67 1.1 gdamore * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 68 1.1 gdamore * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 69 1.1 gdamore * POSSIBILITY OF SUCH DAMAGE. 70 1.1 gdamore */ 71 1.1 gdamore 72 1.1 gdamore /* 73 1.1 gdamore * Device driver for the onboard ethernet MAC found on the AR5312 74 1.1 gdamore * chip's AHB bus. 75 1.1 gdamore * 76 1.1 gdamore * This device is very simliar to the tulip in most regards, and 77 1.1 gdamore * the code is directly derived from NetBSD's tulip.c. However, it 78 1.1 gdamore * is different enough that it did not seem to be a good idea to 79 1.1 gdamore * add further complexity to the tulip driver, so we have our own. 80 1.1 gdamore * 81 1.1 gdamore * Also tulip has a lot of complexity in it for various parts/options 82 1.1 gdamore * that we don't need, and on these little boxes with only ~8MB RAM, we 83 1.1 gdamore * don't want any extra bloat. 84 1.1 gdamore */ 85 1.1 gdamore 86 1.1 gdamore /* 87 1.1 gdamore * TODO: 88 1.1 gdamore * 89 1.1 gdamore * 1) Find out about BUS_MODE_ALIGN16B. This chip can apparently align 90 1.1 gdamore * inbound packets on a half-word boundary, which would make life easier 91 1.1 gdamore * for TCP/IP. (Aligning IP headers on a word.) 92 1.1 gdamore * 93 1.1 gdamore * 2) There is stuff in original tulip to shut down the device when reacting 94 1.33 msaitoh * to a change in link status. Is that needed. 95 1.1 gdamore * 96 1.1 gdamore * 3) Test with variety of 10/100 HDX/FDX scenarios. 97 1.1 gdamore * 98 1.1 gdamore */ 99 1.1 gdamore 100 1.1 gdamore #include <sys/cdefs.h> 101 1.45 rin __KERNEL_RCSID(0, "$NetBSD: if_ae.c,v 1.45 2024/07/05 04:31:49 rin Exp $"); 102 1.1 gdamore 103 1.1 gdamore 104 1.1 gdamore #include <sys/param.h> 105 1.21 matt #include <sys/bus.h> 106 1.1 gdamore #include <sys/callout.h> 107 1.21 matt #include <sys/device.h> 108 1.21 matt #include <sys/endian.h> 109 1.21 matt #include <sys/errno.h> 110 1.21 matt #include <sys/intr.h> 111 1.21 matt #include <sys/ioctl.h> 112 1.21 matt #include <sys/kernel.h> 113 1.1 gdamore #include <sys/mbuf.h> 114 1.1 gdamore #include <sys/socket.h> 115 1.1 gdamore 116 1.1 gdamore #include <uvm/uvm_extern.h> 117 1.1 gdamore 118 1.1 gdamore #include <net/if.h> 119 1.1 gdamore #include <net/if_dl.h> 120 1.1 gdamore #include <net/if_media.h> 121 1.1 gdamore #include <net/if_ether.h> 122 1.1 gdamore 123 1.1 gdamore #include <net/bpf.h> 124 1.1 gdamore 125 1.1 gdamore #include <dev/mii/mii.h> 126 1.1 gdamore #include <dev/mii/miivar.h> 127 1.1 gdamore #include <dev/mii/mii_bitbang.h> 128 1.1 gdamore 129 1.1 gdamore #include <mips/atheros/include/arbusvar.h> 130 1.1 gdamore #include <mips/atheros/dev/aereg.h> 131 1.1 gdamore #include <mips/atheros/dev/aevar.h> 132 1.1 gdamore 133 1.1 gdamore static const struct { 134 1.34 msaitoh uint32_t txth_opmode; /* OPMODE bits */ 135 1.1 gdamore const char *txth_name; /* name of mode */ 136 1.1 gdamore } ae_txthresh[] = { 137 1.1 gdamore { OPMODE_TR_32, "32 words" }, 138 1.1 gdamore { OPMODE_TR_64, "64 words" }, 139 1.1 gdamore { OPMODE_TR_128, "128 words" }, 140 1.1 gdamore { OPMODE_TR_256, "256 words" }, 141 1.1 gdamore { OPMODE_SF, "store and forward mode" }, 142 1.1 gdamore { 0, NULL }, 143 1.1 gdamore }; 144 1.1 gdamore 145 1.35 msaitoh static int ae_match(device_t, struct cfdata *, void *); 146 1.12 dyoung static void ae_attach(device_t, device_t, void *); 147 1.12 dyoung static int ae_detach(device_t, int); 148 1.12 dyoung static int ae_activate(device_t, enum devact); 149 1.1 gdamore 150 1.15 dyoung static int ae_ifflags_cb(struct ethercom *); 151 1.1 gdamore static void ae_reset(struct ae_softc *); 152 1.34 msaitoh static void ae_idle(struct ae_softc *, uint32_t); 153 1.1 gdamore 154 1.1 gdamore static void ae_start(struct ifnet *); 155 1.1 gdamore static void ae_watchdog(struct ifnet *); 156 1.5 christos static int ae_ioctl(struct ifnet *, u_long, void *); 157 1.1 gdamore static int ae_init(struct ifnet *); 158 1.1 gdamore static void ae_stop(struct ifnet *, int); 159 1.1 gdamore 160 1.1 gdamore static void ae_shutdown(void *); 161 1.1 gdamore 162 1.1 gdamore static void ae_rxdrain(struct ae_softc *); 163 1.1 gdamore static int ae_add_rxbuf(struct ae_softc *, int); 164 1.1 gdamore 165 1.1 gdamore static int ae_enable(struct ae_softc *); 166 1.1 gdamore static void ae_disable(struct ae_softc *); 167 1.1 gdamore static void ae_power(int, void *); 168 1.1 gdamore 169 1.1 gdamore static void ae_filter_setup(struct ae_softc *); 170 1.1 gdamore 171 1.1 gdamore static int ae_intr(void *); 172 1.1 gdamore static void ae_rxintr(struct ae_softc *); 173 1.1 gdamore static void ae_txintr(struct ae_softc *); 174 1.1 gdamore 175 1.1 gdamore static void ae_mii_tick(void *); 176 1.23 matt static void ae_mii_statchg(struct ifnet *); 177 1.1 gdamore 178 1.32 msaitoh static int ae_mii_readreg(device_t, int, int, uint16_t *); 179 1.32 msaitoh static int ae_mii_writereg(device_t, int, int, uint16_t); 180 1.1 gdamore 181 1.1 gdamore #ifdef AE_DEBUG 182 1.1 gdamore #define DPRINTF(sc, x) if ((sc)->sc_ethercom.ec_if.if_flags & IFF_DEBUG) \ 183 1.1 gdamore printf x 184 1.1 gdamore #else 185 1.1 gdamore #define DPRINTF(sc, x) /* nothing */ 186 1.1 gdamore #endif 187 1.1 gdamore 188 1.1 gdamore #ifdef AE_STATS 189 1.1 gdamore static void ae_print_stats(struct ae_softc *); 190 1.1 gdamore #endif 191 1.1 gdamore 192 1.24 chs CFATTACH_DECL_NEW(ae, sizeof(struct ae_softc), 193 1.1 gdamore ae_match, ae_attach, ae_detach, ae_activate); 194 1.1 gdamore 195 1.1 gdamore /* 196 1.1 gdamore * ae_match: 197 1.1 gdamore * 198 1.1 gdamore * Check for a device match. 199 1.1 gdamore */ 200 1.1 gdamore int 201 1.12 dyoung ae_match(device_t parent, struct cfdata *cf, void *aux) 202 1.1 gdamore { 203 1.1 gdamore struct arbus_attach_args *aa = aux; 204 1.1 gdamore 205 1.1 gdamore if (strcmp(aa->aa_name, cf->cf_name) == 0) 206 1.1 gdamore return 1; 207 1.1 gdamore 208 1.1 gdamore return 0; 209 1.1 gdamore 210 1.1 gdamore } 211 1.1 gdamore 212 1.1 gdamore /* 213 1.1 gdamore * ae_attach: 214 1.1 gdamore * 215 1.1 gdamore * Attach an ae interface to the system. 216 1.1 gdamore */ 217 1.1 gdamore void 218 1.12 dyoung ae_attach(device_t parent, device_t self, void *aux) 219 1.1 gdamore { 220 1.2 thorpej const uint8_t *enaddr; 221 1.2 thorpej prop_data_t ea; 222 1.12 dyoung struct ae_softc *sc = device_private(self); 223 1.1 gdamore struct arbus_attach_args *aa = aux; 224 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 225 1.34 msaitoh struct mii_data * const mii = &sc->sc_mii; 226 1.1 gdamore int i, error; 227 1.1 gdamore 228 1.24 chs sc->sc_dev = self; 229 1.24 chs 230 1.6 ad callout_init(&sc->sc_tick_callout, 0); 231 1.1 gdamore 232 1.1 gdamore printf(": Atheros AR531X 10/100 Ethernet\n"); 233 1.1 gdamore 234 1.1 gdamore /* 235 1.2 thorpej * Try to get MAC address. 236 1.1 gdamore */ 237 1.24 chs ea = prop_dictionary_get(device_properties(sc->sc_dev), "mac-address"); 238 1.2 thorpej if (ea == NULL) { 239 1.1 gdamore printf("%s: unable to get mac-addr property\n", 240 1.24 chs device_xname(sc->sc_dev)); 241 1.1 gdamore return; 242 1.1 gdamore } 243 1.2 thorpej KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); 244 1.2 thorpej KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); 245 1.2 thorpej enaddr = prop_data_data_nocopy(ea); 246 1.1 gdamore 247 1.1 gdamore /* Announce ourselves. */ 248 1.24 chs printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev), 249 1.1 gdamore ether_sprintf(enaddr)); 250 1.1 gdamore 251 1.3 gdamore sc->sc_cirq = aa->aa_cirq; 252 1.3 gdamore sc->sc_mirq = aa->aa_mirq; 253 1.1 gdamore sc->sc_st = aa->aa_bst; 254 1.1 gdamore sc->sc_dmat = aa->aa_dmat; 255 1.1 gdamore 256 1.1 gdamore SIMPLEQ_INIT(&sc->sc_txfreeq); 257 1.1 gdamore SIMPLEQ_INIT(&sc->sc_txdirtyq); 258 1.1 gdamore 259 1.1 gdamore /* 260 1.1 gdamore * Map registers. 261 1.1 gdamore */ 262 1.1 gdamore sc->sc_size = aa->aa_size; 263 1.1 gdamore if ((error = bus_space_map(sc->sc_st, aa->aa_addr, sc->sc_size, 0, 264 1.1 gdamore &sc->sc_sh)) != 0) { 265 1.1 gdamore printf("%s: unable to map registers, error = %d\n", 266 1.24 chs device_xname(sc->sc_dev), error); 267 1.1 gdamore goto fail_0; 268 1.1 gdamore } 269 1.1 gdamore 270 1.1 gdamore /* 271 1.1 gdamore * Allocate the control data structures, and create and load the 272 1.1 gdamore * DMA map for it. 273 1.1 gdamore */ 274 1.1 gdamore if ((error = bus_dmamem_alloc(sc->sc_dmat, 275 1.1 gdamore sizeof(struct ae_control_data), PAGE_SIZE, 0, &sc->sc_cdseg, 276 1.1 gdamore 1, &sc->sc_cdnseg, 0)) != 0) { 277 1.1 gdamore printf("%s: unable to allocate control data, error = %d\n", 278 1.24 chs device_xname(sc->sc_dev), error); 279 1.1 gdamore goto fail_1; 280 1.1 gdamore } 281 1.1 gdamore 282 1.1 gdamore if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg, 283 1.5 christos sizeof(struct ae_control_data), (void **)&sc->sc_control_data, 284 1.1 gdamore BUS_DMA_COHERENT)) != 0) { 285 1.1 gdamore printf("%s: unable to map control data, error = %d\n", 286 1.24 chs device_xname(sc->sc_dev), error); 287 1.1 gdamore goto fail_2; 288 1.1 gdamore } 289 1.1 gdamore 290 1.1 gdamore if ((error = bus_dmamap_create(sc->sc_dmat, 291 1.1 gdamore sizeof(struct ae_control_data), 1, 292 1.1 gdamore sizeof(struct ae_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { 293 1.1 gdamore printf("%s: unable to create control data DMA map, " 294 1.24 chs "error = %d\n", device_xname(sc->sc_dev), error); 295 1.1 gdamore goto fail_3; 296 1.1 gdamore } 297 1.1 gdamore 298 1.1 gdamore if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, 299 1.1 gdamore sc->sc_control_data, sizeof(struct ae_control_data), NULL, 300 1.1 gdamore 0)) != 0) { 301 1.1 gdamore printf("%s: unable to load control data DMA map, error = %d\n", 302 1.24 chs device_xname(sc->sc_dev), error); 303 1.1 gdamore goto fail_4; 304 1.1 gdamore } 305 1.1 gdamore 306 1.1 gdamore /* 307 1.1 gdamore * Create the transmit buffer DMA maps. 308 1.1 gdamore */ 309 1.1 gdamore for (i = 0; i < AE_TXQUEUELEN; i++) { 310 1.1 gdamore if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 311 1.1 gdamore AE_NTXSEGS, MCLBYTES, 0, 0, 312 1.1 gdamore &sc->sc_txsoft[i].txs_dmamap)) != 0) { 313 1.1 gdamore printf("%s: unable to create tx DMA map %d, " 314 1.24 chs "error = %d\n", device_xname(sc->sc_dev), i, error); 315 1.1 gdamore goto fail_5; 316 1.1 gdamore } 317 1.1 gdamore } 318 1.1 gdamore 319 1.1 gdamore /* 320 1.1 gdamore * Create the receive buffer DMA maps. 321 1.1 gdamore */ 322 1.1 gdamore for (i = 0; i < AE_NRXDESC; i++) { 323 1.1 gdamore if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 324 1.1 gdamore MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 325 1.1 gdamore printf("%s: unable to create rx DMA map %d, " 326 1.24 chs "error = %d\n", device_xname(sc->sc_dev), i, error); 327 1.1 gdamore goto fail_6; 328 1.1 gdamore } 329 1.1 gdamore sc->sc_rxsoft[i].rxs_mbuf = NULL; 330 1.1 gdamore } 331 1.1 gdamore 332 1.1 gdamore /* 333 1.1 gdamore * Reset the chip to a known state. 334 1.1 gdamore */ 335 1.1 gdamore ae_reset(sc); 336 1.1 gdamore 337 1.1 gdamore /* 338 1.1 gdamore * From this point forward, the attachment cannot fail. A failure 339 1.1 gdamore * before this point releases all resources that may have been 340 1.1 gdamore * allocated. 341 1.1 gdamore */ 342 1.1 gdamore sc->sc_flags |= AE_ATTACHED; 343 1.1 gdamore 344 1.1 gdamore /* 345 1.1 gdamore * Initialize our media structures. This may probe the MII, if 346 1.1 gdamore * present. 347 1.1 gdamore */ 348 1.34 msaitoh mii->mii_ifp = ifp; 349 1.34 msaitoh mii->mii_readreg = ae_mii_readreg; 350 1.34 msaitoh mii->mii_writereg = ae_mii_writereg; 351 1.34 msaitoh mii->mii_statchg = ae_mii_statchg; 352 1.34 msaitoh sc->sc_ethercom.ec_mii = mii; 353 1.34 msaitoh ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); 354 1.34 msaitoh mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, 355 1.1 gdamore MII_OFFSET_ANY, 0); 356 1.1 gdamore 357 1.34 msaitoh if (LIST_FIRST(&mii->mii_phys) == NULL) { 358 1.34 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 359 1.34 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 360 1.1 gdamore } else 361 1.34 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 362 1.1 gdamore 363 1.1 gdamore sc->sc_tick = ae_mii_tick; 364 1.1 gdamore 365 1.24 chs strcpy(ifp->if_xname, device_xname(sc->sc_dev)); 366 1.1 gdamore ifp->if_softc = sc; 367 1.1 gdamore ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 368 1.1 gdamore sc->sc_if_flags = ifp->if_flags; 369 1.1 gdamore ifp->if_ioctl = ae_ioctl; 370 1.1 gdamore ifp->if_start = ae_start; 371 1.1 gdamore ifp->if_watchdog = ae_watchdog; 372 1.1 gdamore ifp->if_init = ae_init; 373 1.1 gdamore ifp->if_stop = ae_stop; 374 1.1 gdamore IFQ_SET_READY(&ifp->if_snd); 375 1.1 gdamore 376 1.1 gdamore /* 377 1.1 gdamore * We can support 802.1Q VLAN-sized frames. 378 1.1 gdamore */ 379 1.1 gdamore sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; 380 1.1 gdamore 381 1.1 gdamore /* 382 1.1 gdamore * Attach the interface. 383 1.1 gdamore */ 384 1.1 gdamore if_attach(ifp); 385 1.29 ozaki if_deferred_start_init(ifp, NULL); 386 1.1 gdamore ether_ifattach(ifp, enaddr); 387 1.15 dyoung ether_set_ifflags_cb(&sc->sc_ethercom, ae_ifflags_cb); 388 1.1 gdamore 389 1.24 chs rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), 390 1.25 tls RND_TYPE_NET, RND_FLAG_DEFAULT); 391 1.1 gdamore 392 1.1 gdamore /* 393 1.1 gdamore * Make sure the interface is shutdown during reboot. 394 1.1 gdamore */ 395 1.1 gdamore sc->sc_sdhook = shutdownhook_establish(ae_shutdown, sc); 396 1.1 gdamore if (sc->sc_sdhook == NULL) 397 1.1 gdamore printf("%s: WARNING: unable to establish shutdown hook\n", 398 1.24 chs device_xname(sc->sc_dev)); 399 1.1 gdamore 400 1.1 gdamore /* 401 1.1 gdamore * Add a suspend hook to make sure we come back up after a 402 1.1 gdamore * resume. 403 1.1 gdamore */ 404 1.24 chs sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev), 405 1.4 jmcneill ae_power, sc); 406 1.1 gdamore if (sc->sc_powerhook == NULL) 407 1.1 gdamore printf("%s: WARNING: unable to establish power hook\n", 408 1.24 chs device_xname(sc->sc_dev)); 409 1.1 gdamore return; 410 1.1 gdamore 411 1.1 gdamore /* 412 1.1 gdamore * Free any resources we've allocated during the failed attach 413 1.1 gdamore * attempt. Do this in reverse order and fall through. 414 1.1 gdamore */ 415 1.1 gdamore fail_6: 416 1.1 gdamore for (i = 0; i < AE_NRXDESC; i++) { 417 1.1 gdamore if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 418 1.1 gdamore bus_dmamap_destroy(sc->sc_dmat, 419 1.1 gdamore sc->sc_rxsoft[i].rxs_dmamap); 420 1.1 gdamore } 421 1.1 gdamore fail_5: 422 1.1 gdamore for (i = 0; i < AE_TXQUEUELEN; i++) { 423 1.1 gdamore if (sc->sc_txsoft[i].txs_dmamap != NULL) 424 1.1 gdamore bus_dmamap_destroy(sc->sc_dmat, 425 1.1 gdamore sc->sc_txsoft[i].txs_dmamap); 426 1.1 gdamore } 427 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); 428 1.1 gdamore fail_4: 429 1.1 gdamore bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); 430 1.1 gdamore fail_3: 431 1.5 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, 432 1.1 gdamore sizeof(struct ae_control_data)); 433 1.1 gdamore fail_2: 434 1.1 gdamore bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); 435 1.1 gdamore fail_1: 436 1.1 gdamore bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_size); 437 1.1 gdamore fail_0: 438 1.1 gdamore return; 439 1.1 gdamore } 440 1.1 gdamore 441 1.1 gdamore /* 442 1.1 gdamore * ae_activate: 443 1.1 gdamore * 444 1.1 gdamore * Handle device activation/deactivation requests. 445 1.1 gdamore */ 446 1.1 gdamore int 447 1.12 dyoung ae_activate(device_t self, enum devact act) 448 1.1 gdamore { 449 1.12 dyoung struct ae_softc *sc = device_private(self); 450 1.1 gdamore 451 1.1 gdamore switch (act) { 452 1.1 gdamore case DVACT_DEACTIVATE: 453 1.1 gdamore if_deactivate(&sc->sc_ethercom.ec_if); 454 1.16 dyoung return 0; 455 1.16 dyoung default: 456 1.16 dyoung return EOPNOTSUPP; 457 1.1 gdamore } 458 1.1 gdamore } 459 1.1 gdamore 460 1.1 gdamore /* 461 1.1 gdamore * ae_detach: 462 1.1 gdamore * 463 1.1 gdamore * Detach a device interface. 464 1.1 gdamore */ 465 1.1 gdamore int 466 1.12 dyoung ae_detach(device_t self, int flags) 467 1.1 gdamore { 468 1.12 dyoung struct ae_softc *sc = device_private(self); 469 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 470 1.1 gdamore struct ae_rxsoft *rxs; 471 1.1 gdamore struct ae_txsoft *txs; 472 1.1 gdamore int i; 473 1.1 gdamore 474 1.1 gdamore /* 475 1.1 gdamore * Succeed now if there isn't any work to do. 476 1.1 gdamore */ 477 1.1 gdamore if ((sc->sc_flags & AE_ATTACHED) == 0) 478 1.1 gdamore return (0); 479 1.1 gdamore 480 1.1 gdamore /* Unhook our tick handler. */ 481 1.1 gdamore if (sc->sc_tick) 482 1.1 gdamore callout_stop(&sc->sc_tick_callout); 483 1.1 gdamore 484 1.1 gdamore /* Detach all PHYs */ 485 1.1 gdamore mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); 486 1.1 gdamore 487 1.1 gdamore rnd_detach_source(&sc->sc_rnd_source); 488 1.1 gdamore ether_ifdetach(ifp); 489 1.1 gdamore if_detach(ifp); 490 1.1 gdamore 491 1.39 thorpej /* Delete all remaining media. */ 492 1.39 thorpej ifmedia_fini(&sc->sc_mii.mii_media); 493 1.39 thorpej 494 1.1 gdamore for (i = 0; i < AE_NRXDESC; i++) { 495 1.1 gdamore rxs = &sc->sc_rxsoft[i]; 496 1.1 gdamore if (rxs->rxs_mbuf != NULL) { 497 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); 498 1.1 gdamore m_freem(rxs->rxs_mbuf); 499 1.1 gdamore rxs->rxs_mbuf = NULL; 500 1.1 gdamore } 501 1.1 gdamore bus_dmamap_destroy(sc->sc_dmat, rxs->rxs_dmamap); 502 1.1 gdamore } 503 1.1 gdamore for (i = 0; i < AE_TXQUEUELEN; i++) { 504 1.1 gdamore txs = &sc->sc_txsoft[i]; 505 1.1 gdamore if (txs->txs_mbuf != NULL) { 506 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); 507 1.1 gdamore m_freem(txs->txs_mbuf); 508 1.1 gdamore txs->txs_mbuf = NULL; 509 1.1 gdamore } 510 1.1 gdamore bus_dmamap_destroy(sc->sc_dmat, txs->txs_dmamap); 511 1.1 gdamore } 512 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); 513 1.1 gdamore bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); 514 1.5 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, 515 1.1 gdamore sizeof(struct ae_control_data)); 516 1.1 gdamore bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); 517 1.1 gdamore 518 1.1 gdamore shutdownhook_disestablish(sc->sc_sdhook); 519 1.1 gdamore powerhook_disestablish(sc->sc_powerhook); 520 1.1 gdamore 521 1.1 gdamore bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_size); 522 1.1 gdamore 523 1.1 gdamore 524 1.1 gdamore return (0); 525 1.1 gdamore } 526 1.1 gdamore 527 1.1 gdamore /* 528 1.1 gdamore * ae_shutdown: 529 1.1 gdamore * 530 1.1 gdamore * Make sure the interface is stopped at reboot time. 531 1.1 gdamore */ 532 1.1 gdamore static void 533 1.1 gdamore ae_shutdown(void *arg) 534 1.1 gdamore { 535 1.1 gdamore struct ae_softc *sc = arg; 536 1.1 gdamore 537 1.1 gdamore ae_stop(&sc->sc_ethercom.ec_if, 1); 538 1.1 gdamore } 539 1.1 gdamore 540 1.1 gdamore /* 541 1.1 gdamore * ae_start: [ifnet interface function] 542 1.1 gdamore * 543 1.1 gdamore * Start packet transmission on the interface. 544 1.1 gdamore */ 545 1.1 gdamore static void 546 1.1 gdamore ae_start(struct ifnet *ifp) 547 1.1 gdamore { 548 1.1 gdamore struct ae_softc *sc = ifp->if_softc; 549 1.1 gdamore struct mbuf *m0, *m; 550 1.26 matt struct ae_txsoft *txs; 551 1.1 gdamore bus_dmamap_t dmamap; 552 1.1 gdamore int error, firsttx, nexttx, lasttx = 1, ofree, seg; 553 1.1 gdamore 554 1.1 gdamore DPRINTF(sc, ("%s: ae_start: sc_flags 0x%08x, if_flags 0x%08x\n", 555 1.24 chs device_xname(sc->sc_dev), sc->sc_flags, ifp->if_flags)); 556 1.1 gdamore 557 1.1 gdamore 558 1.41 thorpej if ((ifp->if_flags & IFF_RUNNING) == 0) 559 1.1 gdamore return; 560 1.1 gdamore 561 1.1 gdamore /* 562 1.1 gdamore * Remember the previous number of free descriptors and 563 1.1 gdamore * the first descriptor we'll use. 564 1.1 gdamore */ 565 1.1 gdamore ofree = sc->sc_txfree; 566 1.1 gdamore firsttx = sc->sc_txnext; 567 1.1 gdamore 568 1.1 gdamore DPRINTF(sc, ("%s: ae_start: txfree %d, txnext %d\n", 569 1.24 chs device_xname(sc->sc_dev), ofree, firsttx)); 570 1.1 gdamore 571 1.1 gdamore /* 572 1.1 gdamore * Loop through the send queue, setting up transmit descriptors 573 1.1 gdamore * until we drain the queue, or use up all available transmit 574 1.1 gdamore * descriptors. 575 1.1 gdamore */ 576 1.1 gdamore while ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) != NULL && 577 1.1 gdamore sc->sc_txfree != 0) { 578 1.1 gdamore /* 579 1.1 gdamore * Grab a packet off the queue. 580 1.1 gdamore */ 581 1.1 gdamore IFQ_POLL(&ifp->if_snd, m0); 582 1.1 gdamore if (m0 == NULL) 583 1.1 gdamore break; 584 1.1 gdamore m = NULL; 585 1.1 gdamore 586 1.1 gdamore dmamap = txs->txs_dmamap; 587 1.1 gdamore 588 1.1 gdamore /* 589 1.1 gdamore * Load the DMA map. If this fails, the packet either 590 1.43 andvar * didn't fit in the allotted number of segments, or we were 591 1.1 gdamore * short on resources. In this case, we'll copy and try 592 1.1 gdamore * again. 593 1.1 gdamore */ 594 1.1 gdamore if (((mtod(m0, uintptr_t) & 3) != 0) || 595 1.1 gdamore bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, 596 1.34 msaitoh BUS_DMA_WRITE | BUS_DMA_NOWAIT) != 0) { 597 1.1 gdamore MGETHDR(m, M_DONTWAIT, MT_DATA); 598 1.1 gdamore if (m == NULL) { 599 1.1 gdamore printf("%s: unable to allocate Tx mbuf\n", 600 1.24 chs device_xname(sc->sc_dev)); 601 1.1 gdamore break; 602 1.1 gdamore } 603 1.1 gdamore MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); 604 1.1 gdamore if (m0->m_pkthdr.len > MHLEN) { 605 1.1 gdamore MCLGET(m, M_DONTWAIT); 606 1.1 gdamore if ((m->m_flags & M_EXT) == 0) { 607 1.1 gdamore printf("%s: unable to allocate Tx " 608 1.24 chs "cluster\n", device_xname(sc->sc_dev)); 609 1.1 gdamore m_freem(m); 610 1.1 gdamore break; 611 1.1 gdamore } 612 1.1 gdamore } 613 1.5 christos m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); 614 1.1 gdamore m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; 615 1.1 gdamore error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, 616 1.34 msaitoh m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); 617 1.1 gdamore if (error) { 618 1.1 gdamore printf("%s: unable to load Tx buffer, " 619 1.24 chs "error = %d\n", device_xname(sc->sc_dev), 620 1.1 gdamore error); 621 1.1 gdamore break; 622 1.1 gdamore } 623 1.1 gdamore } 624 1.1 gdamore 625 1.1 gdamore /* 626 1.1 gdamore * Ensure we have enough descriptors free to describe 627 1.1 gdamore * the packet. 628 1.1 gdamore */ 629 1.1 gdamore if (dmamap->dm_nsegs > sc->sc_txfree) { 630 1.1 gdamore /* 631 1.1 gdamore * Not enough free descriptors to transmit this 632 1.1 gdamore * packet. We haven't committed to anything yet, 633 1.1 gdamore * so just unload the DMA map, put the packet 634 1.1 gdamore * back on the queue, and punt. Notify the upper 635 1.1 gdamore * layer that there are no more slots left. 636 1.1 gdamore * 637 1.1 gdamore * XXX We could allocate an mbuf and copy, but 638 1.1 gdamore * XXX it is worth it? 639 1.1 gdamore */ 640 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, dmamap); 641 1.45 rin m_freem(m); 642 1.1 gdamore break; 643 1.1 gdamore } 644 1.1 gdamore 645 1.1 gdamore IFQ_DEQUEUE(&ifp->if_snd, m0); 646 1.1 gdamore if (m != NULL) { 647 1.1 gdamore m_freem(m0); 648 1.1 gdamore m0 = m; 649 1.1 gdamore } 650 1.1 gdamore 651 1.1 gdamore /* 652 1.1 gdamore * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. 653 1.1 gdamore */ 654 1.1 gdamore 655 1.1 gdamore /* Sync the DMA map. */ 656 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, 657 1.1 gdamore BUS_DMASYNC_PREWRITE); 658 1.1 gdamore 659 1.1 gdamore /* 660 1.1 gdamore * Initialize the transmit descriptors. 661 1.1 gdamore */ 662 1.1 gdamore for (nexttx = sc->sc_txnext, seg = 0; 663 1.1 gdamore seg < dmamap->dm_nsegs; 664 1.1 gdamore seg++, nexttx = AE_NEXTTX(nexttx)) { 665 1.1 gdamore /* 666 1.1 gdamore * If this is the first descriptor we're 667 1.1 gdamore * enqueueing, don't set the OWN bit just 668 1.1 gdamore * yet. That could cause a race condition. 669 1.1 gdamore * We'll do it below. 670 1.1 gdamore */ 671 1.1 gdamore sc->sc_txdescs[nexttx].ad_status = 672 1.1 gdamore (nexttx == firsttx) ? 0 : ADSTAT_OWN; 673 1.1 gdamore sc->sc_txdescs[nexttx].ad_bufaddr1 = 674 1.1 gdamore dmamap->dm_segs[seg].ds_addr; 675 1.1 gdamore sc->sc_txdescs[nexttx].ad_ctl = 676 1.1 gdamore (dmamap->dm_segs[seg].ds_len << 677 1.1 gdamore ADCTL_SIZE1_SHIFT) | 678 1.1 gdamore (nexttx == (AE_NTXDESC - 1) ? 679 1.1 gdamore ADCTL_ER : 0); 680 1.1 gdamore lasttx = nexttx; 681 1.1 gdamore } 682 1.1 gdamore 683 1.1 gdamore KASSERT(lasttx != -1); 684 1.1 gdamore 685 1.1 gdamore /* Set `first segment' and `last segment' appropriately. */ 686 1.1 gdamore sc->sc_txdescs[sc->sc_txnext].ad_ctl |= ADCTL_Tx_FS; 687 1.1 gdamore sc->sc_txdescs[lasttx].ad_ctl |= ADCTL_Tx_LS; 688 1.1 gdamore 689 1.1 gdamore #ifdef AE_DEBUG 690 1.1 gdamore if (ifp->if_flags & IFF_DEBUG) { 691 1.1 gdamore printf(" txsoft %p transmit chain:\n", txs); 692 1.1 gdamore for (seg = sc->sc_txnext;; seg = AE_NEXTTX(seg)) { 693 1.1 gdamore printf(" descriptor %d:\n", seg); 694 1.1 gdamore printf(" ad_status: 0x%08x\n", 695 1.1 gdamore sc->sc_txdescs[seg].ad_status); 696 1.1 gdamore printf(" ad_ctl: 0x%08x\n", 697 1.1 gdamore sc->sc_txdescs[seg].ad_ctl); 698 1.1 gdamore printf(" ad_bufaddr1: 0x%08x\n", 699 1.1 gdamore sc->sc_txdescs[seg].ad_bufaddr1); 700 1.1 gdamore printf(" ad_bufaddr2: 0x%08x\n", 701 1.1 gdamore sc->sc_txdescs[seg].ad_bufaddr2); 702 1.1 gdamore if (seg == lasttx) 703 1.1 gdamore break; 704 1.1 gdamore } 705 1.1 gdamore } 706 1.1 gdamore #endif 707 1.1 gdamore 708 1.1 gdamore /* Sync the descriptors we're using. */ 709 1.1 gdamore AE_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs, 710 1.34 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 711 1.1 gdamore 712 1.1 gdamore /* 713 1.1 gdamore * Store a pointer to the packet so we can free it later, 714 1.1 gdamore * and remember what txdirty will be once the packet is 715 1.1 gdamore * done. 716 1.1 gdamore */ 717 1.1 gdamore txs->txs_mbuf = m0; 718 1.1 gdamore txs->txs_firstdesc = sc->sc_txnext; 719 1.1 gdamore txs->txs_lastdesc = lasttx; 720 1.1 gdamore txs->txs_ndescs = dmamap->dm_nsegs; 721 1.1 gdamore 722 1.1 gdamore /* Advance the tx pointer. */ 723 1.1 gdamore sc->sc_txfree -= dmamap->dm_nsegs; 724 1.1 gdamore sc->sc_txnext = nexttx; 725 1.1 gdamore 726 1.1 gdamore SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 727 1.1 gdamore SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 728 1.1 gdamore 729 1.1 gdamore /* 730 1.1 gdamore * Pass the packet to any BPF listeners. 731 1.1 gdamore */ 732 1.31 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 733 1.1 gdamore } 734 1.1 gdamore 735 1.1 gdamore if (sc->sc_txfree != ofree) { 736 1.1 gdamore DPRINTF(sc, ("%s: packets enqueued, IC on %d, OWN on %d\n", 737 1.24 chs device_xname(sc->sc_dev), lasttx, firsttx)); 738 1.1 gdamore /* 739 1.1 gdamore * Cause a transmit interrupt to happen on the 740 1.1 gdamore * last packet we enqueued. 741 1.1 gdamore */ 742 1.1 gdamore sc->sc_txdescs[lasttx].ad_ctl |= ADCTL_Tx_IC; 743 1.1 gdamore AE_CDTXSYNC(sc, lasttx, 1, 744 1.34 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 745 1.1 gdamore 746 1.1 gdamore /* 747 1.1 gdamore * The entire packet chain is set up. Give the 748 1.1 gdamore * first descriptor to the chip now. 749 1.1 gdamore */ 750 1.1 gdamore sc->sc_txdescs[firsttx].ad_status |= ADSTAT_OWN; 751 1.1 gdamore AE_CDTXSYNC(sc, firsttx, 1, 752 1.34 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 753 1.1 gdamore 754 1.1 gdamore /* Wake up the transmitter. */ 755 1.1 gdamore /* XXX USE AUTOPOLLING? */ 756 1.1 gdamore AE_WRITE(sc, CSR_TXPOLL, TXPOLL_TPD); 757 1.1 gdamore AE_BARRIER(sc); 758 1.1 gdamore 759 1.1 gdamore /* Set a watchdog timer in case the chip flakes out. */ 760 1.1 gdamore ifp->if_timer = 5; 761 1.1 gdamore } 762 1.1 gdamore } 763 1.1 gdamore 764 1.1 gdamore /* 765 1.1 gdamore * ae_watchdog: [ifnet interface function] 766 1.1 gdamore * 767 1.1 gdamore * Watchdog timer handler. 768 1.1 gdamore */ 769 1.1 gdamore static void 770 1.1 gdamore ae_watchdog(struct ifnet *ifp) 771 1.1 gdamore { 772 1.1 gdamore struct ae_softc *sc = ifp->if_softc; 773 1.1 gdamore int doing_transmit; 774 1.1 gdamore 775 1.1 gdamore doing_transmit = (! SIMPLEQ_EMPTY(&sc->sc_txdirtyq)); 776 1.1 gdamore 777 1.1 gdamore if (doing_transmit) { 778 1.24 chs printf("%s: transmit timeout\n", device_xname(sc->sc_dev)); 779 1.38 thorpej if_statinc(ifp, if_oerrors); 780 1.1 gdamore } 781 1.1 gdamore else 782 1.24 chs printf("%s: spurious watchdog timeout\n", device_xname(sc->sc_dev)); 783 1.1 gdamore 784 1.1 gdamore (void) ae_init(ifp); 785 1.1 gdamore 786 1.1 gdamore /* Try to get more packets going. */ 787 1.1 gdamore ae_start(ifp); 788 1.1 gdamore } 789 1.1 gdamore 790 1.15 dyoung /* If the interface is up and running, only modify the receive 791 1.15 dyoung * filter when changing to/from promiscuous mode. Otherwise return 792 1.15 dyoung * ENETRESET so that ether_ioctl will reset the chip. 793 1.15 dyoung */ 794 1.15 dyoung static int 795 1.15 dyoung ae_ifflags_cb(struct ethercom *ec) 796 1.15 dyoung { 797 1.15 dyoung struct ifnet *ifp = &ec->ec_if; 798 1.15 dyoung struct ae_softc *sc = ifp->if_softc; 799 1.37 msaitoh u_short change = ifp->if_flags ^ sc->sc_if_flags; 800 1.15 dyoung 801 1.34 msaitoh if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) 802 1.15 dyoung return ENETRESET; 803 1.15 dyoung else if ((change & IFF_PROMISC) != 0) 804 1.15 dyoung ae_filter_setup(sc); 805 1.15 dyoung return 0; 806 1.15 dyoung } 807 1.15 dyoung 808 1.1 gdamore /* 809 1.1 gdamore * ae_ioctl: [ifnet interface function] 810 1.1 gdamore * 811 1.1 gdamore * Handle control requests from the operator. 812 1.1 gdamore */ 813 1.1 gdamore static int 814 1.5 christos ae_ioctl(struct ifnet *ifp, u_long cmd, void *data) 815 1.1 gdamore { 816 1.1 gdamore struct ae_softc *sc = ifp->if_softc; 817 1.1 gdamore int s, error; 818 1.1 gdamore 819 1.1 gdamore s = splnet(); 820 1.1 gdamore 821 1.15 dyoung error = ether_ioctl(ifp, cmd, data); 822 1.15 dyoung if (error == ENETRESET) { 823 1.15 dyoung if (ifp->if_flags & IFF_RUNNING) { 824 1.15 dyoung /* 825 1.15 dyoung * Multicast list has changed. Set the 826 1.15 dyoung * hardware filter accordingly. 827 1.15 dyoung */ 828 1.1 gdamore ae_filter_setup(sc); 829 1.1 gdamore } 830 1.15 dyoung error = 0; 831 1.1 gdamore } 832 1.1 gdamore 833 1.1 gdamore /* Try to get more packets going. */ 834 1.1 gdamore if (AE_IS_ENABLED(sc)) 835 1.1 gdamore ae_start(ifp); 836 1.1 gdamore 837 1.1 gdamore sc->sc_if_flags = ifp->if_flags; 838 1.1 gdamore splx(s); 839 1.1 gdamore return (error); 840 1.1 gdamore } 841 1.1 gdamore 842 1.1 gdamore /* 843 1.1 gdamore * ae_intr: 844 1.1 gdamore * 845 1.1 gdamore * Interrupt service routine. 846 1.1 gdamore */ 847 1.1 gdamore int 848 1.1 gdamore ae_intr(void *arg) 849 1.1 gdamore { 850 1.1 gdamore struct ae_softc *sc = arg; 851 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 852 1.34 msaitoh uint32_t status, rxstatus, txstatus; 853 1.1 gdamore int handled = 0, txthresh; 854 1.1 gdamore 855 1.24 chs DPRINTF(sc, ("%s: ae_intr\n", device_xname(sc->sc_dev))); 856 1.1 gdamore 857 1.1 gdamore #ifdef DEBUG 858 1.1 gdamore if (AE_IS_ENABLED(sc) == 0) 859 1.24 chs panic("%s: ae_intr: not enabled", device_xname(sc->sc_dev)); 860 1.1 gdamore #endif 861 1.1 gdamore 862 1.1 gdamore /* 863 1.1 gdamore * If the interface isn't running, the interrupt couldn't 864 1.1 gdamore * possibly have come from us. 865 1.1 gdamore */ 866 1.1 gdamore if ((ifp->if_flags & IFF_RUNNING) == 0 || 867 1.24 chs !device_is_active(sc->sc_dev)) { 868 1.1 gdamore printf("spurious?!?\n"); 869 1.1 gdamore return (0); 870 1.1 gdamore } 871 1.1 gdamore 872 1.1 gdamore for (;;) { 873 1.1 gdamore status = AE_READ(sc, CSR_STATUS); 874 1.1 gdamore if (status) { 875 1.1 gdamore AE_WRITE(sc, CSR_STATUS, status); 876 1.1 gdamore AE_BARRIER(sc); 877 1.1 gdamore } 878 1.1 gdamore 879 1.1 gdamore if ((status & sc->sc_inten) == 0) 880 1.1 gdamore break; 881 1.1 gdamore 882 1.1 gdamore handled = 1; 883 1.1 gdamore 884 1.1 gdamore rxstatus = status & sc->sc_rxint_mask; 885 1.1 gdamore txstatus = status & sc->sc_txint_mask; 886 1.1 gdamore 887 1.1 gdamore if (rxstatus) { 888 1.1 gdamore /* Grab new any new packets. */ 889 1.1 gdamore ae_rxintr(sc); 890 1.1 gdamore 891 1.1 gdamore if (rxstatus & STATUS_RU) { 892 1.1 gdamore printf("%s: receive ring overrun\n", 893 1.24 chs device_xname(sc->sc_dev)); 894 1.1 gdamore /* Get the receive process going again. */ 895 1.1 gdamore AE_WRITE(sc, CSR_RXPOLL, RXPOLL_RPD); 896 1.1 gdamore AE_BARRIER(sc); 897 1.1 gdamore break; 898 1.1 gdamore } 899 1.1 gdamore } 900 1.1 gdamore 901 1.1 gdamore if (txstatus) { 902 1.1 gdamore /* Sweep up transmit descriptors. */ 903 1.1 gdamore ae_txintr(sc); 904 1.1 gdamore 905 1.1 gdamore if (txstatus & STATUS_TJT) 906 1.1 gdamore printf("%s: transmit jabber timeout\n", 907 1.24 chs device_xname(sc->sc_dev)); 908 1.1 gdamore 909 1.1 gdamore if (txstatus & STATUS_UNF) { 910 1.1 gdamore /* 911 1.1 gdamore * Increase our transmit threshold if 912 1.1 gdamore * another is available. 913 1.1 gdamore */ 914 1.1 gdamore txthresh = sc->sc_txthresh + 1; 915 1.1 gdamore if (ae_txthresh[txthresh].txth_name != NULL) { 916 1.1 gdamore uint32_t opmode; 917 1.1 gdamore /* Idle the transmit process. */ 918 1.1 gdamore opmode = AE_READ(sc, CSR_OPMODE); 919 1.1 gdamore ae_idle(sc, OPMODE_ST); 920 1.1 gdamore 921 1.1 gdamore sc->sc_txthresh = txthresh; 922 1.34 msaitoh opmode &= ~(OPMODE_TR | OPMODE_SF); 923 1.1 gdamore opmode |= 924 1.1 gdamore ae_txthresh[txthresh].txth_opmode; 925 1.1 gdamore printf("%s: transmit underrun; new " 926 1.1 gdamore "threshold: %s\n", 927 1.24 chs device_xname(sc->sc_dev), 928 1.1 gdamore ae_txthresh[txthresh].txth_name); 929 1.1 gdamore 930 1.1 gdamore /* 931 1.1 gdamore * Set the new threshold and restart 932 1.1 gdamore * the transmit process. 933 1.1 gdamore */ 934 1.1 gdamore AE_WRITE(sc, CSR_OPMODE, opmode); 935 1.1 gdamore AE_BARRIER(sc); 936 1.1 gdamore } 937 1.1 gdamore /* 938 1.1 gdamore * XXX Log every Nth underrun from 939 1.1 gdamore * XXX now on? 940 1.1 gdamore */ 941 1.1 gdamore } 942 1.1 gdamore } 943 1.1 gdamore 944 1.34 msaitoh if (status & (STATUS_TPS | STATUS_RPS)) { 945 1.1 gdamore if (status & STATUS_TPS) 946 1.1 gdamore printf("%s: transmit process stopped\n", 947 1.24 chs device_xname(sc->sc_dev)); 948 1.1 gdamore if (status & STATUS_RPS) 949 1.1 gdamore printf("%s: receive process stopped\n", 950 1.24 chs device_xname(sc->sc_dev)); 951 1.1 gdamore (void) ae_init(ifp); 952 1.1 gdamore break; 953 1.1 gdamore } 954 1.1 gdamore 955 1.1 gdamore if (status & STATUS_SE) { 956 1.1 gdamore const char *str; 957 1.1 gdamore 958 1.1 gdamore if (status & STATUS_TX_ABORT) 959 1.1 gdamore str = "tx abort"; 960 1.1 gdamore else if (status & STATUS_RX_ABORT) 961 1.1 gdamore str = "rx abort"; 962 1.1 gdamore else 963 1.1 gdamore str = "unknown error"; 964 1.1 gdamore 965 1.1 gdamore printf("%s: fatal system error: %s\n", 966 1.24 chs device_xname(sc->sc_dev), str); 967 1.1 gdamore (void) ae_init(ifp); 968 1.1 gdamore break; 969 1.1 gdamore } 970 1.1 gdamore 971 1.1 gdamore /* 972 1.1 gdamore * Not handled: 973 1.1 gdamore * 974 1.1 gdamore * Transmit buffer unavailable -- normal 975 1.1 gdamore * condition, nothing to do, really. 976 1.1 gdamore * 977 1.1 gdamore * General purpose timer experied -- we don't 978 1.1 gdamore * use the general purpose timer. 979 1.1 gdamore * 980 1.1 gdamore * Early receive interrupt -- not available on 981 1.1 gdamore * all chips, we just use RI. We also only 982 1.1 gdamore * use single-segment receive DMA, so this 983 1.1 gdamore * is mostly useless. 984 1.1 gdamore */ 985 1.1 gdamore } 986 1.1 gdamore 987 1.1 gdamore /* Try to get more packets going. */ 988 1.29 ozaki if_schedule_deferred_start(ifp); 989 1.1 gdamore 990 1.1 gdamore if (handled) 991 1.1 gdamore rnd_add_uint32(&sc->sc_rnd_source, status); 992 1.1 gdamore return (handled); 993 1.1 gdamore } 994 1.1 gdamore 995 1.1 gdamore /* 996 1.1 gdamore * ae_rxintr: 997 1.1 gdamore * 998 1.1 gdamore * Helper; handle receive interrupts. 999 1.1 gdamore */ 1000 1.1 gdamore static void 1001 1.1 gdamore ae_rxintr(struct ae_softc *sc) 1002 1.1 gdamore { 1003 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1004 1.1 gdamore struct ae_rxsoft *rxs; 1005 1.1 gdamore struct mbuf *m; 1006 1.34 msaitoh uint32_t rxstat; 1007 1.1 gdamore int i, len; 1008 1.1 gdamore 1009 1.1 gdamore for (i = sc->sc_rxptr;; i = AE_NEXTRX(i)) { 1010 1.1 gdamore rxs = &sc->sc_rxsoft[i]; 1011 1.1 gdamore 1012 1.1 gdamore AE_CDRXSYNC(sc, i, 1013 1.34 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1014 1.1 gdamore 1015 1.1 gdamore rxstat = sc->sc_rxdescs[i].ad_status; 1016 1.1 gdamore 1017 1.1 gdamore if (rxstat & ADSTAT_OWN) { 1018 1.1 gdamore /* 1019 1.1 gdamore * We have processed all of the receive buffers. 1020 1.1 gdamore */ 1021 1.1 gdamore break; 1022 1.1 gdamore } 1023 1.1 gdamore 1024 1.1 gdamore /* 1025 1.1 gdamore * If any collisions were seen on the wire, count one. 1026 1.1 gdamore */ 1027 1.1 gdamore if (rxstat & ADSTAT_Rx_CS) 1028 1.38 thorpej if_statinc(ifp, if_collisions); 1029 1.1 gdamore 1030 1.1 gdamore /* 1031 1.1 gdamore * If an error occurred, update stats, clear the status 1032 1.1 gdamore * word, and leave the packet buffer in place. It will 1033 1.1 gdamore * simply be reused the next time the ring comes around. 1034 1.1 gdamore * If 802.1Q VLAN MTU is enabled, ignore the Frame Too Long 1035 1.1 gdamore * error. 1036 1.1 gdamore */ 1037 1.1 gdamore if (rxstat & ADSTAT_ES && 1038 1.1 gdamore ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) == 0 || 1039 1.1 gdamore (rxstat & (ADSTAT_Rx_DE | ADSTAT_Rx_RF | 1040 1.1 gdamore ADSTAT_Rx_DB | ADSTAT_Rx_CE)) != 0)) { 1041 1.1 gdamore #define PRINTERR(bit, str) \ 1042 1.1 gdamore if (rxstat & (bit)) \ 1043 1.1 gdamore printf("%s: receive error: %s\n", \ 1044 1.24 chs device_xname(sc->sc_dev), str) 1045 1.38 thorpej if_statinc(ifp, if_ierrors); 1046 1.1 gdamore PRINTERR(ADSTAT_Rx_DE, "descriptor error"); 1047 1.1 gdamore PRINTERR(ADSTAT_Rx_RF, "runt frame"); 1048 1.1 gdamore PRINTERR(ADSTAT_Rx_TL, "frame too long"); 1049 1.1 gdamore PRINTERR(ADSTAT_Rx_RE, "MII error"); 1050 1.1 gdamore PRINTERR(ADSTAT_Rx_DB, "dribbling bit"); 1051 1.1 gdamore PRINTERR(ADSTAT_Rx_CE, "CRC error"); 1052 1.1 gdamore #undef PRINTERR 1053 1.1 gdamore AE_INIT_RXDESC(sc, i); 1054 1.1 gdamore continue; 1055 1.1 gdamore } 1056 1.1 gdamore 1057 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, 1058 1.1 gdamore rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); 1059 1.1 gdamore 1060 1.1 gdamore /* 1061 1.1 gdamore * No errors; receive the packet. Note the chip 1062 1.1 gdamore * includes the CRC with every packet. 1063 1.1 gdamore */ 1064 1.1 gdamore len = ADSTAT_Rx_LENGTH(rxstat) - ETHER_CRC_LEN; 1065 1.1 gdamore 1066 1.1 gdamore /* 1067 1.1 gdamore * XXX: the Atheros part can align on half words. what 1068 1.1 gdamore * is the performance implication of this? Probably 1069 1.1 gdamore * minimal, and we should use it... 1070 1.1 gdamore */ 1071 1.1 gdamore #ifdef __NO_STRICT_ALIGNMENT 1072 1.1 gdamore /* 1073 1.1 gdamore * Allocate a new mbuf cluster. If that fails, we are 1074 1.1 gdamore * out of memory, and must drop the packet and recycle 1075 1.1 gdamore * the buffer that's already attached to this descriptor. 1076 1.1 gdamore */ 1077 1.1 gdamore m = rxs->rxs_mbuf; 1078 1.1 gdamore if (ae_add_rxbuf(sc, i) != 0) { 1079 1.38 thorpej if_statinc(ifp, if_ierrors); 1080 1.1 gdamore AE_INIT_RXDESC(sc, i); 1081 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, 1082 1.1 gdamore rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1083 1.1 gdamore continue; 1084 1.1 gdamore } 1085 1.1 gdamore #else 1086 1.1 gdamore /* 1087 1.1 gdamore * The chip's receive buffers must be 4-byte aligned. 1088 1.1 gdamore * But this means that the data after the Ethernet header 1089 1.1 gdamore * is misaligned. We must allocate a new buffer and 1090 1.1 gdamore * copy the data, shifted forward 2 bytes. 1091 1.1 gdamore */ 1092 1.1 gdamore MGETHDR(m, M_DONTWAIT, MT_DATA); 1093 1.1 gdamore if (m == NULL) { 1094 1.1 gdamore dropit: 1095 1.38 thorpej if_statinc(ifp, if_ierrors); 1096 1.1 gdamore AE_INIT_RXDESC(sc, i); 1097 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, 1098 1.1 gdamore rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1099 1.1 gdamore continue; 1100 1.1 gdamore } 1101 1.1 gdamore MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 1102 1.1 gdamore if (len > (MHLEN - 2)) { 1103 1.1 gdamore MCLGET(m, M_DONTWAIT); 1104 1.1 gdamore if ((m->m_flags & M_EXT) == 0) { 1105 1.1 gdamore m_freem(m); 1106 1.1 gdamore goto dropit; 1107 1.1 gdamore } 1108 1.1 gdamore } 1109 1.1 gdamore m->m_data += 2; 1110 1.1 gdamore 1111 1.1 gdamore /* 1112 1.1 gdamore * Note that we use clusters for incoming frames, so the 1113 1.1 gdamore * buffer is virtually contiguous. 1114 1.1 gdamore */ 1115 1.5 christos memcpy(mtod(m, void *), mtod(rxs->rxs_mbuf, void *), len); 1116 1.1 gdamore 1117 1.1 gdamore /* Allow the receive descriptor to continue using its mbuf. */ 1118 1.1 gdamore AE_INIT_RXDESC(sc, i); 1119 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, 1120 1.1 gdamore rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1121 1.1 gdamore #endif /* __NO_STRICT_ALIGNMENT */ 1122 1.1 gdamore 1123 1.28 ozaki m_set_rcvif(m, ifp); 1124 1.1 gdamore m->m_pkthdr.len = m->m_len = len; 1125 1.1 gdamore 1126 1.1 gdamore /* Pass it on. */ 1127 1.27 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1128 1.1 gdamore } 1129 1.1 gdamore 1130 1.1 gdamore /* Update the receive pointer. */ 1131 1.1 gdamore sc->sc_rxptr = i; 1132 1.1 gdamore } 1133 1.1 gdamore 1134 1.1 gdamore /* 1135 1.1 gdamore * ae_txintr: 1136 1.1 gdamore * 1137 1.1 gdamore * Helper; handle transmit interrupts. 1138 1.1 gdamore */ 1139 1.1 gdamore static void 1140 1.1 gdamore ae_txintr(struct ae_softc *sc) 1141 1.1 gdamore { 1142 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1143 1.1 gdamore struct ae_txsoft *txs; 1144 1.34 msaitoh uint32_t txstat; 1145 1.1 gdamore 1146 1.1 gdamore DPRINTF(sc, ("%s: ae_txintr: sc_flags 0x%08x\n", 1147 1.24 chs device_xname(sc->sc_dev), sc->sc_flags)); 1148 1.1 gdamore 1149 1.1 gdamore /* 1150 1.1 gdamore * Go through our Tx list and free mbufs for those 1151 1.1 gdamore * frames that have been transmitted. 1152 1.1 gdamore */ 1153 1.1 gdamore while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 1154 1.1 gdamore AE_CDTXSYNC(sc, txs->txs_lastdesc, 1155 1.1 gdamore txs->txs_ndescs, 1156 1.34 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1157 1.1 gdamore 1158 1.1 gdamore #ifdef AE_DEBUG 1159 1.1 gdamore if (ifp->if_flags & IFF_DEBUG) { 1160 1.1 gdamore int i; 1161 1.1 gdamore printf(" txsoft %p transmit chain:\n", txs); 1162 1.1 gdamore for (i = txs->txs_firstdesc;; i = AE_NEXTTX(i)) { 1163 1.1 gdamore printf(" descriptor %d:\n", i); 1164 1.1 gdamore printf(" ad_status: 0x%08x\n", 1165 1.1 gdamore sc->sc_txdescs[i].ad_status); 1166 1.1 gdamore printf(" ad_ctl: 0x%08x\n", 1167 1.1 gdamore sc->sc_txdescs[i].ad_ctl); 1168 1.1 gdamore printf(" ad_bufaddr1: 0x%08x\n", 1169 1.1 gdamore sc->sc_txdescs[i].ad_bufaddr1); 1170 1.1 gdamore printf(" ad_bufaddr2: 0x%08x\n", 1171 1.1 gdamore sc->sc_txdescs[i].ad_bufaddr2); 1172 1.1 gdamore if (i == txs->txs_lastdesc) 1173 1.1 gdamore break; 1174 1.1 gdamore } 1175 1.1 gdamore } 1176 1.1 gdamore #endif 1177 1.1 gdamore 1178 1.1 gdamore txstat = sc->sc_txdescs[txs->txs_lastdesc].ad_status; 1179 1.1 gdamore if (txstat & ADSTAT_OWN) 1180 1.1 gdamore break; 1181 1.1 gdamore 1182 1.1 gdamore SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 1183 1.1 gdamore 1184 1.1 gdamore sc->sc_txfree += txs->txs_ndescs; 1185 1.1 gdamore 1186 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, 1187 1.1 gdamore 0, txs->txs_dmamap->dm_mapsize, 1188 1.1 gdamore BUS_DMASYNC_POSTWRITE); 1189 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); 1190 1.1 gdamore m_freem(txs->txs_mbuf); 1191 1.1 gdamore txs->txs_mbuf = NULL; 1192 1.1 gdamore 1193 1.1 gdamore SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 1194 1.1 gdamore 1195 1.1 gdamore /* 1196 1.1 gdamore * Check for errors and collisions. 1197 1.1 gdamore */ 1198 1.1 gdamore #ifdef AE_STATS 1199 1.1 gdamore if (txstat & ADSTAT_Tx_UF) 1200 1.1 gdamore sc->sc_stats.ts_tx_uf++; 1201 1.1 gdamore if (txstat & ADSTAT_Tx_TO) 1202 1.1 gdamore sc->sc_stats.ts_tx_to++; 1203 1.1 gdamore if (txstat & ADSTAT_Tx_EC) 1204 1.1 gdamore sc->sc_stats.ts_tx_ec++; 1205 1.1 gdamore if (txstat & ADSTAT_Tx_LC) 1206 1.1 gdamore sc->sc_stats.ts_tx_lc++; 1207 1.1 gdamore #endif 1208 1.1 gdamore 1209 1.38 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(ifp); 1210 1.34 msaitoh if (txstat & (ADSTAT_Tx_UF | ADSTAT_Tx_TO)) 1211 1.44 riastrad if_statinc_ref(ifp, nsr, if_oerrors); 1212 1.1 gdamore 1213 1.1 gdamore if (txstat & ADSTAT_Tx_EC) 1214 1.44 riastrad if_statadd_ref(ifp, nsr, if_collisions, 16); 1215 1.38 thorpej else if (ADSTAT_Tx_COLLISIONS(txstat)) 1216 1.44 riastrad if_statadd_ref(ifp, nsr, if_collisions, 1217 1.38 thorpej ADSTAT_Tx_COLLISIONS(txstat)); 1218 1.1 gdamore if (txstat & ADSTAT_Tx_LC) 1219 1.44 riastrad if_statinc_ref(ifp, nsr, if_collisions); 1220 1.1 gdamore 1221 1.44 riastrad if_statinc_ref(ifp, nsr, if_opackets); 1222 1.38 thorpej IF_STAT_PUTREF(ifp); 1223 1.1 gdamore } 1224 1.1 gdamore 1225 1.1 gdamore /* 1226 1.1 gdamore * If there are no more pending transmissions, cancel the watchdog 1227 1.1 gdamore * timer. 1228 1.1 gdamore */ 1229 1.1 gdamore if (txs == NULL) 1230 1.1 gdamore ifp->if_timer = 0; 1231 1.1 gdamore } 1232 1.1 gdamore 1233 1.1 gdamore #ifdef AE_STATS 1234 1.1 gdamore void 1235 1.1 gdamore ae_print_stats(struct ae_softc *sc) 1236 1.1 gdamore { 1237 1.1 gdamore 1238 1.1 gdamore printf("%s: tx_uf %lu, tx_to %lu, tx_ec %lu, tx_lc %lu\n", 1239 1.24 chs device_xname(sc->sc_dev), 1240 1.1 gdamore sc->sc_stats.ts_tx_uf, sc->sc_stats.ts_tx_to, 1241 1.1 gdamore sc->sc_stats.ts_tx_ec, sc->sc_stats.ts_tx_lc); 1242 1.1 gdamore } 1243 1.1 gdamore #endif 1244 1.1 gdamore 1245 1.1 gdamore /* 1246 1.1 gdamore * ae_reset: 1247 1.1 gdamore * 1248 1.1 gdamore * Perform a soft reset on the chip. 1249 1.1 gdamore */ 1250 1.1 gdamore void 1251 1.1 gdamore ae_reset(struct ae_softc *sc) 1252 1.1 gdamore { 1253 1.1 gdamore int i; 1254 1.1 gdamore 1255 1.1 gdamore AE_WRITE(sc, CSR_BUSMODE, BUSMODE_SWR); 1256 1.1 gdamore AE_BARRIER(sc); 1257 1.1 gdamore 1258 1.1 gdamore /* 1259 1.1 gdamore * The chip doesn't take itself out of reset automatically. 1260 1.1 gdamore * We need to do so after 2us. 1261 1.1 gdamore */ 1262 1.1 gdamore delay(10); 1263 1.1 gdamore AE_WRITE(sc, CSR_BUSMODE, 0); 1264 1.1 gdamore AE_BARRIER(sc); 1265 1.1 gdamore 1266 1.1 gdamore for (i = 0; i < 1000; i++) { 1267 1.1 gdamore /* 1268 1.1 gdamore * Wait a bit for the reset to complete before peeking 1269 1.1 gdamore * at the chip again. 1270 1.1 gdamore */ 1271 1.1 gdamore delay(10); 1272 1.1 gdamore if (AE_ISSET(sc, CSR_BUSMODE, BUSMODE_SWR) == 0) 1273 1.1 gdamore break; 1274 1.1 gdamore } 1275 1.1 gdamore 1276 1.1 gdamore if (AE_ISSET(sc, CSR_BUSMODE, BUSMODE_SWR)) 1277 1.24 chs printf("%s: reset failed to complete\n", device_xname(sc->sc_dev)); 1278 1.1 gdamore 1279 1.1 gdamore delay(1000); 1280 1.1 gdamore } 1281 1.1 gdamore 1282 1.1 gdamore /* 1283 1.1 gdamore * ae_init: [ ifnet interface function ] 1284 1.1 gdamore * 1285 1.1 gdamore * Initialize the interface. Must be called at splnet(). 1286 1.1 gdamore */ 1287 1.1 gdamore static int 1288 1.1 gdamore ae_init(struct ifnet *ifp) 1289 1.1 gdamore { 1290 1.1 gdamore struct ae_softc *sc = ifp->if_softc; 1291 1.1 gdamore struct ae_txsoft *txs; 1292 1.1 gdamore struct ae_rxsoft *rxs; 1293 1.7 dyoung const uint8_t *enaddr; 1294 1.1 gdamore int i, error = 0; 1295 1.1 gdamore 1296 1.1 gdamore if ((error = ae_enable(sc)) != 0) 1297 1.1 gdamore goto out; 1298 1.1 gdamore 1299 1.1 gdamore /* 1300 1.1 gdamore * Cancel any pending I/O. 1301 1.1 gdamore */ 1302 1.1 gdamore ae_stop(ifp, 0); 1303 1.1 gdamore 1304 1.1 gdamore /* 1305 1.1 gdamore * Reset the chip to a known state. 1306 1.1 gdamore */ 1307 1.1 gdamore ae_reset(sc); 1308 1.1 gdamore 1309 1.1 gdamore /* 1310 1.1 gdamore * Initialize the BUSMODE register. 1311 1.1 gdamore */ 1312 1.1 gdamore AE_WRITE(sc, CSR_BUSMODE, 1313 1.1 gdamore /* XXX: not sure if this is a good thing or not... */ 1314 1.1 gdamore //BUSMODE_ALIGN_16B | 1315 1.1 gdamore BUSMODE_BAR | BUSMODE_BLE | BUSMODE_PBL_4LW); 1316 1.1 gdamore AE_BARRIER(sc); 1317 1.1 gdamore 1318 1.1 gdamore /* 1319 1.1 gdamore * Initialize the transmit descriptor ring. 1320 1.1 gdamore */ 1321 1.1 gdamore memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs)); 1322 1.1 gdamore for (i = 0; i < AE_NTXDESC; i++) { 1323 1.1 gdamore sc->sc_txdescs[i].ad_ctl = 0; 1324 1.1 gdamore sc->sc_txdescs[i].ad_bufaddr2 = 1325 1.1 gdamore AE_CDTXADDR(sc, AE_NEXTTX(i)); 1326 1.1 gdamore } 1327 1.1 gdamore sc->sc_txdescs[AE_NTXDESC - 1].ad_ctl |= ADCTL_ER; 1328 1.1 gdamore AE_CDTXSYNC(sc, 0, AE_NTXDESC, 1329 1.34 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1330 1.1 gdamore sc->sc_txfree = AE_NTXDESC; 1331 1.1 gdamore sc->sc_txnext = 0; 1332 1.1 gdamore 1333 1.1 gdamore /* 1334 1.1 gdamore * Initialize the transmit job descriptors. 1335 1.1 gdamore */ 1336 1.1 gdamore SIMPLEQ_INIT(&sc->sc_txfreeq); 1337 1.1 gdamore SIMPLEQ_INIT(&sc->sc_txdirtyq); 1338 1.1 gdamore for (i = 0; i < AE_TXQUEUELEN; i++) { 1339 1.1 gdamore txs = &sc->sc_txsoft[i]; 1340 1.1 gdamore txs->txs_mbuf = NULL; 1341 1.1 gdamore SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 1342 1.1 gdamore } 1343 1.1 gdamore 1344 1.1 gdamore /* 1345 1.1 gdamore * Initialize the receive descriptor and receive job 1346 1.1 gdamore * descriptor rings. 1347 1.1 gdamore */ 1348 1.1 gdamore for (i = 0; i < AE_NRXDESC; i++) { 1349 1.1 gdamore rxs = &sc->sc_rxsoft[i]; 1350 1.1 gdamore if (rxs->rxs_mbuf == NULL) { 1351 1.1 gdamore if ((error = ae_add_rxbuf(sc, i)) != 0) { 1352 1.1 gdamore printf("%s: unable to allocate or map rx " 1353 1.1 gdamore "buffer %d, error = %d\n", 1354 1.24 chs device_xname(sc->sc_dev), i, error); 1355 1.1 gdamore /* 1356 1.1 gdamore * XXX Should attempt to run with fewer receive 1357 1.1 gdamore * XXX buffers instead of just failing. 1358 1.1 gdamore */ 1359 1.1 gdamore ae_rxdrain(sc); 1360 1.1 gdamore goto out; 1361 1.1 gdamore } 1362 1.1 gdamore } else 1363 1.1 gdamore AE_INIT_RXDESC(sc, i); 1364 1.1 gdamore } 1365 1.1 gdamore sc->sc_rxptr = 0; 1366 1.1 gdamore 1367 1.1 gdamore /* 1368 1.1 gdamore * Initialize the interrupt mask and enable interrupts. 1369 1.1 gdamore */ 1370 1.1 gdamore /* normal interrupts */ 1371 1.35 msaitoh sc->sc_inten = STATUS_TI | STATUS_TU | STATUS_RI | STATUS_NIS; 1372 1.1 gdamore 1373 1.1 gdamore /* abnormal interrupts */ 1374 1.1 gdamore sc->sc_inten |= STATUS_TPS | STATUS_TJT | STATUS_UNF | 1375 1.1 gdamore STATUS_RU | STATUS_RPS | STATUS_SE | STATUS_AIS; 1376 1.1 gdamore 1377 1.34 msaitoh sc->sc_rxint_mask = STATUS_RI | STATUS_RU; 1378 1.34 msaitoh sc->sc_txint_mask = STATUS_TI | STATUS_UNF | STATUS_TJT; 1379 1.1 gdamore 1380 1.1 gdamore sc->sc_rxint_mask &= sc->sc_inten; 1381 1.1 gdamore sc->sc_txint_mask &= sc->sc_inten; 1382 1.1 gdamore 1383 1.1 gdamore AE_WRITE(sc, CSR_INTEN, sc->sc_inten); 1384 1.1 gdamore AE_WRITE(sc, CSR_STATUS, 0xffffffff); 1385 1.1 gdamore 1386 1.1 gdamore /* 1387 1.1 gdamore * Give the transmit and receive rings to the chip. 1388 1.1 gdamore */ 1389 1.1 gdamore AE_WRITE(sc, CSR_TXLIST, AE_CDTXADDR(sc, sc->sc_txnext)); 1390 1.1 gdamore AE_WRITE(sc, CSR_RXLIST, AE_CDRXADDR(sc, sc->sc_rxptr)); 1391 1.1 gdamore AE_BARRIER(sc); 1392 1.1 gdamore 1393 1.1 gdamore /* 1394 1.1 gdamore * Set the station address. 1395 1.1 gdamore */ 1396 1.7 dyoung enaddr = CLLADDR(ifp->if_sadl); 1397 1.1 gdamore AE_WRITE(sc, CSR_MACHI, enaddr[5] << 16 | enaddr[4]); 1398 1.1 gdamore AE_WRITE(sc, CSR_MACLO, enaddr[3] << 24 | enaddr[2] << 16 | 1399 1.1 gdamore enaddr[1] << 8 | enaddr[0]); 1400 1.1 gdamore AE_BARRIER(sc); 1401 1.1 gdamore 1402 1.1 gdamore /* 1403 1.1 gdamore * Set the receive filter. This will start the transmit and 1404 1.1 gdamore * receive processes. 1405 1.1 gdamore */ 1406 1.1 gdamore ae_filter_setup(sc); 1407 1.1 gdamore 1408 1.1 gdamore /* 1409 1.1 gdamore * Set the current media. 1410 1.1 gdamore */ 1411 1.10 dyoung if ((error = ether_mediachange(ifp)) != 0) 1412 1.10 dyoung goto out; 1413 1.1 gdamore 1414 1.1 gdamore /* 1415 1.1 gdamore * Start the mac. 1416 1.1 gdamore */ 1417 1.1 gdamore AE_SET(sc, CSR_MACCTL, MACCTL_RE | MACCTL_TE); 1418 1.1 gdamore AE_BARRIER(sc); 1419 1.1 gdamore 1420 1.1 gdamore /* 1421 1.1 gdamore * Write out the opmode. 1422 1.1 gdamore */ 1423 1.1 gdamore AE_WRITE(sc, CSR_OPMODE, OPMODE_SR | OPMODE_ST | 1424 1.1 gdamore ae_txthresh[sc->sc_txthresh].txth_opmode); 1425 1.1 gdamore /* 1426 1.1 gdamore * Start the receive process. 1427 1.1 gdamore */ 1428 1.1 gdamore AE_WRITE(sc, CSR_RXPOLL, RXPOLL_RPD); 1429 1.1 gdamore AE_BARRIER(sc); 1430 1.1 gdamore 1431 1.1 gdamore if (sc->sc_tick != NULL) { 1432 1.1 gdamore /* Start the one second clock. */ 1433 1.1 gdamore callout_reset(&sc->sc_tick_callout, hz >> 3, sc->sc_tick, sc); 1434 1.1 gdamore } 1435 1.1 gdamore 1436 1.1 gdamore /* 1437 1.1 gdamore * Note that the interface is now running. 1438 1.1 gdamore */ 1439 1.1 gdamore ifp->if_flags |= IFF_RUNNING; 1440 1.1 gdamore sc->sc_if_flags = ifp->if_flags; 1441 1.1 gdamore 1442 1.1 gdamore out: 1443 1.1 gdamore if (error) { 1444 1.41 thorpej ifp->if_flags &= ~IFF_RUNNING; 1445 1.1 gdamore ifp->if_timer = 0; 1446 1.24 chs printf("%s: interface not running\n", device_xname(sc->sc_dev)); 1447 1.1 gdamore } 1448 1.1 gdamore return (error); 1449 1.1 gdamore } 1450 1.1 gdamore 1451 1.1 gdamore /* 1452 1.1 gdamore * ae_enable: 1453 1.1 gdamore * 1454 1.1 gdamore * Enable the chip. 1455 1.1 gdamore */ 1456 1.1 gdamore static int 1457 1.1 gdamore ae_enable(struct ae_softc *sc) 1458 1.1 gdamore { 1459 1.1 gdamore 1460 1.1 gdamore if (AE_IS_ENABLED(sc) == 0) { 1461 1.3 gdamore sc->sc_ih = arbus_intr_establish(sc->sc_cirq, sc->sc_mirq, 1462 1.3 gdamore ae_intr, sc); 1463 1.1 gdamore if (sc->sc_ih == NULL) { 1464 1.1 gdamore printf("%s: unable to establish interrupt\n", 1465 1.24 chs device_xname(sc->sc_dev)); 1466 1.1 gdamore return (EIO); 1467 1.1 gdamore } 1468 1.1 gdamore sc->sc_flags |= AE_ENABLED; 1469 1.1 gdamore } 1470 1.1 gdamore return (0); 1471 1.1 gdamore } 1472 1.1 gdamore 1473 1.1 gdamore /* 1474 1.1 gdamore * ae_disable: 1475 1.1 gdamore * 1476 1.1 gdamore * Disable the chip. 1477 1.1 gdamore */ 1478 1.1 gdamore static void 1479 1.1 gdamore ae_disable(struct ae_softc *sc) 1480 1.1 gdamore { 1481 1.1 gdamore 1482 1.1 gdamore if (AE_IS_ENABLED(sc)) { 1483 1.1 gdamore arbus_intr_disestablish(sc->sc_ih); 1484 1.1 gdamore sc->sc_flags &= ~AE_ENABLED; 1485 1.1 gdamore } 1486 1.1 gdamore } 1487 1.1 gdamore 1488 1.1 gdamore /* 1489 1.1 gdamore * ae_power: 1490 1.1 gdamore * 1491 1.1 gdamore * Power management (suspend/resume) hook. 1492 1.1 gdamore */ 1493 1.1 gdamore static void 1494 1.1 gdamore ae_power(int why, void *arg) 1495 1.1 gdamore { 1496 1.1 gdamore struct ae_softc *sc = arg; 1497 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1498 1.1 gdamore int s; 1499 1.1 gdamore 1500 1.1 gdamore printf("power called: %d, %x\n", why, (uint32_t)arg); 1501 1.1 gdamore s = splnet(); 1502 1.1 gdamore switch (why) { 1503 1.1 gdamore case PWR_STANDBY: 1504 1.1 gdamore /* do nothing! */ 1505 1.1 gdamore break; 1506 1.1 gdamore case PWR_SUSPEND: 1507 1.1 gdamore ae_stop(ifp, 0); 1508 1.1 gdamore ae_disable(sc); 1509 1.1 gdamore break; 1510 1.1 gdamore case PWR_RESUME: 1511 1.1 gdamore if (ifp->if_flags & IFF_UP) { 1512 1.1 gdamore ae_enable(sc); 1513 1.1 gdamore ae_init(ifp); 1514 1.1 gdamore } 1515 1.1 gdamore break; 1516 1.1 gdamore case PWR_SOFTSUSPEND: 1517 1.1 gdamore case PWR_SOFTSTANDBY: 1518 1.1 gdamore case PWR_SOFTRESUME: 1519 1.1 gdamore break; 1520 1.1 gdamore } 1521 1.1 gdamore splx(s); 1522 1.1 gdamore } 1523 1.1 gdamore 1524 1.1 gdamore /* 1525 1.1 gdamore * ae_rxdrain: 1526 1.1 gdamore * 1527 1.1 gdamore * Drain the receive queue. 1528 1.1 gdamore */ 1529 1.1 gdamore static void 1530 1.1 gdamore ae_rxdrain(struct ae_softc *sc) 1531 1.1 gdamore { 1532 1.1 gdamore struct ae_rxsoft *rxs; 1533 1.1 gdamore int i; 1534 1.1 gdamore 1535 1.1 gdamore for (i = 0; i < AE_NRXDESC; i++) { 1536 1.1 gdamore rxs = &sc->sc_rxsoft[i]; 1537 1.1 gdamore if (rxs->rxs_mbuf != NULL) { 1538 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); 1539 1.1 gdamore m_freem(rxs->rxs_mbuf); 1540 1.1 gdamore rxs->rxs_mbuf = NULL; 1541 1.1 gdamore } 1542 1.1 gdamore } 1543 1.1 gdamore } 1544 1.1 gdamore 1545 1.1 gdamore /* 1546 1.1 gdamore * ae_stop: [ ifnet interface function ] 1547 1.1 gdamore * 1548 1.1 gdamore * Stop transmission on the interface. 1549 1.1 gdamore */ 1550 1.1 gdamore static void 1551 1.1 gdamore ae_stop(struct ifnet *ifp, int disable) 1552 1.1 gdamore { 1553 1.1 gdamore struct ae_softc *sc = ifp->if_softc; 1554 1.1 gdamore struct ae_txsoft *txs; 1555 1.1 gdamore 1556 1.1 gdamore if (sc->sc_tick != NULL) { 1557 1.1 gdamore /* Stop the one second clock. */ 1558 1.1 gdamore callout_stop(&sc->sc_tick_callout); 1559 1.1 gdamore } 1560 1.1 gdamore 1561 1.1 gdamore /* Down the MII. */ 1562 1.1 gdamore mii_down(&sc->sc_mii); 1563 1.1 gdamore 1564 1.1 gdamore /* Disable interrupts. */ 1565 1.1 gdamore AE_WRITE(sc, CSR_INTEN, 0); 1566 1.1 gdamore 1567 1.1 gdamore /* Stop the transmit and receive processes. */ 1568 1.1 gdamore AE_WRITE(sc, CSR_OPMODE, 0); 1569 1.1 gdamore AE_WRITE(sc, CSR_RXLIST, 0); 1570 1.1 gdamore AE_WRITE(sc, CSR_TXLIST, 0); 1571 1.1 gdamore AE_CLR(sc, CSR_MACCTL, MACCTL_TE | MACCTL_RE); 1572 1.1 gdamore AE_BARRIER(sc); 1573 1.1 gdamore 1574 1.1 gdamore /* 1575 1.1 gdamore * Release any queued transmit buffers. 1576 1.1 gdamore */ 1577 1.1 gdamore while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 1578 1.1 gdamore SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 1579 1.1 gdamore if (txs->txs_mbuf != NULL) { 1580 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); 1581 1.1 gdamore m_freem(txs->txs_mbuf); 1582 1.1 gdamore txs->txs_mbuf = NULL; 1583 1.1 gdamore } 1584 1.1 gdamore SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 1585 1.1 gdamore } 1586 1.1 gdamore 1587 1.1 gdamore /* 1588 1.1 gdamore * Mark the interface down and cancel the watchdog timer. 1589 1.1 gdamore */ 1590 1.41 thorpej ifp->if_flags &= ~IFF_RUNNING; 1591 1.1 gdamore sc->sc_if_flags = ifp->if_flags; 1592 1.1 gdamore ifp->if_timer = 0; 1593 1.1 gdamore 1594 1.13 dyoung if (disable) { 1595 1.13 dyoung ae_rxdrain(sc); 1596 1.13 dyoung ae_disable(sc); 1597 1.13 dyoung } 1598 1.13 dyoung 1599 1.1 gdamore /* 1600 1.1 gdamore * Reset the chip (needed on some flavors to actually disable it). 1601 1.1 gdamore */ 1602 1.1 gdamore ae_reset(sc); 1603 1.1 gdamore } 1604 1.1 gdamore 1605 1.1 gdamore /* 1606 1.1 gdamore * ae_add_rxbuf: 1607 1.1 gdamore * 1608 1.1 gdamore * Add a receive buffer to the indicated descriptor. 1609 1.1 gdamore */ 1610 1.1 gdamore static int 1611 1.1 gdamore ae_add_rxbuf(struct ae_softc *sc, int idx) 1612 1.1 gdamore { 1613 1.1 gdamore struct ae_rxsoft *rxs = &sc->sc_rxsoft[idx]; 1614 1.1 gdamore struct mbuf *m; 1615 1.1 gdamore int error; 1616 1.1 gdamore 1617 1.1 gdamore MGETHDR(m, M_DONTWAIT, MT_DATA); 1618 1.1 gdamore if (m == NULL) 1619 1.1 gdamore return (ENOBUFS); 1620 1.1 gdamore 1621 1.1 gdamore MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 1622 1.1 gdamore MCLGET(m, M_DONTWAIT); 1623 1.1 gdamore if ((m->m_flags & M_EXT) == 0) { 1624 1.1 gdamore m_freem(m); 1625 1.1 gdamore return (ENOBUFS); 1626 1.1 gdamore } 1627 1.1 gdamore 1628 1.1 gdamore if (rxs->rxs_mbuf != NULL) 1629 1.1 gdamore bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); 1630 1.1 gdamore 1631 1.1 gdamore rxs->rxs_mbuf = m; 1632 1.1 gdamore 1633 1.1 gdamore error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap, 1634 1.1 gdamore m->m_ext.ext_buf, m->m_ext.ext_size, NULL, 1635 1.34 msaitoh BUS_DMA_READ | BUS_DMA_NOWAIT); 1636 1.1 gdamore if (error) { 1637 1.1 gdamore printf("%s: can't load rx DMA map %d, error = %d\n", 1638 1.24 chs device_xname(sc->sc_dev), idx, error); 1639 1.1 gdamore panic("ae_add_rxbuf"); /* XXX */ 1640 1.1 gdamore } 1641 1.1 gdamore 1642 1.1 gdamore bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, 1643 1.1 gdamore rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1644 1.1 gdamore 1645 1.1 gdamore AE_INIT_RXDESC(sc, idx); 1646 1.1 gdamore 1647 1.1 gdamore return (0); 1648 1.1 gdamore } 1649 1.1 gdamore 1650 1.1 gdamore /* 1651 1.1 gdamore * ae_filter_setup: 1652 1.1 gdamore * 1653 1.1 gdamore * Set the chip's receive filter. 1654 1.1 gdamore */ 1655 1.1 gdamore static void 1656 1.1 gdamore ae_filter_setup(struct ae_softc *sc) 1657 1.1 gdamore { 1658 1.1 gdamore struct ethercom *ec = &sc->sc_ethercom; 1659 1.1 gdamore struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1660 1.1 gdamore struct ether_multi *enm; 1661 1.1 gdamore struct ether_multistep step; 1662 1.1 gdamore uint32_t hash, mchash[2]; 1663 1.1 gdamore uint32_t macctl = 0; 1664 1.1 gdamore 1665 1.1 gdamore /* 1666 1.1 gdamore * If the chip is running, we need to reset the interface, 1667 1.1 gdamore * and will revisit here (with IFF_RUNNING) clear. The 1668 1.1 gdamore * chip seems to really not like to have its multicast 1669 1.1 gdamore * filter programmed without a reset. 1670 1.1 gdamore */ 1671 1.1 gdamore if (ifp->if_flags & IFF_RUNNING) { 1672 1.1 gdamore (void) ae_init(ifp); 1673 1.1 gdamore return; 1674 1.1 gdamore } 1675 1.1 gdamore 1676 1.1 gdamore DPRINTF(sc, ("%s: ae_filter_setup: sc_flags 0x%08x\n", 1677 1.24 chs device_xname(sc->sc_dev), sc->sc_flags)); 1678 1.1 gdamore 1679 1.1 gdamore macctl = AE_READ(sc, CSR_MACCTL); 1680 1.1 gdamore macctl &= ~(MACCTL_PR | MACCTL_PM); 1681 1.1 gdamore macctl |= MACCTL_HASH; 1682 1.1 gdamore macctl |= MACCTL_HBD; 1683 1.1 gdamore macctl |= MACCTL_PR; 1684 1.1 gdamore 1685 1.1 gdamore if (ifp->if_flags & IFF_PROMISC) { 1686 1.1 gdamore macctl |= MACCTL_PR; 1687 1.1 gdamore goto allmulti; 1688 1.1 gdamore } 1689 1.1 gdamore 1690 1.1 gdamore mchash[0] = mchash[1] = 0; 1691 1.1 gdamore 1692 1.36 msaitoh ETHER_LOCK(ec); 1693 1.1 gdamore ETHER_FIRST_MULTI(step, ec, enm); 1694 1.1 gdamore while (enm != NULL) { 1695 1.1 gdamore if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 1696 1.1 gdamore /* 1697 1.1 gdamore * We must listen to a range of multicast addresses. 1698 1.1 gdamore * For now, just accept all multicasts, rather than 1699 1.1 gdamore * trying to set only those filter bits needed to match 1700 1.1 gdamore * the range. (At this time, the only use of address 1701 1.1 gdamore * ranges is for IP multicast routing, for which the 1702 1.1 gdamore * range is big enough to require all bits set.) 1703 1.1 gdamore */ 1704 1.36 msaitoh ETHER_UNLOCK(ec); 1705 1.1 gdamore goto allmulti; 1706 1.1 gdamore } 1707 1.1 gdamore 1708 1.1 gdamore /* Verify whether we use big or little endian hashes */ 1709 1.1 gdamore hash = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3f; 1710 1.1 gdamore mchash[hash >> 5] |= 1 << (hash & 0x1f); 1711 1.1 gdamore ETHER_NEXT_MULTI(step, enm); 1712 1.1 gdamore } 1713 1.36 msaitoh ETHER_UNLOCK(ec); 1714 1.1 gdamore ifp->if_flags &= ~IFF_ALLMULTI; 1715 1.1 gdamore goto setit; 1716 1.1 gdamore 1717 1.1 gdamore allmulti: 1718 1.1 gdamore ifp->if_flags |= IFF_ALLMULTI; 1719 1.1 gdamore mchash[0] = mchash[1] = 0xffffffff; 1720 1.1 gdamore macctl |= MACCTL_PM; 1721 1.1 gdamore 1722 1.1 gdamore setit: 1723 1.1 gdamore AE_WRITE(sc, CSR_HTHI, mchash[0]); 1724 1.1 gdamore AE_WRITE(sc, CSR_HTHI, mchash[1]); 1725 1.1 gdamore 1726 1.1 gdamore AE_WRITE(sc, CSR_MACCTL, macctl); 1727 1.1 gdamore AE_BARRIER(sc); 1728 1.1 gdamore 1729 1.1 gdamore DPRINTF(sc, ("%s: ae_filter_setup: returning %x\n", 1730 1.24 chs device_xname(sc->sc_dev), macctl)); 1731 1.1 gdamore } 1732 1.1 gdamore 1733 1.1 gdamore /* 1734 1.1 gdamore * ae_idle: 1735 1.1 gdamore * 1736 1.1 gdamore * Cause the transmit and/or receive processes to go idle. 1737 1.1 gdamore */ 1738 1.1 gdamore void 1739 1.34 msaitoh ae_idle(struct ae_softc *sc, uint32_t bits) 1740 1.1 gdamore { 1741 1.1 gdamore static const char * const txstate_names[] = { 1742 1.1 gdamore "STOPPED", 1743 1.1 gdamore "RUNNING - FETCH", 1744 1.1 gdamore "RUNNING - WAIT", 1745 1.1 gdamore "RUNNING - READING", 1746 1.1 gdamore "-- RESERVED --", 1747 1.1 gdamore "RUNNING - SETUP", 1748 1.1 gdamore "SUSPENDED", 1749 1.1 gdamore "RUNNING - CLOSE", 1750 1.1 gdamore }; 1751 1.1 gdamore static const char * const rxstate_names[] = { 1752 1.1 gdamore "STOPPED", 1753 1.1 gdamore "RUNNING - FETCH", 1754 1.1 gdamore "RUNNING - CHECK", 1755 1.1 gdamore "RUNNING - WAIT", 1756 1.1 gdamore "SUSPENDED", 1757 1.1 gdamore "RUNNING - CLOSE", 1758 1.1 gdamore "RUNNING - FLUSH", 1759 1.1 gdamore "RUNNING - QUEUE", 1760 1.1 gdamore }; 1761 1.1 gdamore 1762 1.34 msaitoh uint32_t csr, ackmask = 0; 1763 1.1 gdamore int i; 1764 1.1 gdamore 1765 1.1 gdamore if (bits & OPMODE_ST) 1766 1.1 gdamore ackmask |= STATUS_TPS; 1767 1.1 gdamore 1768 1.1 gdamore if (bits & OPMODE_SR) 1769 1.1 gdamore ackmask |= STATUS_RPS; 1770 1.1 gdamore 1771 1.1 gdamore AE_CLR(sc, CSR_OPMODE, bits); 1772 1.1 gdamore 1773 1.1 gdamore for (i = 0; i < 1000; i++) { 1774 1.1 gdamore if (AE_ISSET(sc, CSR_STATUS, ackmask) == ackmask) 1775 1.1 gdamore break; 1776 1.1 gdamore delay(10); 1777 1.1 gdamore } 1778 1.1 gdamore 1779 1.1 gdamore csr = AE_READ(sc, CSR_STATUS); 1780 1.1 gdamore if ((csr & ackmask) != ackmask) { 1781 1.1 gdamore if ((bits & OPMODE_ST) != 0 && (csr & STATUS_TPS) == 0 && 1782 1.1 gdamore (csr & STATUS_TS) != STATUS_TS_STOPPED) { 1783 1.1 gdamore printf("%s: transmit process failed to idle: " 1784 1.24 chs "state %s\n", device_xname(sc->sc_dev), 1785 1.1 gdamore txstate_names[(csr & STATUS_TS) >> 20]); 1786 1.1 gdamore } 1787 1.1 gdamore if ((bits & OPMODE_SR) != 0 && (csr & STATUS_RPS) == 0 && 1788 1.1 gdamore (csr & STATUS_RS) != STATUS_RS_STOPPED) { 1789 1.1 gdamore printf("%s: receive process failed to idle: " 1790 1.24 chs "state %s\n", device_xname(sc->sc_dev), 1791 1.1 gdamore rxstate_names[(csr & STATUS_RS) >> 17]); 1792 1.1 gdamore } 1793 1.1 gdamore } 1794 1.1 gdamore } 1795 1.1 gdamore 1796 1.1 gdamore /***************************************************************************** 1797 1.1 gdamore * Support functions for MII-attached media. 1798 1.1 gdamore *****************************************************************************/ 1799 1.1 gdamore 1800 1.1 gdamore /* 1801 1.1 gdamore * ae_mii_tick: 1802 1.1 gdamore * 1803 1.1 gdamore * One second timer, used to tick the MII. 1804 1.1 gdamore */ 1805 1.1 gdamore static void 1806 1.1 gdamore ae_mii_tick(void *arg) 1807 1.1 gdamore { 1808 1.1 gdamore struct ae_softc *sc = arg; 1809 1.1 gdamore int s; 1810 1.1 gdamore 1811 1.24 chs if (!device_is_active(sc->sc_dev)) 1812 1.1 gdamore return; 1813 1.1 gdamore 1814 1.1 gdamore s = splnet(); 1815 1.1 gdamore mii_tick(&sc->sc_mii); 1816 1.1 gdamore splx(s); 1817 1.1 gdamore 1818 1.1 gdamore callout_reset(&sc->sc_tick_callout, hz, sc->sc_tick, sc); 1819 1.1 gdamore } 1820 1.1 gdamore 1821 1.1 gdamore /* 1822 1.1 gdamore * ae_mii_statchg: [mii interface function] 1823 1.1 gdamore * 1824 1.1 gdamore * Callback from PHY when media changes. 1825 1.1 gdamore */ 1826 1.1 gdamore static void 1827 1.23 matt ae_mii_statchg(struct ifnet *ifp) 1828 1.1 gdamore { 1829 1.23 matt struct ae_softc *sc = ifp->if_softc; 1830 1.1 gdamore uint32_t macctl, flowc; 1831 1.1 gdamore 1832 1.1 gdamore //opmode = AE_READ(sc, CSR_OPMODE); 1833 1.1 gdamore macctl = AE_READ(sc, CSR_MACCTL); 1834 1.1 gdamore 1835 1.1 gdamore /* XXX: do we need to do this? */ 1836 1.1 gdamore /* Idle the transmit and receive processes. */ 1837 1.34 msaitoh //ae_idle(sc, OPMODE_ST | OPMODE_SR); 1838 1.1 gdamore 1839 1.1 gdamore if (sc->sc_mii.mii_media_active & IFM_FDX) { 1840 1.1 gdamore flowc = FLOWC_FCE; 1841 1.1 gdamore macctl &= ~MACCTL_DRO; 1842 1.1 gdamore macctl |= MACCTL_FDX; 1843 1.1 gdamore } else { 1844 1.1 gdamore flowc = 0; /* cannot do flow control in HDX */ 1845 1.1 gdamore macctl |= MACCTL_DRO; 1846 1.1 gdamore macctl &= ~MACCTL_FDX; 1847 1.1 gdamore } 1848 1.1 gdamore 1849 1.1 gdamore AE_WRITE(sc, CSR_FLOWC, flowc); 1850 1.1 gdamore AE_WRITE(sc, CSR_MACCTL, macctl); 1851 1.1 gdamore 1852 1.1 gdamore /* restore operational mode */ 1853 1.1 gdamore //AE_WRITE(sc, CSR_OPMODE, opmode); 1854 1.1 gdamore AE_BARRIER(sc); 1855 1.1 gdamore } 1856 1.1 gdamore 1857 1.1 gdamore /* 1858 1.1 gdamore * ae_mii_readreg: 1859 1.1 gdamore * 1860 1.1 gdamore * Read a PHY register. 1861 1.1 gdamore */ 1862 1.1 gdamore static int 1863 1.32 msaitoh ae_mii_readreg(device_t self, int phy, int reg, uint16_t *val) 1864 1.1 gdamore { 1865 1.12 dyoung struct ae_softc *sc = device_private(self); 1866 1.1 gdamore uint32_t addr; 1867 1.1 gdamore int i; 1868 1.1 gdamore 1869 1.1 gdamore addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT); 1870 1.1 gdamore AE_WRITE(sc, CSR_MIIADDR, addr); 1871 1.1 gdamore AE_BARRIER(sc); 1872 1.1 gdamore for (i = 0; i < 100000000; i++) { 1873 1.1 gdamore if ((AE_READ(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0) 1874 1.1 gdamore break; 1875 1.1 gdamore } 1876 1.1 gdamore 1877 1.32 msaitoh if (i >= 100000000) 1878 1.32 msaitoh return ETIMEDOUT; 1879 1.32 msaitoh 1880 1.32 msaitoh *val = AE_READ(sc, CSR_MIIDATA) & 0xffff; 1881 1.32 msaitoh return 0; 1882 1.1 gdamore } 1883 1.1 gdamore 1884 1.1 gdamore /* 1885 1.1 gdamore * ae_mii_writereg: 1886 1.1 gdamore * 1887 1.1 gdamore * Write a PHY register. 1888 1.1 gdamore */ 1889 1.32 msaitoh static int 1890 1.32 msaitoh ae_mii_writereg(device_t self, int phy, int reg, uint16_t val) 1891 1.1 gdamore { 1892 1.12 dyoung struct ae_softc *sc = device_private(self); 1893 1.1 gdamore uint32_t addr; 1894 1.1 gdamore int i; 1895 1.1 gdamore 1896 1.1 gdamore /* write the data register */ 1897 1.1 gdamore AE_WRITE(sc, CSR_MIIDATA, val); 1898 1.1 gdamore 1899 1.1 gdamore /* write the address to latch it in */ 1900 1.1 gdamore addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT) | 1901 1.1 gdamore MIIADDR_WRITE; 1902 1.1 gdamore AE_WRITE(sc, CSR_MIIADDR, addr); 1903 1.1 gdamore AE_BARRIER(sc); 1904 1.1 gdamore 1905 1.1 gdamore for (i = 0; i < 100000000; i++) { 1906 1.1 gdamore if ((AE_READ(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0) 1907 1.1 gdamore break; 1908 1.1 gdamore } 1909 1.32 msaitoh 1910 1.32 msaitoh if (i >= 100000000) 1911 1.32 msaitoh return ETIMEDOUT; 1912 1.32 msaitoh 1913 1.32 msaitoh return 0; 1914 1.1 gdamore } 1915