if_ate.c revision 192027
1155324Simp/*- 2155324Simp * Copyright (c) 2006 M. Warner Losh. All rights reserved. 3155324Simp * 4155324Simp * Redistribution and use in source and binary forms, with or without 5155324Simp * modification, are permitted provided that the following conditions 6155324Simp * are met: 7155324Simp * 1. Redistributions of source code must retain the above copyright 8155324Simp * notice, this list of conditions and the following disclaimer. 9155324Simp * 2. Redistributions in binary form must reproduce the above copyright 10155324Simp * notice, this list of conditions and the following disclaimer in the 11155324Simp * documentation and/or other materials provided with the distribution. 12155324Simp * 13185267Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14185267Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15185267Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16185267Simp * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17185267Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18185267Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19185267Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20185267Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21185267Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22185267Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23185267Simp * SUCH DAMAGE. 24155324Simp */ 25155324Simp 26192018Sstas/* TODO 27155324Simp * 28192018Sstas * 1) Turn on the clock in pmc? Turn off? 29192018Sstas * 2) GPIO initializtion in board setup code. 30155324Simp */ 31155324Simp 32155324Simp#include <sys/cdefs.h> 33155324Simp__FBSDID("$FreeBSD: head/sys/arm/at91/if_ate.c 192027 2009-05-12 21:14:36Z stas $"); 34155324Simp 35155324Simp#include <sys/param.h> 36155324Simp#include <sys/systm.h> 37155324Simp#include <sys/bus.h> 38155324Simp#include <sys/kernel.h> 39155324Simp#include <sys/mbuf.h> 40155324Simp#include <sys/malloc.h> 41155324Simp#include <sys/module.h> 42155324Simp#include <sys/rman.h> 43155324Simp#include <sys/socket.h> 44155324Simp#include <sys/sockio.h> 45163522Simp#include <sys/sysctl.h> 46155324Simp#include <machine/bus.h> 47155324Simp 48155324Simp#include <net/ethernet.h> 49155324Simp#include <net/if.h> 50155324Simp#include <net/if_arp.h> 51155324Simp#include <net/if_dl.h> 52155324Simp#include <net/if_media.h> 53155324Simp#include <net/if_mib.h> 54155324Simp#include <net/if_types.h> 55155324Simp 56155324Simp#ifdef INET 57155324Simp#include <netinet/in.h> 58155324Simp#include <netinet/in_systm.h> 59155324Simp#include <netinet/in_var.h> 60155324Simp#include <netinet/ip.h> 61155324Simp#endif 62155324Simp 63155324Simp#include <net/bpf.h> 64155324Simp#include <net/bpfdesc.h> 65155324Simp 66155324Simp#include <dev/mii/mii.h> 67155324Simp#include <dev/mii/miivar.h> 68155324Simp#include <arm/at91/if_atereg.h> 69155324Simp 70155324Simp#include "miibus_if.h" 71155324Simp 72165778Sticso#define ATE_MAX_TX_BUFFERS 2 /* We have ping-pong tx buffers */ 73156831Simp#define ATE_MAX_RX_BUFFERS 64 74155324Simp 75191959Sstas/* 76191959Sstas * Driver-specific flags. 77191959Sstas */ 78191959Sstas#define ATE_FLAG_DETACHING 0x01 79191960Sstas#define ATE_FLAG_MULTICAST 0x02 80191959Sstas 81155324Simpstruct ate_softc 82155324Simp{ 83155324Simp struct ifnet *ifp; /* ifnet pointer */ 84155324Simp struct mtx sc_mtx; /* basically a perimeter lock */ 85155324Simp device_t dev; /* Myself */ 86155324Simp device_t miibus; /* My child miibus */ 87155324Simp void *intrhand; /* Interrupt handle */ 88155324Simp struct resource *irq_res; /* IRQ resource */ 89155324Simp struct resource *mem_res; /* Memory resource */ 90155324Simp struct callout tick_ch; /* Tick callout */ 91155324Simp bus_dma_tag_t mtag; /* bus dma tag for mbufs */ 92155324Simp bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS]; 93157562Simp struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */ 94155324Simp bus_dma_tag_t rxtag; 95155324Simp bus_dmamap_t rx_map[ATE_MAX_RX_BUFFERS]; 96157562Simp void *rx_buf[ATE_MAX_RX_BUFFERS]; /* RX buffer space */ 97157562Simp int rx_buf_ptr; 98155324Simp bus_dma_tag_t rx_desc_tag; 99155324Simp bus_dmamap_t rx_desc_map; 100155324Simp int txcur; /* current tx map pointer */ 101155324Simp bus_addr_t rx_desc_phys; 102155324Simp eth_rx_desc_t *rx_descs; 103159708Simp int use_rmii; 104155324Simp struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */ 105191959Sstas int flags; 106191959Sstas int if_flags; 107155324Simp}; 108155324Simp 109155324Simpstatic inline uint32_t 110155324SimpRD4(struct ate_softc *sc, bus_size_t off) 111155324Simp{ 112155324Simp return bus_read_4(sc->mem_res, off); 113155324Simp} 114155324Simp 115155324Simpstatic inline void 116155324SimpWR4(struct ate_softc *sc, bus_size_t off, uint32_t val) 117155324Simp{ 118155324Simp bus_write_4(sc->mem_res, off, val); 119155324Simp} 120155324Simp 121192027Sstasstatic inline void 122192027SstasBARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags) 123192027Sstas{ 124192027Sstas 125192027Sstas bus_barrier(sc->mem_res, off, len, flags); 126192027Sstas} 127192027Sstas 128155324Simp#define ATE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 129155324Simp#define ATE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 130155324Simp#define ATE_LOCK_INIT(_sc) \ 131155324Simp mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ 132155324Simp MTX_NETWORK_LOCK, MTX_DEF) 133155324Simp#define ATE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 134155324Simp#define ATE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 135155324Simp#define ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 136155324Simp 137155324Simpstatic devclass_t ate_devclass; 138155324Simp 139155324Simp/* ifnet entry points */ 140155324Simp 141155324Simpstatic void ateinit_locked(void *); 142155324Simpstatic void atestart_locked(struct ifnet *); 143155324Simp 144155324Simpstatic void ateinit(void *); 145155324Simpstatic void atestart(struct ifnet *); 146155324Simpstatic void atestop(struct ate_softc *); 147155324Simpstatic int ateioctl(struct ifnet * ifp, u_long, caddr_t); 148155324Simp 149155324Simp/* bus entry points */ 150155324Simp 151155324Simpstatic int ate_probe(device_t dev); 152155324Simpstatic int ate_attach(device_t dev); 153155324Simpstatic int ate_detach(device_t dev); 154155324Simpstatic void ate_intr(void *); 155155324Simp 156155324Simp/* helper routines */ 157155324Simpstatic int ate_activate(device_t dev); 158192018Sstasstatic void ate_deactivate(struct ate_softc *sc); 159155324Simpstatic int ate_ifmedia_upd(struct ifnet *ifp); 160155324Simpstatic void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 161166573Simpstatic int ate_get_mac(struct ate_softc *sc, u_char *eaddr); 162155445Scognetstatic void ate_set_mac(struct ate_softc *sc, u_char *eaddr); 163191959Sstasstatic void ate_rxfilter(struct ate_softc *sc); 164155324Simp 165155324Simp/* 166155324Simp * The AT91 family of products has the ethernet called EMAC. However, 167155324Simp * it isn't self identifying. It is anticipated that the parent bus 168155324Simp * code will take care to only add ate devices where they really are. As 169155324Simp * such, we do nothing here to identify the device and just set its name. 170155324Simp */ 171155324Simpstatic int 172155324Simpate_probe(device_t dev) 173155324Simp{ 174155324Simp device_set_desc(dev, "EMAC"); 175155324Simp return (0); 176155324Simp} 177155324Simp 178155324Simpstatic int 179155324Simpate_attach(device_t dev) 180155324Simp{ 181155324Simp struct ate_softc *sc = device_get_softc(dev); 182155324Simp struct ifnet *ifp = NULL; 183163522Simp struct sysctl_ctx_list *sctx; 184163522Simp struct sysctl_oid *soid; 185182477Sstas u_char eaddr[ETHER_ADDR_LEN]; 186182477Sstas uint32_t rnd; 187192018Sstas int rid, err; 188155324Simp 189155324Simp sc->dev = dev; 190192018Sstas ATE_LOCK_INIT(sc); 191192018Sstas 192192018Sstas /* 193192018Sstas * Allocate resources. 194192018Sstas */ 195192018Sstas rid = 0; 196192018Sstas sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 197192018Sstas RF_ACTIVE); 198192018Sstas if (sc->mem_res == NULL) { 199192018Sstas device_printf(dev, "could not allocate memory resources.\n"); 200192018Sstas err = ENOMEM; 201192018Sstas goto out; 202192018Sstas } 203192018Sstas rid = 0; 204192018Sstas sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 205192018Sstas RF_ACTIVE); 206192018Sstas if (sc->irq_res == NULL) { 207192018Sstas device_printf(dev, "could not allocate interrupt resources.\n"); 208192018Sstas err = ENOMEM; 209192018Sstas goto out; 210192018Sstas } 211192018Sstas 212155324Simp err = ate_activate(dev); 213155324Simp if (err) 214155324Simp goto out; 215155324Simp 216159708Simp sc->use_rmii = (RD4(sc, ETH_CFG) & ETH_CFG_RMII) == ETH_CFG_RMII; 217159708Simp 218182476Sstas /* Sysctls */ 219163522Simp sctx = device_get_sysctl_ctx(dev); 220163522Simp soid = device_get_sysctl_tree(dev); 221163522Simp SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "rmii", 222163522Simp CTLFLAG_RD, &sc->use_rmii, 0, "rmii in use"); 223163522Simp 224155324Simp /* calling atestop before ifp is set is OK */ 225192018Sstas ATE_LOCK(sc); 226155324Simp atestop(sc); 227192018Sstas ATE_UNLOCK(sc); 228155324Simp callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0); 229155324Simp 230166573Simp if ((err = ate_get_mac(sc, eaddr)) != 0) { 231182477Sstas /* 232182524Sstas * No MAC address configured. Generate the random one. 233182477Sstas */ 234182477Sstas if (bootverbose) 235182477Sstas device_printf(dev, 236182524Sstas "Generating random ethernet address.\n"); 237182477Sstas rnd = arc4random(); 238182477Sstas 239182477Sstas /* 240182555Simp * Set OUI to convenient locally assigned address. 'b' 241182555Simp * is 0x62, which has the locally assigned bit set, and 242182555Simp * the broadcast/multicast bit clear. 243182477Sstas */ 244182555Simp eaddr[0] = 'b'; 245182555Simp eaddr[1] = 's'; 246182555Simp eaddr[2] = 'd'; 247182477Sstas eaddr[3] = (rnd >> 16) & 0xff; 248182477Sstas eaddr[4] = (rnd >> 8) & 0xff; 249182477Sstas eaddr[5] = rnd & 0xff; 250166573Simp } 251155445Scognet ate_set_mac(sc, eaddr); 252155324Simp 253155405Scognet sc->ifp = ifp = if_alloc(IFT_ETHER); 254155324Simp if (mii_phy_probe(dev, &sc->miibus, ate_ifmedia_upd, ate_ifmedia_sts)) { 255155324Simp device_printf(dev, "Cannot find my PHY.\n"); 256155324Simp err = ENXIO; 257155324Simp goto out; 258155324Simp } 259155324Simp 260155324Simp ifp->if_softc = sc; 261155324Simp if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 262155324Simp ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 263165779Sticso ifp->if_capabilities |= IFCAP_VLAN_MTU; 264165779Sticso ifp->if_capenable |= IFCAP_VLAN_MTU; /* the hw bits already set */ 265155324Simp ifp->if_start = atestart; 266155324Simp ifp->if_ioctl = ateioctl; 267155324Simp ifp->if_init = ateinit; 268155324Simp ifp->if_baudrate = 10000000; 269155324Simp IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 270166625Smlaier ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; 271155324Simp IFQ_SET_READY(&ifp->if_snd); 272155324Simp ifp->if_timer = 0; 273155324Simp ifp->if_linkmib = &sc->mibdata; 274155324Simp ifp->if_linkmiblen = sizeof(sc->mibdata); 275155324Simp sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS; 276191959Sstas sc->if_flags = ifp->if_flags; 277155324Simp 278155324Simp ether_ifattach(ifp, eaddr); 279155324Simp 280155324Simp /* 281192018Sstas * Activate the interrupt. 282155324Simp */ 283155324Simp err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, 284166901Spiso NULL, ate_intr, sc, &sc->intrhand); 285155324Simp if (err) { 286192018Sstas device_printf(dev, "could not establish interrupt handler.\n"); 287155324Simp ether_ifdetach(ifp); 288192018Sstas goto out; 289155324Simp } 290192018Sstas 291192018Sstasout: 292155324Simp if (err) 293192018Sstas ate_detach(dev); 294155324Simp return (err); 295155324Simp} 296155324Simp 297155324Simpstatic int 298155324Simpate_detach(device_t dev) 299155324Simp{ 300192018Sstas struct ate_softc *sc; 301192018Sstas struct ifnet *ifp; 302192018Sstas 303192018Sstas sc = device_get_softc(dev); 304192018Sstas KASSERT(sc != NULL, ("[ate: %d]: sc is NULL", __LINE__)); 305192018Sstas ifp = sc->ifp; 306192018Sstas if (device_is_attached(dev)) { 307192018Sstas ATE_LOCK(sc); 308192018Sstas sc->flags |= ATE_FLAG_DETACHING; 309192018Sstas atestop(sc); 310192018Sstas ATE_UNLOCK(sc); 311192018Sstas callout_drain(&sc->tick_ch); 312192018Sstas ether_ifdetach(ifp); 313192018Sstas } 314192018Sstas if (sc->miibus != NULL) { 315192018Sstas device_delete_child(dev, sc->miibus); 316192018Sstas sc->miibus = NULL; 317192018Sstas } 318192018Sstas bus_generic_detach(sc->dev); 319192018Sstas ate_deactivate(sc); 320192018Sstas if (sc->intrhand != NULL) { 321192018Sstas bus_teardown_intr(dev, sc->irq_res, sc->intrhand); 322192018Sstas sc->intrhand = NULL; 323192018Sstas } 324192018Sstas if (ifp != NULL) { 325192018Sstas if_free(ifp); 326192018Sstas sc->ifp = NULL; 327192018Sstas } 328192018Sstas if (sc->mem_res != NULL) { 329192018Sstas bus_release_resource(dev, SYS_RES_IOPORT, 330192018Sstas rman_get_rid(sc->mem_res), sc->mem_res); 331192018Sstas sc->mem_res = NULL; 332192018Sstas } 333192018Sstas if (sc->irq_res != NULL) { 334192018Sstas bus_release_resource(dev, SYS_RES_IRQ, 335192018Sstas rman_get_rid(sc->irq_res), sc->irq_res); 336192018Sstas sc->irq_res = NULL; 337192018Sstas } 338192018Sstas ATE_LOCK_DESTROY(sc); 339192018Sstas return (0); 340155324Simp} 341155324Simp 342155324Simpstatic void 343155324Simpate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 344155324Simp{ 345155324Simp struct ate_softc *sc; 346155324Simp 347155324Simp if (error != 0) 348155324Simp return; 349155324Simp sc = (struct ate_softc *)arg; 350155324Simp sc->rx_desc_phys = segs[0].ds_addr; 351155324Simp} 352155324Simp 353157562Simpstatic void 354157562Simpate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 355157562Simp{ 356157562Simp struct ate_softc *sc; 357157562Simp int i; 358157562Simp 359157562Simp if (error != 0) 360157562Simp return; 361157562Simp sc = (struct ate_softc *)arg; 362157562Simp i = sc->rx_buf_ptr; 363157562Simp 364157562Simp /* 365157562Simp * For the last buffer, set the wrap bit so the controller 366157562Simp * restarts from the first descriptor. 367157562Simp */ 368163937Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE); 369157562Simp if (i == ATE_MAX_RX_BUFFERS - 1) 370157562Simp sc->rx_descs[i].addr = segs[0].ds_addr | ETH_WRAP_BIT; 371157562Simp else 372157562Simp sc->rx_descs[i].addr = segs[0].ds_addr; 373163937Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_POSTWRITE); 374157562Simp sc->rx_descs[i].status = 0; 375157562Simp /* Flush the memory in the mbuf */ 376157562Simp bus_dmamap_sync(sc->rxtag, sc->rx_map[i], BUS_DMASYNC_PREREAD); 377157562Simp} 378157562Simp 379155324Simp/* 380155324Simp * Compute the multicast filter for this device using the standard 381155324Simp * algorithm. I wonder why this isn't in ether somewhere as a lot 382155324Simp * of different MAC chips use this method (or the reverse the bits) 383155324Simp * method. 384155324Simp */ 385191960Sstasstatic int 386155324Simpate_setmcast(struct ate_softc *sc) 387155324Simp{ 388155324Simp uint32_t index; 389155324Simp uint32_t mcaf[2]; 390155324Simp u_char *af = (u_char *) mcaf; 391155324Simp struct ifmultiaddr *ifma; 392191960Sstas struct ifnet *ifp; 393155324Simp 394191960Sstas ifp = sc->ifp; 395191960Sstas 396191960Sstas if ((ifp->if_flags & IFF_PROMISC) != 0) 397191960Sstas return (0); 398191960Sstas if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 399191960Sstas WR4(sc, ETH_HSL, 0xffffffff); 400191960Sstas WR4(sc, ETH_HSH, 0xffffffff); 401191960Sstas return (1); 402191960Sstas } 403191960Sstas 404191960Sstas /* 405191960Sstas * Compute the multicast hash. 406191960Sstas */ 407155324Simp mcaf[0] = 0; 408155324Simp mcaf[1] = 0; 409191960Sstas IF_ADDR_LOCK(ifp); 410191960Sstas TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 411155324Simp if (ifma->ifma_addr->sa_family != AF_LINK) 412155324Simp continue; 413155324Simp index = ether_crc32_be(LLADDR((struct sockaddr_dl *) 414155324Simp ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; 415155324Simp af[index >> 3] |= 1 << (index & 7); 416155324Simp } 417191960Sstas IF_ADDR_UNLOCK(ifp); 418155324Simp 419155324Simp /* 420155324Simp * Write the hash to the hash register. This card can also 421155324Simp * accept unicast packets as well as multicast packets using this 422155324Simp * register for easier bridging operations, but we don't take 423155324Simp * advantage of that. Locks here are to avoid LOR with the 424155324Simp * IF_ADDR_LOCK, but might not be strictly necessary. 425155324Simp */ 426155324Simp WR4(sc, ETH_HSL, mcaf[0]); 427155324Simp WR4(sc, ETH_HSH, mcaf[1]); 428191960Sstas return (mcaf[0] || mcaf[1]); 429155324Simp} 430155324Simp 431155324Simpstatic int 432155324Simpate_activate(device_t dev) 433155324Simp{ 434155324Simp struct ate_softc *sc; 435192018Sstas int err, i; 436155324Simp 437155324Simp sc = device_get_softc(dev); 438155324Simp /* 439155324Simp * Allocate DMA tags and maps 440155324Simp */ 441183670Simp err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 442183670Simp BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 443183670Simp 1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->mtag); 444155324Simp if (err != 0) 445155324Simp goto errout; 446155324Simp for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 447155324Simp err = bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i]); 448155324Simp if (err != 0) 449155324Simp goto errout; 450155324Simp } 451155324Simp /* 452155324Simp * Allocate our Rx buffers. This chip has a rx structure that's filled 453155324Simp * in 454155324Simp */ 455155324Simp 456155324Simp /* 457155324Simp * Allocate DMA tags and maps for RX. 458155324Simp */ 459183670Simp err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 460183670Simp BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 461183670Simp 1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->rxtag); 462155324Simp if (err != 0) 463155324Simp goto errout; 464155324Simp 465155324Simp /* Dma TAG and MAP for the rx descriptors. */ 466183670Simp err = bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_rx_desc_t), 467183670Simp 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 468155324Simp ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), 1, 469155324Simp ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), 0, busdma_lock_mutex, 470155324Simp &sc->sc_mtx, &sc->rx_desc_tag); 471155324Simp if (err != 0) 472155324Simp goto errout; 473156831Simp if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs, 474156831Simp BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rx_desc_map) != 0) 475155324Simp goto errout; 476157562Simp if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map, 477155324Simp sc->rx_descs, ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), 478155324Simp ate_getaddr, sc, 0) != 0) 479155324Simp goto errout; 480155324Simp for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) { 481157562Simp sc->rx_buf_ptr = i; 482157562Simp if (bus_dmamem_alloc(sc->rxtag, (void **)&sc->rx_buf[i], 483157562Simp BUS_DMA_NOWAIT, &sc->rx_map[i]) != 0) 484155324Simp goto errout; 485157562Simp if (bus_dmamap_load(sc->rxtag, sc->rx_map[i], sc->rx_buf[i], 486157562Simp MCLBYTES, ate_load_rx_buf, sc, 0) != 0) 487157562Simp goto errout; 488155324Simp } 489157562Simp sc->rx_buf_ptr = 0; 490156831Simp /* Flush the memory for the EMAC rx descriptor */ 491155324Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE); 492155324Simp /* Write the descriptor queue address. */ 493155324Simp WR4(sc, ETH_RBQP, sc->rx_desc_phys); 494155324Simp return (0); 495192018Sstas 496155324Simperrout: 497155324Simp return (ENOMEM); 498155324Simp} 499155324Simp 500155324Simpstatic void 501192018Sstasate_deactivate(struct ate_softc *sc) 502155324Simp{ 503192018Sstas int i; 504155324Simp 505192018Sstas KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__)); 506192018Sstas if (sc->mtag != NULL) { 507192018Sstas for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 508192018Sstas if (sc->sent_mbuf[i] != NULL) { 509192018Sstas bus_dmamap_sync(sc->mtag, sc->tx_map[i], 510192018Sstas BUS_DMASYNC_POSTWRITE); 511192018Sstas bus_dmamap_unload(sc->mtag, sc->tx_map[i]); 512192018Sstas m_freem(sc->sent_mbuf[i]); 513155324Simp } 514192018Sstas bus_dmamap_destroy(sc->mtag, sc->tx_map[i]); 515192018Sstas sc->sent_mbuf[i] = NULL; 516192018Sstas sc->tx_map[i] = NULL; 517155324Simp } 518192018Sstas bus_dma_tag_destroy(sc->mtag); 519192018Sstas } 520192018Sstas if (sc->rx_desc_tag != NULL) { 521192018Sstas if (sc->rx_descs != NULL) { 522192018Sstas if (sc->rx_desc_phys != 0) { 523192018Sstas bus_dmamap_sync(sc->rx_desc_tag, 524192018Sstas sc->rx_desc_map, BUS_DMASYNC_POSTREAD); 525192018Sstas bus_dmamap_unload(sc->rx_desc_tag, 526192018Sstas sc->rx_desc_map); 527192018Sstas sc->rx_desc_phys = 0; 528155324Simp } 529155324Simp } 530155324Simp } 531192018Sstas if (sc->rxtag != NULL) { 532192018Sstas for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) { 533192018Sstas if (sc->rx_buf[i] != NULL) { 534192018Sstas if (sc->rx_descs[i].addr != 0) { 535192018Sstas bus_dmamap_sync(sc->rxtag, 536192018Sstas sc->rx_map[i], 537192018Sstas BUS_DMASYNC_POSTREAD); 538192018Sstas bus_dmamap_unload(sc->rxtag, 539192018Sstas sc->rx_map[i]); 540192018Sstas sc->rx_descs[i].addr = 0; 541192018Sstas } 542192018Sstas bus_dmamem_free(sc->rxtag, sc->rx_buf[i], 543192018Sstas sc->rx_map[i]); 544192018Sstas sc->rx_buf[i] = NULL; 545192018Sstas sc->rx_map[i] = NULL; 546192018Sstas } 547192018Sstas } 548192018Sstas bus_dma_tag_destroy(sc->rxtag); 549192018Sstas } 550192018Sstas if (sc->rx_desc_tag != NULL) { 551192018Sstas if (sc->rx_descs != NULL) 552192018Sstas bus_dmamem_free(sc->rx_desc_tag, sc->rx_descs, 553192018Sstas sc->rx_desc_map); 554192018Sstas bus_dma_tag_destroy(sc->rx_desc_tag); 555192018Sstas sc->rx_descs = NULL; 556192018Sstas sc->rx_desc_tag = NULL; 557192018Sstas } 558155324Simp} 559155324Simp 560155324Simp/* 561155324Simp * Change media according to request. 562155324Simp */ 563155324Simpstatic int 564155324Simpate_ifmedia_upd(struct ifnet *ifp) 565155324Simp{ 566155324Simp struct ate_softc *sc = ifp->if_softc; 567155324Simp struct mii_data *mii; 568155324Simp 569155324Simp mii = device_get_softc(sc->miibus); 570155324Simp ATE_LOCK(sc); 571155324Simp mii_mediachg(mii); 572155324Simp ATE_UNLOCK(sc); 573155324Simp return (0); 574155324Simp} 575155324Simp 576155324Simp/* 577155324Simp * Notify the world which media we're using. 578155324Simp */ 579155324Simpstatic void 580155324Simpate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 581155324Simp{ 582155324Simp struct ate_softc *sc = ifp->if_softc; 583155324Simp struct mii_data *mii; 584155324Simp 585155324Simp mii = device_get_softc(sc->miibus); 586155324Simp ATE_LOCK(sc); 587155324Simp mii_pollstat(mii); 588155324Simp ifmr->ifm_active = mii->mii_media_active; 589155324Simp ifmr->ifm_status = mii->mii_media_status; 590155324Simp ATE_UNLOCK(sc); 591155324Simp} 592155324Simp 593155324Simpstatic void 594163937Simpate_stat_update(struct ate_softc *sc, int active) 595163937Simp{ 596192027Sstas uint32_t reg; 597192027Sstas 598163937Simp /* 599163937Simp * The speed and full/half-duplex state needs to be reflected 600163937Simp * in the ETH_CFG register. 601163937Simp */ 602192027Sstas reg = RD4(sc, ETH_CFG); 603192027Sstas reg &= ~(ETH_CFG_SPD | ETH_CFG_FD); 604192027Sstas if (IFM_SUBTYPE(active) != IFM_10_T) 605192027Sstas reg |= ETH_CFG_SPD; 606163937Simp if (active & IFM_FDX) 607192027Sstas reg |= ETH_CFG_FD; 608192027Sstas WR4(sc, ETH_CFG, reg); 609163937Simp} 610163937Simp 611163937Simpstatic void 612155324Simpate_tick(void *xsc) 613155324Simp{ 614155324Simp struct ate_softc *sc = xsc; 615163937Simp struct ifnet *ifp = sc->ifp; 616155324Simp struct mii_data *mii; 617155324Simp int active; 618163937Simp uint32_t c; 619155324Simp 620155324Simp /* 621155324Simp * The KB920x boot loader tests ETH_SR & ETH_SR_LINK and will ask 622155324Simp * the MII if there's a link if this bit is clear. Not sure if we 623155324Simp * should do the same thing here or not. 624155324Simp */ 625155324Simp ATE_ASSERT_LOCKED(sc); 626155324Simp if (sc->miibus != NULL) { 627155324Simp mii = device_get_softc(sc->miibus); 628155324Simp active = mii->mii_media_active; 629155324Simp mii_tick(mii); 630155324Simp if (mii->mii_media_status & IFM_ACTIVE && 631163937Simp active != mii->mii_media_active) 632163937Simp ate_stat_update(sc, mii->mii_media_active); 633155324Simp } 634155324Simp 635155324Simp /* 636155324Simp * Update the stats as best we can. When we're done, clear 637155324Simp * the status counters and start over. We're supposed to read these 638155324Simp * registers often enough that they won't overflow. Hopefully 639155324Simp * once a second is often enough. Some don't map well to 640155324Simp * the dot3Stats mib, so for those we just count them as general 641155324Simp * errors. Stats for iframes, ibutes, oframes and obytes are 642155324Simp * collected elsewhere. These registers zero on a read to prevent 643163937Simp * races. For all the collision stats, also update the collision 644163937Simp * stats for the interface. 645155324Simp */ 646155324Simp sc->mibdata.dot3StatsAlignmentErrors += RD4(sc, ETH_ALE); 647155324Simp sc->mibdata.dot3StatsFCSErrors += RD4(sc, ETH_SEQE); 648163937Simp c = RD4(sc, ETH_SCOL); 649163937Simp ifp->if_collisions += c; 650163937Simp sc->mibdata.dot3StatsSingleCollisionFrames += c; 651163937Simp c = RD4(sc, ETH_MCOL); 652163937Simp sc->mibdata.dot3StatsMultipleCollisionFrames += c; 653163937Simp ifp->if_collisions += c; 654155324Simp sc->mibdata.dot3StatsSQETestErrors += RD4(sc, ETH_SQEE); 655155324Simp sc->mibdata.dot3StatsDeferredTransmissions += RD4(sc, ETH_DTE); 656163937Simp c = RD4(sc, ETH_LCOL); 657163937Simp sc->mibdata.dot3StatsLateCollisions += c; 658163937Simp ifp->if_collisions += c; 659163937Simp c = RD4(sc, ETH_ECOL); 660163937Simp sc->mibdata.dot3StatsExcessiveCollisions += c; 661163937Simp ifp->if_collisions += c; 662155324Simp sc->mibdata.dot3StatsCarrierSenseErrors += RD4(sc, ETH_CSE); 663155324Simp sc->mibdata.dot3StatsFrameTooLongs += RD4(sc, ETH_ELR); 664155324Simp sc->mibdata.dot3StatsInternalMacReceiveErrors += RD4(sc, ETH_DRFC); 665155324Simp /* 666155324Simp * not sure where to lump these, so count them against the errors 667155324Simp * for the interface. 668155324Simp */ 669163937Simp sc->ifp->if_oerrors += RD4(sc, ETH_TUE); 670155324Simp sc->ifp->if_ierrors += RD4(sc, ETH_CDE) + RD4(sc, ETH_RJB) + 671155324Simp RD4(sc, ETH_USF); 672155324Simp 673155324Simp /* 674155324Simp * Schedule another timeout one second from now. 675155324Simp */ 676155324Simp callout_reset(&sc->tick_ch, hz, ate_tick, sc); 677155324Simp} 678155324Simp 679155324Simpstatic void 680155445Scognetate_set_mac(struct ate_softc *sc, u_char *eaddr) 681155445Scognet{ 682155445Scognet WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) | 683155445Scognet (eaddr[1] << 8) | eaddr[0]); 684155445Scognet WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4])); 685155445Scognet} 686155445Scognet 687166573Simpstatic int 688155324Simpate_get_mac(struct ate_softc *sc, u_char *eaddr) 689155324Simp{ 690182477Sstas bus_size_t sa_low_reg[] = { ETH_SA1L, ETH_SA2L, ETH_SA3L, ETH_SA4L }; 691182477Sstas bus_size_t sa_high_reg[] = { ETH_SA1H, ETH_SA2H, ETH_SA3H, ETH_SA4H }; 692166573Simp uint32_t low, high; 693182477Sstas int i; 694155324Simp 695166573Simp /* 696166573Simp * The boot loader setup the MAC with an address, if one is set in 697182477Sstas * the loader. Grab one MAC address from the SA[1-4][HL] registers. 698166573Simp */ 699182477Sstas for (i = 0; i < 4; i++) { 700182477Sstas low = RD4(sc, sa_low_reg[i]); 701182477Sstas high = RD4(sc, sa_high_reg[i]); 702182477Sstas if ((low | (high & 0xffff)) != 0) { 703182477Sstas eaddr[0] = low & 0xff; 704182477Sstas eaddr[1] = (low >> 8) & 0xff; 705182477Sstas eaddr[2] = (low >> 16) & 0xff; 706182477Sstas eaddr[3] = (low >> 24) & 0xff; 707182477Sstas eaddr[4] = high & 0xff; 708182477Sstas eaddr[5] = (high >> 8) & 0xff; 709182477Sstas return (0); 710182477Sstas } 711182477Sstas } 712182477Sstas return (ENXIO); 713155324Simp} 714155324Simp 715155324Simpstatic void 716155324Simpate_intr(void *xsc) 717155324Simp{ 718155324Simp struct ate_softc *sc = xsc; 719163937Simp struct ifnet *ifp = sc->ifp; 720192027Sstas struct mbuf *mb; 721192027Sstas void *bp; 722192027Sstas uint32_t status, reg, rx_stat; 723155324Simp int i; 724156831Simp 725155324Simp status = RD4(sc, ETH_ISR); 726155324Simp if (status == 0) 727155324Simp return; 728155324Simp if (status & ETH_ISR_RCOM) { 729155324Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 730155324Simp BUS_DMASYNC_POSTREAD); 731157562Simp while (sc->rx_descs[sc->rx_buf_ptr].addr & ETH_CPU_OWNER) { 732157562Simp i = sc->rx_buf_ptr; 733157562Simp sc->rx_buf_ptr = (i + 1) % ATE_MAX_RX_BUFFERS; 734157562Simp bp = sc->rx_buf[i]; 735156831Simp rx_stat = sc->rx_descs[i].status; 736156831Simp if ((rx_stat & ETH_LEN_MASK) == 0) { 737156831Simp printf("ignoring bogus 0 len packet\n"); 738163937Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 739163937Simp BUS_DMASYNC_PREWRITE); 740157562Simp sc->rx_descs[i].addr &= ~ETH_CPU_OWNER; 741156831Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 742163937Simp BUS_DMASYNC_POSTWRITE); 743156831Simp continue; 744155324Simp } 745156831Simp /* Flush memory for mbuf so we don't get stale bytes */ 746156831Simp bus_dmamap_sync(sc->rxtag, sc->rx_map[i], 747156831Simp BUS_DMASYNC_POSTREAD); 748163937Simp WR4(sc, ETH_RSR, RD4(sc, ETH_RSR)); 749163937Simp 750156831Simp /* 751156831Simp * The length returned by the device includes the 752156831Simp * ethernet CRC calculation for the packet, but 753156831Simp * ifnet drivers are supposed to discard it. 754156831Simp */ 755157562Simp mb = m_devget(sc->rx_buf[i], 756157562Simp (rx_stat & ETH_LEN_MASK) - ETHER_CRC_LEN, 757163937Simp ETHER_ALIGN, ifp, NULL); 758163937Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 759163937Simp BUS_DMASYNC_PREWRITE); 760157562Simp sc->rx_descs[i].addr &= ~ETH_CPU_OWNER; 761157562Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 762163937Simp BUS_DMASYNC_POSTWRITE); 763156831Simp bus_dmamap_sync(sc->rxtag, sc->rx_map[i], 764156831Simp BUS_DMASYNC_PREREAD); 765163937Simp if (mb != NULL) { 766163937Simp ifp->if_ipackets++; 767163937Simp (*ifp->if_input)(ifp, mb); 768163937Simp } 769163937Simp 770155324Simp } 771155324Simp } 772155324Simp if (status & ETH_ISR_TCOM) { 773156831Simp ATE_LOCK(sc); 774163937Simp /* XXX TSR register should be cleared */ 775156831Simp if (sc->sent_mbuf[0]) { 776179693Swkoszek bus_dmamap_sync(sc->mtag, sc->tx_map[0], 777163937Simp BUS_DMASYNC_POSTWRITE); 778192018Sstas bus_dmamap_unload(sc->mtag, sc->tx_map[0]); 779155324Simp m_freem(sc->sent_mbuf[0]); 780163937Simp ifp->if_opackets++; 781156831Simp sc->sent_mbuf[0] = NULL; 782156831Simp } 783155324Simp if (sc->sent_mbuf[1]) { 784155324Simp if (RD4(sc, ETH_TSR) & ETH_TSR_IDLE) { 785179693Swkoszek bus_dmamap_sync(sc->mtag, sc->tx_map[1], 786163937Simp BUS_DMASYNC_POSTWRITE); 787192018Sstas bus_dmamap_unload(sc->mtag, sc->tx_map[1]); 788155324Simp m_freem(sc->sent_mbuf[1]); 789163937Simp ifp->if_opackets++; 790155324Simp sc->txcur = 0; 791155324Simp sc->sent_mbuf[0] = sc->sent_mbuf[1] = NULL; 792155324Simp } else { 793155324Simp sc->sent_mbuf[0] = sc->sent_mbuf[1]; 794155324Simp sc->sent_mbuf[1] = NULL; 795155324Simp sc->txcur = 1; 796155324Simp } 797155324Simp } else { 798155324Simp sc->sent_mbuf[0] = NULL; 799155324Simp sc->txcur = 0; 800155324Simp } 801156831Simp /* 802156831Simp * We're no longer busy, so clear the busy flag and call the 803156831Simp * start routine to xmit more packets. 804156831Simp */ 805156831Simp sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 806156831Simp atestart_locked(sc->ifp); 807156831Simp ATE_UNLOCK(sc); 808155324Simp } 809155324Simp if (status & ETH_ISR_RBNA) { 810155324Simp /* Workaround Errata #11 */ 811192027Sstas reg = RD4(sc, ETH_CTL); 812192027Sstas WR4(sc, ETH_CTL, reg & ~ETH_CTL_RE); 813192027Sstas BARRIER(sc, ETH_CTL, 4, BUS_SPACE_BARRIER_WRITE); 814192027Sstas WR4(sc, ETH_CTL, reg | ETH_CTL_RE); 815155324Simp } 816155324Simp} 817155324Simp 818155324Simp/* 819155324Simp * Reset and initialize the chip 820155324Simp */ 821155324Simpstatic void 822155324Simpateinit_locked(void *xsc) 823155324Simp{ 824155324Simp struct ate_softc *sc = xsc; 825155324Simp struct ifnet *ifp = sc->ifp; 826163937Simp struct mii_data *mii; 827192027Sstas uint32_t reg; 828155324Simp 829155324Simp ATE_ASSERT_LOCKED(sc); 830155324Simp 831155324Simp /* 832155324Simp * XXX TODO(3) 833155324Simp * we need to turn on the EMAC clock in the pmc. With the 834155324Simp * default boot loader, this is already turned on. However, we 835155324Simp * need to think about how best to turn it on/off as the interface 836155324Simp * is brought up/down, as well as dealing with the mii bus... 837155324Simp * 838155324Simp * We also need to multiplex the pins correctly. 839155324Simp */ 840155324Simp 841155324Simp /* 842155324Simp * There are two different ways that the mii bus is connected 843155324Simp * to this chip. Select the right one based on a compile-time 844155324Simp * option. 845155324Simp */ 846192027Sstas reg = RD4(sc, ETH_CFG); 847159708Simp if (sc->use_rmii) 848192027Sstas reg |= ETH_CFG_RMII; 849159708Simp else 850192027Sstas reg &= ~ETH_CFG_RMII; 851192027Sstas WR4(sc, ETH_CFG, reg); 852159708Simp 853191960Sstas ate_rxfilter(sc); 854191960Sstas 855191960Sstas /* 856191960Sstas * Turn on MACs and interrupt processing. 857191960Sstas */ 858155324Simp WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE); 859156831Simp WR4(sc, ETH_IER, ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA); 860155324Simp 861155324Simp /* 862155324Simp * Boot loader fills in MAC address. If that's not the case, then 863155324Simp * we should set SA1L and SA1H here to the appropriate value. Note: 864155324Simp * the byte order is big endian, not little endian, so we have some 865155324Simp * swapping to do. Again, if we need it (which I don't think we do). 866155324Simp */ 867155324Simp 868165779Sticso /* enable big packets */ 869165779Sticso WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG); 870165779Sticso 871155324Simp /* 872155324Simp * Set 'running' flag, and clear output active flag 873155324Simp * and attempt to start the output 874155324Simp */ 875155324Simp ifp->if_drv_flags |= IFF_DRV_RUNNING; 876155324Simp ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 877163937Simp 878163937Simp mii = device_get_softc(sc->miibus); 879163937Simp mii_pollstat(mii); 880163937Simp ate_stat_update(sc, mii->mii_media_active); 881155324Simp atestart_locked(ifp); 882155324Simp 883155324Simp callout_reset(&sc->tick_ch, hz, ate_tick, sc); 884155324Simp} 885155324Simp 886155324Simp/* 887155324Simp * dequeu packets and transmit 888155324Simp */ 889155324Simpstatic void 890155324Simpatestart_locked(struct ifnet *ifp) 891155324Simp{ 892155324Simp struct ate_softc *sc = ifp->if_softc; 893155324Simp struct mbuf *m, *mdefrag; 894155324Simp bus_dma_segment_t segs[1]; 895163937Simp int nseg, e; 896155324Simp 897155324Simp ATE_ASSERT_LOCKED(sc); 898155324Simp if (ifp->if_drv_flags & IFF_DRV_OACTIVE) 899155324Simp return; 900155324Simp 901156831Simp while (sc->txcur < ATE_MAX_TX_BUFFERS) { 902156831Simp /* 903156831Simp * check to see if there's room to put another packet into the 904156831Simp * xmit queue. The EMAC chip has a ping-pong buffer for xmit 905156831Simp * packets. We use OACTIVE to indicate "we can stuff more into 906156831Simp * our buffers (clear) or not (set)." 907156831Simp */ 908156831Simp if (!(RD4(sc, ETH_TSR) & ETH_TSR_BNQ)) { 909156831Simp ifp->if_drv_flags |= IFF_DRV_OACTIVE; 910156831Simp return; 911156831Simp } 912156831Simp IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 913156831Simp if (m == 0) { 914156831Simp ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 915156831Simp return; 916156831Simp } 917163937Simp e = bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txcur], m, 918163937Simp segs, &nseg, 0); 919163937Simp if (e == EFBIG) { 920163937Simp mdefrag = m_defrag(m, M_DONTWAIT); 921163937Simp if (mdefrag == NULL) { 922163937Simp IFQ_DRV_PREPEND(&ifp->if_snd, m); 923163937Simp return; 924163937Simp } 925163937Simp m = mdefrag; 926163937Simp e = bus_dmamap_load_mbuf_sg(sc->mtag, 927163937Simp sc->tx_map[sc->txcur], m, segs, &nseg, 0); 928156831Simp } 929163937Simp if (e != 0) { 930156831Simp m_freem(m); 931156831Simp continue; 932156831Simp } 933156831Simp bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txcur], 934156831Simp BUS_DMASYNC_PREWRITE); 935155324Simp 936156831Simp /* 937156831Simp * tell the hardware to xmit the packet. 938156831Simp */ 939156831Simp WR4(sc, ETH_TAR, segs[0].ds_addr); 940192027Sstas BARRIER(sc, ETH_TAR, 8, BUS_SPACE_BARRIER_WRITE); 941156831Simp WR4(sc, ETH_TCR, segs[0].ds_len); 942155324Simp 943156831Simp /* 944156831Simp * Tap off here if there is a bpf listener. 945156831Simp */ 946156831Simp BPF_MTAP(ifp, m); 947155324Simp 948156831Simp sc->sent_mbuf[sc->txcur] = m; 949156831Simp sc->txcur++; 950156831Simp } 951155324Simp} 952155324Simp 953155324Simpstatic void 954155324Simpateinit(void *xsc) 955155324Simp{ 956155324Simp struct ate_softc *sc = xsc; 957155324Simp ATE_LOCK(sc); 958155324Simp ateinit_locked(sc); 959155324Simp ATE_UNLOCK(sc); 960155324Simp} 961155324Simp 962155324Simpstatic void 963155324Simpatestart(struct ifnet *ifp) 964155324Simp{ 965155324Simp struct ate_softc *sc = ifp->if_softc; 966155324Simp ATE_LOCK(sc); 967155324Simp atestart_locked(ifp); 968155324Simp ATE_UNLOCK(sc); 969155324Simp} 970155324Simp 971155324Simp/* 972155324Simp * Turn off interrupts, and stop the nic. Can be called with sc->ifp NULL 973155324Simp * so be careful. 974155324Simp */ 975155324Simpstatic void 976155324Simpatestop(struct ate_softc *sc) 977155324Simp{ 978192018Sstas struct ifnet *ifp; 979192018Sstas int i; 980155324Simp 981192018Sstas ATE_ASSERT_LOCKED(sc); 982192018Sstas ifp = sc->ifp; 983155324Simp if (ifp) { 984155324Simp ifp->if_timer = 0; 985155324Simp ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 986155324Simp } 987155324Simp 988155324Simp callout_stop(&sc->tick_ch); 989155324Simp 990155324Simp /* 991155324Simp * Enable some parts of the MAC that are needed always (like the 992155324Simp * MII bus. This turns off the RE and TE bits, which will remain 993155405Scognet * off until ateinit() is called to turn them on. With RE and TE 994155324Simp * turned off, there's no DMA to worry about after this write. 995155324Simp */ 996155324Simp WR4(sc, ETH_CTL, ETH_CTL_MPE); 997155324Simp 998155324Simp /* 999155324Simp * Turn off all the configured options and revert to defaults. 1000155324Simp */ 1001155324Simp WR4(sc, ETH_CFG, ETH_CFG_CLK_32); 1002155324Simp 1003155324Simp /* 1004155324Simp * Turn off all the interrupts, and ack any pending ones by reading 1005155324Simp * the ISR. 1006155324Simp */ 1007155324Simp WR4(sc, ETH_IDR, 0xffffffff); 1008155324Simp RD4(sc, ETH_ISR); 1009155324Simp 1010155324Simp /* 1011155324Simp * Clear out the Transmit and Receiver Status registers of any 1012155324Simp * errors they may be reporting 1013155324Simp */ 1014155324Simp WR4(sc, ETH_TSR, 0xffffffff); 1015155324Simp WR4(sc, ETH_RSR, 0xffffffff); 1016155324Simp 1017155324Simp /* 1018192018Sstas * Release TX resources. 1019155324Simp */ 1020192018Sstas for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 1021192018Sstas if (sc->sent_mbuf[i] != NULL) { 1022192018Sstas bus_dmamap_sync(sc->mtag, sc->tx_map[i], 1023192018Sstas BUS_DMASYNC_POSTWRITE); 1024192018Sstas bus_dmamap_unload(sc->mtag, sc->tx_map[i]); 1025192018Sstas m_freem(sc->sent_mbuf[i]); 1026192018Sstas sc->sent_mbuf[i] = NULL; 1027192018Sstas } 1028192018Sstas } 1029155324Simp 1030155324Simp /* 1031155324Simp * XXX we should power down the EMAC if it isn't in use, after 1032155324Simp * putting it into loopback mode. This saves about 400uA according 1033155324Simp * to the datasheet. 1034155324Simp */ 1035155324Simp} 1036155324Simp 1037191959Sstasstatic void 1038191959Sstasate_rxfilter(struct ate_softc *sc) 1039191959Sstas{ 1040191959Sstas struct ifnet *ifp; 1041191959Sstas uint32_t reg; 1042191960Sstas int enabled; 1043191959Sstas 1044191959Sstas KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__)); 1045191959Sstas ATE_ASSERT_LOCKED(sc); 1046191959Sstas ifp = sc->ifp; 1047191959Sstas 1048191959Sstas /* 1049191959Sstas * Wipe out old filter settings. 1050191959Sstas */ 1051191959Sstas reg = RD4(sc, ETH_CFG); 1052191959Sstas reg &= ~(ETH_CFG_CAF | ETH_CFG_MTI | ETH_CFG_UNI); 1053191959Sstas reg |= ETH_CFG_NBC; 1054191960Sstas sc->flags &= ~ATE_FLAG_MULTICAST; 1055191959Sstas 1056191959Sstas /* 1057191959Sstas * Set new parameters. 1058191959Sstas */ 1059191959Sstas if ((ifp->if_flags & IFF_BROADCAST) != 0) 1060191959Sstas reg &= ~ETH_CFG_NBC; 1061191960Sstas if ((ifp->if_flags & IFF_PROMISC) != 0) { 1062191959Sstas reg |= ETH_CFG_CAF; 1063191960Sstas } else { 1064191960Sstas enabled = ate_setmcast(sc); 1065191960Sstas if (enabled != 0) { 1066191960Sstas reg |= ETH_CFG_MTI; 1067191960Sstas sc->flags |= ATE_FLAG_MULTICAST; 1068191960Sstas } 1069191960Sstas } 1070191959Sstas WR4(sc, ETH_CFG, reg); 1071191959Sstas} 1072191959Sstas 1073155324Simpstatic int 1074155324Simpateioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1075155324Simp{ 1076155324Simp struct ate_softc *sc = ifp->if_softc; 1077157562Simp struct mii_data *mii; 1078157562Simp struct ifreq *ifr = (struct ifreq *)data; 1079191959Sstas int drv_flags, flags; 1080191960Sstas int mask, error, enabled; 1081155324Simp 1082191960Sstas error = 0; 1083191959Sstas flags = ifp->if_flags; 1084191959Sstas drv_flags = ifp->if_drv_flags; 1085155324Simp switch (cmd) { 1086155324Simp case SIOCSIFFLAGS: 1087155324Simp ATE_LOCK(sc); 1088191959Sstas if ((flags & IFF_UP) != 0) { 1089191959Sstas if ((drv_flags & IFF_DRV_RUNNING) != 0) { 1090191959Sstas if (((flags ^ sc->if_flags) 1091191959Sstas & (IFF_PROMISC | IFF_ALLMULTI)) != 0) 1092191959Sstas ate_rxfilter(sc); 1093191959Sstas } else { 1094191959Sstas if ((sc->flags & ATE_FLAG_DETACHING) == 0) 1095191959Sstas ateinit_locked(sc); 1096191959Sstas } 1097191959Sstas } else if ((drv_flags & IFF_DRV_RUNNING) != 0) { 1098155324Simp ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1099155324Simp atestop(sc); 1100155324Simp } 1101191959Sstas sc->if_flags = flags; 1102155324Simp ATE_UNLOCK(sc); 1103155324Simp break; 1104155324Simp 1105155324Simp case SIOCADDMULTI: 1106155324Simp case SIOCDELMULTI: 1107191960Sstas if ((drv_flags & IFF_DRV_RUNNING) != 0) { 1108191960Sstas ATE_LOCK(sc); 1109191960Sstas enabled = ate_setmcast(sc); 1110191960Sstas if (enabled != (sc->flags & ATE_FLAG_MULTICAST)) 1111191960Sstas ate_rxfilter(sc); 1112191960Sstas ATE_UNLOCK(sc); 1113191960Sstas } 1114155324Simp break; 1115155324Simp 1116157562Simp case SIOCSIFMEDIA: 1117157562Simp case SIOCGIFMEDIA: 1118157562Simp mii = device_get_softc(sc->miibus); 1119157562Simp error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1120157562Simp break; 1121165779Sticso case SIOCSIFCAP: 1122165779Sticso mask = ifp->if_capenable ^ ifr->ifr_reqcap; 1123165779Sticso if (mask & IFCAP_VLAN_MTU) { 1124165779Sticso ATE_LOCK(sc); 1125165779Sticso if (ifr->ifr_reqcap & IFCAP_VLAN_MTU) { 1126165779Sticso WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG); 1127165779Sticso ifp->if_capenable |= IFCAP_VLAN_MTU; 1128165779Sticso } else { 1129165779Sticso WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_BIG); 1130165779Sticso ifp->if_capenable &= ~IFCAP_VLAN_MTU; 1131165779Sticso } 1132165779Sticso ATE_UNLOCK(sc); 1133165779Sticso } 1134155324Simp default: 1135155324Simp error = ether_ioctl(ifp, cmd, data); 1136155324Simp break; 1137155324Simp } 1138155324Simp return (error); 1139155324Simp} 1140155324Simp 1141155324Simpstatic void 1142155324Simpate_child_detached(device_t dev, device_t child) 1143155324Simp{ 1144155324Simp struct ate_softc *sc; 1145155324Simp 1146155324Simp sc = device_get_softc(dev); 1147155324Simp if (child == sc->miibus) 1148155324Simp sc->miibus = NULL; 1149155324Simp} 1150155324Simp 1151155324Simp/* 1152155324Simp * MII bus support routines. 1153155324Simp */ 1154155324Simpstatic int 1155155324Simpate_miibus_readreg(device_t dev, int phy, int reg) 1156155324Simp{ 1157155324Simp struct ate_softc *sc; 1158155324Simp int val; 1159155324Simp 1160155324Simp /* 1161155324Simp * XXX if we implement agressive power savings, then we need 1162155324Simp * XXX to make sure that the clock to the emac is on here 1163155324Simp */ 1164155324Simp 1165155324Simp sc = device_get_softc(dev); 1166155324Simp DELAY(1); /* Hangs w/o this delay really 30.5us atm */ 1167155324Simp WR4(sc, ETH_MAN, ETH_MAN_REG_RD(phy, reg)); 1168155324Simp while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0) 1169155324Simp continue; 1170155324Simp val = RD4(sc, ETH_MAN) & ETH_MAN_VALUE_MASK; 1171155324Simp 1172155324Simp return (val); 1173155324Simp} 1174155324Simp 1175155324Simpstatic void 1176155324Simpate_miibus_writereg(device_t dev, int phy, int reg, int data) 1177155324Simp{ 1178155324Simp struct ate_softc *sc; 1179155324Simp 1180155324Simp /* 1181155324Simp * XXX if we implement agressive power savings, then we need 1182155324Simp * XXX to make sure that the clock to the emac is on here 1183155324Simp */ 1184155324Simp 1185155324Simp sc = device_get_softc(dev); 1186155324Simp WR4(sc, ETH_MAN, ETH_MAN_REG_WR(phy, reg, data)); 1187155324Simp while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0) 1188155324Simp continue; 1189155324Simp return; 1190155324Simp} 1191155324Simp 1192155324Simpstatic device_method_t ate_methods[] = { 1193155324Simp /* Device interface */ 1194155324Simp DEVMETHOD(device_probe, ate_probe), 1195155324Simp DEVMETHOD(device_attach, ate_attach), 1196155324Simp DEVMETHOD(device_detach, ate_detach), 1197155324Simp 1198155324Simp /* Bus interface */ 1199155324Simp DEVMETHOD(bus_child_detached, ate_child_detached), 1200155324Simp 1201155324Simp /* MII interface */ 1202155324Simp DEVMETHOD(miibus_readreg, ate_miibus_readreg), 1203155324Simp DEVMETHOD(miibus_writereg, ate_miibus_writereg), 1204155324Simp 1205155324Simp { 0, 0 } 1206155324Simp}; 1207155324Simp 1208155324Simpstatic driver_t ate_driver = { 1209155324Simp "ate", 1210155324Simp ate_methods, 1211155324Simp sizeof(struct ate_softc), 1212155324Simp}; 1213155324Simp 1214155324SimpDRIVER_MODULE(ate, atmelarm, ate_driver, ate_devclass, 0, 0); 1215155324SimpDRIVER_MODULE(miibus, ate, miibus_driver, miibus_devclass, 0, 0); 1216155324SimpMODULE_DEPEND(ate, miibus, 1, 1, 1); 1217155324SimpMODULE_DEPEND(ate, ether, 1, 1, 1); 1218