if_ate.c revision 238895
1155324Simp/*- 2155324Simp * Copyright (c) 2006 M. Warner Losh. All rights reserved. 3213496Scognet * Copyright (c) 2009 Greg Ansley. All rights reserved. 4155324Simp * 5155324Simp * Redistribution and use in source and binary forms, with or without 6155324Simp * modification, are permitted provided that the following conditions 7155324Simp * are met: 8155324Simp * 1. Redistributions of source code must retain the above copyright 9155324Simp * notice, this list of conditions and the following disclaimer. 10155324Simp * 2. Redistributions in binary form must reproduce the above copyright 11155324Simp * notice, this list of conditions and the following disclaimer in the 12155324Simp * documentation and/or other materials provided with the distribution. 13155324Simp * 14185267Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15185267Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16185267Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17185267Simp * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18185267Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19185267Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20185267Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21185267Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22185267Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23185267Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24185267Simp * SUCH DAMAGE. 25155324Simp */ 26155324Simp 27192018Sstas/* TODO 28155324Simp * 29192018Sstas * 1) Turn on the clock in pmc? Turn off? 30192018Sstas * 2) GPIO initializtion in board setup code. 31155324Simp */ 32155324Simp 33155324Simp#include <sys/cdefs.h> 34155324Simp__FBSDID("$FreeBSD: head/sys/arm/at91/if_ate.c 238895 2012-07-30 06:00:31Z imp $"); 35155324Simp 36155324Simp#include <sys/param.h> 37155324Simp#include <sys/systm.h> 38155324Simp#include <sys/bus.h> 39155324Simp#include <sys/kernel.h> 40213496Scognet#include <sys/malloc.h> 41155324Simp#include <sys/mbuf.h> 42155324Simp#include <sys/module.h> 43155324Simp#include <sys/rman.h> 44155324Simp#include <sys/socket.h> 45155324Simp#include <sys/sockio.h> 46163522Simp#include <sys/sysctl.h> 47213496Scognet 48155324Simp#include <machine/bus.h> 49155324Simp 50155324Simp#include <net/ethernet.h> 51155324Simp#include <net/if.h> 52155324Simp#include <net/if_arp.h> 53155324Simp#include <net/if_dl.h> 54155324Simp#include <net/if_media.h> 55155324Simp#include <net/if_mib.h> 56155324Simp#include <net/if_types.h> 57155324Simp 58155324Simp#ifdef INET 59155324Simp#include <netinet/in.h> 60155324Simp#include <netinet/in_systm.h> 61155324Simp#include <netinet/in_var.h> 62155324Simp#include <netinet/ip.h> 63155324Simp#endif 64155324Simp 65155324Simp#include <net/bpf.h> 66155324Simp#include <net/bpfdesc.h> 67155324Simp 68155324Simp#include <dev/mii/mii.h> 69155324Simp#include <dev/mii/miivar.h> 70213496Scognet 71213496Scognet#include "opt_at91.h" 72213496Scognet#include <arm/at91/at91reg.h> 73213496Scognet#include <arm/at91/at91var.h> 74155324Simp#include <arm/at91/if_atereg.h> 75155324Simp 76155324Simp#include "miibus_if.h" 77155324Simp 78191959Sstas/* 79191959Sstas * Driver-specific flags. 80191959Sstas */ 81213496Scognet#define ATE_FLAG_DETACHING 0x01 82213496Scognet#define ATE_FLAG_MULTICAST 0x02 83191959Sstas 84213496Scognet/* 85213496Scognet * Old EMAC assumes whole packet fits in one buffer; 86213496Scognet * new EBACB assumes all receive buffers are 128 bytes 87213496Scognet */ 88213496Scognet#define RX_BUF_SIZE(sc) (sc->is_emacb ? 128 : MCLBYTES) 89213496Scognet 90213496Scognet/* 91213496Scognet * EMACB has an 11 bit counter for Rx/Tx Descriptors 92213496Scognet * for max total of 1024 decriptors each. 93213496Scognet */ 94213496Scognet#define ATE_MAX_RX_DESCR 1024 95213496Scognet#define ATE_MAX_TX_DESCR 1024 96213496Scognet 97213496Scognet/* How many buffers to allocate */ 98213496Scognet#define ATE_MAX_TX_BUFFERS 4 /* We have ping-pong tx buffers */ 99213496Scognet 100213496Scognet/* How much memory to use for rx buffers */ 101213496Scognet#define ATE_RX_MEMORY (ATE_MAX_RX_DESCR * 128) 102213496Scognet 103213496Scognet/* Actual number of descriptors we allocate */ 104213496Scognet#define ATE_NUM_RX_DESCR ATE_MAX_RX_DESCR 105213496Scognet#define ATE_NUM_TX_DESCR ATE_MAX_TX_BUFFERS 106213496Scognet 107213496Scognet#if ATE_NUM_TX_DESCR > ATE_MAX_TX_DESCR 108213496Scognet#error "Can't have more TX buffers that descriptors" 109213496Scognet#endif 110213496Scognet#if ATE_NUM_RX_DESCR > ATE_MAX_RX_DESCR 111213496Scognet#error "Can't have more RX buffers that descriptors" 112213496Scognet#endif 113213496Scognet 114213496Scognet/* Wrap indexes the same way the hardware does */ 115213496Scognet#define NEXT_RX_IDX(sc, cur) \ 116213496Scognet ((sc->rx_descs[cur].addr & ETH_WRAP_BIT) ? 0 : (cur + 1)) 117213496Scognet 118213496Scognet#define NEXT_TX_IDX(sc, cur) \ 119213496Scognet ((sc->tx_descs[cur].status & ETHB_TX_WRAP) ? 0 : (cur + 1)) 120213496Scognet 121155324Simpstruct ate_softc 122155324Simp{ 123234281Smarius struct ifnet *ifp; /* ifnet pointer */ 124234281Smarius struct mtx sc_mtx; /* Basically a perimeter lock */ 125234281Smarius device_t dev; /* Myself */ 126234281Smarius device_t miibus; /* My child miibus */ 127234281Smarius struct resource *irq_res; /* IRQ resource */ 128234281Smarius struct resource *mem_res; /* Memory resource */ 129234281Smarius struct callout tick_ch; /* Tick callout */ 130192063Sstas struct ifmib_iso_8802_3 mibdata; /* Stuff for network mgmt */ 131234281Smarius bus_dma_tag_t mtag; /* bus dma tag for mbufs */ 132213496Scognet bus_dma_tag_t rx_tag; 133213496Scognet bus_dma_tag_t rx_desc_tag; 134213496Scognet bus_dmamap_t rx_desc_map; 135213496Scognet bus_dmamap_t rx_map[ATE_MAX_RX_DESCR]; 136234281Smarius bus_addr_t rx_desc_phys; /* PA of rx descriptors */ 137234281Smarius eth_rx_desc_t *rx_descs; /* VA of rx descriptors */ 138234281Smarius void *rx_buf[ATE_NUM_RX_DESCR]; /* RX buffer space */ 139234281Smarius int rxhead; /* Current RX map/desc index */ 140234281Smarius uint32_t rx_buf_size; /* Size of Rx buffers */ 141213496Scognet 142213496Scognet bus_dma_tag_t tx_desc_tag; 143213496Scognet bus_dmamap_t tx_desc_map; 144213496Scognet bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS]; 145234281Smarius bus_addr_t tx_desc_phys; /* PA of tx descriptors */ 146234281Smarius eth_tx_desc_t *tx_descs; /* VA of tx descriptors */ 147234281Smarius int txhead; /* Current TX map/desc index */ 148234281Smarius int txtail; /* Current TX map/desc index */ 149234281Smarius struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */ 150234281Smarius void *intrhand; /* Interrupt handle */ 151234281Smarius int flags; 152234281Smarius int if_flags; 153234281Smarius int use_rmii; 154234281Smarius int is_emacb; /* SAM9x hardware version */ 155155324Simp}; 156155324Simp 157155324Simpstatic inline uint32_t 158155324SimpRD4(struct ate_softc *sc, bus_size_t off) 159155324Simp{ 160192063Sstas 161192063Sstas return (bus_read_4(sc->mem_res, off)); 162155324Simp} 163155324Simp 164155324Simpstatic inline void 165155324SimpWR4(struct ate_softc *sc, bus_size_t off, uint32_t val) 166155324Simp{ 167192063Sstas 168155324Simp bus_write_4(sc->mem_res, off, val); 169155324Simp} 170155324Simp 171192027Sstasstatic inline void 172192027SstasBARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags) 173192027Sstas{ 174192027Sstas 175192027Sstas bus_barrier(sc->mem_res, off, len, flags); 176192027Sstas} 177192027Sstas 178192063Sstas#define ATE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 179155324Simp#define ATE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 180192063Sstas#define ATE_LOCK_INIT(_sc) \ 181192063Sstas mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ 182155324Simp MTX_NETWORK_LOCK, MTX_DEF) 183192063Sstas#define ATE_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 184192063Sstas#define ATE_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 185192063Sstas#define ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 186155324Simp 187155324Simpstatic devclass_t ate_devclass; 188155324Simp 189192063Sstas/* 190192063Sstas * ifnet entry points. 191192063Sstas */ 192192063Sstasstatic void ateinit_locked(void *); 193192063Sstasstatic void atestart_locked(struct ifnet *); 194155324Simp 195192063Sstasstatic void ateinit(void *); 196192063Sstasstatic void atestart(struct ifnet *); 197192063Sstasstatic void atestop(struct ate_softc *); 198192063Sstasstatic int ateioctl(struct ifnet * ifp, u_long, caddr_t); 199155324Simp 200192063Sstas/* 201192063Sstas * Bus entry points. 202192063Sstas */ 203192063Sstasstatic int ate_probe(device_t dev); 204192063Sstasstatic int ate_attach(device_t dev); 205192063Sstasstatic int ate_detach(device_t dev); 206192063Sstasstatic void ate_intr(void *); 207155324Simp 208192063Sstas/* 209192063Sstas * Helper routines. 210192063Sstas */ 211192063Sstasstatic int ate_activate(device_t dev); 212192063Sstasstatic void ate_deactivate(struct ate_softc *sc); 213192063Sstasstatic int ate_ifmedia_upd(struct ifnet *ifp); 214192063Sstasstatic void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 215192063Sstasstatic int ate_get_mac(struct ate_softc *sc, u_char *eaddr); 216192063Sstasstatic void ate_set_mac(struct ate_softc *sc, u_char *eaddr); 217191959Sstasstatic void ate_rxfilter(struct ate_softc *sc); 218155324Simp 219213496Scognetstatic int ate_miibus_readreg(device_t dev, int phy, int reg); 220213496Scognet 221213496Scognetstatic int ate_miibus_writereg(device_t dev, int phy, int reg, int data); 222155324Simp/* 223213496Scognet * The AT91 family of products has the ethernet interface called EMAC. 224213496Scognet * However, it isn't self identifying. It is anticipated that the parent bus 225155324Simp * code will take care to only add ate devices where they really are. As 226155324Simp * such, we do nothing here to identify the device and just set its name. 227155324Simp */ 228155324Simpstatic int 229155324Simpate_probe(device_t dev) 230155324Simp{ 231192063Sstas 232155324Simp device_set_desc(dev, "EMAC"); 233155324Simp return (0); 234155324Simp} 235155324Simp 236155324Simpstatic int 237155324Simpate_attach(device_t dev) 238155324Simp{ 239192063Sstas struct ate_softc *sc; 240155324Simp struct ifnet *ifp = NULL; 241163522Simp struct sysctl_ctx_list *sctx; 242163522Simp struct sysctl_oid *soid; 243182477Sstas u_char eaddr[ETHER_ADDR_LEN]; 244182477Sstas uint32_t rnd; 245192018Sstas int rid, err; 246155324Simp 247192063Sstas sc = device_get_softc(dev); 248155324Simp sc->dev = dev; 249192018Sstas ATE_LOCK_INIT(sc); 250234281Smarius 251192018Sstas rid = 0; 252192018Sstas sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 253192018Sstas RF_ACTIVE); 254192018Sstas if (sc->mem_res == NULL) { 255192018Sstas device_printf(dev, "could not allocate memory resources.\n"); 256192018Sstas err = ENOMEM; 257192018Sstas goto out; 258192018Sstas } 259192018Sstas rid = 0; 260192018Sstas sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 261192018Sstas RF_ACTIVE); 262192018Sstas if (sc->irq_res == NULL) { 263192018Sstas device_printf(dev, "could not allocate interrupt resources.\n"); 264192018Sstas err = ENOMEM; 265192018Sstas goto out; 266192018Sstas } 267192018Sstas 268213496Scognet /* New or old version, chooses buffer size. */ 269234291Smarius sc->is_emacb = at91_is_sam9() || at91_is_sam9xe(); 270213496Scognet sc->rx_buf_size = RX_BUF_SIZE(sc); 271213496Scognet 272155324Simp err = ate_activate(dev); 273155324Simp if (err) 274155324Simp goto out; 275155324Simp 276213496Scognet /* Default to what boot rom did */ 277213496Scognet if (!sc->is_emacb) 278213496Scognet sc->use_rmii = 279213496Scognet (RD4(sc, ETH_CFG) & ETH_CFG_RMII) == ETH_CFG_RMII; 280213496Scognet else 281213496Scognet sc->use_rmii = 282213496Scognet (RD4(sc, ETHB_UIO) & ETHB_UIO_RMII) == ETHB_UIO_RMII; 283159708Simp 284213496Scognet#ifdef AT91_ATE_USE_RMII 285213496Scognet /* Compile time override */ 286213496Scognet sc->use_rmii = 1; 287213496Scognet#endif 288182476Sstas /* Sysctls */ 289163522Simp sctx = device_get_sysctl_ctx(dev); 290163522Simp soid = device_get_sysctl_tree(dev); 291163522Simp SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "rmii", 292213496Scognet CTLFLAG_RW, &sc->use_rmii, 0, "rmii in use"); 293163522Simp 294192063Sstas /* Calling atestop before ifp is set is OK. */ 295192018Sstas ATE_LOCK(sc); 296155324Simp atestop(sc); 297192018Sstas ATE_UNLOCK(sc); 298213496Scognet callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0); 299155324Simp 300166573Simp if ((err = ate_get_mac(sc, eaddr)) != 0) { 301213496Scognet /* No MAC address configured. Generate the random one. */ 302213496Scognet if (bootverbose) 303182477Sstas device_printf(dev, 304182524Sstas "Generating random ethernet address.\n"); 305182477Sstas rnd = arc4random(); 306182477Sstas 307182477Sstas /* 308182555Simp * Set OUI to convenient locally assigned address. 'b' 309182555Simp * is 0x62, which has the locally assigned bit set, and 310182555Simp * the broadcast/multicast bit clear. 311182477Sstas */ 312182555Simp eaddr[0] = 'b'; 313182555Simp eaddr[1] = 's'; 314182555Simp eaddr[2] = 'd'; 315182477Sstas eaddr[3] = (rnd >> 16) & 0xff; 316213496Scognet eaddr[4] = (rnd >> 8) & 0xff; 317213496Scognet eaddr[5] = (rnd >> 0) & 0xff; 318166573Simp } 319155324Simp 320155405Scognet sc->ifp = ifp = if_alloc(IFT_ETHER); 321213894Smarius err = mii_attach(dev, &sc->miibus, ifp, ate_ifmedia_upd, 322213894Smarius ate_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); 323213894Smarius if (err != 0) { 324213894Smarius device_printf(dev, "attaching PHYs failed\n"); 325155324Simp goto out; 326155324Simp } 327213496Scognet /* 328234281Smarius * XXX: Clear the isolate bit, or we won't get up, 329234281Smarius * at least on the HL201 330213496Scognet */ 331213496Scognet ate_miibus_writereg(dev, 0, 0, 0x3000); 332155324Simp 333155324Simp ifp->if_softc = sc; 334155324Simp if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 335155324Simp ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 336165779Sticso ifp->if_capabilities |= IFCAP_VLAN_MTU; 337192063Sstas ifp->if_capenable |= IFCAP_VLAN_MTU; /* The hw bits already set. */ 338155324Simp ifp->if_start = atestart; 339155324Simp ifp->if_ioctl = ateioctl; 340155324Simp ifp->if_init = ateinit; 341155324Simp ifp->if_baudrate = 10000000; 342213496Scognet IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 343213496Scognet ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; 344155324Simp IFQ_SET_READY(&ifp->if_snd); 345155324Simp ifp->if_linkmib = &sc->mibdata; 346155324Simp ifp->if_linkmiblen = sizeof(sc->mibdata); 347155324Simp sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS; 348191959Sstas sc->if_flags = ifp->if_flags; 349155324Simp 350155324Simp ether_ifattach(ifp, eaddr); 351155324Simp 352213496Scognet /* Activate the interrupt. */ 353155324Simp err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, 354166901Spiso NULL, ate_intr, sc, &sc->intrhand); 355155324Simp if (err) { 356192018Sstas device_printf(dev, "could not establish interrupt handler.\n"); 357155324Simp ether_ifdetach(ifp); 358192018Sstas goto out; 359155324Simp } 360192018Sstas 361192018Sstasout: 362155324Simp if (err) 363192018Sstas ate_detach(dev); 364155324Simp return (err); 365155324Simp} 366155324Simp 367155324Simpstatic int 368155324Simpate_detach(device_t dev) 369155324Simp{ 370192018Sstas struct ate_softc *sc; 371192018Sstas struct ifnet *ifp; 372192018Sstas 373192018Sstas sc = device_get_softc(dev); 374192018Sstas KASSERT(sc != NULL, ("[ate: %d]: sc is NULL", __LINE__)); 375192018Sstas ifp = sc->ifp; 376192018Sstas if (device_is_attached(dev)) { 377192018Sstas ATE_LOCK(sc); 378213496Scognet sc->flags |= ATE_FLAG_DETACHING; 379213496Scognet atestop(sc); 380192018Sstas ATE_UNLOCK(sc); 381192018Sstas callout_drain(&sc->tick_ch); 382213496Scognet ether_ifdetach(ifp); 383192018Sstas } 384192018Sstas if (sc->miibus != NULL) { 385192018Sstas device_delete_child(dev, sc->miibus); 386192018Sstas sc->miibus = NULL; 387192018Sstas } 388192018Sstas bus_generic_detach(sc->dev); 389192018Sstas ate_deactivate(sc); 390192018Sstas if (sc->intrhand != NULL) { 391192018Sstas bus_teardown_intr(dev, sc->irq_res, sc->intrhand); 392192018Sstas sc->intrhand = NULL; 393192018Sstas } 394192018Sstas if (ifp != NULL) { 395192018Sstas if_free(ifp); 396192018Sstas sc->ifp = NULL; 397192018Sstas } 398192018Sstas if (sc->mem_res != NULL) { 399192018Sstas bus_release_resource(dev, SYS_RES_IOPORT, 400192018Sstas rman_get_rid(sc->mem_res), sc->mem_res); 401192018Sstas sc->mem_res = NULL; 402192018Sstas } 403192018Sstas if (sc->irq_res != NULL) { 404192018Sstas bus_release_resource(dev, SYS_RES_IRQ, 405192018Sstas rman_get_rid(sc->irq_res), sc->irq_res); 406192018Sstas sc->irq_res = NULL; 407192018Sstas } 408192018Sstas ATE_LOCK_DESTROY(sc); 409192018Sstas return (0); 410155324Simp} 411155324Simp 412155324Simpstatic void 413155324Simpate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 414155324Simp{ 415155324Simp 416155324Simp if (error != 0) 417155324Simp return; 418213496Scognet *(bus_addr_t *)arg = segs[0].ds_addr; 419155324Simp} 420155324Simp 421157562Simpstatic void 422157562Simpate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 423157562Simp{ 424157562Simp struct ate_softc *sc; 425157562Simp 426157562Simp if (error != 0) 427157562Simp return; 428157562Simp sc = (struct ate_softc *)arg; 429157562Simp 430163937Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE); 431213496Scognet sc->rx_descs[sc->rxhead].addr = segs[0].ds_addr; 432213496Scognet sc->rx_descs[sc->rxhead].status = 0; 433163937Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_POSTWRITE); 434157562Simp} 435157562Simp 436218387Sticsostatic uint32_t 437218387Sticsoate_mac_hash(const uint8_t *buf) 438218387Sticso{ 439218387Sticso uint32_t index = 0; 440218387Sticso for (int i = 0; i < 48; i++) { 441218387Sticso index ^= ((buf[i >> 3] >> (i & 7)) & 1) << (i % 6); 442218387Sticso } 443218387Sticso return (index); 444218387Sticso} 445218387Sticso 446155324Simp/* 447213251Sticso * Compute the multicast filter for this device. 448155324Simp */ 449191960Sstasstatic int 450155324Simpate_setmcast(struct ate_softc *sc) 451155324Simp{ 452155324Simp uint32_t index; 453155324Simp uint32_t mcaf[2]; 454155324Simp u_char *af = (u_char *) mcaf; 455155324Simp struct ifmultiaddr *ifma; 456191960Sstas struct ifnet *ifp; 457155324Simp 458191960Sstas ifp = sc->ifp; 459191960Sstas 460191960Sstas if ((ifp->if_flags & IFF_PROMISC) != 0) 461191960Sstas return (0); 462191960Sstas if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 463191960Sstas WR4(sc, ETH_HSL, 0xffffffff); 464191960Sstas WR4(sc, ETH_HSH, 0xffffffff); 465191960Sstas return (1); 466191960Sstas } 467191960Sstas 468213496Scognet /* Compute the multicast hash. */ 469155324Simp mcaf[0] = 0; 470155324Simp mcaf[1] = 0; 471195049Srwatson if_maddr_rlock(ifp); 472191960Sstas TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 473155324Simp if (ifma->ifma_addr->sa_family != AF_LINK) 474155324Simp continue; 475218387Sticso index = ate_mac_hash(LLADDR((struct sockaddr_dl *) 476218387Sticso ifma->ifma_addr)); 477155324Simp af[index >> 3] |= 1 << (index & 7); 478155324Simp } 479195049Srwatson if_maddr_runlock(ifp); 480155324Simp 481155324Simp /* 482155324Simp * Write the hash to the hash register. This card can also 483155324Simp * accept unicast packets as well as multicast packets using this 484155324Simp * register for easier bridging operations, but we don't take 485155324Simp * advantage of that. Locks here are to avoid LOR with the 486195049Srwatson * if_maddr_rlock, but might not be strictly necessary. 487155324Simp */ 488155324Simp WR4(sc, ETH_HSL, mcaf[0]); 489155324Simp WR4(sc, ETH_HSH, mcaf[1]); 490191960Sstas return (mcaf[0] || mcaf[1]); 491155324Simp} 492155324Simp 493155324Simpstatic int 494155324Simpate_activate(device_t dev) 495155324Simp{ 496155324Simp struct ate_softc *sc; 497213496Scognet int i; 498155324Simp 499155324Simp sc = device_get_softc(dev); 500192063Sstas 501213496Scognet /* Allocate DMA tags and maps for TX mbufs */ 502213496Scognet if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 503183670Simp BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 504213496Scognet 1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->mtag)) 505155324Simp goto errout; 506155324Simp for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 507213496Scognet if ( bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i])) 508155324Simp goto errout; 509155324Simp } 510192063Sstas 511155324Simp 512213496Scognet /* DMA tag and map for the RX descriptors. */ 513213496Scognet if (bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_rx_desc_t), 514183670Simp 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 515213496Scognet ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 1, 516213496Scognet ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 0, busdma_lock_mutex, 517213496Scognet &sc->sc_mtx, &sc->rx_desc_tag)) 518155324Simp goto errout; 519156831Simp if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs, 520156831Simp BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rx_desc_map) != 0) 521155324Simp goto errout; 522157562Simp if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map, 523213496Scognet sc->rx_descs, ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 524213496Scognet ate_getaddr, &sc->rx_desc_phys, 0) != 0) 525155324Simp goto errout; 526192063Sstas 527213496Scognet /* Allocate DMA tags and maps for RX. buffers */ 528213496Scognet if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 529213496Scognet BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 530213496Scognet sc->rx_buf_size, 1, sc->rx_buf_size, 0, 531213496Scognet busdma_lock_mutex, &sc->sc_mtx, &sc->rx_tag)) 532213496Scognet goto errout; 533213496Scognet 534192063Sstas /* 535213496Scognet * Allocate our RX buffers. 536213496Scognet * This chip has a RX structure that's filled in. 537213496Scognet * XXX On MACB (SAM9 part) we should receive directly into mbuf 538213496Scognet * to avoid the copy. XXX 539192063Sstas */ 540213496Scognet sc->rxhead = 0; 541213496Scognet for (sc->rxhead = 0; sc->rxhead < ATE_RX_MEMORY/sc->rx_buf_size; 542213496Scognet sc->rxhead++) { 543213496Scognet if (bus_dmamem_alloc(sc->rx_tag, 544213496Scognet (void **)&sc->rx_buf[sc->rxhead], BUS_DMA_NOWAIT, 545213496Scognet &sc->rx_map[sc->rxhead]) != 0) 546155324Simp goto errout; 547213496Scognet 548213496Scognet if (bus_dmamap_load(sc->rx_tag, sc->rx_map[sc->rxhead], 549213496Scognet sc->rx_buf[sc->rxhead], sc->rx_buf_size, 550213496Scognet ate_load_rx_buf, sc, 0) != 0) { 551213496Scognet printf("bus_dmamem_load\n"); 552157562Simp goto errout; 553213496Scognet } 554213496Scognet bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead], BUS_DMASYNC_PREREAD); 555155324Simp } 556213496Scognet 557213496Scognet /* 558213496Scognet * For the last buffer, set the wrap bit so the controller 559213496Scognet * restarts from the first descriptor. 560213496Scognet */ 561213496Scognet sc->rx_descs[--sc->rxhead].addr |= ETH_WRAP_BIT; 562213496Scognet sc->rxhead = 0; 563213496Scognet 564192063Sstas /* Flush the memory for the EMAC rx descriptor. */ 565155324Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE); 566213496Scognet 567155324Simp /* Write the descriptor queue address. */ 568155324Simp WR4(sc, ETH_RBQP, sc->rx_desc_phys); 569213496Scognet 570213496Scognet /* 571213496Scognet * DMA tag and map for the TX descriptors. 572213496Scognet */ 573213496Scognet if (bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_tx_desc_t), 574213496Scognet 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 575213496Scognet ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 1, 576213496Scognet ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 0, busdma_lock_mutex, 577213496Scognet &sc->sc_mtx, &sc->tx_desc_tag) != 0) 578213496Scognet goto errout; 579213496Scognet 580213496Scognet if (bus_dmamem_alloc(sc->tx_desc_tag, (void **)&sc->tx_descs, 581213496Scognet BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->tx_desc_map) != 0) 582213496Scognet goto errout; 583213496Scognet 584213496Scognet if (bus_dmamap_load(sc->tx_desc_tag, sc->tx_desc_map, 585213496Scognet sc->tx_descs, ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 586213496Scognet ate_getaddr, &sc->tx_desc_phys, 0) != 0) 587213496Scognet goto errout; 588213496Scognet 589213496Scognet /* Initilize descriptors; mark all empty */ 590213496Scognet for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 591213496Scognet sc->tx_descs[i].addr =0; 592213496Scognet sc->tx_descs[i].status = ETHB_TX_USED; 593213496Scognet sc->sent_mbuf[i] = NULL; 594213496Scognet } 595213496Scognet 596213496Scognet /* Mark last entry to cause wrap when indexing through */ 597213496Scognet sc->tx_descs[ATE_MAX_TX_BUFFERS - 1].status = 598213496Scognet ETHB_TX_WRAP | ETHB_TX_USED; 599213496Scognet 600213496Scognet /* Flush the memory for the EMAC tx descriptor. */ 601213496Scognet bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE); 602213496Scognet 603213496Scognet sc->txhead = sc->txtail = 0; 604213496Scognet if (sc->is_emacb) { 605213496Scognet /* Write the descriptor queue address. */ 606213496Scognet WR4(sc, ETHB_TBQP, sc->tx_desc_phys); 607213496Scognet 608238895Simp /* EMACB: Enable transceiver input clock */ 609213496Scognet WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) | ETHB_UIO_CLKE); 610238895Simp } 611213496Scognet 612155324Simp return (0); 613192018Sstas 614155324Simperrout: 615155324Simp return (ENOMEM); 616155324Simp} 617155324Simp 618155324Simpstatic void 619192018Sstasate_deactivate(struct ate_softc *sc) 620155324Simp{ 621192018Sstas int i; 622155324Simp 623192018Sstas KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__)); 624192018Sstas if (sc->mtag != NULL) { 625192018Sstas for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 626192018Sstas if (sc->sent_mbuf[i] != NULL) { 627192018Sstas bus_dmamap_sync(sc->mtag, sc->tx_map[i], 628192018Sstas BUS_DMASYNC_POSTWRITE); 629192018Sstas bus_dmamap_unload(sc->mtag, sc->tx_map[i]); 630192018Sstas m_freem(sc->sent_mbuf[i]); 631155324Simp } 632192018Sstas bus_dmamap_destroy(sc->mtag, sc->tx_map[i]); 633192018Sstas sc->sent_mbuf[i] = NULL; 634192018Sstas sc->tx_map[i] = NULL; 635155324Simp } 636192018Sstas bus_dma_tag_destroy(sc->mtag); 637192018Sstas } 638192018Sstas if (sc->rx_desc_tag != NULL) { 639192018Sstas if (sc->rx_descs != NULL) { 640192018Sstas if (sc->rx_desc_phys != 0) { 641192018Sstas bus_dmamap_sync(sc->rx_desc_tag, 642192018Sstas sc->rx_desc_map, BUS_DMASYNC_POSTREAD); 643192018Sstas bus_dmamap_unload(sc->rx_desc_tag, 644192018Sstas sc->rx_desc_map); 645192018Sstas sc->rx_desc_phys = 0; 646155324Simp } 647155324Simp } 648155324Simp } 649213496Scognet if (sc->rx_tag != NULL) { 650213496Scognet for (i = 0; sc->rx_buf[i] != NULL; i++) { 651213496Scognet if (sc->rx_descs[i].addr != 0) { 652213496Scognet bus_dmamap_sync(sc->rx_tag, 653213496Scognet sc->rx_map[i], 654213496Scognet BUS_DMASYNC_POSTREAD); 655213496Scognet bus_dmamap_unload(sc->rx_tag, 656192018Sstas sc->rx_map[i]); 657213496Scognet sc->rx_descs[i].addr = 0; 658192018Sstas } 659213496Scognet bus_dmamem_free(sc->rx_tag, sc->rx_buf[i], 660213496Scognet sc->rx_map[i]); 661213496Scognet sc->rx_buf[i] = NULL; 662213496Scognet sc->rx_map[i] = NULL; 663192018Sstas } 664213496Scognet bus_dma_tag_destroy(sc->rx_tag); 665192018Sstas } 666192018Sstas if (sc->rx_desc_tag != NULL) { 667192018Sstas if (sc->rx_descs != NULL) 668192018Sstas bus_dmamem_free(sc->rx_desc_tag, sc->rx_descs, 669192018Sstas sc->rx_desc_map); 670192018Sstas bus_dma_tag_destroy(sc->rx_desc_tag); 671192018Sstas sc->rx_descs = NULL; 672192018Sstas sc->rx_desc_tag = NULL; 673192018Sstas } 674213496Scognet 675213496Scognet if (sc->is_emacb) 676238895Simp WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) & ~ETHB_UIO_CLKE); 677155324Simp} 678155324Simp 679155324Simp/* 680155324Simp * Change media according to request. 681155324Simp */ 682155324Simpstatic int 683155324Simpate_ifmedia_upd(struct ifnet *ifp) 684155324Simp{ 685155324Simp struct ate_softc *sc = ifp->if_softc; 686155324Simp struct mii_data *mii; 687155324Simp 688155324Simp mii = device_get_softc(sc->miibus); 689155324Simp ATE_LOCK(sc); 690155324Simp mii_mediachg(mii); 691155324Simp ATE_UNLOCK(sc); 692155324Simp return (0); 693155324Simp} 694155324Simp 695155324Simp/* 696155324Simp * Notify the world which media we're using. 697155324Simp */ 698155324Simpstatic void 699155324Simpate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 700155324Simp{ 701155324Simp struct ate_softc *sc = ifp->if_softc; 702155324Simp struct mii_data *mii; 703155324Simp 704155324Simp mii = device_get_softc(sc->miibus); 705155324Simp ATE_LOCK(sc); 706155324Simp mii_pollstat(mii); 707155324Simp ifmr->ifm_active = mii->mii_media_active; 708155324Simp ifmr->ifm_status = mii->mii_media_status; 709155324Simp ATE_UNLOCK(sc); 710155324Simp} 711155324Simp 712155324Simpstatic void 713163937Simpate_stat_update(struct ate_softc *sc, int active) 714163937Simp{ 715192027Sstas uint32_t reg; 716192027Sstas 717163937Simp /* 718163937Simp * The speed and full/half-duplex state needs to be reflected 719163937Simp * in the ETH_CFG register. 720163937Simp */ 721192027Sstas reg = RD4(sc, ETH_CFG); 722192027Sstas reg &= ~(ETH_CFG_SPD | ETH_CFG_FD); 723192027Sstas if (IFM_SUBTYPE(active) != IFM_10_T) 724192027Sstas reg |= ETH_CFG_SPD; 725163937Simp if (active & IFM_FDX) 726192027Sstas reg |= ETH_CFG_FD; 727192027Sstas WR4(sc, ETH_CFG, reg); 728163937Simp} 729163937Simp 730163937Simpstatic void 731155324Simpate_tick(void *xsc) 732155324Simp{ 733155324Simp struct ate_softc *sc = xsc; 734163937Simp struct ifnet *ifp = sc->ifp; 735155324Simp struct mii_data *mii; 736155324Simp int active; 737163937Simp uint32_t c; 738155324Simp 739155324Simp /* 740155324Simp * The KB920x boot loader tests ETH_SR & ETH_SR_LINK and will ask 741155324Simp * the MII if there's a link if this bit is clear. Not sure if we 742155324Simp * should do the same thing here or not. 743155324Simp */ 744155324Simp ATE_ASSERT_LOCKED(sc); 745155324Simp if (sc->miibus != NULL) { 746155324Simp mii = device_get_softc(sc->miibus); 747155324Simp active = mii->mii_media_active; 748155324Simp mii_tick(mii); 749155324Simp if (mii->mii_media_status & IFM_ACTIVE && 750234281Smarius active != mii->mii_media_active) 751163937Simp ate_stat_update(sc, mii->mii_media_active); 752155324Simp } 753155324Simp 754155324Simp /* 755155324Simp * Update the stats as best we can. When we're done, clear 756155324Simp * the status counters and start over. We're supposed to read these 757155324Simp * registers often enough that they won't overflow. Hopefully 758155324Simp * once a second is often enough. Some don't map well to 759155324Simp * the dot3Stats mib, so for those we just count them as general 760155324Simp * errors. Stats for iframes, ibutes, oframes and obytes are 761155324Simp * collected elsewhere. These registers zero on a read to prevent 762163937Simp * races. For all the collision stats, also update the collision 763163937Simp * stats for the interface. 764155324Simp */ 765155324Simp sc->mibdata.dot3StatsAlignmentErrors += RD4(sc, ETH_ALE); 766155324Simp sc->mibdata.dot3StatsFCSErrors += RD4(sc, ETH_SEQE); 767163937Simp c = RD4(sc, ETH_SCOL); 768163937Simp ifp->if_collisions += c; 769163937Simp sc->mibdata.dot3StatsSingleCollisionFrames += c; 770163937Simp c = RD4(sc, ETH_MCOL); 771163937Simp sc->mibdata.dot3StatsMultipleCollisionFrames += c; 772163937Simp ifp->if_collisions += c; 773155324Simp sc->mibdata.dot3StatsSQETestErrors += RD4(sc, ETH_SQEE); 774155324Simp sc->mibdata.dot3StatsDeferredTransmissions += RD4(sc, ETH_DTE); 775163937Simp c = RD4(sc, ETH_LCOL); 776163937Simp sc->mibdata.dot3StatsLateCollisions += c; 777163937Simp ifp->if_collisions += c; 778163937Simp c = RD4(sc, ETH_ECOL); 779163937Simp sc->mibdata.dot3StatsExcessiveCollisions += c; 780163937Simp ifp->if_collisions += c; 781155324Simp sc->mibdata.dot3StatsCarrierSenseErrors += RD4(sc, ETH_CSE); 782155324Simp sc->mibdata.dot3StatsFrameTooLongs += RD4(sc, ETH_ELR); 783155324Simp sc->mibdata.dot3StatsInternalMacReceiveErrors += RD4(sc, ETH_DRFC); 784192063Sstas 785155324Simp /* 786192063Sstas * Not sure where to lump these, so count them against the errors 787155324Simp * for the interface. 788155324Simp */ 789163937Simp sc->ifp->if_oerrors += RD4(sc, ETH_TUE); 790155324Simp sc->ifp->if_ierrors += RD4(sc, ETH_CDE) + RD4(sc, ETH_RJB) + 791155324Simp RD4(sc, ETH_USF); 792155324Simp 793213496Scognet /* Schedule another timeout one second from now. */ 794155324Simp callout_reset(&sc->tick_ch, hz, ate_tick, sc); 795155324Simp} 796155324Simp 797155324Simpstatic void 798155445Scognetate_set_mac(struct ate_softc *sc, u_char *eaddr) 799155445Scognet{ 800192063Sstas 801155445Scognet WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) | 802155445Scognet (eaddr[1] << 8) | eaddr[0]); 803155445Scognet WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4])); 804155445Scognet} 805155445Scognet 806166573Simpstatic int 807155324Simpate_get_mac(struct ate_softc *sc, u_char *eaddr) 808155324Simp{ 809182477Sstas bus_size_t sa_low_reg[] = { ETH_SA1L, ETH_SA2L, ETH_SA3L, ETH_SA4L }; 810182477Sstas bus_size_t sa_high_reg[] = { ETH_SA1H, ETH_SA2H, ETH_SA3H, ETH_SA4H }; 811166573Simp uint32_t low, high; 812182477Sstas int i; 813155324Simp 814166573Simp /* 815213496Scognet * The boot loader may setup the MAC with an address(es), grab the 816213496Scognet * first MAC address from the SA[1-4][HL] registers. 817166573Simp */ 818182477Sstas for (i = 0; i < 4; i++) { 819182477Sstas low = RD4(sc, sa_low_reg[i]); 820182477Sstas high = RD4(sc, sa_high_reg[i]); 821182477Sstas if ((low | (high & 0xffff)) != 0) { 822182477Sstas eaddr[0] = low & 0xff; 823182477Sstas eaddr[1] = (low >> 8) & 0xff; 824182477Sstas eaddr[2] = (low >> 16) & 0xff; 825182477Sstas eaddr[3] = (low >> 24) & 0xff; 826182477Sstas eaddr[4] = high & 0xff; 827182477Sstas eaddr[5] = (high >> 8) & 0xff; 828182477Sstas return (0); 829182477Sstas } 830182477Sstas } 831182477Sstas return (ENXIO); 832155324Simp} 833155324Simp 834155324Simpstatic void 835155324Simpate_intr(void *xsc) 836155324Simp{ 837155324Simp struct ate_softc *sc = xsc; 838163937Simp struct ifnet *ifp = sc->ifp; 839192027Sstas struct mbuf *mb; 840213496Scognet eth_rx_desc_t *rxdhead; 841213496Scognet uint32_t status, reg, idx; 842213496Scognet int remain, count, done; 843156831Simp 844155324Simp status = RD4(sc, ETH_ISR); 845155324Simp if (status == 0) 846155324Simp return; 847213496Scognet 848155324Simp if (status & ETH_ISR_RCOM) { 849238895Simp bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 850155324Simp BUS_DMASYNC_POSTREAD); 851213496Scognet 852238895Simp rxdhead = &sc->rx_descs[sc->rxhead]; 853238895Simp while (rxdhead->addr & ETH_CPU_OWNER) { 854213496Scognet if (!sc->is_emacb) { 855213496Scognet /* 856213496Scognet * Simulate SAM9 FIRST/LAST bits for RM9200. 857213496Scognet * RM9200 EMAC has only on Rx buffer per packet. 858213496Scognet * But sometime we are handed a zero lenght packet. 859213496Scognet */ 860213496Scognet if ((rxdhead->status & ETH_LEN_MASK) == 0) 861213496Scognet rxdhead->status = 0; /* Mark error */ 862213496Scognet else 863213496Scognet rxdhead->status |= ETH_BUF_FIRST | ETH_BUF_LAST; 864213496Scognet } 865213496Scognet 866213496Scognet if ((rxdhead->status & ETH_BUF_FIRST) == 0) { 867213496Scognet /* Something went wrong during RX so 868213496Scognet release back to EMAC all buffers of invalid packets. 869213496Scognet */ 870213496Scognet rxdhead->status = 0; 871213496Scognet rxdhead->addr &= ~ETH_CPU_OWNER; 872213496Scognet sc->rxhead = NEXT_RX_IDX(sc, sc->rxhead); 873213496Scognet rxdhead = &sc->rx_descs[sc->rxhead]; 874156831Simp continue; 875155324Simp } 876163937Simp 877213496Scognet /* Find end of packet or start of next */ 878213496Scognet idx = sc->rxhead; 879213496Scognet if ((sc->rx_descs[idx].status & ETH_BUF_LAST) == 0) { 880213496Scognet idx = NEXT_RX_IDX(sc, idx); 881213496Scognet 882213496Scognet while ((sc->rx_descs[idx].addr & ETH_CPU_OWNER) && 883213496Scognet ((sc->rx_descs[idx].status & 884213496Scognet (ETH_BUF_FIRST|ETH_BUF_LAST))== 0)) 885213496Scognet idx = NEXT_RX_IDX(sc, idx); 886213496Scognet } 887213496Scognet 888213496Scognet /* Packet NOT yet completely in memory; we are done */ 889213496Scognet if ((sc->rx_descs[idx].addr & ETH_CPU_OWNER) == 0 || 890213496Scognet ((sc->rx_descs[idx].status & (ETH_BUF_FIRST|ETH_BUF_LAST))== 0)) 891213496Scognet break; 892213496Scognet 893213496Scognet /* Packets with no end descriptor are invalid. */ 894213496Scognet if ((sc->rx_descs[idx].status & ETH_BUF_LAST) == 0) { 895213496Scognet rxdhead->status &= ~ETH_BUF_FIRST; 896213496Scognet continue; 897213496Scognet } 898213496Scognet 899213496Scognet /* FCS is not coppied into mbuf. */ 900213496Scognet remain = (sc->rx_descs[idx].status & ETH_LEN_MASK) - 4; 901213496Scognet 902213496Scognet /* Get an appropriately sized mbuf */ 903213496Scognet if (remain + ETHER_ALIGN >= MINCLSIZE) 904213496Scognet mb = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 905213496Scognet else 906213496Scognet MGETHDR(mb, M_DONTWAIT, MT_DATA); 907213496Scognet 908213496Scognet if (mb == NULL) { 909213496Scognet sc->ifp->if_iqdrops++; 910213496Scognet rxdhead->status = 0; 911213496Scognet continue; 912213496Scognet } 913213496Scognet mb->m_data += ETHER_ALIGN; 914213496Scognet mb->m_pkthdr.rcvif = ifp; 915213496Scognet 916213496Scognet WR4(sc, ETH_RSR, RD4(sc, ETH_RSR)); /* Reset status */ 917213496Scognet 918213496Scognet /* Now we process the buffers that make up the packet */ 919213496Scognet do { 920213496Scognet 921213496Scognet /* Last buffer may just be 1-4 bytes of FCS so remain 922213496Scognet * may be zero for last decriptor. */ 923213496Scognet if (remain > 0) { 924213496Scognet /* Make sure we get the current bytes */ 925213496Scognet bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead], 926213496Scognet BUS_DMASYNC_POSTREAD); 927213496Scognet 928213496Scognet count = MIN(remain, sc->rx_buf_size); 929213496Scognet 930213496Scognet /* XXX Performance robbing copy. Could 931213496Scognet * recieve directly to mbufs if not an 932238895Simp * RM9200. And even then we could likely 933238895Simp * copy just the protocol headers. XXX */ 934213496Scognet m_append(mb, count, sc->rx_buf[sc->rxhead]); 935213496Scognet remain -= count; 936213496Scognet } 937213496Scognet 938213496Scognet done = (rxdhead->status & ETH_BUF_LAST) != 0; 939213496Scognet 940213496Scognet /* Return the descriptor to the EMAC */ 941213496Scognet rxdhead->status = 0; 942213496Scognet rxdhead->addr &= ~ETH_CPU_OWNER; 943213496Scognet bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, 944213496Scognet BUS_DMASYNC_PREWRITE); 945213496Scognet 946213496Scognet /* Move on to next descriptor with wrap */ 947213496Scognet sc->rxhead = NEXT_RX_IDX(sc, sc->rxhead); 948213496Scognet rxdhead = &sc->rx_descs[sc->rxhead]; 949213496Scognet 950213496Scognet } while (!done); 951213496Scognet 952163937Simp if (mb != NULL) { 953163937Simp ifp->if_ipackets++; 954163937Simp (*ifp->if_input)(ifp, mb); 955163937Simp } 956155324Simp } 957155324Simp } 958213496Scognet 959213496Scognet 960155324Simp if (status & ETH_ISR_TCOM) { 961213496Scognet bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, 962213496Scognet BUS_DMASYNC_POSTREAD); 963213496Scognet 964156831Simp ATE_LOCK(sc); 965163937Simp /* XXX TSR register should be cleared */ 966234281Smarius if (!sc->is_emacb) { 967213496Scognet /* Simulate Transmit descriptor table */ 968213496Scognet 969213496Scognet /* First packet done */ 970213496Scognet if (sc->txtail < sc->txhead) 971213496Scognet sc->tx_descs[sc->txtail].status |= ETHB_TX_USED; 972213496Scognet 973213496Scognet /* Second Packet done */ 974213496Scognet if (sc->txtail + 1 < sc->txhead && 975213496Scognet RD4(sc, ETH_TSR) & ETH_TSR_IDLE) 976213496Scognet sc->tx_descs[sc->txtail + 1].status |= ETHB_TX_USED; 977213496Scognet } 978213496Scognet 979213496Scognet while (sc->txtail != sc->txhead && 980213496Scognet sc->tx_descs[sc->txtail].status & ETHB_TX_USED ) { 981213496Scognet 982213496Scognet bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail], 983163937Simp BUS_DMASYNC_POSTWRITE); 984213496Scognet bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]); 985213496Scognet m_freem(sc->sent_mbuf[sc->txtail]); 986213496Scognet sc->tx_descs[sc->txtail].addr = 0; 987213496Scognet sc->sent_mbuf[sc->txtail] = NULL; 988213496Scognet 989163937Simp ifp->if_opackets++; 990213496Scognet sc->txtail = NEXT_TX_IDX(sc, sc->txtail); 991156831Simp } 992213496Scognet 993213496Scognet /* Flush descriptors to EMAC */ 994213496Scognet bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE); 995213496Scognet 996156831Simp /* 997156831Simp * We're no longer busy, so clear the busy flag and call the 998156831Simp * start routine to xmit more packets. 999156831Simp */ 1000156831Simp sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1001156831Simp atestart_locked(sc->ifp); 1002156831Simp ATE_UNLOCK(sc); 1003155324Simp } 1004213496Scognet 1005155324Simp if (status & ETH_ISR_RBNA) { 1006213496Scognet /* Workaround RM9200 Errata #11 */ 1007192028Sstas if (bootverbose) 1008192028Sstas device_printf(sc->dev, "RBNA workaround\n"); 1009192027Sstas reg = RD4(sc, ETH_CTL); 1010192027Sstas WR4(sc, ETH_CTL, reg & ~ETH_CTL_RE); 1011192027Sstas BARRIER(sc, ETH_CTL, 4, BUS_SPACE_BARRIER_WRITE); 1012192027Sstas WR4(sc, ETH_CTL, reg | ETH_CTL_RE); 1013155324Simp } 1014238895Simp 1015238895Simp /* XXX need to work around SAM9260 errata 43.2.4.1: 1016238895Simp * disable the mac, reset tx buffer, enable mac on TUND */ 1017155324Simp} 1018155324Simp 1019155324Simp/* 1020192063Sstas * Reset and initialize the chip. 1021155324Simp */ 1022155324Simpstatic void 1023155324Simpateinit_locked(void *xsc) 1024155324Simp{ 1025155324Simp struct ate_softc *sc = xsc; 1026155324Simp struct ifnet *ifp = sc->ifp; 1027213496Scognet struct mii_data *mii; 1028192064Sstas uint8_t eaddr[ETHER_ADDR_LEN]; 1029192027Sstas uint32_t reg; 1030155324Simp 1031155324Simp ATE_ASSERT_LOCKED(sc); 1032155324Simp 1033155324Simp /* 1034155324Simp * XXX TODO(3) 1035155324Simp * we need to turn on the EMAC clock in the pmc. With the 1036155324Simp * default boot loader, this is already turned on. However, we 1037155324Simp * need to think about how best to turn it on/off as the interface 1038155324Simp * is brought up/down, as well as dealing with the mii bus... 1039155324Simp * 1040213496Scognet * We also need to multiplex the pins correctly (in board_xxx.c). 1041155324Simp */ 1042155324Simp 1043155324Simp /* 1044155324Simp * There are two different ways that the mii bus is connected 1045213496Scognet * to this chip mii or rmii. 1046155324Simp */ 1047213496Scognet if (!sc->is_emacb) { 1048213496Scognet /* RM9200 */ 1049213496Scognet reg = RD4(sc, ETH_CFG); 1050213496Scognet if (sc->use_rmii) 1051213496Scognet reg |= ETH_CFG_RMII; 1052213496Scognet else 1053213496Scognet reg &= ~ETH_CFG_RMII; 1054213496Scognet WR4(sc, ETH_CFG, reg); 1055213496Scognet } else { 1056213496Scognet /* SAM9 */ 1057213496Scognet reg = ETHB_UIO_CLKE; 1058234281Smarius reg |= (sc->use_rmii) ? ETHB_UIO_RMII : 0; 1059213496Scognet WR4(sc, ETHB_UIO, reg); 1060213496Scognet } 1061159708Simp 1062191960Sstas ate_rxfilter(sc); 1063191960Sstas 1064191960Sstas /* 1065192064Sstas * Set the chip MAC address. 1066192064Sstas */ 1067192064Sstas bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN); 1068192064Sstas ate_set_mac(sc, eaddr); 1069192064Sstas 1070213496Scognet /* Make sure we know state of TX queue */ 1071213496Scognet sc->txhead = sc->txtail = 0; 1072213496Scognet if (sc->is_emacb) { 1073213496Scognet /* Write the descriptor queue address. */ 1074213496Scognet WR4(sc, ETHB_TBQP, sc->tx_desc_phys); 1075213496Scognet } 1076213496Scognet 1077192064Sstas /* 1078191960Sstas * Turn on MACs and interrupt processing. 1079191960Sstas */ 1080155324Simp WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE); 1081156831Simp WR4(sc, ETH_IER, ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA); 1082155324Simp 1083192063Sstas /* Enable big packets. */ 1084165779Sticso WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG); 1085165779Sticso 1086155324Simp /* 1087155324Simp * Set 'running' flag, and clear output active flag 1088192063Sstas * and attempt to start the output. 1089155324Simp */ 1090155324Simp ifp->if_drv_flags |= IFF_DRV_RUNNING; 1091155324Simp ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1092163937Simp 1093163937Simp mii = device_get_softc(sc->miibus); 1094163937Simp mii_pollstat(mii); 1095163937Simp ate_stat_update(sc, mii->mii_media_active); 1096155324Simp atestart_locked(ifp); 1097155324Simp 1098155324Simp callout_reset(&sc->tick_ch, hz, ate_tick, sc); 1099155324Simp} 1100155324Simp 1101155324Simp/* 1102192063Sstas * Dequeue packets and transmit. 1103155324Simp */ 1104155324Simpstatic void 1105155324Simpatestart_locked(struct ifnet *ifp) 1106155324Simp{ 1107155324Simp struct ate_softc *sc = ifp->if_softc; 1108155324Simp struct mbuf *m, *mdefrag; 1109155324Simp bus_dma_segment_t segs[1]; 1110163937Simp int nseg, e; 1111155324Simp 1112155324Simp ATE_ASSERT_LOCKED(sc); 1113155324Simp if (ifp->if_drv_flags & IFF_DRV_OACTIVE) 1114155324Simp return; 1115155324Simp 1116213496Scognet while (sc->tx_descs[sc->txhead].status & ETHB_TX_USED) { 1117156831Simp /* 1118192063Sstas * Check to see if there's room to put another packet into the 1119213496Scognet * xmit queue. The old EMAC version has a ping-pong buffer for 1120213496Scognet * xmit packets. We use OACTIVE to indicate "we can stuff more 1121213496Scognet * into our buffers (clear) or not (set)." 1122156831Simp */ 1123213496Scognet if (!sc->is_emacb) { 1124213496Scognet /* RM9200 has only two hardware entries */ 1125213496Scognet if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) { 1126213496Scognet ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1127213496Scognet return; 1128213496Scognet } 1129156831Simp } 1130213496Scognet 1131156831Simp IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1132213496Scognet if (m == 0) 1133213496Scognet break; 1134213496Scognet 1135213496Scognet e = bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txhead], m, 1136163937Simp segs, &nseg, 0); 1137163937Simp if (e == EFBIG) { 1138163937Simp mdefrag = m_defrag(m, M_DONTWAIT); 1139163937Simp if (mdefrag == NULL) { 1140163937Simp IFQ_DRV_PREPEND(&ifp->if_snd, m); 1141163937Simp return; 1142163937Simp } 1143163937Simp m = mdefrag; 1144163937Simp e = bus_dmamap_load_mbuf_sg(sc->mtag, 1145213496Scognet sc->tx_map[sc->txhead], m, segs, &nseg, 0); 1146156831Simp } 1147163937Simp if (e != 0) { 1148156831Simp m_freem(m); 1149156831Simp continue; 1150156831Simp } 1151213496Scognet sc->sent_mbuf[sc->txhead] = m; 1152213496Scognet 1153213496Scognet bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txhead], 1154156831Simp BUS_DMASYNC_PREWRITE); 1155155324Simp 1156213496Scognet /* Tell the hardware to xmit the packet. */ 1157213496Scognet if (!sc->is_emacb) { 1158213496Scognet WR4(sc, ETH_TAR, segs[0].ds_addr); 1159213496Scognet BARRIER(sc, ETH_TAR, 4, BUS_SPACE_BARRIER_WRITE); 1160213496Scognet WR4(sc, ETH_TCR, segs[0].ds_len); 1161213496Scognet } else { 1162213496Scognet bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, 1163213496Scognet BUS_DMASYNC_POSTWRITE); 1164213496Scognet sc->tx_descs[sc->txhead].addr = segs[0].ds_addr; 1165213496Scognet sc->tx_descs[sc->txhead].status = segs[0].ds_len | 1166213496Scognet (sc->tx_descs[sc->txhead].status & ETHB_TX_WRAP) | 1167213496Scognet ETHB_TX_BUF_LAST; 1168213496Scognet bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, 1169213496Scognet BUS_DMASYNC_PREWRITE); 1170213496Scognet WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETHB_CTL_TGO); 1171213496Scognet } 1172213496Scognet sc->txhead = NEXT_TX_IDX(sc, sc->txhead); 1173234281Smarius 1174213496Scognet /* Tap off here if there is a bpf listener. */ 1175156831Simp BPF_MTAP(ifp, m); 1176213496Scognet } 1177155324Simp 1178213496Scognet if ((sc->tx_descs[sc->txhead].status & ETHB_TX_USED) == 0) 1179213496Scognet ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1180155324Simp} 1181155324Simp 1182155324Simpstatic void 1183155324Simpateinit(void *xsc) 1184155324Simp{ 1185155324Simp struct ate_softc *sc = xsc; 1186192063Sstas 1187155324Simp ATE_LOCK(sc); 1188155324Simp ateinit_locked(sc); 1189155324Simp ATE_UNLOCK(sc); 1190155324Simp} 1191155324Simp 1192155324Simpstatic void 1193155324Simpatestart(struct ifnet *ifp) 1194155324Simp{ 1195155324Simp struct ate_softc *sc = ifp->if_softc; 1196192063Sstas 1197155324Simp ATE_LOCK(sc); 1198155324Simp atestart_locked(ifp); 1199155324Simp ATE_UNLOCK(sc); 1200155324Simp} 1201155324Simp 1202155324Simp/* 1203192063Sstas * Turn off interrupts, and stop the NIC. Can be called with sc->ifp NULL, 1204155324Simp * so be careful. 1205155324Simp */ 1206155324Simpstatic void 1207155324Simpatestop(struct ate_softc *sc) 1208155324Simp{ 1209192018Sstas struct ifnet *ifp; 1210192018Sstas int i; 1211155324Simp 1212192018Sstas ATE_ASSERT_LOCKED(sc); 1213192018Sstas ifp = sc->ifp; 1214155324Simp if (ifp) { 1215213496Scognet //ifp->if_timer = 0; 1216155324Simp ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1217155324Simp } 1218155324Simp 1219155324Simp callout_stop(&sc->tick_ch); 1220155324Simp 1221155324Simp /* 1222155324Simp * Enable some parts of the MAC that are needed always (like the 1223155324Simp * MII bus. This turns off the RE and TE bits, which will remain 1224155405Scognet * off until ateinit() is called to turn them on. With RE and TE 1225155324Simp * turned off, there's no DMA to worry about after this write. 1226155324Simp */ 1227155324Simp WR4(sc, ETH_CTL, ETH_CTL_MPE); 1228155324Simp 1229155324Simp /* 1230155324Simp * Turn off all the configured options and revert to defaults. 1231155324Simp */ 1232155324Simp 1233213496Scognet /* Make sure thate the MDIO clk is less than 1234213496Scognet * 2.5 Mhz. Can no longer default to /32 since 1235213496Scognet * SAM9 family may have MCK > 80 Mhz */ 1236213496Scognet if (at91_master_clock <= 2000000) 1237213496Scognet WR4(sc, ETH_CFG, ETH_CFG_CLK_8); 1238213496Scognet else if (at91_master_clock <= 4000000) 1239213496Scognet WR4(sc, ETH_CFG, ETH_CFG_CLK_16); 1240213496Scognet else if (at91_master_clock <= 800000) 1241213496Scognet WR4(sc, ETH_CFG, ETH_CFG_CLK_32); 1242213496Scognet else 1243213496Scognet WR4(sc, ETH_CFG, ETH_CFG_CLK_64); 1244213496Scognet 1245155324Simp /* 1246155324Simp * Turn off all the interrupts, and ack any pending ones by reading 1247155324Simp * the ISR. 1248155324Simp */ 1249155324Simp WR4(sc, ETH_IDR, 0xffffffff); 1250155324Simp RD4(sc, ETH_ISR); 1251155324Simp 1252155324Simp /* 1253155324Simp * Clear out the Transmit and Receiver Status registers of any 1254155324Simp * errors they may be reporting 1255155324Simp */ 1256155324Simp WR4(sc, ETH_TSR, 0xffffffff); 1257155324Simp WR4(sc, ETH_RSR, 0xffffffff); 1258155324Simp 1259213496Scognet /* Release TX resources. */ 1260192018Sstas for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { 1261192018Sstas if (sc->sent_mbuf[i] != NULL) { 1262192018Sstas bus_dmamap_sync(sc->mtag, sc->tx_map[i], 1263192018Sstas BUS_DMASYNC_POSTWRITE); 1264192018Sstas bus_dmamap_unload(sc->mtag, sc->tx_map[i]); 1265192018Sstas m_freem(sc->sent_mbuf[i]); 1266192018Sstas sc->sent_mbuf[i] = NULL; 1267192018Sstas } 1268192018Sstas } 1269155324Simp 1270213496Scognet /* Turn off transeiver input clock */ 1271213496Scognet if (sc->is_emacb) 1272238895Simp WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) & ~ETHB_UIO_CLKE); 1273213496Scognet 1274155324Simp /* 1275155324Simp * XXX we should power down the EMAC if it isn't in use, after 1276155324Simp * putting it into loopback mode. This saves about 400uA according 1277155324Simp * to the datasheet. 1278155324Simp */ 1279155324Simp} 1280155324Simp 1281191959Sstasstatic void 1282191959Sstasate_rxfilter(struct ate_softc *sc) 1283191959Sstas{ 1284191959Sstas struct ifnet *ifp; 1285191959Sstas uint32_t reg; 1286191960Sstas int enabled; 1287191959Sstas 1288191959Sstas KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__)); 1289191959Sstas ATE_ASSERT_LOCKED(sc); 1290191959Sstas ifp = sc->ifp; 1291191959Sstas 1292213496Scognet /* Wipe out old filter settings. */ 1293191959Sstas reg = RD4(sc, ETH_CFG); 1294191959Sstas reg &= ~(ETH_CFG_CAF | ETH_CFG_MTI | ETH_CFG_UNI); 1295191959Sstas reg |= ETH_CFG_NBC; 1296191960Sstas sc->flags &= ~ATE_FLAG_MULTICAST; 1297191959Sstas 1298213496Scognet /* Set new parameters. */ 1299191959Sstas if ((ifp->if_flags & IFF_BROADCAST) != 0) 1300191959Sstas reg &= ~ETH_CFG_NBC; 1301191960Sstas if ((ifp->if_flags & IFF_PROMISC) != 0) { 1302191959Sstas reg |= ETH_CFG_CAF; 1303191960Sstas } else { 1304191960Sstas enabled = ate_setmcast(sc); 1305191960Sstas if (enabled != 0) { 1306191960Sstas reg |= ETH_CFG_MTI; 1307191960Sstas sc->flags |= ATE_FLAG_MULTICAST; 1308191960Sstas } 1309191960Sstas } 1310191959Sstas WR4(sc, ETH_CFG, reg); 1311191959Sstas} 1312191959Sstas 1313155324Simpstatic int 1314155324Simpateioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1315155324Simp{ 1316155324Simp struct ate_softc *sc = ifp->if_softc; 1317213496Scognet struct mii_data *mii; 1318234281Smarius struct ifreq *ifr = (struct ifreq *)data; 1319191959Sstas int drv_flags, flags; 1320191960Sstas int mask, error, enabled; 1321155324Simp 1322191960Sstas error = 0; 1323191959Sstas flags = ifp->if_flags; 1324191959Sstas drv_flags = ifp->if_drv_flags; 1325155324Simp switch (cmd) { 1326155324Simp case SIOCSIFFLAGS: 1327155324Simp ATE_LOCK(sc); 1328191959Sstas if ((flags & IFF_UP) != 0) { 1329191959Sstas if ((drv_flags & IFF_DRV_RUNNING) != 0) { 1330191959Sstas if (((flags ^ sc->if_flags) 1331191959Sstas & (IFF_PROMISC | IFF_ALLMULTI)) != 0) 1332191959Sstas ate_rxfilter(sc); 1333191959Sstas } else { 1334213496Scognet if ((sc->flags & ATE_FLAG_DETACHING) == 0) 1335213496Scognet ateinit_locked(sc); 1336191959Sstas } 1337191959Sstas } else if ((drv_flags & IFF_DRV_RUNNING) != 0) { 1338213496Scognet ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1339155324Simp atestop(sc); 1340155324Simp } 1341191959Sstas sc->if_flags = flags; 1342155324Simp ATE_UNLOCK(sc); 1343155324Simp break; 1344155324Simp 1345155324Simp case SIOCADDMULTI: 1346155324Simp case SIOCDELMULTI: 1347191960Sstas if ((drv_flags & IFF_DRV_RUNNING) != 0) { 1348191960Sstas ATE_LOCK(sc); 1349191960Sstas enabled = ate_setmcast(sc); 1350191960Sstas if (enabled != (sc->flags & ATE_FLAG_MULTICAST)) 1351191960Sstas ate_rxfilter(sc); 1352191960Sstas ATE_UNLOCK(sc); 1353191960Sstas } 1354155324Simp break; 1355155324Simp 1356213496Scognet case SIOCSIFMEDIA: 1357213496Scognet case SIOCGIFMEDIA: 1358213496Scognet mii = device_get_softc(sc->miibus); 1359213496Scognet error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1360213496Scognet break; 1361165779Sticso case SIOCSIFCAP: 1362165779Sticso mask = ifp->if_capenable ^ ifr->ifr_reqcap; 1363165779Sticso if (mask & IFCAP_VLAN_MTU) { 1364165779Sticso ATE_LOCK(sc); 1365165779Sticso if (ifr->ifr_reqcap & IFCAP_VLAN_MTU) { 1366165779Sticso WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG); 1367165779Sticso ifp->if_capenable |= IFCAP_VLAN_MTU; 1368165779Sticso } else { 1369165779Sticso WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_BIG); 1370165779Sticso ifp->if_capenable &= ~IFCAP_VLAN_MTU; 1371165779Sticso } 1372165779Sticso ATE_UNLOCK(sc); 1373165779Sticso } 1374155324Simp default: 1375155324Simp error = ether_ioctl(ifp, cmd, data); 1376155324Simp break; 1377155324Simp } 1378155324Simp return (error); 1379155324Simp} 1380155324Simp 1381155324Simpstatic void 1382155324Simpate_child_detached(device_t dev, device_t child) 1383155324Simp{ 1384155324Simp struct ate_softc *sc; 1385155324Simp 1386155324Simp sc = device_get_softc(dev); 1387155324Simp if (child == sc->miibus) 1388155324Simp sc->miibus = NULL; 1389155324Simp} 1390155324Simp 1391155324Simp/* 1392155324Simp * MII bus support routines. 1393155324Simp */ 1394155324Simpstatic int 1395155324Simpate_miibus_readreg(device_t dev, int phy, int reg) 1396155324Simp{ 1397155324Simp struct ate_softc *sc; 1398155324Simp int val; 1399155324Simp 1400155324Simp /* 1401155324Simp * XXX if we implement agressive power savings, then we need 1402155324Simp * XXX to make sure that the clock to the emac is on here 1403155324Simp */ 1404155324Simp 1405155324Simp sc = device_get_softc(dev); 1406155324Simp DELAY(1); /* Hangs w/o this delay really 30.5us atm */ 1407155324Simp WR4(sc, ETH_MAN, ETH_MAN_REG_RD(phy, reg)); 1408155324Simp while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0) 1409155324Simp continue; 1410155324Simp val = RD4(sc, ETH_MAN) & ETH_MAN_VALUE_MASK; 1411155324Simp 1412155324Simp return (val); 1413155324Simp} 1414155324Simp 1415194015Savgstatic int 1416155324Simpate_miibus_writereg(device_t dev, int phy, int reg, int data) 1417155324Simp{ 1418155324Simp struct ate_softc *sc; 1419234281Smarius 1420155324Simp /* 1421155324Simp * XXX if we implement agressive power savings, then we need 1422155324Simp * XXX to make sure that the clock to the emac is on here 1423155324Simp */ 1424155324Simp 1425155324Simp sc = device_get_softc(dev); 1426155324Simp WR4(sc, ETH_MAN, ETH_MAN_REG_WR(phy, reg, data)); 1427155324Simp while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0) 1428155324Simp continue; 1429194015Savg return (0); 1430155324Simp} 1431155324Simp 1432155324Simpstatic device_method_t ate_methods[] = { 1433155324Simp /* Device interface */ 1434155324Simp DEVMETHOD(device_probe, ate_probe), 1435155324Simp DEVMETHOD(device_attach, ate_attach), 1436155324Simp DEVMETHOD(device_detach, ate_detach), 1437155324Simp 1438155324Simp /* Bus interface */ 1439155324Simp DEVMETHOD(bus_child_detached, ate_child_detached), 1440155324Simp 1441155324Simp /* MII interface */ 1442155324Simp DEVMETHOD(miibus_readreg, ate_miibus_readreg), 1443155324Simp DEVMETHOD(miibus_writereg, ate_miibus_writereg), 1444155324Simp 1445234281Smarius DEVMETHOD_END 1446155324Simp}; 1447155324Simp 1448155324Simpstatic driver_t ate_driver = { 1449155324Simp "ate", 1450155324Simp ate_methods, 1451155324Simp sizeof(struct ate_softc), 1452155324Simp}; 1453155324Simp 1454234281SmariusDRIVER_MODULE(ate, atmelarm, ate_driver, ate_devclass, NULL, NULL); 1455234281SmariusDRIVER_MODULE(miibus, ate, miibus_driver, miibus_devclass, NULL, NULL); 1456155324SimpMODULE_DEPEND(ate, miibus, 1, 1, 1); 1457155324SimpMODULE_DEPEND(ate, ether, 1, 1, 1); 1458