1 1.36 rin /* $NetBSD: at91emac.c,v 1.36 2024/07/05 04:31:49 rin Exp $ */ 2 1.2 matt 3 1.2 matt /* 4 1.2 matt * Copyright (c) 2007 Embedtronics Oy 5 1.2 matt * All rights reserved. 6 1.2 matt * 7 1.2 matt * Based on arch/arm/ep93xx/epe.c 8 1.2 matt * 9 1.2 matt * Copyright (c) 2004 Jesse Off 10 1.2 matt * All rights reserved. 11 1.2 matt * 12 1.2 matt * Redistribution and use in source and binary forms, with or without 13 1.2 matt * modification, are permitted provided that the following conditions 14 1.2 matt * are met: 15 1.2 matt * 1. Redistributions of source code must retain the above copyright 16 1.2 matt * notice, this list of conditions and the following disclaimer. 17 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright 18 1.2 matt * notice, this list of conditions and the following disclaimer in the 19 1.2 matt * documentation and/or other materials provided with the distribution. 20 1.2 matt * 21 1.2 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 1.2 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 1.2 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 1.2 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 1.2 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 1.2 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 1.2 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 1.2 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 1.2 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 1.2 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 1.2 matt * POSSIBILITY OF SUCH DAMAGE. 32 1.2 matt */ 33 1.2 matt 34 1.2 matt #include <sys/cdefs.h> 35 1.36 rin __KERNEL_RCSID(0, "$NetBSD: at91emac.c,v 1.36 2024/07/05 04:31:49 rin Exp $"); 36 1.2 matt 37 1.2 matt #include <sys/types.h> 38 1.2 matt #include <sys/param.h> 39 1.2 matt #include <sys/systm.h> 40 1.2 matt #include <sys/ioctl.h> 41 1.2 matt #include <sys/kernel.h> 42 1.2 matt #include <sys/proc.h> 43 1.2 matt #include <sys/time.h> 44 1.2 matt #include <sys/device.h> 45 1.2 matt #include <uvm/uvm_extern.h> 46 1.2 matt 47 1.10 dyoung #include <sys/bus.h> 48 1.2 matt #include <machine/intr.h> 49 1.2 matt 50 1.2 matt #include <arm/cpufunc.h> 51 1.2 matt 52 1.2 matt #include <net/if.h> 53 1.2 matt #include <net/if_dl.h> 54 1.2 matt #include <net/if_types.h> 55 1.2 matt #include <net/if_media.h> 56 1.2 matt #include <net/if_ether.h> 57 1.20 msaitoh #include <net/bpf.h> 58 1.2 matt 59 1.2 matt #include <dev/mii/mii.h> 60 1.2 matt #include <dev/mii/miivar.h> 61 1.2 matt 62 1.2 matt #ifdef INET 63 1.2 matt #include <netinet/in.h> 64 1.2 matt #include <netinet/in_systm.h> 65 1.2 matt #include <netinet/in_var.h> 66 1.2 matt #include <netinet/ip.h> 67 1.2 matt #include <netinet/if_inarp.h> 68 1.2 matt #endif 69 1.2 matt 70 1.2 matt #include <arm/at91/at91var.h> 71 1.2 matt #include <arm/at91/at91emacreg.h> 72 1.2 matt #include <arm/at91/at91emacvar.h> 73 1.2 matt 74 1.2 matt #define DEFAULT_MDCDIV 32 75 1.2 matt 76 1.2 matt #ifndef EMAC_FAST 77 1.2 matt #define EMAC_FAST 78 1.2 matt #endif 79 1.2 matt 80 1.2 matt #ifndef EMAC_FAST 81 1.2 matt #define EMAC_READ(x) \ 82 1.2 matt bus_space_read_4(sc->sc_iot, sc->sc_ioh, (EPE_ ## x)) 83 1.2 matt #define EMAC_WRITE(x, y) \ 84 1.2 matt bus_space_write_4(sc->sc_iot, sc->sc_ioh, (EPE_ ## x), (y)) 85 1.2 matt #else 86 1.2 matt #define EMAC_READ(x) ETHREG(x) 87 1.2 matt #define EMAC_WRITE(x, y) ETHREG(x) = (y) 88 1.2 matt #endif /* ! EMAC_FAST */ 89 1.2 matt 90 1.2 matt static int emac_match(device_t, cfdata_t, void *); 91 1.2 matt static void emac_attach(device_t, device_t, void *); 92 1.2 matt static void emac_init(struct emac_softc *); 93 1.27 msaitoh static int emac_intr(void* arg); 94 1.2 matt static int emac_gctx(struct emac_softc *); 95 1.23 msaitoh int emac_mii_readreg (device_t, int, int, uint16_t *); 96 1.23 msaitoh int emac_mii_writereg (device_t, int, int, uint16_t); 97 1.11 matt void emac_statchg (struct ifnet *); 98 1.2 matt void emac_tick (void *); 99 1.2 matt static int emac_ifioctl (struct ifnet *, u_long, void *); 100 1.2 matt static void emac_ifstart (struct ifnet *); 101 1.2 matt static void emac_ifwatchdog (struct ifnet *); 102 1.2 matt static int emac_ifinit (struct ifnet *); 103 1.2 matt static void emac_ifstop (struct ifnet *, int); 104 1.2 matt static void emac_setaddr (struct ifnet *); 105 1.2 matt 106 1.11 matt CFATTACH_DECL_NEW(at91emac, sizeof(struct emac_softc), 107 1.2 matt emac_match, emac_attach, NULL, NULL); 108 1.2 matt 109 1.2 matt #ifdef EMAC_DEBUG 110 1.2 matt int emac_debug = EMAC_DEBUG; 111 1.26 msaitoh #define DPRINTFN(n, fmt) if (emac_debug >= (n)) printf fmt 112 1.2 matt #else 113 1.26 msaitoh #define DPRINTFN(n, fmt) 114 1.2 matt #endif 115 1.2 matt 116 1.2 matt static int 117 1.2 matt emac_match(device_t parent, cfdata_t match, void *aux) 118 1.2 matt { 119 1.2 matt if (strcmp(match->cf_name, "at91emac") == 0) 120 1.2 matt return 2; 121 1.2 matt return 0; 122 1.2 matt } 123 1.2 matt 124 1.2 matt static void 125 1.2 matt emac_attach(device_t parent, device_t self, void *aux) 126 1.2 matt { 127 1.2 matt struct emac_softc *sc = device_private(self); 128 1.2 matt struct at91bus_attach_args *sa = aux; 129 1.2 matt prop_data_t enaddr; 130 1.2 matt uint32_t u; 131 1.2 matt 132 1.2 matt printf("\n"); 133 1.2 matt sc->sc_dev = self; 134 1.2 matt sc->sc_iot = sa->sa_iot; 135 1.2 matt sc->sc_pid = sa->sa_pid; 136 1.2 matt sc->sc_dmat = sa->sa_dmat; 137 1.2 matt 138 1.2 matt if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) 139 1.2 matt panic("%s: Cannot map registers", device_xname(self)); 140 1.2 matt 141 1.2 matt /* enable peripheral clock */ 142 1.2 matt at91_peripheral_clock(sc->sc_pid, 1); 143 1.2 matt 144 1.2 matt /* configure emac: */ 145 1.2 matt EMAC_WRITE(ETH_CTL, 0); // disable everything 146 1.2 matt EMAC_WRITE(ETH_IDR, -1); // disable interrupts 147 1.2 matt EMAC_WRITE(ETH_RBQP, 0); // clear receive 148 1.26 msaitoh EMAC_WRITE(ETH_CFG, 149 1.26 msaitoh ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); 150 1.2 matt EMAC_WRITE(ETH_TCR, 0); // send nothing 151 1.2 matt //(void)EMAC_READ(ETH_ISR); 152 1.2 matt u = EMAC_READ(ETH_TSR); 153 1.2 matt EMAC_WRITE(ETH_TSR, (u & (ETH_TSR_UND | ETH_TSR_COMP | ETH_TSR_BNQ 154 1.2 matt | ETH_TSR_IDLE | ETH_TSR_RLE 155 1.26 msaitoh | ETH_TSR_COL | ETH_TSR_OVR))); 156 1.2 matt u = EMAC_READ(ETH_RSR); 157 1.26 msaitoh EMAC_WRITE(ETH_RSR, (u & (ETH_RSR_OVR | ETH_RSR_REC | ETH_RSR_BNA))); 158 1.2 matt 159 1.2 matt /* Fetch the Ethernet address from property if set. */ 160 1.8 martin enaddr = prop_dictionary_get(device_properties(self), "mac-address"); 161 1.2 matt 162 1.2 matt if (enaddr != NULL) { 163 1.2 matt KASSERT(prop_object_type(enaddr) == PROP_TYPE_DATA); 164 1.2 matt KASSERT(prop_data_size(enaddr) == ETHER_ADDR_LEN); 165 1.2 matt memcpy(sc->sc_enaddr, prop_data_data_nocopy(enaddr), 166 1.2 matt ETHER_ADDR_LEN); 167 1.2 matt } else { 168 1.2 matt static const uint8_t hardcoded[ETHER_ADDR_LEN] = { 169 1.2 matt 0x00, 0x0d, 0x10, 0x81, 0x0c, 0x94 170 1.2 matt }; 171 1.2 matt memcpy(sc->sc_enaddr, hardcoded, ETHER_ADDR_LEN); 172 1.2 matt } 173 1.2 matt 174 1.26 msaitoh at91_intr_establish(sc->sc_pid, IPL_NET, INTR_HIGH_LEVEL, emac_intr, 175 1.26 msaitoh sc); 176 1.2 matt emac_init(sc); 177 1.2 matt } 178 1.2 matt 179 1.2 matt static int 180 1.2 matt emac_gctx(struct emac_softc *sc) 181 1.2 matt { 182 1.13 skrll uint32_t tsr; 183 1.2 matt 184 1.2 matt tsr = EMAC_READ(ETH_TSR); 185 1.2 matt if (!(tsr & ETH_TSR_BNQ)) { 186 1.2 matt // no space left 187 1.2 matt return 0; 188 1.2 matt } 189 1.2 matt 190 1.2 matt // free sent frames 191 1.2 matt while (sc->txqc > (tsr & ETH_TSR_IDLE ? 0 : 1)) { 192 1.2 matt int i = sc->txqi % TX_QLEN; 193 1.2 matt bus_dmamap_sync(sc->sc_dmat, sc->txq[i].m_dmamap, 0, 194 1.26 msaitoh sc->txq[i].m->m_pkthdr.len, BUS_DMASYNC_POSTWRITE); 195 1.2 matt bus_dmamap_unload(sc->sc_dmat, sc->txq[i].m_dmamap); 196 1.2 matt m_freem(sc->txq[i].m); 197 1.26 msaitoh DPRINTFN(2,("%s: freed idx #%i mbuf %p (txqc=%i)\n", 198 1.26 msaitoh __FUNCTION__, i, sc->txq[i].m, sc->txqc)); 199 1.2 matt sc->txq[i].m = NULL; 200 1.2 matt sc->txqi = (i + 1) % TX_QLEN; 201 1.2 matt sc->txqc--; 202 1.2 matt } 203 1.2 matt 204 1.2 matt // mark we're free 205 1.34 thorpej if (sc->tx_busy) { 206 1.34 thorpej sc->tx_busy = false; 207 1.2 matt /* Disable transmit-buffer-free interrupt */ 208 1.2 matt /*EMAC_WRITE(ETH_IDR, ETH_ISR_TBRE);*/ 209 1.2 matt } 210 1.2 matt 211 1.2 matt return 1; 212 1.2 matt } 213 1.2 matt 214 1.2 matt static int 215 1.2 matt emac_intr(void *arg) 216 1.2 matt { 217 1.2 matt struct emac_softc *sc = (struct emac_softc *)arg; 218 1.2 matt struct ifnet * ifp = &sc->sc_ec.ec_if; 219 1.15 skrll uint32_t imr, isr, ctl; 220 1.2 matt int bi; 221 1.2 matt 222 1.2 matt imr = ~EMAC_READ(ETH_IMR); 223 1.26 msaitoh if (!(imr & (ETH_ISR_RCOM | ETH_ISR_TBRE | ETH_ISR_TIDLE 224 1.26 msaitoh | ETH_ISR_RBNA | ETH_ISR_ROVR))) { 225 1.2 matt // interrupt not enabled, can't be us 226 1.2 matt return 0; 227 1.2 matt } 228 1.2 matt 229 1.2 matt isr = EMAC_READ(ETH_ISR) & imr; 230 1.26 msaitoh #ifdef EMAC_DEBUG 231 1.26 msaitoh uint32_t rsr = 232 1.15 skrll #endif 233 1.15 skrll EMAC_READ(ETH_RSR); // get receive status register 234 1.2 matt 235 1.26 msaitoh DPRINTFN(2, ("%s: isr=0x%08X rsr=0x%08X imr=0x%08X\n", __FUNCTION__, 236 1.26 msaitoh isr, rsr, imr)); 237 1.2 matt 238 1.2 matt if (isr & ETH_ISR_RBNA) { // out of receive buffers 239 1.2 matt EMAC_WRITE(ETH_RSR, ETH_RSR_BNA); // clear interrupt 240 1.2 matt ctl = EMAC_READ(ETH_CTL); // get current control register value 241 1.2 matt EMAC_WRITE(ETH_CTL, ctl & ~ETH_CTL_RE); // disable receiver 242 1.2 matt EMAC_WRITE(ETH_RSR, ETH_RSR_BNA); // clear BNA bit 243 1.2 matt EMAC_WRITE(ETH_CTL, ctl | ETH_CTL_RE); // re-enable receiver 244 1.30 skrll if_statinc(ifp, if_ierrors); 245 1.31 skrll if_statinc(ifp, if_ipackets); 246 1.2 matt DPRINTFN(1,("%s: out of receive buffers\n", __FUNCTION__)); 247 1.2 matt } 248 1.2 matt if (isr & ETH_ISR_ROVR) { 249 1.2 matt EMAC_WRITE(ETH_RSR, ETH_RSR_OVR); // clear interrupt 250 1.30 skrll if_statinc(ifp, if_ierrors); 251 1.31 skrll if_statinc(ifp, if_ipackets); 252 1.2 matt DPRINTFN(1,("%s: receive overrun\n", __FUNCTION__)); 253 1.2 matt } 254 1.26 msaitoh 255 1.2 matt if (isr & ETH_ISR_RCOM) { // packet has been received! 256 1.2 matt uint32_t nfo; 257 1.2 matt // @@@ if memory is NOT coherent, then we're in trouble @@@@ 258 1.2 matt // bus_dmamap_sync(sc->sc_dmat, sc->rbqpage_dmamap, 0, sc->rbqlen, BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 259 1.2 matt // printf("## RDSC[%i].ADDR=0x%08X\n", sc->rxqi % RX_QLEN, sc->RDSC[sc->rxqi % RX_QLEN].Addr); 260 1.26 msaitoh DPRINTFN(2,("#2 RDSC[%i].INFO=0x%08X\n", sc->rxqi % RX_QLEN, 261 1.26 msaitoh sc->RDSC[sc->rxqi % RX_QLEN].Info)); 262 1.2 matt while (sc->RDSC[(bi = sc->rxqi % RX_QLEN)].Addr & ETH_RDSC_F_USED) { 263 1.2 matt int fl; 264 1.2 matt struct mbuf *m; 265 1.2 matt 266 1.2 matt nfo = sc->RDSC[bi].Info; 267 1.27 msaitoh fl = (nfo & ETH_RDSC_I_LEN) - 4; 268 1.2 matt DPRINTFN(2,("## nfo=0x%08X\n", nfo)); 269 1.2 matt 270 1.2 matt MGETHDR(m, M_DONTWAIT, MT_DATA); 271 1.2 matt if (m != NULL) MCLGET(m, M_DONTWAIT); 272 1.2 matt if (m != NULL && (m->m_flags & M_EXT)) { 273 1.26 msaitoh bus_dmamap_sync(sc->sc_dmat, 274 1.26 msaitoh sc->rxq[bi].m_dmamap, 0, 275 1.26 msaitoh MCLBYTES, BUS_DMASYNC_POSTREAD); 276 1.26 msaitoh bus_dmamap_unload(sc->sc_dmat, 277 1.2 matt sc->rxq[bi].m_dmamap); 278 1.17 ozaki m_set_rcvif(sc->rxq[bi].m, ifp); 279 1.26 msaitoh sc->rxq[bi].m->m_pkthdr.len = 280 1.2 matt sc->rxq[bi].m->m_len = fl; 281 1.2 matt DPRINTFN(2,("received %u bytes packet\n", fl)); 282 1.16 ozaki if_percpuq_enqueue(ifp->if_percpuq, sc->rxq[bi].m); 283 1.2 matt if (mtod(m, intptr_t) & 3) { 284 1.2 matt m_adj(m, mtod(m, intptr_t) & 3); 285 1.2 matt } 286 1.2 matt sc->rxq[bi].m = m; 287 1.26 msaitoh bus_dmamap_load(sc->sc_dmat, 288 1.26 msaitoh sc->rxq[bi].m_dmamap, 289 1.2 matt m->m_ext.ext_buf, MCLBYTES, 290 1.2 matt NULL, BUS_DMA_NOWAIT); 291 1.26 msaitoh bus_dmamap_sync(sc->sc_dmat, 292 1.26 msaitoh sc->rxq[bi].m_dmamap, 0, 293 1.26 msaitoh MCLBYTES, BUS_DMASYNC_PREREAD); 294 1.2 matt sc->RDSC[bi].Info = 0; 295 1.2 matt sc->RDSC[bi].Addr = 296 1.2 matt sc->rxq[bi].m_dmamap->dm_segs[0].ds_addr 297 1.2 matt | (bi == (RX_QLEN-1) ? ETH_RDSC_F_WRAP : 0); 298 1.2 matt } else { 299 1.2 matt /* Drop packets until we can get replacement 300 1.2 matt * empty mbufs for the RXDQ. 301 1.2 matt */ 302 1.36 rin m_freem(m); 303 1.30 skrll if_statinc(ifp, if_ierrors); 304 1.26 msaitoh } 305 1.2 matt sc->rxqi++; 306 1.2 matt } 307 1.2 matt // bus_dmamap_sync(sc->sc_dmat, sc->rbqpage_dmamap, 0, sc->rbqlen, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 308 1.2 matt } 309 1.2 matt 310 1.19 ozaki if (emac_gctx(sc) > 0) 311 1.19 ozaki if_schedule_deferred_start(ifp); 312 1.2 matt #if 0 // reloop 313 1.2 matt irq = EMAC_READ(IntStsC); 314 1.26 msaitoh if ((irq & (IntSts_RxSQ | IntSts_ECI)) != 0) 315 1.2 matt goto begin; 316 1.2 matt #endif 317 1.2 matt 318 1.2 matt return (1); 319 1.2 matt } 320 1.2 matt 321 1.2 matt 322 1.2 matt static void 323 1.2 matt emac_init(struct emac_softc *sc) 324 1.2 matt { 325 1.2 matt bus_dma_segment_t segs; 326 1.2 matt void *addr; 327 1.2 matt int rsegs, err, i; 328 1.2 matt struct ifnet * ifp = &sc->sc_ec.ec_if; 329 1.26 msaitoh struct mii_data * const mii = &sc->sc_mii; 330 1.2 matt uint32_t u; 331 1.2 matt #if 0 332 1.2 matt int mdcdiv = DEFAULT_MDCDIV; 333 1.2 matt #endif 334 1.2 matt 335 1.2 matt callout_init(&sc->emac_tick_ch, 0); 336 1.2 matt 337 1.2 matt // ok... 338 1.2 matt EMAC_WRITE(ETH_CTL, ETH_CTL_MPE); // disable everything 339 1.2 matt EMAC_WRITE(ETH_IDR, -1); // disable interrupts 340 1.2 matt EMAC_WRITE(ETH_RBQP, 0); // clear receive 341 1.26 msaitoh EMAC_WRITE(ETH_CFG, 342 1.26 msaitoh ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); 343 1.2 matt EMAC_WRITE(ETH_TCR, 0); // send nothing 344 1.2 matt // (void)EMAC_READ(ETH_ISR); 345 1.2 matt u = EMAC_READ(ETH_TSR); 346 1.2 matt EMAC_WRITE(ETH_TSR, (u & (ETH_TSR_UND | ETH_TSR_COMP | ETH_TSR_BNQ 347 1.2 matt | ETH_TSR_IDLE | ETH_TSR_RLE 348 1.26 msaitoh | ETH_TSR_COL | ETH_TSR_OVR))); 349 1.2 matt u = EMAC_READ(ETH_RSR); 350 1.26 msaitoh EMAC_WRITE(ETH_RSR, (u & (ETH_RSR_OVR | ETH_RSR_REC | ETH_RSR_BNA))); 351 1.2 matt 352 1.2 matt /* configure EMAC */ 353 1.26 msaitoh EMAC_WRITE(ETH_CFG, 354 1.26 msaitoh ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); 355 1.2 matt EMAC_WRITE(ETH_CTL, ETH_CTL_MPE); 356 1.2 matt #if 0 357 1.12 chs if (device_cfdata(sc->sc_dev)->cf_flags) 358 1.12 chs mdcdiv = device_cfdata(sc->sc_dev)->cf_flags; 359 1.2 matt #endif 360 1.2 matt /* set ethernet address */ 361 1.2 matt EMAC_WRITE(ETH_SA1L, (sc->sc_enaddr[3] << 24) 362 1.2 matt | (sc->sc_enaddr[2] << 16) | (sc->sc_enaddr[1] << 8) 363 1.2 matt | (sc->sc_enaddr[0])); 364 1.2 matt EMAC_WRITE(ETH_SA1H, (sc->sc_enaddr[5] << 8) 365 1.2 matt | (sc->sc_enaddr[4])); 366 1.2 matt EMAC_WRITE(ETH_SA2L, 0); 367 1.2 matt EMAC_WRITE(ETH_SA2H, 0); 368 1.2 matt EMAC_WRITE(ETH_SA3L, 0); 369 1.2 matt EMAC_WRITE(ETH_SA3H, 0); 370 1.2 matt EMAC_WRITE(ETH_SA4L, 0); 371 1.2 matt EMAC_WRITE(ETH_SA4H, 0); 372 1.2 matt 373 1.2 matt /* Allocate a page of memory for receive queue descriptors */ 374 1.2 matt sc->rbqlen = (ETH_RDSC_SIZE * (RX_QLEN + 1) * 2 + PAGE_SIZE - 1) / PAGE_SIZE; 375 1.2 matt sc->rbqlen *= PAGE_SIZE; 376 1.2 matt DPRINTFN(1,("%s: rbqlen=%i\n", __FUNCTION__, sc->rbqlen)); 377 1.2 matt 378 1.2 matt err = bus_dmamem_alloc(sc->sc_dmat, sc->rbqlen, 0, 379 1.2 matt MAX(16384, PAGE_SIZE), // see EMAC errata why forced to 16384 byte boundary 380 1.2 matt &segs, 1, &rsegs, BUS_DMA_WAITOK); 381 1.2 matt if (err == 0) { 382 1.2 matt DPRINTFN(1,("%s: -> bus_dmamem_map\n", __FUNCTION__)); 383 1.2 matt err = bus_dmamem_map(sc->sc_dmat, &segs, 1, sc->rbqlen, 384 1.26 msaitoh &sc->rbqpage, (BUS_DMA_WAITOK | BUS_DMA_COHERENT)); 385 1.2 matt } 386 1.2 matt if (err == 0) { 387 1.2 matt DPRINTFN(1,("%s: -> bus_dmamap_create\n", __FUNCTION__)); 388 1.2 matt err = bus_dmamap_create(sc->sc_dmat, sc->rbqlen, 1, 389 1.2 matt sc->rbqlen, MAX(16384, PAGE_SIZE), BUS_DMA_WAITOK, 390 1.2 matt &sc->rbqpage_dmamap); 391 1.2 matt } 392 1.2 matt if (err == 0) { 393 1.2 matt DPRINTFN(1,("%s: -> bus_dmamap_load\n", __FUNCTION__)); 394 1.2 matt err = bus_dmamap_load(sc->sc_dmat, sc->rbqpage_dmamap, 395 1.2 matt sc->rbqpage, sc->rbqlen, NULL, BUS_DMA_WAITOK); 396 1.2 matt } 397 1.2 matt if (err != 0) { 398 1.2 matt panic("%s: Cannot get DMA memory", device_xname(sc->sc_dev)); 399 1.2 matt } 400 1.2 matt sc->rbqpage_dsaddr = sc->rbqpage_dmamap->dm_segs[0].ds_addr; 401 1.2 matt 402 1.5 cegger memset(sc->rbqpage, 0, sc->rbqlen); 403 1.2 matt 404 1.2 matt /* Set up pointers to start of each queue in kernel addr space. 405 1.2 matt * Each descriptor queue or status queue entry uses 2 words 406 1.2 matt */ 407 1.2 matt sc->RDSC = (void*)sc->rbqpage; 408 1.2 matt 409 1.2 matt /* Populate the RXQ with mbufs */ 410 1.2 matt sc->rxqi = 0; 411 1.26 msaitoh for (i = 0; i < RX_QLEN; i++) { 412 1.2 matt struct mbuf *m; 413 1.2 matt 414 1.26 msaitoh err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 415 1.26 msaitoh PAGE_SIZE, BUS_DMA_WAITOK, &sc->rxq[i].m_dmamap); 416 1.26 msaitoh if (err) 417 1.26 msaitoh panic("%s: dmamap_create failed: %i\n", 418 1.26 msaitoh __FUNCTION__, err); 419 1.26 msaitoh 420 1.2 matt MGETHDR(m, M_WAIT, MT_DATA); 421 1.2 matt MCLGET(m, M_WAIT); 422 1.2 matt sc->rxq[i].m = m; 423 1.2 matt if (mtod(m, intptr_t) & 3) { 424 1.2 matt m_adj(m, mtod(m, intptr_t) & 3); 425 1.2 matt } 426 1.26 msaitoh err = bus_dmamap_load(sc->sc_dmat, sc->rxq[i].m_dmamap, 427 1.26 msaitoh m->m_ext.ext_buf, MCLBYTES, NULL, 428 1.2 matt BUS_DMA_WAITOK); 429 1.26 msaitoh if (err) 430 1.26 msaitoh panic("%s: dmamap_load failed: %i\n", 431 1.26 msaitoh __FUNCTION__, err); 432 1.26 msaitoh 433 1.2 matt sc->RDSC[i].Addr = sc->rxq[i].m_dmamap->dm_segs[0].ds_addr 434 1.2 matt | (i == (RX_QLEN-1) ? ETH_RDSC_F_WRAP : 0); 435 1.2 matt sc->RDSC[i].Info = 0; 436 1.2 matt bus_dmamap_sync(sc->sc_dmat, sc->rxq[i].m_dmamap, 0, 437 1.2 matt MCLBYTES, BUS_DMASYNC_PREREAD); 438 1.2 matt } 439 1.2 matt 440 1.2 matt /* prepare transmit queue */ 441 1.2 matt for (i = 0; i < TX_QLEN; i++) { 442 1.2 matt err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 443 1.2 matt (BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW), 444 1.2 matt &sc->txq[i].m_dmamap); 445 1.2 matt if (err) 446 1.2 matt panic("ARGH #1"); 447 1.2 matt sc->txq[i].m = NULL; 448 1.2 matt } 449 1.2 matt 450 1.2 matt /* Program each queue's start addr, cur addr, and len registers 451 1.26 msaitoh * with the physical addresses. 452 1.2 matt */ 453 1.2 matt bus_dmamap_sync(sc->sc_dmat, sc->rbqpage_dmamap, 0, sc->rbqlen, 454 1.2 matt BUS_DMASYNC_PREREAD); 455 1.2 matt addr = (void *)sc->rbqpage_dmamap->dm_segs[0].ds_addr; 456 1.13 skrll EMAC_WRITE(ETH_RBQP, (uint32_t)addr); 457 1.2 matt 458 1.2 matt /* Divide HCLK by 32 for MDC clock */ 459 1.26 msaitoh mii->mii_ifp = ifp; 460 1.26 msaitoh mii->mii_readreg = emac_mii_readreg; 461 1.26 msaitoh mii->mii_writereg = emac_mii_writereg; 462 1.26 msaitoh mii->mii_statchg = emac_statchg; 463 1.26 msaitoh sc->sc_ec.ec_mii = mii; 464 1.32 thorpej ifmedia_init(&mii->mii_media, IFM_IMASK, ether_mediachange, 465 1.32 thorpej ether_mediastatus); 466 1.26 msaitoh mii_attach((device_t )sc, mii, 0xffffffff, MII_PHY_ANY, 467 1.2 matt MII_OFFSET_ANY, 0); 468 1.26 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 469 1.2 matt 470 1.2 matt // enable / disable interrupts 471 1.2 matt 472 1.2 matt #if 0 473 1.2 matt // enable / disable interrupts 474 1.2 matt EMAC_WRITE(ETH_IDR, -1); 475 1.2 matt EMAC_WRITE(ETH_IER, ETH_ISR_RCOM | ETH_ISR_TBRE | ETH_ISR_TIDLE 476 1.2 matt | ETH_ISR_RBNA | ETH_ISR_ROVR); 477 1.2 matt // (void)EMAC_READ(ETH_ISR); // why 478 1.2 matt 479 1.2 matt // enable transmitter / receiver 480 1.2 matt EMAC_WRITE(ETH_CTL, ETH_CTL_TE | ETH_CTL_RE | ETH_CTL_ISR 481 1.2 matt | ETH_CTL_CSR | ETH_CTL_MPE); 482 1.2 matt #endif 483 1.2 matt /* 484 1.2 matt * We can support 802.1Q VLAN-sized frames. 485 1.2 matt */ 486 1.2 matt sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; 487 1.2 matt 488 1.27 msaitoh strcpy(ifp->if_xname, device_xname(sc->sc_dev)); 489 1.27 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 490 1.27 msaitoh ifp->if_ioctl = emac_ifioctl; 491 1.27 msaitoh ifp->if_start = emac_ifstart; 492 1.27 msaitoh ifp->if_watchdog = emac_ifwatchdog; 493 1.27 msaitoh ifp->if_init = emac_ifinit; 494 1.27 msaitoh ifp->if_stop = emac_ifstop; 495 1.27 msaitoh ifp->if_timer = 0; 496 1.2 matt ifp->if_softc = sc; 497 1.27 msaitoh IFQ_SET_READY(&ifp->if_snd); 498 1.27 msaitoh if_attach(ifp); 499 1.19 ozaki if_deferred_start_init(ifp, NULL); 500 1.27 msaitoh ether_ifattach(ifp, (sc)->sc_enaddr); 501 1.2 matt } 502 1.2 matt 503 1.2 matt int 504 1.23 msaitoh emac_mii_readreg(device_t self, int phy, int reg, uint16_t *val) 505 1.2 matt { 506 1.15 skrll #ifndef EMAC_FAST 507 1.15 skrll struct emac_softc *sc = device_private(self); 508 1.15 skrll #endif 509 1.11 matt 510 1.2 matt EMAC_WRITE(ETH_MAN, (ETH_MAN_HIGH | ETH_MAN_RW_RD 511 1.2 matt | ((phy << ETH_MAN_PHYA_SHIFT) & ETH_MAN_PHYA) 512 1.2 matt | ((reg << ETH_MAN_REGA_SHIFT) & ETH_MAN_REGA) 513 1.2 matt | ETH_MAN_CODE_IEEE802_3)); 514 1.26 msaitoh while (!(EMAC_READ(ETH_SR) & ETH_SR_IDLE)) 515 1.26 msaitoh ; 516 1.23 msaitoh *val = EMAC_READ(ETH_MAN) & ETH_MAN_DATA; 517 1.23 msaitoh 518 1.23 msaitoh return 0; 519 1.2 matt } 520 1.2 matt 521 1.23 msaitoh int 522 1.23 msaitoh emac_mii_writereg(device_t self, int phy, int reg, uint16_t val) 523 1.2 matt { 524 1.15 skrll #ifndef EMAC_FAST 525 1.15 skrll struct emac_softc *sc = device_private(self); 526 1.15 skrll #endif 527 1.11 matt 528 1.2 matt EMAC_WRITE(ETH_MAN, (ETH_MAN_HIGH | ETH_MAN_RW_WR 529 1.2 matt | ((phy << ETH_MAN_PHYA_SHIFT) & ETH_MAN_PHYA) 530 1.2 matt | ((reg << ETH_MAN_REGA_SHIFT) & ETH_MAN_REGA) 531 1.2 matt | ETH_MAN_CODE_IEEE802_3 532 1.2 matt | (val & ETH_MAN_DATA))); 533 1.26 msaitoh while (!(EMAC_READ(ETH_SR) & ETH_SR_IDLE)) 534 1.26 msaitoh ; 535 1.23 msaitoh 536 1.23 msaitoh return 0; 537 1.2 matt } 538 1.2 matt 539 1.2 matt void 540 1.11 matt emac_statchg(struct ifnet *ifp) 541 1.2 matt { 542 1.27 msaitoh struct emac_softc *sc = ifp->if_softc; 543 1.27 msaitoh uint32_t reg; 544 1.2 matt 545 1.27 msaitoh /* 546 1.27 msaitoh * We must keep the MAC and the PHY in sync as 547 1.27 msaitoh * to the status of full-duplex! 548 1.27 msaitoh */ 549 1.2 matt reg = EMAC_READ(ETH_CFG); 550 1.27 msaitoh if (sc->sc_mii.mii_media_active & IFM_FDX) 551 1.27 msaitoh reg |= ETH_CFG_FD; 552 1.27 msaitoh else 553 1.27 msaitoh reg &= ~ETH_CFG_FD; 554 1.2 matt EMAC_WRITE(ETH_CFG, reg); 555 1.2 matt } 556 1.2 matt 557 1.2 matt void 558 1.3 dsl emac_tick(void *arg) 559 1.2 matt { 560 1.2 matt struct emac_softc* sc = (struct emac_softc *)arg; 561 1.2 matt struct ifnet * ifp = &sc->sc_ec.ec_if; 562 1.2 matt int s; 563 1.13 skrll uint32_t misses; 564 1.2 matt 565 1.30 skrll if_statadd(ifp, if_collisions, EMAC_READ(ETH_SCOL) + EMAC_READ(ETH_MCOL)); 566 1.2 matt /* These misses are ok, they will happen if the RAM/CPU can't keep up */ 567 1.2 matt misses = EMAC_READ(ETH_DRFC); 568 1.26 msaitoh if (misses > 0) 569 1.2 matt printf("%s: %d rx misses\n", device_xname(sc->sc_dev), misses); 570 1.2 matt 571 1.2 matt s = splnet(); 572 1.2 matt if (emac_gctx(sc) > 0 && IFQ_IS_EMPTY(&ifp->if_snd) == 0) { 573 1.2 matt emac_ifstart(ifp); 574 1.2 matt } 575 1.2 matt splx(s); 576 1.2 matt 577 1.2 matt mii_tick(&sc->sc_mii); 578 1.2 matt callout_reset(&sc->emac_tick_ch, hz, emac_tick, sc); 579 1.2 matt } 580 1.2 matt 581 1.2 matt 582 1.2 matt static int 583 1.2 matt emac_ifioctl(struct ifnet *ifp, u_long cmd, void *data) 584 1.2 matt { 585 1.2 matt int s, error; 586 1.2 matt 587 1.2 matt s = splnet(); 588 1.26 msaitoh switch (cmd) { 589 1.2 matt default: 590 1.2 matt error = ether_ioctl(ifp, cmd, data); 591 1.2 matt if (error == ENETRESET) { 592 1.2 matt if (ifp->if_flags & IFF_RUNNING) 593 1.2 matt emac_setaddr(ifp); 594 1.2 matt error = 0; 595 1.2 matt } 596 1.2 matt } 597 1.2 matt splx(s); 598 1.2 matt return error; 599 1.2 matt } 600 1.2 matt 601 1.2 matt static void 602 1.3 dsl emac_ifstart(struct ifnet *ifp) 603 1.2 matt { 604 1.2 matt struct emac_softc *sc = (struct emac_softc *)ifp->if_softc; 605 1.2 matt struct mbuf *m; 606 1.2 matt bus_dma_segment_t *segs; 607 1.2 matt int s, bi, err, nsegs; 608 1.2 matt 609 1.26 msaitoh s = splnet(); 610 1.2 matt start: 611 1.2 matt if (emac_gctx(sc) == 0) { 612 1.2 matt /* Enable transmit-buffer-free interrupt */ 613 1.2 matt EMAC_WRITE(ETH_IER, ETH_ISR_TBRE); 614 1.34 thorpej sc->tx_busy = true; 615 1.2 matt ifp->if_timer = 10; 616 1.2 matt splx(s); 617 1.2 matt return; 618 1.2 matt } 619 1.2 matt 620 1.2 matt ifp->if_timer = 0; 621 1.2 matt 622 1.2 matt IFQ_POLL(&ifp->if_snd, m); 623 1.2 matt if (m == NULL) { 624 1.2 matt splx(s); 625 1.2 matt return; 626 1.2 matt } 627 1.2 matt //more: 628 1.2 matt bi = (sc->txqi + sc->txqc) % TX_QLEN; 629 1.2 matt if ((err = bus_dmamap_load_mbuf(sc->sc_dmat, sc->txq[bi].m_dmamap, m, 630 1.26 msaitoh BUS_DMA_NOWAIT)) || 631 1.2 matt sc->txq[bi].m_dmamap->dm_segs[0].ds_addr & 0x3 || 632 1.2 matt sc->txq[bi].m_dmamap->dm_nsegs > 1) { 633 1.2 matt /* Copy entire mbuf chain to new single */ 634 1.2 matt struct mbuf *mn; 635 1.2 matt 636 1.26 msaitoh if (err == 0) 637 1.2 matt bus_dmamap_unload(sc->sc_dmat, sc->txq[bi].m_dmamap); 638 1.2 matt 639 1.2 matt MGETHDR(mn, M_DONTWAIT, MT_DATA); 640 1.2 matt if (mn == NULL) goto stop; 641 1.2 matt if (m->m_pkthdr.len > MHLEN) { 642 1.2 matt MCLGET(mn, M_DONTWAIT); 643 1.2 matt if ((mn->m_flags & M_EXT) == 0) { 644 1.2 matt m_freem(mn); 645 1.2 matt goto stop; 646 1.2 matt } 647 1.2 matt } 648 1.2 matt m_copydata(m, 0, m->m_pkthdr.len, mtod(mn, void *)); 649 1.2 matt mn->m_pkthdr.len = mn->m_len = m->m_pkthdr.len; 650 1.2 matt IFQ_DEQUEUE(&ifp->if_snd, m); 651 1.2 matt m_freem(m); 652 1.2 matt m = mn; 653 1.2 matt bus_dmamap_load_mbuf(sc->sc_dmat, sc->txq[bi].m_dmamap, m, 654 1.2 matt BUS_DMA_NOWAIT); 655 1.2 matt } else { 656 1.2 matt IFQ_DEQUEUE(&ifp->if_snd, m); 657 1.2 matt } 658 1.2 matt 659 1.21 msaitoh bpf_mtap(ifp, m, BPF_D_OUT); 660 1.2 matt 661 1.2 matt nsegs = sc->txq[bi].m_dmamap->dm_nsegs; 662 1.2 matt segs = sc->txq[bi].m_dmamap->dm_segs; 663 1.2 matt if (nsegs > 1) { 664 1.2 matt panic("#### ARGH #2"); 665 1.2 matt } 666 1.2 matt 667 1.2 matt sc->txq[bi].m = m; 668 1.2 matt sc->txqc++; 669 1.2 matt 670 1.2 matt DPRINTFN(2,("%s: start sending idx #%i mbuf %p (txqc=%i, phys %p), len=%u\n", __FUNCTION__, bi, sc->txq[bi].m, sc->txqc, (void*)segs->ds_addr, 671 1.2 matt (unsigned)m->m_pkthdr.len)); 672 1.2 matt #ifdef DIAGNOSTIC 673 1.2 matt if (sc->txqc > TX_QLEN) { 674 1.2 matt panic("%s: txqc %i > %i", __FUNCTION__, sc->txqc, TX_QLEN); 675 1.2 matt } 676 1.2 matt #endif 677 1.2 matt 678 1.26 msaitoh bus_dmamap_sync(sc->sc_dmat, sc->txq[bi].m_dmamap, 0, 679 1.26 msaitoh sc->txq[bi].m_dmamap->dm_mapsize, 680 1.2 matt BUS_DMASYNC_PREWRITE); 681 1.2 matt 682 1.2 matt EMAC_WRITE(ETH_TAR, segs->ds_addr); 683 1.2 matt EMAC_WRITE(ETH_TCR, m->m_pkthdr.len); 684 1.2 matt if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 685 1.2 matt goto start; 686 1.2 matt stop: 687 1.2 matt 688 1.2 matt splx(s); 689 1.2 matt return; 690 1.2 matt } 691 1.2 matt 692 1.2 matt static void 693 1.3 dsl emac_ifwatchdog(struct ifnet *ifp) 694 1.2 matt { 695 1.2 matt struct emac_softc *sc = (struct emac_softc *)ifp->if_softc; 696 1.2 matt 697 1.2 matt if ((ifp->if_flags & IFF_RUNNING) == 0) 698 1.2 matt return; 699 1.27 msaitoh printf("%s: device timeout, CTL = 0x%08x, CFG = 0x%08x\n", 700 1.2 matt device_xname(sc->sc_dev), EMAC_READ(ETH_CTL), EMAC_READ(ETH_CFG)); 701 1.2 matt } 702 1.2 matt 703 1.2 matt static int 704 1.3 dsl emac_ifinit(struct ifnet *ifp) 705 1.2 matt { 706 1.2 matt struct emac_softc *sc = ifp->if_softc; 707 1.2 matt int s = splnet(); 708 1.2 matt 709 1.2 matt callout_stop(&sc->emac_tick_ch); 710 1.2 matt 711 1.2 matt // enable interrupts 712 1.2 matt EMAC_WRITE(ETH_IDR, -1); 713 1.2 matt EMAC_WRITE(ETH_IER, ETH_ISR_RCOM | ETH_ISR_TBRE | ETH_ISR_TIDLE 714 1.2 matt | ETH_ISR_RBNA | ETH_ISR_ROVR); 715 1.2 matt 716 1.2 matt // enable transmitter / receiver 717 1.2 matt EMAC_WRITE(ETH_CTL, ETH_CTL_TE | ETH_CTL_RE | ETH_CTL_ISR 718 1.2 matt | ETH_CTL_CSR | ETH_CTL_MPE); 719 1.2 matt 720 1.2 matt mii_mediachg(&sc->sc_mii); 721 1.2 matt callout_reset(&sc->emac_tick_ch, hz, emac_tick, sc); 722 1.27 msaitoh ifp->if_flags |= IFF_RUNNING; 723 1.2 matt splx(s); 724 1.2 matt return 0; 725 1.2 matt } 726 1.2 matt 727 1.2 matt static void 728 1.3 dsl emac_ifstop(struct ifnet *ifp, int disable) 729 1.2 matt { 730 1.13 skrll // uint32_t u; 731 1.2 matt struct emac_softc *sc = ifp->if_softc; 732 1.2 matt 733 1.2 matt #if 0 734 1.2 matt EMAC_WRITE(ETH_CTL, ETH_CTL_MPE); // disable everything 735 1.2 matt EMAC_WRITE(ETH_IDR, -1); // disable interrupts 736 1.2 matt // EMAC_WRITE(ETH_RBQP, 0); // clear receive 737 1.26 msaitoh EMAC_WRITE(ETH_CFG, 738 1.26 msaitoh ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); 739 1.2 matt EMAC_WRITE(ETH_TCR, 0); // send nothing 740 1.2 matt // (void)EMAC_READ(ETH_ISR); 741 1.2 matt u = EMAC_READ(ETH_TSR); 742 1.2 matt EMAC_WRITE(ETH_TSR, (u & (ETH_TSR_UND | ETH_TSR_COMP | ETH_TSR_BNQ 743 1.2 matt | ETH_TSR_IDLE | ETH_TSR_RLE 744 1.26 msaitoh | ETH_TSR_COL | ETH_TSR_OVR))); 745 1.2 matt u = EMAC_READ(ETH_RSR); 746 1.26 msaitoh EMAC_WRITE(ETH_RSR, (u & (ETH_RSR_OVR | ETH_RSR_REC | ETH_RSR_BNA))); 747 1.2 matt #endif 748 1.2 matt callout_stop(&sc->emac_tick_ch); 749 1.2 matt 750 1.2 matt /* Down the MII. */ 751 1.2 matt mii_down(&sc->sc_mii); 752 1.2 matt 753 1.34 thorpej ifp->if_flags &= ~IFF_RUNNING; 754 1.2 matt ifp->if_timer = 0; 755 1.2 matt sc->sc_mii.mii_media_status &= ~IFM_ACTIVE; 756 1.2 matt } 757 1.2 matt 758 1.2 matt static void 759 1.3 dsl emac_setaddr(struct ifnet *ifp) 760 1.2 matt { 761 1.2 matt struct emac_softc *sc = ifp->if_softc; 762 1.28 msaitoh struct ethercom *ec = &sc->sc_ec; 763 1.2 matt struct ether_multi *enm; 764 1.2 matt struct ether_multistep step; 765 1.13 skrll uint8_t ias[3][ETHER_ADDR_LEN]; 766 1.13 skrll uint32_t h, nma = 0, hashes[2] = { 0, 0 }; 767 1.13 skrll uint32_t ctl = EMAC_READ(ETH_CTL); 768 1.13 skrll uint32_t cfg = EMAC_READ(ETH_CFG); 769 1.2 matt 770 1.2 matt /* disable receiver temporarily */ 771 1.2 matt EMAC_WRITE(ETH_CTL, ctl & ~ETH_CTL_RE); 772 1.2 matt 773 1.33 skrll cfg &= ~(ETH_CFG_MTI | ETH_CFG_UNI | ETH_CFG_CAF); 774 1.2 matt 775 1.2 matt if (ifp->if_flags & IFF_PROMISC) { 776 1.27 msaitoh cfg |= ETH_CFG_CAF; 777 1.2 matt } else { 778 1.2 matt cfg &= ~ETH_CFG_CAF; 779 1.2 matt } 780 1.2 matt 781 1.2 matt // ETH_CFG_BIG? 782 1.2 matt 783 1.2 matt ifp->if_flags &= ~IFF_ALLMULTI; 784 1.2 matt 785 1.29 msaitoh ETHER_LOCK(ec); 786 1.28 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 787 1.2 matt while (enm != NULL) { 788 1.2 matt if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 789 1.2 matt /* 790 1.2 matt * We must listen to a range of multicast addresses. 791 1.2 matt * For now, just accept all multicasts, rather than 792 1.2 matt * trying to set only those filter bits needed to match 793 1.2 matt * the range. (At this time, the only use of address 794 1.2 matt * ranges is for IP multicast routing, for which the 795 1.2 matt * range is big enough to require all bits set.) 796 1.2 matt */ 797 1.2 matt cfg |= ETH_CFG_CAF; 798 1.2 matt hashes[0] = 0xffffffffUL; 799 1.2 matt hashes[1] = 0xffffffffUL; 800 1.2 matt ifp->if_flags |= IFF_ALLMULTI; 801 1.2 matt nma = 0; 802 1.2 matt break; 803 1.2 matt } 804 1.2 matt 805 1.2 matt if (nma < 3) { 806 1.2 matt /* We can program 3 perfect address filters for mcast */ 807 1.2 matt memcpy(ias[nma], enm->enm_addrlo, ETHER_ADDR_LEN); 808 1.2 matt } else { 809 1.2 matt /* 810 1.2 matt * XXX: Datasheet is not very clear here, I'm not sure 811 1.2 matt * if I'm doing this right. --joff 812 1.2 matt */ 813 1.2 matt h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); 814 1.2 matt 815 1.2 matt /* Just want the 6 most-significant bits. */ 816 1.2 matt h = h >> 26; 817 1.2 matt 818 1.2 matt hashes[ h / 32 ] |= (1 << (h % 32)); 819 1.2 matt cfg |= ETH_CFG_MTI; 820 1.2 matt } 821 1.2 matt ETHER_NEXT_MULTI(step, enm); 822 1.2 matt nma++; 823 1.2 matt } 824 1.29 msaitoh ETHER_UNLOCK(ec); 825 1.2 matt 826 1.2 matt // program... 827 1.2 matt DPRINTFN(1,("%s: en0 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, 828 1.2 matt sc->sc_enaddr[0], sc->sc_enaddr[1], sc->sc_enaddr[2], 829 1.2 matt sc->sc_enaddr[3], sc->sc_enaddr[4], sc->sc_enaddr[5])); 830 1.2 matt EMAC_WRITE(ETH_SA1L, (sc->sc_enaddr[3] << 24) 831 1.2 matt | (sc->sc_enaddr[2] << 16) | (sc->sc_enaddr[1] << 8) 832 1.2 matt | (sc->sc_enaddr[0])); 833 1.2 matt EMAC_WRITE(ETH_SA1H, (sc->sc_enaddr[5] << 8) 834 1.2 matt | (sc->sc_enaddr[4])); 835 1.2 matt if (nma > 1) { 836 1.28 msaitoh DPRINTFN(1,("%s: en1 %02x:%02x:%02x:%02x:%02x:%02x\n", 837 1.28 msaitoh __FUNCTION__, 838 1.28 msaitoh ias[0][0], ias[0][1], ias[0][2], 839 1.28 msaitoh ias[0][3], ias[0][4], ias[0][5])); 840 1.2 matt EMAC_WRITE(ETH_SA2L, (ias[0][3] << 24) 841 1.2 matt | (ias[0][2] << 16) | (ias[0][1] << 8) 842 1.2 matt | (ias[0][0])); 843 1.2 matt EMAC_WRITE(ETH_SA2H, (ias[0][4] << 8) 844 1.2 matt | (ias[0][5])); 845 1.2 matt } 846 1.2 matt if (nma > 2) { 847 1.28 msaitoh DPRINTFN(1,("%s: en2 %02x:%02x:%02x:%02x:%02x:%02x\n", 848 1.28 msaitoh __FUNCTION__, 849 1.28 msaitoh ias[1][0], ias[1][1], ias[1][2], 850 1.28 msaitoh ias[1][3], ias[1][4], ias[1][5])); 851 1.2 matt EMAC_WRITE(ETH_SA3L, (ias[1][3] << 24) 852 1.2 matt | (ias[1][2] << 16) | (ias[1][1] << 8) 853 1.2 matt | (ias[1][0])); 854 1.2 matt EMAC_WRITE(ETH_SA3H, (ias[1][4] << 8) 855 1.2 matt | (ias[1][5])); 856 1.2 matt } 857 1.2 matt if (nma > 3) { 858 1.28 msaitoh DPRINTFN(1,("%s: en3 %02x:%02x:%02x:%02x:%02x:%02x\n", 859 1.28 msaitoh __FUNCTION__, 860 1.28 msaitoh ias[2][0], ias[2][1], ias[2][2], 861 1.28 msaitoh ias[2][3], ias[2][4], ias[2][5])); 862 1.2 matt EMAC_WRITE(ETH_SA3L, (ias[2][3] << 24) 863 1.2 matt | (ias[2][2] << 16) | (ias[2][1] << 8) 864 1.2 matt | (ias[2][0])); 865 1.2 matt EMAC_WRITE(ETH_SA3H, (ias[2][4] << 8) 866 1.2 matt | (ias[2][5])); 867 1.2 matt } 868 1.2 matt EMAC_WRITE(ETH_HSH, hashes[0]); 869 1.2 matt EMAC_WRITE(ETH_HSL, hashes[1]); 870 1.2 matt EMAC_WRITE(ETH_CFG, cfg); 871 1.2 matt EMAC_WRITE(ETH_CTL, ctl | ETH_CTL_RE); 872 1.2 matt } 873