1188808Sgonzo/*- 2188808Sgonzo * Copyright (c) 2009, Oleksandr Tymoshenko 3188808Sgonzo * All rights reserved. 4188808Sgonzo * 5188808Sgonzo * Redistribution and use in source and binary forms, with or without 6188808Sgonzo * modification, are permitted provided that the following conditions 7188808Sgonzo * are met: 8188808Sgonzo * 1. Redistributions of source code must retain the above copyright 9188808Sgonzo * notice unmodified, this list of conditions, and the following 10188808Sgonzo * disclaimer. 11188808Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 12188808Sgonzo * notice, this list of conditions and the following disclaimer in the 13188808Sgonzo * documentation and/or other materials provided with the distribution. 14188808Sgonzo * 15188808Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16188808Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17188808Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18188808Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19188808Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20188808Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21188808Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22188808Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23188808Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24188808Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25188808Sgonzo * SUCH DAMAGE. 26188808Sgonzo */ 27188808Sgonzo 28188808Sgonzo#include <sys/cdefs.h> 29188808Sgonzo__FBSDID("$FreeBSD: stable/11/sys/mips/atheros/if_arge.c 323205 2017-09-06 02:07:44Z emaste $"); 30188808Sgonzo 31188808Sgonzo/* 32188808Sgonzo * AR71XX gigabit ethernet driver 33188808Sgonzo */ 34192783Sgonzo#ifdef HAVE_KERNEL_OPTION_HEADERS 35192783Sgonzo#include "opt_device_polling.h" 36192783Sgonzo#endif 37192783Sgonzo 38234859Sadrian#include "opt_arge.h" 39234859Sadrian 40188808Sgonzo#include <sys/param.h> 41188808Sgonzo#include <sys/endian.h> 42188808Sgonzo#include <sys/systm.h> 43188808Sgonzo#include <sys/sockio.h> 44257284Sglebius#include <sys/lock.h> 45188808Sgonzo#include <sys/mbuf.h> 46188808Sgonzo#include <sys/malloc.h> 47257284Sglebius#include <sys/mutex.h> 48188808Sgonzo#include <sys/kernel.h> 49188808Sgonzo#include <sys/module.h> 50188808Sgonzo#include <sys/socket.h> 51188808Sgonzo#include <sys/taskqueue.h> 52209802Sadrian#include <sys/sysctl.h> 53188808Sgonzo 54188808Sgonzo#include <net/if.h> 55257284Sglebius#include <net/if_var.h> 56257284Sglebius#include <net/if_media.h> 57188808Sgonzo#include <net/ethernet.h> 58188808Sgonzo#include <net/if_types.h> 59188808Sgonzo 60188808Sgonzo#include <net/bpf.h> 61188808Sgonzo 62188808Sgonzo#include <machine/bus.h> 63188808Sgonzo#include <machine/cache.h> 64188808Sgonzo#include <machine/resource.h> 65188808Sgonzo#include <vm/vm_param.h> 66188808Sgonzo#include <vm/vm.h> 67188808Sgonzo#include <vm/pmap.h> 68188808Sgonzo#include <sys/bus.h> 69188808Sgonzo#include <sys/rman.h> 70188808Sgonzo 71188808Sgonzo#include <dev/mii/mii.h> 72188808Sgonzo#include <dev/mii/miivar.h> 73188808Sgonzo 74188808Sgonzo#include <dev/pci/pcireg.h> 75188808Sgonzo#include <dev/pci/pcivar.h> 76188808Sgonzo 77234862Sadrian#include "opt_arge.h" 78234862Sadrian 79234862Sadrian#if defined(ARGE_MDIO) 80292766Sadrian#include <dev/mdio/mdio.h> 81234862Sadrian#include <dev/etherswitch/miiproxy.h> 82234862Sadrian#include "mdio_if.h" 83234862Sadrian#endif 84234862Sadrian 85234862Sadrian 86188808SgonzoMODULE_DEPEND(arge, ether, 1, 1, 1); 87188808SgonzoMODULE_DEPEND(arge, miibus, 1, 1, 1); 88234862SadrianMODULE_VERSION(arge, 1); 89188808Sgonzo 90188808Sgonzo#include "miibus_if.h" 91188808Sgonzo 92280798Sadrian#include <net/ethernet.h> 93280798Sadrian 94188808Sgonzo#include <mips/atheros/ar71xxreg.h> 95256575Sadrian#include <mips/atheros/ar934xreg.h> /* XXX tsk! */ 96290910Sadrian#include <mips/atheros/qca953xreg.h> /* XXX tsk! */ 97279510Sadrian#include <mips/atheros/qca955xreg.h> /* XXX tsk! */ 98188808Sgonzo#include <mips/atheros/if_argevar.h> 99219589Sadrian#include <mips/atheros/ar71xx_setup.h> 100211477Sadrian#include <mips/atheros/ar71xx_cpudef.h> 101280124Sadrian#include <mips/atheros/ar71xx_macaddr.h> 102188808Sgonzo 103220354Sadriantypedef enum { 104220354Sadrian ARGE_DBG_MII = 0x00000001, 105220356Sadrian ARGE_DBG_INTR = 0x00000002, 106220356Sadrian ARGE_DBG_TX = 0x00000004, 107220356Sadrian ARGE_DBG_RX = 0x00000008, 108220356Sadrian ARGE_DBG_ERR = 0x00000010, 109220356Sadrian ARGE_DBG_RESET = 0x00000020, 110234919Sadrian ARGE_DBG_PLL = 0x00000040, 111220354Sadrian} arge_debug_flags; 112220354Sadrian 113234910Sadrianstatic const char * arge_miicfg_str[] = { 114234910Sadrian "NONE", 115234910Sadrian "GMII", 116234910Sadrian "MII", 117234910Sadrian "RGMII", 118279510Sadrian "RMII", 119279510Sadrian "SGMII" 120234910Sadrian}; 121234910Sadrian 122188808Sgonzo#ifdef ARGE_DEBUG 123220354Sadrian#define ARGEDEBUG(_sc, _m, ...) \ 124220354Sadrian do { \ 125220354Sadrian if ((_m) & (_sc)->arge_debug) \ 126220354Sadrian device_printf((_sc)->arge_dev, __VA_ARGS__); \ 127220354Sadrian } while (0) 128188808Sgonzo#else 129220354Sadrian#define ARGEDEBUG(_sc, _m, ...) 130188808Sgonzo#endif 131188808Sgonzo 132188808Sgonzostatic int arge_attach(device_t); 133188808Sgonzostatic int arge_detach(device_t); 134188808Sgonzostatic void arge_flush_ddr(struct arge_softc *); 135188808Sgonzostatic int arge_ifmedia_upd(struct ifnet *); 136188808Sgonzostatic void arge_ifmedia_sts(struct ifnet *, struct ifmediareq *); 137188808Sgonzostatic int arge_ioctl(struct ifnet *, u_long, caddr_t); 138188808Sgonzostatic void arge_init(void *); 139188808Sgonzostatic void arge_init_locked(struct arge_softc *); 140188808Sgonzostatic void arge_link_task(void *, int); 141232914Sadrianstatic void arge_update_link_locked(struct arge_softc *sc); 142199234Sgonzostatic void arge_set_pll(struct arge_softc *, int, int); 143188808Sgonzostatic int arge_miibus_readreg(device_t, int, int); 144188808Sgonzostatic void arge_miibus_statchg(device_t); 145188808Sgonzostatic int arge_miibus_writereg(device_t, int, int, int); 146188808Sgonzostatic int arge_probe(device_t); 147188808Sgonzostatic void arge_reset_dma(struct arge_softc *); 148188808Sgonzostatic int arge_resume(device_t); 149188808Sgonzostatic int arge_rx_ring_init(struct arge_softc *); 150232912Sadrianstatic void arge_rx_ring_free(struct arge_softc *sc); 151188808Sgonzostatic int arge_tx_ring_init(struct arge_softc *); 152255300Sloosstatic void arge_tx_ring_free(struct arge_softc *); 153192821Sgonzo#ifdef DEVICE_POLLING 154198667Sgonzostatic int arge_poll(struct ifnet *, enum poll_cmd, int); 155192821Sgonzo#endif 156194059Sgonzostatic int arge_shutdown(device_t); 157188808Sgonzostatic void arge_start(struct ifnet *); 158188808Sgonzostatic void arge_start_locked(struct ifnet *); 159188808Sgonzostatic void arge_stop(struct arge_softc *); 160188808Sgonzostatic int arge_suspend(device_t); 161188808Sgonzo 162198667Sgonzostatic int arge_rx_locked(struct arge_softc *); 163188808Sgonzostatic void arge_tx_locked(struct arge_softc *); 164188808Sgonzostatic void arge_intr(void *); 165188808Sgonzostatic int arge_intr_filter(void *); 166188808Sgonzostatic void arge_tick(void *); 167188808Sgonzo 168234862Sadrianstatic void arge_hinted_child(device_t bus, const char *dname, int dunit); 169234862Sadrian 170199234Sgonzo/* 171199234Sgonzo * ifmedia callbacks for multiPHY MAC 172199234Sgonzo */ 173199234Sgonzovoid arge_multiphy_mediastatus(struct ifnet *, struct ifmediareq *); 174199234Sgonzoint arge_multiphy_mediachange(struct ifnet *); 175199234Sgonzo 176188808Sgonzostatic void arge_dmamap_cb(void *, bus_dma_segment_t *, int, int); 177188808Sgonzostatic int arge_dma_alloc(struct arge_softc *); 178188808Sgonzostatic void arge_dma_free(struct arge_softc *); 179188808Sgonzostatic int arge_newbuf(struct arge_softc *, int); 180188808Sgonzostatic __inline void arge_fixup_rx(struct mbuf *); 181188808Sgonzo 182188808Sgonzostatic device_method_t arge_methods[] = { 183188808Sgonzo /* Device interface */ 184188808Sgonzo DEVMETHOD(device_probe, arge_probe), 185188808Sgonzo DEVMETHOD(device_attach, arge_attach), 186188808Sgonzo DEVMETHOD(device_detach, arge_detach), 187188808Sgonzo DEVMETHOD(device_suspend, arge_suspend), 188188808Sgonzo DEVMETHOD(device_resume, arge_resume), 189188808Sgonzo DEVMETHOD(device_shutdown, arge_shutdown), 190188808Sgonzo 191188808Sgonzo /* MII interface */ 192188808Sgonzo DEVMETHOD(miibus_readreg, arge_miibus_readreg), 193188808Sgonzo DEVMETHOD(miibus_writereg, arge_miibus_writereg), 194188808Sgonzo DEVMETHOD(miibus_statchg, arge_miibus_statchg), 195188808Sgonzo 196234862Sadrian /* bus interface */ 197234862Sadrian DEVMETHOD(bus_add_child, device_add_child_ordered), 198234862Sadrian DEVMETHOD(bus_hinted_child, arge_hinted_child), 199234862Sadrian 200227843Smarius DEVMETHOD_END 201188808Sgonzo}; 202188808Sgonzo 203188808Sgonzostatic driver_t arge_driver = { 204188808Sgonzo "arge", 205188808Sgonzo arge_methods, 206188808Sgonzo sizeof(struct arge_softc) 207188808Sgonzo}; 208188808Sgonzo 209188808Sgonzostatic devclass_t arge_devclass; 210188808Sgonzo 211188808SgonzoDRIVER_MODULE(arge, nexus, arge_driver, arge_devclass, 0, 0); 212188808SgonzoDRIVER_MODULE(miibus, arge, miibus_driver, miibus_devclass, 0, 0); 213188808Sgonzo 214234862Sadrian#if defined(ARGE_MDIO) 215234862Sadrianstatic int argemdio_probe(device_t); 216234862Sadrianstatic int argemdio_attach(device_t); 217234862Sadrianstatic int argemdio_detach(device_t); 218234862Sadrian 219188808Sgonzo/* 220234862Sadrian * Declare an additional, separate driver for accessing the MDIO bus. 221234862Sadrian */ 222234862Sadrianstatic device_method_t argemdio_methods[] = { 223234862Sadrian /* Device interface */ 224234862Sadrian DEVMETHOD(device_probe, argemdio_probe), 225234862Sadrian DEVMETHOD(device_attach, argemdio_attach), 226234862Sadrian DEVMETHOD(device_detach, argemdio_detach), 227234862Sadrian 228234862Sadrian /* bus interface */ 229234862Sadrian DEVMETHOD(bus_add_child, device_add_child_ordered), 230234862Sadrian 231234862Sadrian /* MDIO access */ 232234862Sadrian DEVMETHOD(mdio_readreg, arge_miibus_readreg), 233234862Sadrian DEVMETHOD(mdio_writereg, arge_miibus_writereg), 234234862Sadrian}; 235234862Sadrian 236234862SadrianDEFINE_CLASS_0(argemdio, argemdio_driver, argemdio_methods, 237234862Sadrian sizeof(struct arge_softc)); 238234862Sadrianstatic devclass_t argemdio_devclass; 239234862Sadrian 240234862SadrianDRIVER_MODULE(miiproxy, arge, miiproxy_driver, miiproxy_devclass, 0, 0); 241234862SadrianDRIVER_MODULE(argemdio, nexus, argemdio_driver, argemdio_devclass, 0, 0); 242234862SadrianDRIVER_MODULE(mdio, argemdio, mdio_driver, mdio_devclass, 0, 0); 243234862Sadrian#endif 244234862Sadrian 245199038Sgonzostatic struct mtx miibus_mtx; 246199038Sgonzo 247206400SgonzoMTX_SYSINIT(miibus_mtx, &miibus_mtx, "arge mii lock", MTX_DEF); 248199038Sgonzo 249192179Sgonzo/* 250232627Sray * Flushes all 251285121Sadrian * 252285121Sadrian * XXX this needs to be done at interrupt time! Grr! 253188808Sgonzo */ 254188808Sgonzostatic void 255188808Sgonzoarge_flush_ddr(struct arge_softc *sc) 256188808Sgonzo{ 257285121Sadrian switch (sc->arge_mac_unit) { 258285121Sadrian case 0: 259285121Sadrian ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_GE0); 260285121Sadrian break; 261285121Sadrian case 1: 262285121Sadrian ar71xx_device_flush_ddr(AR71XX_CPU_DDR_FLUSH_GE1); 263285121Sadrian break; 264285121Sadrian default: 265285121Sadrian device_printf(sc->arge_dev, "%s: unknown unit (%d)\n", 266285121Sadrian __func__, 267285121Sadrian sc->arge_mac_unit); 268285121Sadrian break; 269285121Sadrian } 270188808Sgonzo} 271188808Sgonzo 272232627Sraystatic int 273188808Sgonzoarge_probe(device_t dev) 274188808Sgonzo{ 275188808Sgonzo 276188808Sgonzo device_set_desc(dev, "Atheros AR71xx built-in ethernet interface"); 277257338Snwhitehorn return (BUS_PROBE_NOWILDCARD); 278188808Sgonzo} 279188808Sgonzo 280290090Sadrian#ifdef ARGE_DEBUG 281209802Sadrianstatic void 282290090Sadrianarge_attach_intr_sysctl(device_t dev, struct sysctl_oid_list *parent) 283290090Sadrian{ 284290090Sadrian struct arge_softc *sc = device_get_softc(dev); 285290090Sadrian struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 286290090Sadrian struct sysctl_oid *tree = device_get_sysctl_tree(dev); 287290090Sadrian struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 288290090Sadrian char sn[8]; 289290090Sadrian int i; 290290090Sadrian 291290090Sadrian tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "intr", 292290090Sadrian CTLFLAG_RD, NULL, "Interrupt statistics"); 293290090Sadrian child = SYSCTL_CHILDREN(tree); 294290090Sadrian for (i = 0; i < 32; i++) { 295290090Sadrian snprintf(sn, sizeof(sn), "%d", i); 296290090Sadrian SYSCTL_ADD_UINT(ctx, child, OID_AUTO, sn, CTLFLAG_RD, 297290090Sadrian &sc->intr_stats.count[i], 0, ""); 298290090Sadrian } 299290090Sadrian} 300290090Sadrian#endif 301290090Sadrian 302290090Sadrianstatic void 303209802Sadrianarge_attach_sysctl(device_t dev) 304209802Sadrian{ 305209802Sadrian struct arge_softc *sc = device_get_softc(dev); 306209802Sadrian struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 307209802Sadrian struct sysctl_oid *tree = device_get_sysctl_tree(dev); 308209802Sadrian 309220355Sadrian#ifdef ARGE_DEBUG 310209802Sadrian SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 311209802Sadrian "debug", CTLFLAG_RW, &sc->arge_debug, 0, 312209802Sadrian "arge interface debugging flags"); 313290090Sadrian arge_attach_intr_sysctl(dev, SYSCTL_CHILDREN(tree)); 314220355Sadrian#endif 315209809Sadrian 316209809Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 317209809Sadrian "tx_pkts_aligned", CTLFLAG_RW, &sc->stats.tx_pkts_aligned, 0, 318209809Sadrian "number of TX aligned packets"); 319209809Sadrian 320209809Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 321232628Sray "tx_pkts_unaligned", CTLFLAG_RW, &sc->stats.tx_pkts_unaligned, 322232628Sray 0, "number of TX unaligned packets"); 323220354Sadrian 324289476Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 325289476Sadrian "tx_pkts_unaligned_start", CTLFLAG_RW, &sc->stats.tx_pkts_unaligned_start, 326289476Sadrian 0, "number of TX unaligned packets (start)"); 327289476Sadrian 328289476Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 329289476Sadrian "tx_pkts_unaligned_len", CTLFLAG_RW, &sc->stats.tx_pkts_unaligned_len, 330289476Sadrian 0, "number of TX unaligned packets (len)"); 331289476Sadrian 332289476Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 333289476Sadrian "tx_pkts_nosegs", CTLFLAG_RW, &sc->stats.tx_pkts_nosegs, 334289476Sadrian 0, "number of TX packets fail with no ring slots avail"); 335289476Sadrian 336289476Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 337289476Sadrian "intr_stray_filter", CTLFLAG_RW, &sc->stats.intr_stray, 338289476Sadrian 0, "number of stray interrupts (filter)"); 339289476Sadrian 340289476Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 341289476Sadrian "intr_stray_intr", CTLFLAG_RW, &sc->stats.intr_stray2, 342289476Sadrian 0, "number of stray interrupts (intr)"); 343289476Sadrian 344289476Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 345289476Sadrian "intr_ok", CTLFLAG_RW, &sc->stats.intr_ok, 346289476Sadrian 0, "number of OK interrupts"); 347220355Sadrian#ifdef ARGE_DEBUG 348220355Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tx_prod", 349220355Sadrian CTLFLAG_RW, &sc->arge_cdata.arge_tx_prod, 0, ""); 350220355Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tx_cons", 351220355Sadrian CTLFLAG_RW, &sc->arge_cdata.arge_tx_cons, 0, ""); 352220355Sadrian SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tx_cnt", 353220355Sadrian CTLFLAG_RW, &sc->arge_cdata.arge_tx_cnt, 0, ""); 354220355Sadrian#endif 355209802Sadrian} 356209802Sadrian 357234862Sadrianstatic void 358234862Sadrianarge_reset_mac(struct arge_softc *sc) 359234862Sadrian{ 360234862Sadrian uint32_t reg; 361256575Sadrian uint32_t reset_reg; 362234862Sadrian 363279791Sadrian ARGEDEBUG(sc, ARGE_DBG_RESET, "%s called\n", __func__); 364279791Sadrian 365234862Sadrian /* Step 1. Soft-reset MAC */ 366234862Sadrian ARGE_SET_BITS(sc, AR71XX_MAC_CFG1, MAC_CFG1_SOFT_RESET); 367234862Sadrian DELAY(20); 368234862Sadrian 369234862Sadrian /* Step 2. Punt the MAC core from the central reset register */ 370256575Sadrian /* 371256575Sadrian * XXX TODO: migrate this (and other) chip specific stuff into 372256575Sadrian * a chipdef method. 373256575Sadrian */ 374256575Sadrian if (sc->arge_mac_unit == 0) { 375256575Sadrian reset_reg = RST_RESET_GE0_MAC; 376256575Sadrian } else { 377256575Sadrian reset_reg = RST_RESET_GE1_MAC; 378256575Sadrian } 379256575Sadrian 380256575Sadrian /* 381256575Sadrian * AR934x (and later) also needs the MDIO block reset. 382279510Sadrian * XXX should methodize this! 383256575Sadrian */ 384256575Sadrian if (ar71xx_soc == AR71XX_SOC_AR9341 || 385256575Sadrian ar71xx_soc == AR71XX_SOC_AR9342 || 386256575Sadrian ar71xx_soc == AR71XX_SOC_AR9344) { 387256575Sadrian if (sc->arge_mac_unit == 0) { 388256575Sadrian reset_reg |= AR934X_RESET_GE0_MDIO; 389256575Sadrian } else { 390256575Sadrian reset_reg |= AR934X_RESET_GE1_MDIO; 391256575Sadrian } 392256575Sadrian } 393279510Sadrian 394279510Sadrian if (ar71xx_soc == AR71XX_SOC_QCA9556 || 395279510Sadrian ar71xx_soc == AR71XX_SOC_QCA9558) { 396279510Sadrian if (sc->arge_mac_unit == 0) { 397279510Sadrian reset_reg |= QCA955X_RESET_GE0_MDIO; 398279510Sadrian } else { 399279510Sadrian reset_reg |= QCA955X_RESET_GE1_MDIO; 400279510Sadrian } 401279510Sadrian } 402290910Sadrian 403290910Sadrian if (ar71xx_soc == AR71XX_SOC_QCA9533 || 404290910Sadrian ar71xx_soc == AR71XX_SOC_QCA9533_V2) { 405290910Sadrian if (sc->arge_mac_unit == 0) { 406290910Sadrian reset_reg |= QCA953X_RESET_GE0_MDIO; 407290910Sadrian } else { 408290910Sadrian reset_reg |= QCA953X_RESET_GE1_MDIO; 409290910Sadrian } 410290910Sadrian } 411290910Sadrian 412256575Sadrian ar71xx_device_stop(reset_reg); 413234862Sadrian DELAY(100); 414256575Sadrian ar71xx_device_start(reset_reg); 415234862Sadrian 416234862Sadrian /* Step 3. Reconfigure MAC block */ 417234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_CFG1, 418234862Sadrian MAC_CFG1_SYNC_RX | MAC_CFG1_RX_ENABLE | 419234862Sadrian MAC_CFG1_SYNC_TX | MAC_CFG1_TX_ENABLE); 420234862Sadrian 421234862Sadrian reg = ARGE_READ(sc, AR71XX_MAC_CFG2); 422234862Sadrian reg |= MAC_CFG2_ENABLE_PADCRC | MAC_CFG2_LENGTH_FIELD ; 423234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_CFG2, reg); 424234862Sadrian 425234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_MAX_FRAME_LEN, 1536); 426234862Sadrian} 427234862Sadrian 428256575Sadrian/* 429256648Sadrian * These values map to the divisor values programmed into 430256648Sadrian * AR71XX_MAC_MII_CFG. 431256648Sadrian * 432256648Sadrian * The index of each value corresponds to the divisor section 433256648Sadrian * value in AR71XX_MAC_MII_CFG (ie, table[0] means '0' in 434256648Sadrian * AR71XX_MAC_MII_CFG, table[1] means '1', etc.) 435256648Sadrian */ 436256648Sadrianstatic const uint32_t ar71xx_mdio_div_table[] = { 437256648Sadrian 4, 4, 6, 8, 10, 14, 20, 28, 438256648Sadrian}; 439256648Sadrian 440256648Sadrianstatic const uint32_t ar7240_mdio_div_table[] = { 441256648Sadrian 2, 2, 4, 6, 8, 12, 18, 26, 32, 40, 48, 56, 62, 70, 78, 96, 442256648Sadrian}; 443256648Sadrian 444256648Sadrianstatic const uint32_t ar933x_mdio_div_table[] = { 445256648Sadrian 4, 4, 6, 8, 10, 14, 20, 28, 34, 42, 50, 58, 66, 74, 82, 98, 446256648Sadrian}; 447256648Sadrian 448256648Sadrian/* 449256648Sadrian * Lookup the divisor to use based on the given frequency. 450256648Sadrian * 451256648Sadrian * Returns the divisor to use, or -ve on error. 452256648Sadrian */ 453256648Sadrianstatic int 454256648Sadrianarge_mdio_get_divider(struct arge_softc *sc, unsigned long mdio_clock) 455256648Sadrian{ 456256648Sadrian unsigned long ref_clock, t; 457256648Sadrian const uint32_t *table; 458256648Sadrian int ndivs; 459256648Sadrian int i; 460256648Sadrian 461256648Sadrian /* 462256648Sadrian * This is the base MDIO frequency on the SoC. 463256648Sadrian * The dividers .. well, divide. Duh. 464256648Sadrian */ 465256648Sadrian ref_clock = ar71xx_mdio_freq(); 466256648Sadrian 467256648Sadrian /* 468256648Sadrian * If either clock is undefined, just tell the 469256648Sadrian * caller to fall through to the defaults. 470256648Sadrian */ 471256648Sadrian if (ref_clock == 0 || mdio_clock == 0) 472256648Sadrian return (-EINVAL); 473256648Sadrian 474256648Sadrian /* 475256648Sadrian * Pick the correct table! 476256648Sadrian */ 477256648Sadrian switch (ar71xx_soc) { 478256648Sadrian case AR71XX_SOC_AR9330: 479256648Sadrian case AR71XX_SOC_AR9331: 480256648Sadrian case AR71XX_SOC_AR9341: 481256648Sadrian case AR71XX_SOC_AR9342: 482256648Sadrian case AR71XX_SOC_AR9344: 483290910Sadrian case AR71XX_SOC_QCA9533: 484290910Sadrian case AR71XX_SOC_QCA9533_V2: 485279510Sadrian case AR71XX_SOC_QCA9556: 486279510Sadrian case AR71XX_SOC_QCA9558: 487256648Sadrian table = ar933x_mdio_div_table; 488256648Sadrian ndivs = nitems(ar933x_mdio_div_table); 489256648Sadrian break; 490256648Sadrian 491256648Sadrian case AR71XX_SOC_AR7240: 492256648Sadrian case AR71XX_SOC_AR7241: 493256648Sadrian case AR71XX_SOC_AR7242: 494256648Sadrian table = ar7240_mdio_div_table; 495256648Sadrian ndivs = nitems(ar7240_mdio_div_table); 496256648Sadrian break; 497256648Sadrian 498256648Sadrian default: 499256648Sadrian table = ar71xx_mdio_div_table; 500256648Sadrian ndivs = nitems(ar71xx_mdio_div_table); 501256648Sadrian } 502256648Sadrian 503256648Sadrian /* 504256648Sadrian * Now, walk through the list and find the first divisor 505256648Sadrian * that falls under the target MDIO frequency. 506256648Sadrian * 507256648Sadrian * The divisors go up, but the corresponding frequencies 508256648Sadrian * are actually decreasing. 509256648Sadrian */ 510256648Sadrian for (i = 0; i < ndivs; i++) { 511256648Sadrian t = ref_clock / table[i]; 512256648Sadrian if (t <= mdio_clock) { 513256648Sadrian return (i); 514256648Sadrian } 515256648Sadrian } 516256648Sadrian 517256648Sadrian ARGEDEBUG(sc, ARGE_DBG_RESET, 518256648Sadrian "No divider found; MDIO=%lu Hz; target=%lu Hz\n", 519256648Sadrian ref_clock, mdio_clock); 520256648Sadrian return (-ENOENT); 521256648Sadrian} 522256648Sadrian 523256648Sadrian/* 524256575Sadrian * Fetch the MDIO bus clock rate. 525256575Sadrian * 526256575Sadrian * For now, the default is DIV_28 for everything 527256648Sadrian * bar AR934x, which will be DIV_58. 528256575Sadrian * 529256575Sadrian * It will definitely need updating to take into account 530256575Sadrian * the MDIO bus core clock rate and the target clock 531256575Sadrian * rate for the chip. 532256575Sadrian */ 533256575Sadrianstatic uint32_t 534256575Sadrianarge_fetch_mdiobus_clock_rate(struct arge_softc *sc) 535256575Sadrian{ 536256648Sadrian int mdio_freq, div; 537256575Sadrian 538256648Sadrian /* 539256648Sadrian * Is the MDIO frequency defined? If so, find a divisor that 540256648Sadrian * makes reasonable sense. Don't overshoot the frequency. 541256648Sadrian */ 542256648Sadrian if (resource_int_value(device_get_name(sc->arge_dev), 543256648Sadrian device_get_unit(sc->arge_dev), 544256648Sadrian "mdio_freq", 545256648Sadrian &mdio_freq) == 0) { 546256648Sadrian sc->arge_mdiofreq = mdio_freq; 547256648Sadrian div = arge_mdio_get_divider(sc, sc->arge_mdiofreq); 548256648Sadrian if (bootverbose) 549256648Sadrian device_printf(sc->arge_dev, 550256648Sadrian "%s: mdio ref freq=%llu Hz, target freq=%llu Hz," 551256648Sadrian " divisor index=%d\n", 552256648Sadrian __func__, 553256648Sadrian (unsigned long long) ar71xx_mdio_freq(), 554256648Sadrian (unsigned long long) mdio_freq, 555256648Sadrian div); 556256648Sadrian if (div >= 0) 557256648Sadrian return (div); 558256648Sadrian } 559256648Sadrian 560256648Sadrian /* 561256648Sadrian * Default value(s). 562256648Sadrian * 563256648Sadrian * XXX obviously these need .. fixing. 564256648Sadrian * 565256648Sadrian * From Linux/OpenWRT: 566256648Sadrian * 567256648Sadrian * + 7240? DIV_6 568256648Sadrian * + Builtin-switch port and not 934x? DIV_10 569256648Sadrian * + Not built-in switch port and 934x? DIV_58 570256648Sadrian * + .. else DIV_28. 571256648Sadrian */ 572256575Sadrian switch (ar71xx_soc) { 573256575Sadrian case AR71XX_SOC_AR9341: 574256575Sadrian case AR71XX_SOC_AR9342: 575256575Sadrian case AR71XX_SOC_AR9344: 576290910Sadrian case AR71XX_SOC_QCA9533: 577290910Sadrian case AR71XX_SOC_QCA9533_V2: 578279510Sadrian case AR71XX_SOC_QCA9556: 579279510Sadrian case AR71XX_SOC_QCA9558: 580256648Sadrian return (MAC_MII_CFG_CLOCK_DIV_58); 581256648Sadrian break; 582256575Sadrian default: 583256575Sadrian return (MAC_MII_CFG_CLOCK_DIV_28); 584256575Sadrian } 585256575Sadrian} 586256575Sadrian 587234862Sadrianstatic void 588234862Sadrianarge_reset_miibus(struct arge_softc *sc) 589234862Sadrian{ 590256575Sadrian uint32_t mdio_div; 591234862Sadrian 592256575Sadrian mdio_div = arge_fetch_mdiobus_clock_rate(sc); 593256575Sadrian 594256575Sadrian /* 595256575Sadrian * XXX AR934x and later; should we be also resetting the 596256575Sadrian * MDIO block(s) using the reset register block? 597256575Sadrian */ 598256575Sadrian 599256575Sadrian /* Reset MII bus; program in the default divisor */ 600256575Sadrian ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET | mdio_div); 601234862Sadrian DELAY(100); 602256575Sadrian ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, mdio_div); 603234862Sadrian DELAY(100); 604234862Sadrian} 605234862Sadrian 606234919Sadrianstatic void 607234919Sadrianarge_fetch_pll_config(struct arge_softc *sc) 608234919Sadrian{ 609234919Sadrian long int val; 610234919Sadrian 611234919Sadrian if (resource_long_value(device_get_name(sc->arge_dev), 612234919Sadrian device_get_unit(sc->arge_dev), 613234919Sadrian "pll_10", &val) == 0) { 614234919Sadrian sc->arge_pllcfg.pll_10 = val; 615234919Sadrian device_printf(sc->arge_dev, "%s: pll_10 = 0x%x\n", 616234919Sadrian __func__, (int) val); 617234919Sadrian } 618234919Sadrian if (resource_long_value(device_get_name(sc->arge_dev), 619234919Sadrian device_get_unit(sc->arge_dev), 620234919Sadrian "pll_100", &val) == 0) { 621234919Sadrian sc->arge_pllcfg.pll_100 = val; 622234919Sadrian device_printf(sc->arge_dev, "%s: pll_100 = 0x%x\n", 623234919Sadrian __func__, (int) val); 624234919Sadrian } 625234919Sadrian if (resource_long_value(device_get_name(sc->arge_dev), 626234919Sadrian device_get_unit(sc->arge_dev), 627234919Sadrian "pll_1000", &val) == 0) { 628234919Sadrian sc->arge_pllcfg.pll_1000 = val; 629234919Sadrian device_printf(sc->arge_dev, "%s: pll_1000 = 0x%x\n", 630234919Sadrian __func__, (int) val); 631234919Sadrian } 632234919Sadrian} 633234919Sadrian 634188808Sgonzostatic int 635188808Sgonzoarge_attach(device_t dev) 636188808Sgonzo{ 637188808Sgonzo struct ifnet *ifp; 638188808Sgonzo struct arge_softc *sc; 639280798Sadrian int error = 0, rid, i; 640199234Sgonzo uint32_t hint; 641220260Sadrian long eeprom_mac_addr = 0; 642234910Sadrian int miicfg = 0; 643254690Ssbruno int readascii = 0; 644263224Sadrian int local_mac = 0; 645280798Sadrian uint8_t local_macaddr[ETHER_ADDR_LEN]; 646280798Sadrian char * local_macstr; 647280798Sadrian char devid_str[32]; 648280798Sadrian int count; 649188808Sgonzo 650188808Sgonzo sc = device_get_softc(dev); 651188808Sgonzo sc->arge_dev = dev; 652188808Sgonzo sc->arge_mac_unit = device_get_unit(dev); 653188808Sgonzo 654220260Sadrian /* 655280798Sadrian * See if there's a "board" MAC address hint available for 656280798Sadrian * this particular device. 657280798Sadrian * 658280798Sadrian * This is in the environment - it'd be nice to use the resource_*() 659280798Sadrian * routines, but at the moment the system is booting, the resource hints 660280798Sadrian * are set to the 'static' map so they're not pulling from kenv. 661280798Sadrian */ 662280798Sadrian snprintf(devid_str, 32, "hint.%s.%d.macaddr", 663280798Sadrian device_get_name(dev), 664280798Sadrian device_get_unit(dev)); 665280798Sadrian if ((local_macstr = kern_getenv(devid_str)) != NULL) { 666280798Sadrian uint32_t tmpmac[ETHER_ADDR_LEN]; 667280798Sadrian 668280798Sadrian /* Have a MAC address; should use it */ 669280798Sadrian device_printf(dev, "Overriding MAC address from environment: '%s'\n", 670280798Sadrian local_macstr); 671280798Sadrian 672280798Sadrian /* Extract out the MAC address */ 673280798Sadrian /* XXX this should all be a generic method */ 674280798Sadrian count = sscanf(local_macstr, "%x%*c%x%*c%x%*c%x%*c%x%*c%x", 675280798Sadrian &tmpmac[0], &tmpmac[1], 676280798Sadrian &tmpmac[2], &tmpmac[3], 677280798Sadrian &tmpmac[4], &tmpmac[5]); 678280798Sadrian if (count == 6) { 679280798Sadrian /* Valid! */ 680280798Sadrian local_mac = 1; 681280798Sadrian for (i = 0; i < ETHER_ADDR_LEN; i++) 682280798Sadrian local_macaddr[i] = tmpmac[i]; 683280798Sadrian } 684280798Sadrian /* Done! */ 685280798Sadrian freeenv(local_macstr); 686280798Sadrian local_macstr = NULL; 687280798Sadrian } 688280798Sadrian 689280798Sadrian /* 690289476Sadrian * Hardware workarounds. 691289476Sadrian */ 692289476Sadrian switch (ar71xx_soc) { 693289744Sadrian case AR71XX_SOC_AR9330: 694289744Sadrian case AR71XX_SOC_AR9331: 695289898Sadrian case AR71XX_SOC_AR9341: 696289898Sadrian case AR71XX_SOC_AR9342: 697289898Sadrian case AR71XX_SOC_AR9344: 698290910Sadrian case AR71XX_SOC_QCA9533: 699290910Sadrian case AR71XX_SOC_QCA9533_V2: 700289476Sadrian case AR71XX_SOC_QCA9556: 701289476Sadrian case AR71XX_SOC_QCA9558: 702289476Sadrian /* Arbitrary alignment */ 703289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_TX_DESC_ALIGN_1BYTE; 704289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE; 705289476Sadrian break; 706289476Sadrian default: 707289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE; 708289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE; 709289476Sadrian break; 710289476Sadrian } 711289476Sadrian 712289476Sadrian /* 713220260Sadrian * Some units (eg the TP-Link WR-1043ND) do not have a convenient 714220260Sadrian * EEPROM location to read the ethernet MAC address from. 715220260Sadrian * OpenWRT simply snaffles it from a fixed location. 716220260Sadrian * 717220260Sadrian * Since multiple units seem to use this feature, include 718220260Sadrian * a method of setting the MAC address based on an flash location 719220260Sadrian * in CPU address space. 720254690Ssbruno * 721254690Ssbruno * Some vendors have decided to store the mac address as a literal 722254690Ssbruno * string of 18 characters in xx:xx:xx:xx:xx:xx format instead of 723254690Ssbruno * an array of numbers. Expose a hint to turn on this conversion 724254690Ssbruno * feature via strtol() 725220260Sadrian */ 726280798Sadrian if (local_mac == 0 && resource_long_value(device_get_name(dev), 727280798Sadrian device_get_unit(dev), "eeprommac", &eeprom_mac_addr) == 0) { 728263224Sadrian local_mac = 1; 729220260Sadrian int i; 730232628Sray const char *mac = 731232628Sray (const char *) MIPS_PHYS_TO_KSEG1(eeprom_mac_addr); 732220260Sadrian device_printf(dev, "Overriding MAC from EEPROM\n"); 733254690Ssbruno if (resource_int_value(device_get_name(dev), device_get_unit(dev), 734254690Ssbruno "readascii", &readascii) == 0) { 735254690Ssbruno device_printf(dev, "Vendor stores MAC in ASCII format\n"); 736254690Ssbruno for (i = 0; i < 6; i++) { 737280798Sadrian local_macaddr[i] = strtol(&(mac[i*3]), NULL, 16); 738254690Ssbruno } 739254690Ssbruno } else { 740254690Ssbruno for (i = 0; i < 6; i++) { 741280798Sadrian local_macaddr[i] = mac[i]; 742254690Ssbruno } 743220260Sadrian } 744220260Sadrian } 745220260Sadrian 746232627Sray KASSERT(((sc->arge_mac_unit == 0) || (sc->arge_mac_unit == 1)), 747188808Sgonzo ("if_arge: Only MAC0 and MAC1 supported")); 748188808Sgonzo 749188808Sgonzo /* 750234919Sadrian * Fetch the PLL configuration. 751234919Sadrian */ 752234919Sadrian arge_fetch_pll_config(sc); 753234919Sadrian 754234919Sadrian /* 755234910Sadrian * Get the MII configuration, if applicable. 756234910Sadrian */ 757234910Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 758234910Sadrian "miimode", &miicfg) == 0) { 759234910Sadrian /* XXX bounds check? */ 760234910Sadrian device_printf(dev, "%s: overriding MII mode to '%s'\n", 761234910Sadrian __func__, arge_miicfg_str[miicfg]); 762234910Sadrian sc->arge_miicfg = miicfg; 763234910Sadrian } 764234910Sadrian 765234910Sadrian /* 766188808Sgonzo * Get which PHY of 5 available we should use for this unit 767188808Sgonzo */ 768234862Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 769234862Sadrian "phymask", &sc->arge_phymask) != 0) { 770188808Sgonzo /* 771232627Sray * Use port 4 (WAN) for GE0. For any other port use 772232627Sray * its PHY the same as its unit number 773188808Sgonzo */ 774188808Sgonzo if (sc->arge_mac_unit == 0) 775234862Sadrian sc->arge_phymask = (1 << 4); 776188808Sgonzo else 777199234Sgonzo /* Use all phys up to 4 */ 778234862Sadrian sc->arge_phymask = (1 << 4) - 1; 779188808Sgonzo 780234862Sadrian device_printf(dev, "No PHY specified, using mask %d\n", sc->arge_phymask); 781188808Sgonzo } 782188808Sgonzo 783199234Sgonzo /* 784279791Sadrian * Get default/hard-coded media & duplex mode. 785199234Sgonzo */ 786232627Sray if (resource_int_value(device_get_name(dev), device_get_unit(dev), 787199234Sgonzo "media", &hint) != 0) 788199234Sgonzo hint = 0; 789188808Sgonzo 790199234Sgonzo if (hint == 1000) 791199234Sgonzo sc->arge_media_type = IFM_1000_T; 792279791Sadrian else if (hint == 100) 793279791Sadrian sc->arge_media_type = IFM_100_TX; 794279791Sadrian else if (hint == 10) 795279791Sadrian sc->arge_media_type = IFM_10_T; 796199234Sgonzo else 797279791Sadrian sc->arge_media_type = 0; 798199234Sgonzo 799232627Sray if (resource_int_value(device_get_name(dev), device_get_unit(dev), 800199234Sgonzo "fduplex", &hint) != 0) 801199234Sgonzo hint = 1; 802199234Sgonzo 803199234Sgonzo if (hint) 804199234Sgonzo sc->arge_duplex_mode = IFM_FDX; 805199234Sgonzo else 806199234Sgonzo sc->arge_duplex_mode = 0; 807199234Sgonzo 808188808Sgonzo mtx_init(&sc->arge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 809188808Sgonzo MTX_DEF); 810188808Sgonzo callout_init_mtx(&sc->arge_stat_callout, &sc->arge_mtx, 0); 811188808Sgonzo TASK_INIT(&sc->arge_link_task, 0, arge_link_task, sc); 812188808Sgonzo 813188808Sgonzo /* Map control/status registers. */ 814188808Sgonzo sc->arge_rid = 0; 815234862Sadrian sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 816234862Sadrian &sc->arge_rid, RF_ACTIVE | RF_SHAREABLE); 817188808Sgonzo 818188808Sgonzo if (sc->arge_res == NULL) { 819188808Sgonzo device_printf(dev, "couldn't map memory\n"); 820188808Sgonzo error = ENXIO; 821188808Sgonzo goto fail; 822188808Sgonzo } 823188808Sgonzo 824188808Sgonzo /* Allocate interrupts */ 825188808Sgonzo rid = 0; 826232627Sray sc->arge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 827188808Sgonzo RF_SHAREABLE | RF_ACTIVE); 828188808Sgonzo 829188808Sgonzo if (sc->arge_irq == NULL) { 830188808Sgonzo device_printf(dev, "couldn't map interrupt\n"); 831188808Sgonzo error = ENXIO; 832188808Sgonzo goto fail; 833188808Sgonzo } 834188808Sgonzo 835188808Sgonzo /* Allocate ifnet structure. */ 836188808Sgonzo ifp = sc->arge_ifp = if_alloc(IFT_ETHER); 837188808Sgonzo 838188808Sgonzo if (ifp == NULL) { 839188808Sgonzo device_printf(dev, "couldn't allocate ifnet structure\n"); 840188808Sgonzo error = ENOSPC; 841188808Sgonzo goto fail; 842188808Sgonzo } 843188808Sgonzo 844188808Sgonzo ifp->if_softc = sc; 845188808Sgonzo if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 846188808Sgonzo ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 847188808Sgonzo ifp->if_ioctl = arge_ioctl; 848188808Sgonzo ifp->if_start = arge_start; 849188808Sgonzo ifp->if_init = arge_init; 850198932Sgonzo sc->arge_if_flags = ifp->if_flags; 851188808Sgonzo 852188808Sgonzo /* XXX: add real size */ 853207554Ssobomax IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 854207554Ssobomax ifp->if_snd.ifq_maxlen = ifqmaxlen; 855188808Sgonzo IFQ_SET_READY(&ifp->if_snd); 856188808Sgonzo 857268235Sloos /* Tell the upper layer(s) we support long frames. */ 858268235Sloos ifp->if_capabilities |= IFCAP_VLAN_MTU; 859268235Sloos 860188808Sgonzo ifp->if_capenable = ifp->if_capabilities; 861192783Sgonzo#ifdef DEVICE_POLLING 862192783Sgonzo ifp->if_capabilities |= IFCAP_POLLING; 863192783Sgonzo#endif 864188808Sgonzo 865280798Sadrian /* If there's a local mac defined, copy that in */ 866280798Sadrian if (local_mac == 1) { 867280798Sadrian (void) ar71xx_mac_addr_init(sc->arge_eaddr, 868280798Sadrian local_macaddr, 0, 0); 869280798Sadrian } else { 870192179Sgonzo /* 871192179Sgonzo * No MAC address configured. Generate the random one. 872192179Sgonzo */ 873198933Sgonzo if (bootverbose) 874232627Sray device_printf(dev, 875192179Sgonzo "Generating random ethernet address.\n"); 876280124Sadrian (void) ar71xx_mac_addr_random_init(sc->arge_eaddr); 877192179Sgonzo } 878263224Sadrian 879188808Sgonzo if (arge_dma_alloc(sc) != 0) { 880188808Sgonzo error = ENXIO; 881188808Sgonzo goto fail; 882188808Sgonzo } 883188808Sgonzo 884234862Sadrian /* 885234862Sadrian * Don't do this for the MDIO bus case - it's already done 886234862Sadrian * as part of the MDIO bus attachment. 887292245Sadrian * 888292245Sadrian * XXX TODO: if we don't do this, we don't ever release the MAC 889292245Sadrian * from reset and we can't use the port. Now, if we define ARGE_MDIO 890292245Sadrian * but we /don't/ define two MDIO busses, then we can't actually 891292245Sadrian * use both MACs. 892234862Sadrian */ 893234862Sadrian#if !defined(ARGE_MDIO) 894192569Sdwhite /* Initialize the MAC block */ 895234862Sadrian arge_reset_mac(sc); 896234862Sadrian arge_reset_miibus(sc); 897234862Sadrian#endif 898232627Sray 899234910Sadrian /* Configure MII mode, just for convienence */ 900234910Sadrian if (sc->arge_miicfg != 0) 901234910Sadrian ar71xx_device_set_mii_if(sc->arge_mac_unit, sc->arge_miicfg); 902234910Sadrian 903232627Sray /* 904188808Sgonzo * Set all Ethernet address registers to the same initial values 905232627Sray * set all four addresses to 66-88-aa-cc-dd-ee 906188808Sgonzo */ 907234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR1, (sc->arge_eaddr[2] << 24) 908234862Sadrian | (sc->arge_eaddr[3] << 16) | (sc->arge_eaddr[4] << 8) 909234862Sadrian | sc->arge_eaddr[5]); 910234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR2, (sc->arge_eaddr[0] << 8) 911234862Sadrian | sc->arge_eaddr[1]); 912188808Sgonzo 913232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG0, 914188808Sgonzo FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT); 915188808Sgonzo 916289476Sadrian /* 917289476Sadrian * SoC specific bits. 918289476Sadrian */ 919219589Sadrian switch (ar71xx_soc) { 920219589Sadrian case AR71XX_SOC_AR7240: 921219589Sadrian case AR71XX_SOC_AR7241: 922219589Sadrian case AR71XX_SOC_AR7242: 923249123Sadrian case AR71XX_SOC_AR9330: 924249123Sadrian case AR71XX_SOC_AR9331: 925256575Sadrian case AR71XX_SOC_AR9341: 926256575Sadrian case AR71XX_SOC_AR9342: 927256575Sadrian case AR71XX_SOC_AR9344: 928290910Sadrian case AR71XX_SOC_QCA9533: 929290910Sadrian case AR71XX_SOC_QCA9533_V2: 930279510Sadrian case AR71XX_SOC_QCA9556: 931279510Sadrian case AR71XX_SOC_QCA9558: 932219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0010ffff); 933219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x015500aa); 934219589Sadrian break; 935256575Sadrian /* AR71xx, AR913x */ 936219589Sadrian default: 937219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0fff0000); 938219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x00001fff); 939219589Sadrian } 940219589Sadrian 941232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMATCH, 942192783Sgonzo FIFO_RX_FILTMATCH_DEFAULT); 943188808Sgonzo 944232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK, 945192783Sgonzo FIFO_RX_FILTMASK_DEFAULT); 946188808Sgonzo 947234862Sadrian#if defined(ARGE_MDIO) 948234862Sadrian sc->arge_miiproxy = mii_attach_proxy(sc->arge_dev); 949234862Sadrian#endif 950199234Sgonzo 951234862Sadrian device_printf(sc->arge_dev, "finishing attachment, phymask %04x" 952234862Sadrian ", proxy %s \n", sc->arge_phymask, sc->arge_miiproxy == NULL ? 953234862Sadrian "null" : "set"); 954234862Sadrian for (i = 0; i < ARGE_NPHY; i++) { 955234862Sadrian if (((1 << i) & sc->arge_phymask) != 0) { 956234862Sadrian error = mii_attach(sc->arge_miiproxy != NULL ? 957234862Sadrian sc->arge_miiproxy : sc->arge_dev, 958234862Sadrian &sc->arge_miibus, sc->arge_ifp, 959234862Sadrian arge_ifmedia_upd, arge_ifmedia_sts, 960234862Sadrian BMSR_DEFCAPMASK, i, MII_OFFSET_ANY, 0); 961234862Sadrian if (error != 0) { 962234862Sadrian device_printf(sc->arge_dev, "unable to attach" 963234862Sadrian " PHY %d: %d\n", i, error); 964234862Sadrian goto fail; 965234862Sadrian } 966199234Sgonzo } 967199234Sgonzo } 968279791Sadrian 969234862Sadrian if (sc->arge_miibus == NULL) { 970234862Sadrian /* no PHY, so use hard-coded values */ 971279791Sadrian ifmedia_init(&sc->arge_ifmedia, 0, 972199234Sgonzo arge_multiphy_mediachange, 973199234Sgonzo arge_multiphy_mediastatus); 974199234Sgonzo ifmedia_add(&sc->arge_ifmedia, 975232627Sray IFM_ETHER | sc->arge_media_type | sc->arge_duplex_mode, 976199234Sgonzo 0, NULL); 977199234Sgonzo ifmedia_set(&sc->arge_ifmedia, 978199234Sgonzo IFM_ETHER | sc->arge_media_type | sc->arge_duplex_mode); 979199234Sgonzo arge_set_pll(sc, sc->arge_media_type, sc->arge_duplex_mode); 980199234Sgonzo } 981199234Sgonzo 982188808Sgonzo /* Call MI attach routine. */ 983234862Sadrian ether_ifattach(sc->arge_ifp, sc->arge_eaddr); 984188808Sgonzo 985188808Sgonzo /* Hook interrupt last to avoid having to lock softc */ 986234862Sadrian error = bus_setup_intr(sc->arge_dev, sc->arge_irq, INTR_TYPE_NET | INTR_MPSAFE, 987188808Sgonzo arge_intr_filter, arge_intr, sc, &sc->arge_intrhand); 988188808Sgonzo 989188808Sgonzo if (error) { 990234862Sadrian device_printf(sc->arge_dev, "couldn't set up irq\n"); 991234862Sadrian ether_ifdetach(sc->arge_ifp); 992188808Sgonzo goto fail; 993188808Sgonzo } 994188808Sgonzo 995209802Sadrian /* setup sysctl variables */ 996234862Sadrian arge_attach_sysctl(sc->arge_dev); 997209802Sadrian 998188808Sgonzofail: 999234862Sadrian if (error) 1000188808Sgonzo arge_detach(dev); 1001188808Sgonzo 1002188808Sgonzo return (error); 1003188808Sgonzo} 1004188808Sgonzo 1005188808Sgonzostatic int 1006188808Sgonzoarge_detach(device_t dev) 1007188808Sgonzo{ 1008192783Sgonzo struct arge_softc *sc = device_get_softc(dev); 1009188808Sgonzo struct ifnet *ifp = sc->arge_ifp; 1010188808Sgonzo 1011232628Sray KASSERT(mtx_initialized(&sc->arge_mtx), 1012232628Sray ("arge mutex not initialized")); 1013188808Sgonzo 1014188808Sgonzo /* These should only be active if attach succeeded */ 1015188808Sgonzo if (device_is_attached(dev)) { 1016188808Sgonzo ARGE_LOCK(sc); 1017188808Sgonzo sc->arge_detach = 1; 1018192783Sgonzo#ifdef DEVICE_POLLING 1019192783Sgonzo if (ifp->if_capenable & IFCAP_POLLING) 1020192783Sgonzo ether_poll_deregister(ifp); 1021192783Sgonzo#endif 1022192783Sgonzo 1023188808Sgonzo arge_stop(sc); 1024188808Sgonzo ARGE_UNLOCK(sc); 1025188808Sgonzo taskqueue_drain(taskqueue_swi, &sc->arge_link_task); 1026188808Sgonzo ether_ifdetach(ifp); 1027188808Sgonzo } 1028188808Sgonzo 1029188808Sgonzo if (sc->arge_miibus) 1030188808Sgonzo device_delete_child(dev, sc->arge_miibus); 1031199234Sgonzo 1032234862Sadrian if (sc->arge_miiproxy) 1033234862Sadrian device_delete_child(dev, sc->arge_miiproxy); 1034234862Sadrian 1035188808Sgonzo bus_generic_detach(dev); 1036188808Sgonzo 1037188808Sgonzo if (sc->arge_intrhand) 1038188808Sgonzo bus_teardown_intr(dev, sc->arge_irq, sc->arge_intrhand); 1039188808Sgonzo 1040188808Sgonzo if (sc->arge_res) 1041232627Sray bus_release_resource(dev, SYS_RES_MEMORY, sc->arge_rid, 1042188808Sgonzo sc->arge_res); 1043188808Sgonzo 1044188808Sgonzo if (ifp) 1045188808Sgonzo if_free(ifp); 1046188808Sgonzo 1047188808Sgonzo arge_dma_free(sc); 1048188808Sgonzo 1049188808Sgonzo mtx_destroy(&sc->arge_mtx); 1050188808Sgonzo 1051188808Sgonzo return (0); 1052188808Sgonzo 1053188808Sgonzo} 1054188808Sgonzo 1055188808Sgonzostatic int 1056188808Sgonzoarge_suspend(device_t dev) 1057188808Sgonzo{ 1058188808Sgonzo 1059188808Sgonzo panic("%s", __func__); 1060188808Sgonzo return 0; 1061188808Sgonzo} 1062188808Sgonzo 1063188808Sgonzostatic int 1064188808Sgonzoarge_resume(device_t dev) 1065188808Sgonzo{ 1066188808Sgonzo 1067188808Sgonzo panic("%s", __func__); 1068188808Sgonzo return 0; 1069188808Sgonzo} 1070188808Sgonzo 1071194059Sgonzostatic int 1072188808Sgonzoarge_shutdown(device_t dev) 1073188808Sgonzo{ 1074188808Sgonzo struct arge_softc *sc; 1075188808Sgonzo 1076188808Sgonzo sc = device_get_softc(dev); 1077188808Sgonzo 1078188808Sgonzo ARGE_LOCK(sc); 1079188808Sgonzo arge_stop(sc); 1080188808Sgonzo ARGE_UNLOCK(sc); 1081194059Sgonzo 1082194059Sgonzo return (0); 1083188808Sgonzo} 1084188808Sgonzo 1085234862Sadrianstatic void 1086234862Sadrianarge_hinted_child(device_t bus, const char *dname, int dunit) 1087234862Sadrian{ 1088234862Sadrian BUS_ADD_CHILD(bus, 0, dname, dunit); 1089234862Sadrian device_printf(bus, "hinted child %s%d\n", dname, dunit); 1090234862Sadrian} 1091234862Sadrian 1092188808Sgonzostatic int 1093290217Sadrianarge_mdio_busy(struct arge_softc *sc) 1094290217Sadrian{ 1095290217Sadrian int i,result; 1096290217Sadrian 1097290217Sadrian for (i = 0; i < ARGE_MII_TIMEOUT; i++) { 1098290217Sadrian DELAY(5); 1099290217Sadrian ARGE_MDIO_BARRIER_READ(sc); 1100290217Sadrian result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR); 1101290217Sadrian if (! result) 1102290217Sadrian return (0); 1103290217Sadrian DELAY(5); 1104290217Sadrian } 1105290217Sadrian return (-1); 1106290217Sadrian} 1107290217Sadrian 1108290217Sadrianstatic int 1109188808Sgonzoarge_miibus_readreg(device_t dev, int phy, int reg) 1110188808Sgonzo{ 1111188808Sgonzo struct arge_softc * sc = device_get_softc(dev); 1112290217Sadrian int result; 1113232627Sray uint32_t addr = (phy << MAC_MII_PHY_ADDR_SHIFT) 1114188808Sgonzo | (reg & MAC_MII_REG_MASK); 1115188808Sgonzo 1116199038Sgonzo mtx_lock(&miibus_mtx); 1117290217Sadrian ARGE_MDIO_BARRIER_RW(sc); 1118234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE); 1119290217Sadrian ARGE_MDIO_BARRIER_WRITE(sc); 1120234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr); 1121290217Sadrian ARGE_MDIO_BARRIER_WRITE(sc); 1122234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_READ); 1123188808Sgonzo 1124290217Sadrian if (arge_mdio_busy(sc) != 0) { 1125199038Sgonzo mtx_unlock(&miibus_mtx); 1126220354Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s timedout\n", __func__); 1127188808Sgonzo /* XXX: return ERRNO istead? */ 1128188808Sgonzo return (-1); 1129188808Sgonzo } 1130188808Sgonzo 1131290217Sadrian ARGE_MDIO_BARRIER_READ(sc); 1132234862Sadrian result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK; 1133290217Sadrian ARGE_MDIO_BARRIER_RW(sc); 1134234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE); 1135199038Sgonzo mtx_unlock(&miibus_mtx); 1136199038Sgonzo 1137232628Sray ARGEDEBUG(sc, ARGE_DBG_MII, 1138232628Sray "%s: phy=%d, reg=%02x, value[%08x]=%04x\n", 1139232628Sray __func__, phy, reg, addr, result); 1140188808Sgonzo 1141188808Sgonzo return (result); 1142188808Sgonzo} 1143188808Sgonzo 1144188808Sgonzostatic int 1145188808Sgonzoarge_miibus_writereg(device_t dev, int phy, int reg, int data) 1146188808Sgonzo{ 1147188808Sgonzo struct arge_softc * sc = device_get_softc(dev); 1148232627Sray uint32_t addr = 1149196794Sgonzo (phy << MAC_MII_PHY_ADDR_SHIFT) | (reg & MAC_MII_REG_MASK); 1150188808Sgonzo 1151234862Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s: phy=%d, reg=%02x, value=%04x\n", __func__, 1152234862Sadrian phy, reg, data); 1153199038Sgonzo 1154199038Sgonzo mtx_lock(&miibus_mtx); 1155290217Sadrian ARGE_MDIO_BARRIER_RW(sc); 1156234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr); 1157290217Sadrian ARGE_MDIO_BARRIER_WRITE(sc); 1158234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CONTROL, data); 1159290217Sadrian ARGE_MDIO_BARRIER_WRITE(sc); 1160188808Sgonzo 1161290217Sadrian if (arge_mdio_busy(sc) != 0) { 1162290217Sadrian mtx_unlock(&miibus_mtx); 1163220354Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s timedout\n", __func__); 1164188808Sgonzo /* XXX: return ERRNO istead? */ 1165188808Sgonzo return (-1); 1166188808Sgonzo } 1167188808Sgonzo 1168290217Sadrian mtx_unlock(&miibus_mtx); 1169188808Sgonzo return (0); 1170188808Sgonzo} 1171188808Sgonzo 1172188808Sgonzostatic void 1173188808Sgonzoarge_miibus_statchg(device_t dev) 1174188808Sgonzo{ 1175232627Sray struct arge_softc *sc; 1176188808Sgonzo 1177188808Sgonzo sc = device_get_softc(dev); 1178188808Sgonzo taskqueue_enqueue(taskqueue_swi, &sc->arge_link_task); 1179188808Sgonzo} 1180188808Sgonzo 1181188808Sgonzostatic void 1182188808Sgonzoarge_link_task(void *arg, int pending) 1183188808Sgonzo{ 1184188808Sgonzo struct arge_softc *sc; 1185232914Sadrian sc = (struct arge_softc *)arg; 1186232914Sadrian 1187232914Sadrian ARGE_LOCK(sc); 1188232914Sadrian arge_update_link_locked(sc); 1189232914Sadrian ARGE_UNLOCK(sc); 1190232914Sadrian} 1191232914Sadrian 1192232914Sadrianstatic void 1193232914Sadrianarge_update_link_locked(struct arge_softc *sc) 1194232914Sadrian{ 1195188808Sgonzo struct mii_data *mii; 1196188808Sgonzo struct ifnet *ifp; 1197199234Sgonzo uint32_t media, duplex; 1198188808Sgonzo 1199188808Sgonzo mii = device_get_softc(sc->arge_miibus); 1200188808Sgonzo ifp = sc->arge_ifp; 1201188808Sgonzo if (mii == NULL || ifp == NULL || 1202188808Sgonzo (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1203188808Sgonzo return; 1204188808Sgonzo } 1205188808Sgonzo 1206279791Sadrian /* 1207279791Sadrian * If we have a static media type configured, then 1208279791Sadrian * use that. Some PHY configurations (eg QCA955x -> AR8327) 1209279791Sadrian * use a static speed/duplex between the SoC and switch, 1210279791Sadrian * even though the front-facing PHY speed changes. 1211279791Sadrian */ 1212279791Sadrian if (sc->arge_media_type != 0) { 1213279791Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s: fixed; media=%d, duplex=%d\n", 1214279791Sadrian __func__, 1215279791Sadrian sc->arge_media_type, 1216279791Sadrian sc->arge_duplex_mode); 1217279791Sadrian if (mii->mii_media_status & IFM_ACTIVE) { 1218279791Sadrian sc->arge_link_status = 1; 1219279791Sadrian } else { 1220279791Sadrian sc->arge_link_status = 0; 1221279791Sadrian } 1222279791Sadrian arge_set_pll(sc, sc->arge_media_type, sc->arge_duplex_mode); 1223279791Sadrian } 1224279791Sadrian 1225188808Sgonzo if (mii->mii_media_status & IFM_ACTIVE) { 1226188808Sgonzo 1227188808Sgonzo media = IFM_SUBTYPE(mii->mii_media_active); 1228188808Sgonzo if (media != IFM_NONE) { 1229188808Sgonzo sc->arge_link_status = 1; 1230199234Sgonzo duplex = mii->mii_media_active & IFM_GMASK; 1231234907Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s: media=%d, duplex=%d\n", 1232234907Sadrian __func__, 1233234907Sadrian media, 1234234907Sadrian duplex); 1235199234Sgonzo arge_set_pll(sc, media, duplex); 1236199234Sgonzo } 1237232914Sadrian } else { 1238199234Sgonzo sc->arge_link_status = 0; 1239232914Sadrian } 1240199234Sgonzo} 1241192783Sgonzo 1242199234Sgonzostatic void 1243199234Sgonzoarge_set_pll(struct arge_softc *sc, int media, int duplex) 1244199234Sgonzo{ 1245211511Sadrian uint32_t cfg, ifcontrol, rx_filtmask; 1246234907Sadrian uint32_t fifo_tx, pll; 1247211511Sadrian int if_speed; 1248192783Sgonzo 1249279791Sadrian /* 1250279791Sadrian * XXX Verify - is this valid for all chips? 1251279791Sadrian * QCA955x (and likely some of the earlier chips!) define 1252279791Sadrian * this as nibble mode and byte mode, and those have to do 1253279791Sadrian * with the interface type (MII/SMII versus GMII/RGMII.) 1254279791Sadrian */ 1255234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "set_pll(%04x, %s)\n", media, 1256234862Sadrian duplex == IFM_FDX ? "full" : "half"); 1257199234Sgonzo cfg = ARGE_READ(sc, AR71XX_MAC_CFG2); 1258232627Sray cfg &= ~(MAC_CFG2_IFACE_MODE_1000 1259232627Sray | MAC_CFG2_IFACE_MODE_10_100 1260199234Sgonzo | MAC_CFG2_FULL_DUPLEX); 1261188808Sgonzo 1262199234Sgonzo if (duplex == IFM_FDX) 1263199234Sgonzo cfg |= MAC_CFG2_FULL_DUPLEX; 1264188808Sgonzo 1265199234Sgonzo ifcontrol = ARGE_READ(sc, AR71XX_MAC_IFCONTROL); 1266199234Sgonzo ifcontrol &= ~MAC_IFCONTROL_SPEED; 1267232627Sray rx_filtmask = 1268199234Sgonzo ARGE_READ(sc, AR71XX_MAC_FIFO_RX_FILTMASK); 1269199234Sgonzo rx_filtmask &= ~FIFO_RX_MASK_BYTE_MODE; 1270188808Sgonzo 1271199234Sgonzo switch(media) { 1272199234Sgonzo case IFM_10_T: 1273199234Sgonzo cfg |= MAC_CFG2_IFACE_MODE_10_100; 1274211511Sadrian if_speed = 10; 1275199234Sgonzo break; 1276199234Sgonzo case IFM_100_TX: 1277199234Sgonzo cfg |= MAC_CFG2_IFACE_MODE_10_100; 1278199234Sgonzo ifcontrol |= MAC_IFCONTROL_SPEED; 1279211511Sadrian if_speed = 100; 1280199234Sgonzo break; 1281199234Sgonzo case IFM_1000_T: 1282199234Sgonzo case IFM_1000_SX: 1283199234Sgonzo cfg |= MAC_CFG2_IFACE_MODE_1000; 1284199234Sgonzo rx_filtmask |= FIFO_RX_MASK_BYTE_MODE; 1285211511Sadrian if_speed = 1000; 1286199234Sgonzo break; 1287199234Sgonzo default: 1288211511Sadrian if_speed = 100; 1289232627Sray device_printf(sc->arge_dev, 1290199234Sgonzo "Unknown media %d\n", media); 1291199234Sgonzo } 1292188808Sgonzo 1293234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: if_speed=%d\n", __func__, if_speed); 1294234907Sadrian 1295219589Sadrian switch (ar71xx_soc) { 1296219589Sadrian case AR71XX_SOC_AR7240: 1297219589Sadrian case AR71XX_SOC_AR7241: 1298219589Sadrian case AR71XX_SOC_AR7242: 1299249123Sadrian case AR71XX_SOC_AR9330: 1300249123Sadrian case AR71XX_SOC_AR9331: 1301256575Sadrian case AR71XX_SOC_AR9341: 1302256575Sadrian case AR71XX_SOC_AR9342: 1303256575Sadrian case AR71XX_SOC_AR9344: 1304290910Sadrian case AR71XX_SOC_QCA9533: 1305290910Sadrian case AR71XX_SOC_QCA9533_V2: 1306279510Sadrian case AR71XX_SOC_QCA9556: 1307279510Sadrian case AR71XX_SOC_QCA9558: 1308219589Sadrian fifo_tx = 0x01f00140; 1309219589Sadrian break; 1310219589Sadrian case AR71XX_SOC_AR9130: 1311219589Sadrian case AR71XX_SOC_AR9132: 1312219589Sadrian fifo_tx = 0x00780fff; 1313219589Sadrian break; 1314256575Sadrian /* AR71xx */ 1315219589Sadrian default: 1316219589Sadrian fifo_tx = 0x008001ff; 1317219589Sadrian } 1318188808Sgonzo 1319199234Sgonzo ARGE_WRITE(sc, AR71XX_MAC_CFG2, cfg); 1320199234Sgonzo ARGE_WRITE(sc, AR71XX_MAC_IFCONTROL, ifcontrol); 1321232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK, 1322199234Sgonzo rx_filtmask); 1323219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_TX_THRESHOLD, fifo_tx); 1324188808Sgonzo 1325234919Sadrian /* fetch PLL registers */ 1326234907Sadrian pll = ar71xx_device_get_eth_pll(sc->arge_mac_unit, if_speed); 1327234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: pll=0x%x\n", __func__, pll); 1328234907Sadrian 1329234919Sadrian /* Override if required by platform data */ 1330234919Sadrian if (if_speed == 10 && sc->arge_pllcfg.pll_10 != 0) 1331234919Sadrian pll = sc->arge_pllcfg.pll_10; 1332234919Sadrian else if (if_speed == 100 && sc->arge_pllcfg.pll_100 != 0) 1333234919Sadrian pll = sc->arge_pllcfg.pll_100; 1334234919Sadrian else if (if_speed == 1000 && sc->arge_pllcfg.pll_1000 != 0) 1335234919Sadrian pll = sc->arge_pllcfg.pll_1000; 1336234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: final pll=0x%x\n", __func__, pll); 1337234919Sadrian 1338234907Sadrian /* XXX ensure pll != 0 */ 1339234907Sadrian ar71xx_device_set_pll_ge(sc->arge_mac_unit, if_speed, pll); 1340234907Sadrian 1341234907Sadrian /* set MII registers */ 1342234992Sadrian /* 1343234992Sadrian * This was introduced to match what the Linux ag71xx ethernet 1344234992Sadrian * driver does. For the AR71xx case, it does set the port 1345234992Sadrian * MII speed. However, if this is done, non-gigabit speeds 1346234992Sadrian * are not at all reliable when speaking via RGMII through 1347234992Sadrian * 'bridge' PHY port that's pretending to be a local PHY. 1348234992Sadrian * 1349234992Sadrian * Until that gets root caused, and until an AR71xx + normal 1350234992Sadrian * PHY board is tested, leave this disabled. 1351234992Sadrian */ 1352234992Sadrian#if 0 1353234907Sadrian ar71xx_device_set_mii_speed(sc->arge_mac_unit, if_speed); 1354234992Sadrian#endif 1355188808Sgonzo} 1356188808Sgonzo 1357199234Sgonzo 1358188808Sgonzostatic void 1359188808Sgonzoarge_reset_dma(struct arge_softc *sc) 1360188808Sgonzo{ 1361279791Sadrian 1362279791Sadrian ARGEDEBUG(sc, ARGE_DBG_RESET, "%s: called\n", __func__); 1363279791Sadrian 1364188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, 0); 1365188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, 0); 1366188808Sgonzo 1367188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_DESC, 0); 1368188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_DESC, 0); 1369188808Sgonzo 1370188808Sgonzo /* Clear all possible RX interrupts */ 1371192569Sdwhite while(ARGE_READ(sc, AR71XX_DMA_RX_STATUS) & DMA_RX_STATUS_PKT_RECVD) 1372188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_PKT_RECVD); 1373188808Sgonzo 1374232627Sray /* 1375188808Sgonzo * Clear all possible TX interrupts 1376188808Sgonzo */ 1377192569Sdwhite while(ARGE_READ(sc, AR71XX_DMA_TX_STATUS) & DMA_TX_STATUS_PKT_SENT) 1378188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_PKT_SENT); 1379188808Sgonzo 1380232627Sray /* 1381188808Sgonzo * Now Rx/Tx errors 1382188808Sgonzo */ 1383232627Sray ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, 1384188808Sgonzo DMA_RX_STATUS_BUS_ERROR | DMA_RX_STATUS_OVERFLOW); 1385232627Sray ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, 1386188808Sgonzo DMA_TX_STATUS_BUS_ERROR | DMA_TX_STATUS_UNDERRUN); 1387232912Sadrian 1388232912Sadrian /* 1389232912Sadrian * Force a DDR flush so any pending data is properly 1390232912Sadrian * flushed to RAM before underlying buffers are freed. 1391232912Sadrian */ 1392232912Sadrian arge_flush_ddr(sc); 1393188808Sgonzo} 1394188808Sgonzo 1395188808Sgonzostatic void 1396188808Sgonzoarge_init(void *xsc) 1397188808Sgonzo{ 1398188808Sgonzo struct arge_softc *sc = xsc; 1399188808Sgonzo 1400188808Sgonzo ARGE_LOCK(sc); 1401188808Sgonzo arge_init_locked(sc); 1402188808Sgonzo ARGE_UNLOCK(sc); 1403188808Sgonzo} 1404188808Sgonzo 1405188808Sgonzostatic void 1406188808Sgonzoarge_init_locked(struct arge_softc *sc) 1407188808Sgonzo{ 1408188808Sgonzo struct ifnet *ifp = sc->arge_ifp; 1409188808Sgonzo struct mii_data *mii; 1410188808Sgonzo 1411188808Sgonzo ARGE_LOCK_ASSERT(sc); 1412188808Sgonzo 1413255021Sloos if ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) 1414255021Sloos return; 1415188808Sgonzo 1416188808Sgonzo /* Init circular RX list. */ 1417188808Sgonzo if (arge_rx_ring_init(sc) != 0) { 1418188808Sgonzo device_printf(sc->arge_dev, 1419188808Sgonzo "initialization failed: no memory for rx buffers\n"); 1420188808Sgonzo arge_stop(sc); 1421188808Sgonzo return; 1422188808Sgonzo } 1423188808Sgonzo 1424188808Sgonzo /* Init tx descriptors. */ 1425188808Sgonzo arge_tx_ring_init(sc); 1426188808Sgonzo 1427188808Sgonzo arge_reset_dma(sc); 1428188808Sgonzo 1429199234Sgonzo if (sc->arge_miibus) { 1430199234Sgonzo mii = device_get_softc(sc->arge_miibus); 1431199234Sgonzo mii_mediachg(mii); 1432199234Sgonzo } 1433199234Sgonzo else { 1434199234Sgonzo /* 1435199234Sgonzo * Sun always shines over multiPHY interface 1436199234Sgonzo */ 1437199234Sgonzo sc->arge_link_status = 1; 1438199234Sgonzo } 1439199234Sgonzo 1440188808Sgonzo ifp->if_drv_flags |= IFF_DRV_RUNNING; 1441188808Sgonzo ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1442188808Sgonzo 1443232914Sadrian if (sc->arge_miibus) { 1444199234Sgonzo callout_reset(&sc->arge_stat_callout, hz, arge_tick, sc); 1445232914Sadrian arge_update_link_locked(sc); 1446232914Sadrian } 1447192783Sgonzo 1448188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_DESC, ARGE_TX_RING_ADDR(sc, 0)); 1449188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_DESC, ARGE_RX_RING_ADDR(sc, 0)); 1450188808Sgonzo 1451188808Sgonzo /* Start listening */ 1452188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, DMA_RX_CONTROL_EN); 1453188808Sgonzo 1454188808Sgonzo /* Enable interrupts */ 1455188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL); 1456188808Sgonzo} 1457188808Sgonzo 1458188808Sgonzo/* 1459209807Sadrian * Return whether the mbuf chain is correctly aligned 1460209807Sadrian * for the arge TX engine. 1461209807Sadrian * 1462289476Sadrian * All the MACs have a length requirement: any non-final 1463289476Sadrian * fragment (ie, descriptor with MORE bit set) needs to have 1464289476Sadrian * a length divisible by 4. 1465256649Sadrian * 1466289476Sadrian * The AR71xx, AR913x require the start address also be 1467289476Sadrian * DWORD aligned. The later MACs don't. 1468209807Sadrian */ 1469209807Sadrianstatic int 1470289476Sadrianarge_mbuf_chain_is_tx_aligned(struct arge_softc *sc, struct mbuf *m0) 1471209807Sadrian{ 1472209807Sadrian struct mbuf *m; 1473209807Sadrian 1474209807Sadrian for (m = m0; m != NULL; m = m->m_next) { 1475289476Sadrian /* 1476289476Sadrian * Only do this for chips that require it. 1477289476Sadrian */ 1478289476Sadrian if ((sc->arge_hw_flags & ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE) && 1479289476Sadrian (mtod(m, intptr_t) & 3) != 0) { 1480289476Sadrian sc->stats.tx_pkts_unaligned_start++; 1481209807Sadrian return 0; 1482289476Sadrian } 1483289476Sadrian 1484289476Sadrian /* 1485289476Sadrian * All chips have this requirement for length. 1486289476Sadrian */ 1487289476Sadrian if ((m->m_next != NULL) && ((m->m_len & 0x03) != 0)) { 1488289476Sadrian sc->stats.tx_pkts_unaligned_len++; 1489209807Sadrian return 0; 1490289476Sadrian } 1491209807Sadrian } 1492209807Sadrian return 1; 1493209807Sadrian} 1494209807Sadrian 1495209807Sadrian/* 1496188808Sgonzo * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 1497188808Sgonzo * pointers to the fragment pointers. 1498188808Sgonzo */ 1499188808Sgonzostatic int 1500188808Sgonzoarge_encap(struct arge_softc *sc, struct mbuf **m_head) 1501188808Sgonzo{ 1502188808Sgonzo struct arge_txdesc *txd; 1503188808Sgonzo struct arge_desc *desc, *prev_desc; 1504188808Sgonzo bus_dma_segment_t txsegs[ARGE_MAXFRAGS]; 1505192569Sdwhite int error, i, nsegs, prod, prev_prod; 1506192783Sgonzo struct mbuf *m; 1507188808Sgonzo 1508188808Sgonzo ARGE_LOCK_ASSERT(sc); 1509188808Sgonzo 1510192783Sgonzo /* 1511289476Sadrian * Fix mbuf chain based on hardware alignment constraints. 1512192783Sgonzo */ 1513192783Sgonzo m = *m_head; 1514289476Sadrian if (! arge_mbuf_chain_is_tx_aligned(sc, m)) { 1515209809Sadrian sc->stats.tx_pkts_unaligned++; 1516243882Sglebius m = m_defrag(*m_head, M_NOWAIT); 1517192783Sgonzo if (m == NULL) { 1518322716Sdelphij m_freem(*m_head); 1519192783Sgonzo *m_head = NULL; 1520192783Sgonzo return (ENOBUFS); 1521192783Sgonzo } 1522192783Sgonzo *m_head = m; 1523209809Sadrian } else 1524209809Sadrian sc->stats.tx_pkts_aligned++; 1525192783Sgonzo 1526188808Sgonzo prod = sc->arge_cdata.arge_tx_prod; 1527188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[prod]; 1528232627Sray error = bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_tx_tag, 1529188808Sgonzo txd->tx_dmamap, *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1530188808Sgonzo 1531188808Sgonzo if (error == EFBIG) { 1532188808Sgonzo panic("EFBIG"); 1533188808Sgonzo } else if (error != 0) 1534188808Sgonzo return (error); 1535188808Sgonzo 1536188808Sgonzo if (nsegs == 0) { 1537188808Sgonzo m_freem(*m_head); 1538188808Sgonzo *m_head = NULL; 1539188808Sgonzo return (EIO); 1540188808Sgonzo } 1541188808Sgonzo 1542188808Sgonzo /* Check number of available descriptors. */ 1543290211Sadrian if (sc->arge_cdata.arge_tx_cnt + nsegs >= (ARGE_TX_RING_COUNT - 2)) { 1544188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap); 1545289476Sadrian sc->stats.tx_pkts_nosegs++; 1546188808Sgonzo return (ENOBUFS); 1547188808Sgonzo } 1548188808Sgonzo 1549188808Sgonzo txd->tx_m = *m_head; 1550188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap, 1551188808Sgonzo BUS_DMASYNC_PREWRITE); 1552188808Sgonzo 1553232627Sray /* 1554188808Sgonzo * Make a list of descriptors for this packet. DMA controller will 1555188808Sgonzo * walk through it while arge_link is not zero. 1556290215Sadrian * 1557290215Sadrian * Since we're in a endless circular buffer, ensure that 1558290215Sadrian * the first descriptor in a multi-descriptor ring is always 1559290215Sadrian * set to EMPTY, then un-do it when we're done populating. 1560188808Sgonzo */ 1561188808Sgonzo prev_prod = prod; 1562188808Sgonzo desc = prev_desc = NULL; 1563188808Sgonzo for (i = 0; i < nsegs; i++) { 1564290215Sadrian uint32_t tmp; 1565290215Sadrian 1566188808Sgonzo desc = &sc->arge_rdata.arge_tx_ring[prod]; 1567188808Sgonzo 1568290215Sadrian /* 1569290215Sadrian * Set DESC_EMPTY so the hardware (hopefully) stops at this 1570290215Sadrian * point. We don't want it to start transmitting descriptors 1571290215Sadrian * before we've finished fleshing this out. 1572290215Sadrian */ 1573290215Sadrian tmp = ARGE_DMASIZE(txsegs[i].ds_len); 1574290215Sadrian if (i == 0) 1575290215Sadrian tmp |= ARGE_DESC_EMPTY; 1576290215Sadrian desc->packet_ctrl = tmp; 1577290215Sadrian 1578289476Sadrian /* XXX Note: only relevant for older MACs; but check length! */ 1579289476Sadrian if ((sc->arge_hw_flags & ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE) && 1580289476Sadrian (txsegs[i].ds_addr & 3)) 1581192783Sgonzo panic("TX packet address unaligned\n"); 1582192783Sgonzo 1583188808Sgonzo desc->packet_addr = txsegs[i].ds_addr; 1584232627Sray 1585188808Sgonzo /* link with previous descriptor */ 1586188808Sgonzo if (prev_desc) 1587188808Sgonzo prev_desc->packet_ctrl |= ARGE_DESC_MORE; 1588188808Sgonzo 1589188808Sgonzo sc->arge_cdata.arge_tx_cnt++; 1590188808Sgonzo prev_desc = desc; 1591188808Sgonzo ARGE_INC(prod, ARGE_TX_RING_COUNT); 1592188808Sgonzo } 1593188808Sgonzo 1594188808Sgonzo /* Update producer index. */ 1595188808Sgonzo sc->arge_cdata.arge_tx_prod = prod; 1596188808Sgonzo 1597290215Sadrian /* 1598290215Sadrian * The descriptors are updated, so enable the first one. 1599290215Sadrian */ 1600290215Sadrian desc = &sc->arge_rdata.arge_tx_ring[prev_prod]; 1601290215Sadrian desc->packet_ctrl &= ~ ARGE_DESC_EMPTY; 1602290215Sadrian 1603188808Sgonzo /* Sync descriptors. */ 1604188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 1605188808Sgonzo sc->arge_cdata.arge_tx_ring_map, 1606188808Sgonzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1607188808Sgonzo 1608290213Sadrian /* Flush writes */ 1609290213Sadrian ARGE_BARRIER_WRITE(sc); 1610290213Sadrian 1611188808Sgonzo /* Start transmitting */ 1612232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: setting DMA_TX_CONTROL_EN\n", 1613232628Sray __func__); 1614188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, DMA_TX_CONTROL_EN); 1615188808Sgonzo return (0); 1616188808Sgonzo} 1617188808Sgonzo 1618188808Sgonzostatic void 1619188808Sgonzoarge_start(struct ifnet *ifp) 1620188808Sgonzo{ 1621188808Sgonzo struct arge_softc *sc; 1622188808Sgonzo 1623188808Sgonzo sc = ifp->if_softc; 1624188808Sgonzo 1625188808Sgonzo ARGE_LOCK(sc); 1626188808Sgonzo arge_start_locked(ifp); 1627188808Sgonzo ARGE_UNLOCK(sc); 1628188808Sgonzo} 1629188808Sgonzo 1630188808Sgonzostatic void 1631188808Sgonzoarge_start_locked(struct ifnet *ifp) 1632188808Sgonzo{ 1633188808Sgonzo struct arge_softc *sc; 1634188808Sgonzo struct mbuf *m_head; 1635220356Sadrian int enq = 0; 1636188808Sgonzo 1637188808Sgonzo sc = ifp->if_softc; 1638188808Sgonzo 1639188808Sgonzo ARGE_LOCK_ASSERT(sc); 1640188808Sgonzo 1641220356Sadrian ARGEDEBUG(sc, ARGE_DBG_TX, "%s: beginning\n", __func__); 1642220356Sadrian 1643188808Sgonzo if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1644188808Sgonzo IFF_DRV_RUNNING || sc->arge_link_status == 0 ) 1645188808Sgonzo return; 1646188808Sgonzo 1647220356Sadrian /* 1648220356Sadrian * Before we go any further, check whether we're already full. 1649220356Sadrian * The below check errors out immediately if the ring is full 1650220356Sadrian * and never gets a chance to set this flag. Although it's 1651220356Sadrian * likely never needed, this at least avoids an unexpected 1652220356Sadrian * situation. 1653220356Sadrian */ 1654220356Sadrian if (sc->arge_cdata.arge_tx_cnt >= ARGE_TX_RING_COUNT - 2) { 1655220356Sadrian ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1656232628Sray ARGEDEBUG(sc, ARGE_DBG_ERR, 1657232628Sray "%s: tx_cnt %d >= max %d; setting IFF_DRV_OACTIVE\n", 1658232628Sray __func__, sc->arge_cdata.arge_tx_cnt, 1659232628Sray ARGE_TX_RING_COUNT - 2); 1660220356Sadrian return; 1661220356Sadrian } 1662220356Sadrian 1663188808Sgonzo arge_flush_ddr(sc); 1664188808Sgonzo 1665188808Sgonzo for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && 1666188808Sgonzo sc->arge_cdata.arge_tx_cnt < ARGE_TX_RING_COUNT - 2; ) { 1667188808Sgonzo IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1668188808Sgonzo if (m_head == NULL) 1669188808Sgonzo break; 1670188808Sgonzo 1671188808Sgonzo 1672188808Sgonzo /* 1673188808Sgonzo * Pack the data into the transmit ring. 1674188808Sgonzo */ 1675188808Sgonzo if (arge_encap(sc, &m_head)) { 1676188808Sgonzo if (m_head == NULL) 1677188808Sgonzo break; 1678188808Sgonzo IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1679188808Sgonzo ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1680188808Sgonzo break; 1681188808Sgonzo } 1682188808Sgonzo 1683188808Sgonzo enq++; 1684188808Sgonzo /* 1685188808Sgonzo * If there's a BPF listener, bounce a copy of this frame 1686188808Sgonzo * to him. 1687188808Sgonzo */ 1688188808Sgonzo ETHER_BPF_MTAP(ifp, m_head); 1689188808Sgonzo } 1690232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: finished; queued %d packets\n", 1691232628Sray __func__, enq); 1692188808Sgonzo} 1693188808Sgonzo 1694188808Sgonzostatic void 1695188808Sgonzoarge_stop(struct arge_softc *sc) 1696188808Sgonzo{ 1697188808Sgonzo struct ifnet *ifp; 1698188808Sgonzo 1699188808Sgonzo ARGE_LOCK_ASSERT(sc); 1700188808Sgonzo 1701188808Sgonzo ifp = sc->arge_ifp; 1702188808Sgonzo ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1703199234Sgonzo if (sc->arge_miibus) 1704199234Sgonzo callout_stop(&sc->arge_stat_callout); 1705188808Sgonzo 1706188808Sgonzo /* mask out interrupts */ 1707188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, 0); 1708188808Sgonzo 1709188808Sgonzo arge_reset_dma(sc); 1710232912Sadrian 1711232912Sadrian /* Flush FIFO and free any existing mbufs */ 1712232912Sadrian arge_flush_ddr(sc); 1713232912Sadrian arge_rx_ring_free(sc); 1714255300Sloos arge_tx_ring_free(sc); 1715188808Sgonzo} 1716188808Sgonzo 1717188808Sgonzo 1718188808Sgonzostatic int 1719188808Sgonzoarge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 1720188808Sgonzo{ 1721188808Sgonzo struct arge_softc *sc = ifp->if_softc; 1722188808Sgonzo struct ifreq *ifr = (struct ifreq *) data; 1723188808Sgonzo struct mii_data *mii; 1724188808Sgonzo int error; 1725192783Sgonzo#ifdef DEVICE_POLLING 1726192783Sgonzo int mask; 1727192783Sgonzo#endif 1728188808Sgonzo 1729188808Sgonzo switch (command) { 1730188808Sgonzo case SIOCSIFFLAGS: 1731198932Sgonzo ARGE_LOCK(sc); 1732198932Sgonzo if ((ifp->if_flags & IFF_UP) != 0) { 1733198932Sgonzo if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1734198932Sgonzo if (((ifp->if_flags ^ sc->arge_if_flags) 1735198939Sgonzo & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 1736198939Sgonzo /* XXX: handle promisc & multi flags */ 1737198939Sgonzo } 1738232627Sray 1739198932Sgonzo } else { 1740198932Sgonzo if (!sc->arge_detach) 1741198932Sgonzo arge_init_locked(sc); 1742198932Sgonzo } 1743198932Sgonzo } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1744198932Sgonzo ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1745198932Sgonzo arge_stop(sc); 1746198932Sgonzo } 1747198932Sgonzo sc->arge_if_flags = ifp->if_flags; 1748198932Sgonzo ARGE_UNLOCK(sc); 1749188808Sgonzo error = 0; 1750188808Sgonzo break; 1751188808Sgonzo case SIOCADDMULTI: 1752188808Sgonzo case SIOCDELMULTI: 1753198932Sgonzo /* XXX: implement SIOCDELMULTI */ 1754188808Sgonzo error = 0; 1755188808Sgonzo break; 1756188808Sgonzo case SIOCGIFMEDIA: 1757188808Sgonzo case SIOCSIFMEDIA: 1758199234Sgonzo if (sc->arge_miibus) { 1759199234Sgonzo mii = device_get_softc(sc->arge_miibus); 1760232628Sray error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, 1761232628Sray command); 1762199234Sgonzo } 1763232627Sray else 1764232628Sray error = ifmedia_ioctl(ifp, ifr, &sc->arge_ifmedia, 1765232628Sray command); 1766188808Sgonzo break; 1767198933Sgonzo case SIOCSIFCAP: 1768198932Sgonzo /* XXX: Check other capabilities */ 1769192783Sgonzo#ifdef DEVICE_POLLING 1770198933Sgonzo mask = ifp->if_capenable ^ ifr->ifr_reqcap; 1771198933Sgonzo if (mask & IFCAP_POLLING) { 1772198933Sgonzo if (ifr->ifr_reqcap & IFCAP_POLLING) { 1773192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, 0); 1774198933Sgonzo error = ether_poll_register(arge_poll, ifp); 1775198933Sgonzo if (error) 1776198933Sgonzo return error; 1777198933Sgonzo ARGE_LOCK(sc); 1778198933Sgonzo ifp->if_capenable |= IFCAP_POLLING; 1779198933Sgonzo ARGE_UNLOCK(sc); 1780198933Sgonzo } else { 1781192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL); 1782198933Sgonzo error = ether_poll_deregister(ifp); 1783198933Sgonzo ARGE_LOCK(sc); 1784198933Sgonzo ifp->if_capenable &= ~IFCAP_POLLING; 1785198933Sgonzo ARGE_UNLOCK(sc); 1786198933Sgonzo } 1787198933Sgonzo } 1788198932Sgonzo error = 0; 1789198933Sgonzo break; 1790192783Sgonzo#endif 1791188808Sgonzo default: 1792188808Sgonzo error = ether_ioctl(ifp, command, data); 1793188808Sgonzo break; 1794188808Sgonzo } 1795188808Sgonzo 1796188808Sgonzo return (error); 1797188808Sgonzo} 1798188808Sgonzo 1799188808Sgonzo/* 1800188808Sgonzo * Set media options. 1801188808Sgonzo */ 1802188808Sgonzostatic int 1803188808Sgonzoarge_ifmedia_upd(struct ifnet *ifp) 1804188808Sgonzo{ 1805188808Sgonzo struct arge_softc *sc; 1806188808Sgonzo struct mii_data *mii; 1807188808Sgonzo struct mii_softc *miisc; 1808188808Sgonzo int error; 1809188808Sgonzo 1810188808Sgonzo sc = ifp->if_softc; 1811188808Sgonzo ARGE_LOCK(sc); 1812188808Sgonzo mii = device_get_softc(sc->arge_miibus); 1813221407Smarius LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1814221407Smarius PHY_RESET(miisc); 1815188808Sgonzo error = mii_mediachg(mii); 1816188808Sgonzo ARGE_UNLOCK(sc); 1817188808Sgonzo 1818188808Sgonzo return (error); 1819188808Sgonzo} 1820188808Sgonzo 1821188808Sgonzo/* 1822188808Sgonzo * Report current media status. 1823188808Sgonzo */ 1824188808Sgonzostatic void 1825188808Sgonzoarge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1826188808Sgonzo{ 1827188808Sgonzo struct arge_softc *sc = ifp->if_softc; 1828188808Sgonzo struct mii_data *mii; 1829188808Sgonzo 1830188808Sgonzo mii = device_get_softc(sc->arge_miibus); 1831188808Sgonzo ARGE_LOCK(sc); 1832188808Sgonzo mii_pollstat(mii); 1833188808Sgonzo ifmr->ifm_active = mii->mii_media_active; 1834188808Sgonzo ifmr->ifm_status = mii->mii_media_status; 1835226478Syongari ARGE_UNLOCK(sc); 1836188808Sgonzo} 1837188808Sgonzo 1838188808Sgonzostruct arge_dmamap_arg { 1839188808Sgonzo bus_addr_t arge_busaddr; 1840188808Sgonzo}; 1841188808Sgonzo 1842188808Sgonzostatic void 1843188808Sgonzoarge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1844188808Sgonzo{ 1845188808Sgonzo struct arge_dmamap_arg *ctx; 1846188808Sgonzo 1847188808Sgonzo if (error != 0) 1848188808Sgonzo return; 1849188808Sgonzo ctx = arg; 1850188808Sgonzo ctx->arge_busaddr = segs[0].ds_addr; 1851188808Sgonzo} 1852188808Sgonzo 1853188808Sgonzostatic int 1854188808Sgonzoarge_dma_alloc(struct arge_softc *sc) 1855188808Sgonzo{ 1856188808Sgonzo struct arge_dmamap_arg ctx; 1857188808Sgonzo struct arge_txdesc *txd; 1858188808Sgonzo struct arge_rxdesc *rxd; 1859188808Sgonzo int error, i; 1860289476Sadrian int arge_tx_align, arge_rx_align; 1861188808Sgonzo 1862289476Sadrian /* Assume 4 byte alignment by default */ 1863289476Sadrian arge_tx_align = 4; 1864289476Sadrian arge_rx_align = 4; 1865289476Sadrian 1866289476Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_TX_DESC_ALIGN_1BYTE) 1867289476Sadrian arge_tx_align = 1; 1868289476Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE) 1869289476Sadrian arge_rx_align = 1; 1870289476Sadrian 1871188808Sgonzo /* Create parent DMA tag. */ 1872188808Sgonzo error = bus_dma_tag_create( 1873188808Sgonzo bus_get_dma_tag(sc->arge_dev), /* parent */ 1874188808Sgonzo 1, 0, /* alignment, boundary */ 1875188808Sgonzo BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1876188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1877188808Sgonzo NULL, NULL, /* filter, filterarg */ 1878188808Sgonzo BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1879188808Sgonzo 0, /* nsegments */ 1880188808Sgonzo BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1881188808Sgonzo 0, /* flags */ 1882188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1883188808Sgonzo &sc->arge_cdata.arge_parent_tag); 1884188808Sgonzo if (error != 0) { 1885232628Sray device_printf(sc->arge_dev, 1886232628Sray "failed to create parent DMA tag\n"); 1887188808Sgonzo goto fail; 1888188808Sgonzo } 1889188808Sgonzo /* Create tag for Tx ring. */ 1890188808Sgonzo error = bus_dma_tag_create( 1891188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1892188808Sgonzo ARGE_RING_ALIGN, 0, /* alignment, boundary */ 1893188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1894188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1895188808Sgonzo NULL, NULL, /* filter, filterarg */ 1896188808Sgonzo ARGE_TX_DMA_SIZE, /* maxsize */ 1897188808Sgonzo 1, /* nsegments */ 1898188808Sgonzo ARGE_TX_DMA_SIZE, /* maxsegsize */ 1899188808Sgonzo 0, /* flags */ 1900188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1901188808Sgonzo &sc->arge_cdata.arge_tx_ring_tag); 1902188808Sgonzo if (error != 0) { 1903232628Sray device_printf(sc->arge_dev, 1904232628Sray "failed to create Tx ring DMA tag\n"); 1905188808Sgonzo goto fail; 1906188808Sgonzo } 1907188808Sgonzo 1908188808Sgonzo /* Create tag for Rx ring. */ 1909188808Sgonzo error = bus_dma_tag_create( 1910188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1911188808Sgonzo ARGE_RING_ALIGN, 0, /* alignment, boundary */ 1912188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1913188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1914188808Sgonzo NULL, NULL, /* filter, filterarg */ 1915188808Sgonzo ARGE_RX_DMA_SIZE, /* maxsize */ 1916188808Sgonzo 1, /* nsegments */ 1917188808Sgonzo ARGE_RX_DMA_SIZE, /* maxsegsize */ 1918188808Sgonzo 0, /* flags */ 1919188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1920188808Sgonzo &sc->arge_cdata.arge_rx_ring_tag); 1921188808Sgonzo if (error != 0) { 1922232628Sray device_printf(sc->arge_dev, 1923232628Sray "failed to create Rx ring DMA tag\n"); 1924188808Sgonzo goto fail; 1925188808Sgonzo } 1926188808Sgonzo 1927188808Sgonzo /* Create tag for Tx buffers. */ 1928188808Sgonzo error = bus_dma_tag_create( 1929188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1930289476Sadrian arge_tx_align, 0, /* alignment, boundary */ 1931188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1932188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1933188808Sgonzo NULL, NULL, /* filter, filterarg */ 1934188808Sgonzo MCLBYTES * ARGE_MAXFRAGS, /* maxsize */ 1935188808Sgonzo ARGE_MAXFRAGS, /* nsegments */ 1936188808Sgonzo MCLBYTES, /* maxsegsize */ 1937188808Sgonzo 0, /* flags */ 1938188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1939188808Sgonzo &sc->arge_cdata.arge_tx_tag); 1940188808Sgonzo if (error != 0) { 1941188808Sgonzo device_printf(sc->arge_dev, "failed to create Tx DMA tag\n"); 1942188808Sgonzo goto fail; 1943188808Sgonzo } 1944188808Sgonzo 1945188808Sgonzo /* Create tag for Rx buffers. */ 1946188808Sgonzo error = bus_dma_tag_create( 1947188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1948289476Sadrian arge_rx_align, 0, /* alignment, boundary */ 1949188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1950188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1951188808Sgonzo NULL, NULL, /* filter, filterarg */ 1952188808Sgonzo MCLBYTES, /* maxsize */ 1953192821Sgonzo ARGE_MAXFRAGS, /* nsegments */ 1954188808Sgonzo MCLBYTES, /* maxsegsize */ 1955188808Sgonzo 0, /* flags */ 1956188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1957188808Sgonzo &sc->arge_cdata.arge_rx_tag); 1958188808Sgonzo if (error != 0) { 1959188808Sgonzo device_printf(sc->arge_dev, "failed to create Rx DMA tag\n"); 1960188808Sgonzo goto fail; 1961188808Sgonzo } 1962188808Sgonzo 1963188808Sgonzo /* Allocate DMA'able memory and load the DMA map for Tx ring. */ 1964188808Sgonzo error = bus_dmamem_alloc(sc->arge_cdata.arge_tx_ring_tag, 1965188808Sgonzo (void **)&sc->arge_rdata.arge_tx_ring, BUS_DMA_WAITOK | 1966232628Sray BUS_DMA_COHERENT | BUS_DMA_ZERO, 1967232628Sray &sc->arge_cdata.arge_tx_ring_map); 1968188808Sgonzo if (error != 0) { 1969188808Sgonzo device_printf(sc->arge_dev, 1970188808Sgonzo "failed to allocate DMA'able memory for Tx ring\n"); 1971188808Sgonzo goto fail; 1972188808Sgonzo } 1973188808Sgonzo 1974188808Sgonzo ctx.arge_busaddr = 0; 1975188808Sgonzo error = bus_dmamap_load(sc->arge_cdata.arge_tx_ring_tag, 1976188808Sgonzo sc->arge_cdata.arge_tx_ring_map, sc->arge_rdata.arge_tx_ring, 1977188808Sgonzo ARGE_TX_DMA_SIZE, arge_dmamap_cb, &ctx, 0); 1978188808Sgonzo if (error != 0 || ctx.arge_busaddr == 0) { 1979188808Sgonzo device_printf(sc->arge_dev, 1980188808Sgonzo "failed to load DMA'able memory for Tx ring\n"); 1981188808Sgonzo goto fail; 1982188808Sgonzo } 1983188808Sgonzo sc->arge_rdata.arge_tx_ring_paddr = ctx.arge_busaddr; 1984188808Sgonzo 1985188808Sgonzo /* Allocate DMA'able memory and load the DMA map for Rx ring. */ 1986188808Sgonzo error = bus_dmamem_alloc(sc->arge_cdata.arge_rx_ring_tag, 1987188808Sgonzo (void **)&sc->arge_rdata.arge_rx_ring, BUS_DMA_WAITOK | 1988232628Sray BUS_DMA_COHERENT | BUS_DMA_ZERO, 1989232628Sray &sc->arge_cdata.arge_rx_ring_map); 1990188808Sgonzo if (error != 0) { 1991188808Sgonzo device_printf(sc->arge_dev, 1992188808Sgonzo "failed to allocate DMA'able memory for Rx ring\n"); 1993188808Sgonzo goto fail; 1994188808Sgonzo } 1995188808Sgonzo 1996188808Sgonzo ctx.arge_busaddr = 0; 1997188808Sgonzo error = bus_dmamap_load(sc->arge_cdata.arge_rx_ring_tag, 1998188808Sgonzo sc->arge_cdata.arge_rx_ring_map, sc->arge_rdata.arge_rx_ring, 1999188808Sgonzo ARGE_RX_DMA_SIZE, arge_dmamap_cb, &ctx, 0); 2000188808Sgonzo if (error != 0 || ctx.arge_busaddr == 0) { 2001188808Sgonzo device_printf(sc->arge_dev, 2002188808Sgonzo "failed to load DMA'able memory for Rx ring\n"); 2003188808Sgonzo goto fail; 2004188808Sgonzo } 2005188808Sgonzo sc->arge_rdata.arge_rx_ring_paddr = ctx.arge_busaddr; 2006188808Sgonzo 2007188808Sgonzo /* Create DMA maps for Tx buffers. */ 2008188808Sgonzo for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2009188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[i]; 2010188808Sgonzo txd->tx_m = NULL; 2011188808Sgonzo txd->tx_dmamap = NULL; 2012188808Sgonzo error = bus_dmamap_create(sc->arge_cdata.arge_tx_tag, 0, 2013188808Sgonzo &txd->tx_dmamap); 2014188808Sgonzo if (error != 0) { 2015188808Sgonzo device_printf(sc->arge_dev, 2016188808Sgonzo "failed to create Tx dmamap\n"); 2017188808Sgonzo goto fail; 2018188808Sgonzo } 2019188808Sgonzo } 2020188808Sgonzo /* Create DMA maps for Rx buffers. */ 2021188808Sgonzo if ((error = bus_dmamap_create(sc->arge_cdata.arge_rx_tag, 0, 2022188808Sgonzo &sc->arge_cdata.arge_rx_sparemap)) != 0) { 2023188808Sgonzo device_printf(sc->arge_dev, 2024188808Sgonzo "failed to create spare Rx dmamap\n"); 2025188808Sgonzo goto fail; 2026188808Sgonzo } 2027188808Sgonzo for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2028188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[i]; 2029188808Sgonzo rxd->rx_m = NULL; 2030188808Sgonzo rxd->rx_dmamap = NULL; 2031188808Sgonzo error = bus_dmamap_create(sc->arge_cdata.arge_rx_tag, 0, 2032188808Sgonzo &rxd->rx_dmamap); 2033188808Sgonzo if (error != 0) { 2034188808Sgonzo device_printf(sc->arge_dev, 2035188808Sgonzo "failed to create Rx dmamap\n"); 2036188808Sgonzo goto fail; 2037188808Sgonzo } 2038188808Sgonzo } 2039188808Sgonzo 2040188808Sgonzofail: 2041188808Sgonzo return (error); 2042188808Sgonzo} 2043188808Sgonzo 2044188808Sgonzostatic void 2045188808Sgonzoarge_dma_free(struct arge_softc *sc) 2046188808Sgonzo{ 2047188808Sgonzo struct arge_txdesc *txd; 2048188808Sgonzo struct arge_rxdesc *rxd; 2049188808Sgonzo int i; 2050188808Sgonzo 2051188808Sgonzo /* Tx ring. */ 2052188808Sgonzo if (sc->arge_cdata.arge_tx_ring_tag) { 2053267363Sjhb if (sc->arge_rdata.arge_tx_ring_paddr) 2054188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_tx_ring_tag, 2055188808Sgonzo sc->arge_cdata.arge_tx_ring_map); 2056267363Sjhb if (sc->arge_rdata.arge_tx_ring) 2057188808Sgonzo bus_dmamem_free(sc->arge_cdata.arge_tx_ring_tag, 2058188808Sgonzo sc->arge_rdata.arge_tx_ring, 2059188808Sgonzo sc->arge_cdata.arge_tx_ring_map); 2060188808Sgonzo sc->arge_rdata.arge_tx_ring = NULL; 2061267363Sjhb sc->arge_rdata.arge_tx_ring_paddr = 0; 2062188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_tx_ring_tag); 2063188808Sgonzo sc->arge_cdata.arge_tx_ring_tag = NULL; 2064188808Sgonzo } 2065188808Sgonzo /* Rx ring. */ 2066188808Sgonzo if (sc->arge_cdata.arge_rx_ring_tag) { 2067267363Sjhb if (sc->arge_rdata.arge_rx_ring_paddr) 2068188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_rx_ring_tag, 2069188808Sgonzo sc->arge_cdata.arge_rx_ring_map); 2070267363Sjhb if (sc->arge_rdata.arge_rx_ring) 2071188808Sgonzo bus_dmamem_free(sc->arge_cdata.arge_rx_ring_tag, 2072188808Sgonzo sc->arge_rdata.arge_rx_ring, 2073188808Sgonzo sc->arge_cdata.arge_rx_ring_map); 2074188808Sgonzo sc->arge_rdata.arge_rx_ring = NULL; 2075267363Sjhb sc->arge_rdata.arge_rx_ring_paddr = 0; 2076188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_rx_ring_tag); 2077188808Sgonzo sc->arge_cdata.arge_rx_ring_tag = NULL; 2078188808Sgonzo } 2079188808Sgonzo /* Tx buffers. */ 2080188808Sgonzo if (sc->arge_cdata.arge_tx_tag) { 2081188808Sgonzo for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2082188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[i]; 2083188808Sgonzo if (txd->tx_dmamap) { 2084188808Sgonzo bus_dmamap_destroy(sc->arge_cdata.arge_tx_tag, 2085188808Sgonzo txd->tx_dmamap); 2086188808Sgonzo txd->tx_dmamap = NULL; 2087188808Sgonzo } 2088188808Sgonzo } 2089188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_tx_tag); 2090188808Sgonzo sc->arge_cdata.arge_tx_tag = NULL; 2091188808Sgonzo } 2092188808Sgonzo /* Rx buffers. */ 2093188808Sgonzo if (sc->arge_cdata.arge_rx_tag) { 2094188808Sgonzo for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2095188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[i]; 2096188808Sgonzo if (rxd->rx_dmamap) { 2097188808Sgonzo bus_dmamap_destroy(sc->arge_cdata.arge_rx_tag, 2098188808Sgonzo rxd->rx_dmamap); 2099188808Sgonzo rxd->rx_dmamap = NULL; 2100188808Sgonzo } 2101188808Sgonzo } 2102188808Sgonzo if (sc->arge_cdata.arge_rx_sparemap) { 2103188808Sgonzo bus_dmamap_destroy(sc->arge_cdata.arge_rx_tag, 2104188808Sgonzo sc->arge_cdata.arge_rx_sparemap); 2105188808Sgonzo sc->arge_cdata.arge_rx_sparemap = 0; 2106188808Sgonzo } 2107188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_rx_tag); 2108188808Sgonzo sc->arge_cdata.arge_rx_tag = NULL; 2109188808Sgonzo } 2110188808Sgonzo 2111188808Sgonzo if (sc->arge_cdata.arge_parent_tag) { 2112188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_parent_tag); 2113188808Sgonzo sc->arge_cdata.arge_parent_tag = NULL; 2114188808Sgonzo } 2115188808Sgonzo} 2116188808Sgonzo 2117188808Sgonzo/* 2118188808Sgonzo * Initialize the transmit descriptors. 2119188808Sgonzo */ 2120188808Sgonzostatic int 2121188808Sgonzoarge_tx_ring_init(struct arge_softc *sc) 2122188808Sgonzo{ 2123188808Sgonzo struct arge_ring_data *rd; 2124188808Sgonzo struct arge_txdesc *txd; 2125188808Sgonzo bus_addr_t addr; 2126188808Sgonzo int i; 2127188808Sgonzo 2128188808Sgonzo sc->arge_cdata.arge_tx_prod = 0; 2129188808Sgonzo sc->arge_cdata.arge_tx_cons = 0; 2130188808Sgonzo sc->arge_cdata.arge_tx_cnt = 0; 2131188808Sgonzo 2132188808Sgonzo rd = &sc->arge_rdata; 2133323205Semaste bzero(rd->arge_tx_ring, sizeof(*rd->arge_tx_ring)); 2134188808Sgonzo for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2135188808Sgonzo if (i == ARGE_TX_RING_COUNT - 1) 2136188808Sgonzo addr = ARGE_TX_RING_ADDR(sc, 0); 2137188808Sgonzo else 2138188808Sgonzo addr = ARGE_TX_RING_ADDR(sc, i + 1); 2139188808Sgonzo rd->arge_tx_ring[i].packet_ctrl = ARGE_DESC_EMPTY; 2140188808Sgonzo rd->arge_tx_ring[i].next_desc = addr; 2141188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[i]; 2142188808Sgonzo txd->tx_m = NULL; 2143188808Sgonzo } 2144188808Sgonzo 2145188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 2146188808Sgonzo sc->arge_cdata.arge_tx_ring_map, 2147188808Sgonzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2148188808Sgonzo 2149188808Sgonzo return (0); 2150188808Sgonzo} 2151188808Sgonzo 2152188808Sgonzo/* 2153255300Sloos * Free the Tx ring, unload any pending dma transaction and free the mbuf. 2154255300Sloos */ 2155255300Sloosstatic void 2156255300Sloosarge_tx_ring_free(struct arge_softc *sc) 2157255300Sloos{ 2158255300Sloos struct arge_txdesc *txd; 2159255300Sloos int i; 2160255300Sloos 2161255300Sloos /* Free the Tx buffers. */ 2162255300Sloos for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2163255300Sloos txd = &sc->arge_cdata.arge_txdesc[i]; 2164255300Sloos if (txd->tx_dmamap) { 2165255300Sloos bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, 2166255300Sloos txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); 2167255300Sloos bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, 2168255300Sloos txd->tx_dmamap); 2169255300Sloos } 2170255300Sloos if (txd->tx_m) 2171255300Sloos m_freem(txd->tx_m); 2172255300Sloos txd->tx_m = NULL; 2173255300Sloos } 2174255300Sloos} 2175255300Sloos 2176255300Sloos/* 2177188808Sgonzo * Initialize the RX descriptors and allocate mbufs for them. Note that 2178188808Sgonzo * we arrange the descriptors in a closed ring, so that the last descriptor 2179188808Sgonzo * points back to the first. 2180188808Sgonzo */ 2181188808Sgonzostatic int 2182188808Sgonzoarge_rx_ring_init(struct arge_softc *sc) 2183188808Sgonzo{ 2184188808Sgonzo struct arge_ring_data *rd; 2185188808Sgonzo struct arge_rxdesc *rxd; 2186188808Sgonzo bus_addr_t addr; 2187188808Sgonzo int i; 2188188808Sgonzo 2189188808Sgonzo sc->arge_cdata.arge_rx_cons = 0; 2190188808Sgonzo 2191188808Sgonzo rd = &sc->arge_rdata; 2192323205Semaste bzero(rd->arge_rx_ring, sizeof(*rd->arge_rx_ring)); 2193188808Sgonzo for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2194188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[i]; 2195232912Sadrian if (rxd->rx_m != NULL) { 2196232912Sadrian device_printf(sc->arge_dev, 2197232912Sadrian "%s: ring[%d] rx_m wasn't free?\n", 2198232912Sadrian __func__, 2199232912Sadrian i); 2200232912Sadrian } 2201188808Sgonzo rxd->rx_m = NULL; 2202188808Sgonzo rxd->desc = &rd->arge_rx_ring[i]; 2203188808Sgonzo if (i == ARGE_RX_RING_COUNT - 1) 2204188808Sgonzo addr = ARGE_RX_RING_ADDR(sc, 0); 2205188808Sgonzo else 2206188808Sgonzo addr = ARGE_RX_RING_ADDR(sc, i + 1); 2207188808Sgonzo rd->arge_rx_ring[i].next_desc = addr; 2208192783Sgonzo if (arge_newbuf(sc, i) != 0) { 2209188808Sgonzo return (ENOBUFS); 2210192783Sgonzo } 2211188808Sgonzo } 2212188808Sgonzo 2213188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2214188808Sgonzo sc->arge_cdata.arge_rx_ring_map, 2215195434Sgonzo BUS_DMASYNC_PREWRITE); 2216188808Sgonzo 2217188808Sgonzo return (0); 2218188808Sgonzo} 2219188808Sgonzo 2220188808Sgonzo/* 2221232912Sadrian * Free all the buffers in the RX ring. 2222232912Sadrian * 2223232912Sadrian * TODO: ensure that DMA is disabled and no pending DMA 2224232912Sadrian * is lurking in the FIFO. 2225232912Sadrian */ 2226232912Sadrianstatic void 2227232912Sadrianarge_rx_ring_free(struct arge_softc *sc) 2228232912Sadrian{ 2229232912Sadrian int i; 2230232912Sadrian struct arge_rxdesc *rxd; 2231232912Sadrian 2232232912Sadrian ARGE_LOCK_ASSERT(sc); 2233232912Sadrian 2234232912Sadrian for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2235232912Sadrian rxd = &sc->arge_cdata.arge_rxdesc[i]; 2236232912Sadrian /* Unmap the mbuf */ 2237232912Sadrian if (rxd->rx_m != NULL) { 2238232912Sadrian bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, 2239232912Sadrian rxd->rx_dmamap); 2240232912Sadrian m_free(rxd->rx_m); 2241232912Sadrian rxd->rx_m = NULL; 2242232912Sadrian } 2243232912Sadrian } 2244232912Sadrian} 2245232912Sadrian 2246232912Sadrian/* 2247188808Sgonzo * Initialize an RX descriptor and attach an MBUF cluster. 2248188808Sgonzo */ 2249188808Sgonzostatic int 2250188808Sgonzoarge_newbuf(struct arge_softc *sc, int idx) 2251188808Sgonzo{ 2252188808Sgonzo struct arge_desc *desc; 2253188808Sgonzo struct arge_rxdesc *rxd; 2254188808Sgonzo struct mbuf *m; 2255188808Sgonzo bus_dma_segment_t segs[1]; 2256188808Sgonzo bus_dmamap_t map; 2257188808Sgonzo int nsegs; 2258188808Sgonzo 2259289671Sadrian /* XXX TODO: should just allocate an explicit 2KiB buffer */ 2260243882Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 2261188808Sgonzo if (m == NULL) 2262188808Sgonzo return (ENOBUFS); 2263188808Sgonzo m->m_len = m->m_pkthdr.len = MCLBYTES; 2264289476Sadrian 2265289476Sadrian /* 2266289476Sadrian * Add extra space to "adjust" (copy) the packet back to be aligned 2267289476Sadrian * for purposes of IPv4/IPv6 header contents. 2268289476Sadrian */ 2269289671Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) 2270289671Sadrian m_adj(m, sizeof(uint64_t)); 2271289671Sadrian /* 2272289671Sadrian * If it's a 1-byte aligned buffer, then just offset it two bytes 2273289671Sadrian * and that will give us a hopefully correctly DWORD aligned 2274289671Sadrian * L3 payload - and we won't have to undo it afterwards. 2275289671Sadrian */ 2276289671Sadrian else if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE) 2277289671Sadrian m_adj(m, sizeof(uint16_t)); 2278188808Sgonzo 2279188808Sgonzo if (bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_rx_tag, 2280188808Sgonzo sc->arge_cdata.arge_rx_sparemap, m, segs, &nsegs, 0) != 0) { 2281188808Sgonzo m_freem(m); 2282188808Sgonzo return (ENOBUFS); 2283188808Sgonzo } 2284188808Sgonzo KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2285188808Sgonzo 2286188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[idx]; 2287188808Sgonzo if (rxd->rx_m != NULL) { 2288188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap); 2289188808Sgonzo } 2290188808Sgonzo map = rxd->rx_dmamap; 2291188808Sgonzo rxd->rx_dmamap = sc->arge_cdata.arge_rx_sparemap; 2292188808Sgonzo sc->arge_cdata.arge_rx_sparemap = map; 2293188808Sgonzo rxd->rx_m = m; 2294188808Sgonzo desc = rxd->desc; 2295289476Sadrian if ((sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) && 2296289476Sadrian segs[0].ds_addr & 3) 2297192783Sgonzo panic("RX packet address unaligned"); 2298188808Sgonzo desc->packet_addr = segs[0].ds_addr; 2299192783Sgonzo desc->packet_ctrl = ARGE_DESC_EMPTY | ARGE_DMASIZE(segs[0].ds_len); 2300188808Sgonzo 2301195434Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2302195434Sgonzo sc->arge_cdata.arge_rx_ring_map, 2303195434Sgonzo BUS_DMASYNC_PREWRITE); 2304195434Sgonzo 2305188808Sgonzo return (0); 2306188808Sgonzo} 2307188808Sgonzo 2308289671Sadrian/* 2309289671Sadrian * Move the data backwards 16 bits to (hopefully!) ensure the 2310289671Sadrian * IPv4/IPv6 payload is aligned. 2311289671Sadrian * 2312289671Sadrian * This is required for earlier hardware where the RX path 2313289671Sadrian * requires DWORD aligned buffers. 2314289671Sadrian */ 2315188808Sgonzostatic __inline void 2316188808Sgonzoarge_fixup_rx(struct mbuf *m) 2317188808Sgonzo{ 2318198933Sgonzo int i; 2319198933Sgonzo uint16_t *src, *dst; 2320188808Sgonzo 2321188808Sgonzo src = mtod(m, uint16_t *); 2322188808Sgonzo dst = src - 1; 2323188808Sgonzo 2324195434Sgonzo for (i = 0; i < m->m_len / sizeof(uint16_t); i++) { 2325188808Sgonzo *dst++ = *src++; 2326195434Sgonzo } 2327188808Sgonzo 2328195434Sgonzo if (m->m_len % sizeof(uint16_t)) 2329195434Sgonzo *(uint8_t *)dst = *(uint8_t *)src; 2330195434Sgonzo 2331188808Sgonzo m->m_data -= ETHER_ALIGN; 2332188808Sgonzo} 2333188808Sgonzo 2334192783Sgonzo#ifdef DEVICE_POLLING 2335198667Sgonzostatic int 2336192783Sgonzoarge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 2337192783Sgonzo{ 2338192783Sgonzo struct arge_softc *sc = ifp->if_softc; 2339198667Sgonzo int rx_npkts = 0; 2340188808Sgonzo 2341198933Sgonzo if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2342192783Sgonzo ARGE_LOCK(sc); 2343192783Sgonzo arge_tx_locked(sc); 2344198667Sgonzo rx_npkts = arge_rx_locked(sc); 2345192783Sgonzo ARGE_UNLOCK(sc); 2346198933Sgonzo } 2347198667Sgonzo 2348198667Sgonzo return (rx_npkts); 2349192783Sgonzo} 2350192783Sgonzo#endif /* DEVICE_POLLING */ 2351192783Sgonzo 2352192783Sgonzo 2353188808Sgonzostatic void 2354188808Sgonzoarge_tx_locked(struct arge_softc *sc) 2355188808Sgonzo{ 2356188808Sgonzo struct arge_txdesc *txd; 2357188808Sgonzo struct arge_desc *cur_tx; 2358188808Sgonzo struct ifnet *ifp; 2359188808Sgonzo uint32_t ctrl; 2360188808Sgonzo int cons, prod; 2361188808Sgonzo 2362188808Sgonzo ARGE_LOCK_ASSERT(sc); 2363188808Sgonzo 2364188808Sgonzo cons = sc->arge_cdata.arge_tx_cons; 2365188808Sgonzo prod = sc->arge_cdata.arge_tx_prod; 2366220356Sadrian 2367232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: cons=%d, prod=%d\n", __func__, cons, 2368232628Sray prod); 2369220356Sadrian 2370188808Sgonzo if (cons == prod) 2371188808Sgonzo return; 2372188808Sgonzo 2373188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 2374188808Sgonzo sc->arge_cdata.arge_tx_ring_map, 2375188808Sgonzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2376188808Sgonzo 2377188808Sgonzo ifp = sc->arge_ifp; 2378188808Sgonzo /* 2379188808Sgonzo * Go through our tx list and free mbufs for those 2380188808Sgonzo * frames that have been transmitted. 2381188808Sgonzo */ 2382188808Sgonzo for (; cons != prod; ARGE_INC(cons, ARGE_TX_RING_COUNT)) { 2383188808Sgonzo cur_tx = &sc->arge_rdata.arge_tx_ring[cons]; 2384188808Sgonzo ctrl = cur_tx->packet_ctrl; 2385188808Sgonzo /* Check if descriptor has "finished" flag */ 2386188808Sgonzo if ((ctrl & ARGE_DESC_EMPTY) == 0) 2387188808Sgonzo break; 2388188808Sgonzo 2389188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_PKT_SENT); 2390188808Sgonzo 2391188808Sgonzo sc->arge_cdata.arge_tx_cnt--; 2392188808Sgonzo ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2393188808Sgonzo 2394188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[cons]; 2395188808Sgonzo 2396271858Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 2397188808Sgonzo 2398188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap, 2399188808Sgonzo BUS_DMASYNC_POSTWRITE); 2400188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap); 2401188808Sgonzo 2402188808Sgonzo /* Free only if it's first descriptor in list */ 2403188808Sgonzo if (txd->tx_m) 2404188808Sgonzo m_freem(txd->tx_m); 2405188808Sgonzo txd->tx_m = NULL; 2406188808Sgonzo 2407188808Sgonzo /* reset descriptor */ 2408188808Sgonzo cur_tx->packet_addr = 0; 2409188808Sgonzo } 2410188808Sgonzo 2411188808Sgonzo sc->arge_cdata.arge_tx_cons = cons; 2412188808Sgonzo 2413188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 2414188808Sgonzo sc->arge_cdata.arge_tx_ring_map, BUS_DMASYNC_PREWRITE); 2415188808Sgonzo} 2416188808Sgonzo 2417188808Sgonzo 2418198667Sgonzostatic int 2419188808Sgonzoarge_rx_locked(struct arge_softc *sc) 2420188808Sgonzo{ 2421188808Sgonzo struct arge_rxdesc *rxd; 2422188808Sgonzo struct ifnet *ifp = sc->arge_ifp; 2423192783Sgonzo int cons, prog, packet_len, i; 2424188808Sgonzo struct arge_desc *cur_rx; 2425188808Sgonzo struct mbuf *m; 2426198667Sgonzo int rx_npkts = 0; 2427188808Sgonzo 2428188808Sgonzo ARGE_LOCK_ASSERT(sc); 2429188808Sgonzo 2430188808Sgonzo cons = sc->arge_cdata.arge_rx_cons; 2431188808Sgonzo 2432188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2433188808Sgonzo sc->arge_cdata.arge_rx_ring_map, 2434188808Sgonzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2435188808Sgonzo 2436232627Sray for (prog = 0; prog < ARGE_RX_RING_COUNT; 2437188808Sgonzo ARGE_INC(cons, ARGE_RX_RING_COUNT)) { 2438188808Sgonzo cur_rx = &sc->arge_rdata.arge_rx_ring[cons]; 2439188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[cons]; 2440188808Sgonzo m = rxd->rx_m; 2441188808Sgonzo 2442188808Sgonzo if ((cur_rx->packet_ctrl & ARGE_DESC_EMPTY) != 0) 2443232627Sray break; 2444188808Sgonzo 2445188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_PKT_RECVD); 2446188808Sgonzo 2447188808Sgonzo prog++; 2448188808Sgonzo 2449188808Sgonzo packet_len = ARGE_DMASIZE(cur_rx->packet_ctrl); 2450188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap, 2451195434Sgonzo BUS_DMASYNC_POSTREAD); 2452188808Sgonzo m = rxd->rx_m; 2453188808Sgonzo 2454289671Sadrian /* 2455289671Sadrian * If the MAC requires 4 byte alignment then the RX setup 2456289671Sadrian * routine will have pre-offset things; so un-offset it here. 2457289671Sadrian */ 2458289671Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) 2459289671Sadrian arge_fixup_rx(m); 2460289671Sadrian 2461188808Sgonzo m->m_pkthdr.rcvif = ifp; 2462188808Sgonzo /* Skip 4 bytes of CRC */ 2463188808Sgonzo m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN; 2464271858Sglebius if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 2465198667Sgonzo rx_npkts++; 2466188808Sgonzo 2467188808Sgonzo ARGE_UNLOCK(sc); 2468188808Sgonzo (*ifp->if_input)(ifp, m); 2469188808Sgonzo ARGE_LOCK(sc); 2470192783Sgonzo cur_rx->packet_addr = 0; 2471192783Sgonzo } 2472188808Sgonzo 2473192783Sgonzo if (prog > 0) { 2474192783Sgonzo 2475192783Sgonzo i = sc->arge_cdata.arge_rx_cons; 2476192783Sgonzo for (; prog > 0 ; prog--) { 2477192783Sgonzo if (arge_newbuf(sc, i) != 0) { 2478232627Sray device_printf(sc->arge_dev, 2479192783Sgonzo "Failed to allocate buffer\n"); 2480192783Sgonzo break; 2481192783Sgonzo } 2482192783Sgonzo ARGE_INC(i, ARGE_RX_RING_COUNT); 2483188808Sgonzo } 2484188808Sgonzo 2485188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2486188808Sgonzo sc->arge_cdata.arge_rx_ring_map, 2487195434Sgonzo BUS_DMASYNC_PREWRITE); 2488188808Sgonzo 2489188808Sgonzo sc->arge_cdata.arge_rx_cons = cons; 2490188808Sgonzo } 2491198667Sgonzo 2492198667Sgonzo return (rx_npkts); 2493188808Sgonzo} 2494188808Sgonzo 2495188808Sgonzostatic int 2496188808Sgonzoarge_intr_filter(void *arg) 2497188808Sgonzo{ 2498188808Sgonzo struct arge_softc *sc = arg; 2499188808Sgonzo uint32_t status, ints; 2500188808Sgonzo 2501188808Sgonzo status = ARGE_READ(sc, AR71XX_DMA_INTR_STATUS); 2502188808Sgonzo ints = ARGE_READ(sc, AR71XX_DMA_INTR); 2503188808Sgonzo 2504220354Sadrian ARGEDEBUG(sc, ARGE_DBG_INTR, "int mask(filter) = %b\n", ints, 2505188808Sgonzo "\20\10RX_BUS_ERROR\7RX_OVERFLOW\5RX_PKT_RCVD" 2506188808Sgonzo "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT"); 2507232627Sray ARGEDEBUG(sc, ARGE_DBG_INTR, "status(filter) = %b\n", status, 2508188808Sgonzo "\20\10RX_BUS_ERROR\7RX_OVERFLOW\5RX_PKT_RCVD" 2509188808Sgonzo "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT"); 2510188808Sgonzo 2511188808Sgonzo if (status & DMA_INTR_ALL) { 2512191644Sgonzo sc->arge_intr_status |= status; 2513192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, 0); 2514289476Sadrian sc->stats.intr_ok++; 2515188808Sgonzo return (FILTER_SCHEDULE_THREAD); 2516232627Sray } 2517188808Sgonzo 2518188808Sgonzo sc->arge_intr_status = 0; 2519289476Sadrian sc->stats.intr_stray++; 2520188808Sgonzo return (FILTER_STRAY); 2521188808Sgonzo} 2522188808Sgonzo 2523188808Sgonzostatic void 2524188808Sgonzoarge_intr(void *arg) 2525188808Sgonzo{ 2526188808Sgonzo struct arge_softc *sc = arg; 2527188808Sgonzo uint32_t status; 2528220356Sadrian struct ifnet *ifp = sc->arge_ifp; 2529290090Sadrian#ifdef ARGE_DEBUG 2530290090Sadrian int i; 2531290090Sadrian#endif 2532188808Sgonzo 2533192783Sgonzo status = ARGE_READ(sc, AR71XX_DMA_INTR_STATUS); 2534192783Sgonzo status |= sc->arge_intr_status; 2535188808Sgonzo 2536232627Sray ARGEDEBUG(sc, ARGE_DBG_INTR, "int status(intr) = %b\n", status, 2537188808Sgonzo "\20\10\7RX_OVERFLOW\5RX_PKT_RCVD" 2538188808Sgonzo "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT"); 2539188808Sgonzo 2540232627Sray /* 2541232627Sray * Is it our interrupt at all? 2542188808Sgonzo */ 2543289476Sadrian if (status == 0) { 2544289476Sadrian sc->stats.intr_stray2++; 2545188808Sgonzo return; 2546289476Sadrian } 2547188808Sgonzo 2548290090Sadrian#ifdef ARGE_DEBUG 2549290090Sadrian for (i = 0; i < 32; i++) { 2550290214Sadrian if (status & (1U << i)) { 2551290123Sadrian sc->intr_stats.count[i]++; 2552290090Sadrian } 2553290090Sadrian } 2554290090Sadrian#endif 2555290090Sadrian 2556188808Sgonzo if (status & DMA_INTR_RX_BUS_ERROR) { 2557188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_BUS_ERROR); 2558188808Sgonzo device_printf(sc->arge_dev, "RX bus error"); 2559188808Sgonzo return; 2560188808Sgonzo } 2561188808Sgonzo 2562188808Sgonzo if (status & DMA_INTR_TX_BUS_ERROR) { 2563188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_BUS_ERROR); 2564188808Sgonzo device_printf(sc->arge_dev, "TX bus error"); 2565188808Sgonzo return; 2566188808Sgonzo } 2567188808Sgonzo 2568192783Sgonzo ARGE_LOCK(sc); 2569285121Sadrian arge_flush_ddr(sc); 2570188808Sgonzo 2571192783Sgonzo if (status & DMA_INTR_RX_PKT_RCVD) 2572192783Sgonzo arge_rx_locked(sc); 2573188808Sgonzo 2574232627Sray /* 2575232627Sray * RX overrun disables the receiver. 2576232627Sray * Clear indication and re-enable rx. 2577192783Sgonzo */ 2578192783Sgonzo if ( status & DMA_INTR_RX_OVERFLOW) { 2579192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_OVERFLOW); 2580192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, DMA_RX_CONTROL_EN); 2581220356Sadrian sc->stats.rx_overflow++; 2582192783Sgonzo } 2583188808Sgonzo 2584192783Sgonzo if (status & DMA_INTR_TX_PKT_SENT) 2585192783Sgonzo arge_tx_locked(sc); 2586232627Sray /* 2587232627Sray * Underrun turns off TX. Clear underrun indication. 2588232627Sray * If there's anything left in the ring, reactivate the tx. 2589192783Sgonzo */ 2590192569Sdwhite if (status & DMA_INTR_TX_UNDERRUN) { 2591192569Sdwhite ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_UNDERRUN); 2592220356Sadrian sc->stats.tx_underflow++; 2593232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: TX underrun; tx_cnt=%d\n", 2594232628Sray __func__, sc->arge_cdata.arge_tx_cnt); 2595219590Sadrian if (sc->arge_cdata.arge_tx_cnt > 0 ) { 2596232627Sray ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, 2597192783Sgonzo DMA_TX_CONTROL_EN); 2598192783Sgonzo } 2599192569Sdwhite } 2600192569Sdwhite 2601192946Sgonzo /* 2602220357Sadrian * If we've finished TXing and there's space for more packets 2603220357Sadrian * to be queued for TX, do so. Otherwise we may end up in a 2604220357Sadrian * situation where the interface send queue was filled 2605220357Sadrian * whilst the hardware queue was full, then the hardware 2606220357Sadrian * queue was drained by the interface send queue wasn't, 2607220357Sadrian * and thus if_start() is never called to kick-start 2608220357Sadrian * the send process (and all subsequent packets are simply 2609220357Sadrian * discarded. 2610220357Sadrian * 2611220357Sadrian * XXX TODO: make sure that the hardware deals nicely 2612220357Sadrian * with the possibility of the queue being enabled above 2613220357Sadrian * after a TX underrun, then having the hardware queue added 2614220357Sadrian * to below. 2615220357Sadrian */ 2616220357Sadrian if (status & (DMA_INTR_TX_PKT_SENT | DMA_INTR_TX_UNDERRUN) && 2617220357Sadrian (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { 2618220357Sadrian if (!IFQ_IS_EMPTY(&ifp->if_snd)) 2619220357Sadrian arge_start_locked(ifp); 2620220357Sadrian } 2621220357Sadrian 2622220357Sadrian /* 2623192946Sgonzo * We handled all bits, clear status 2624192946Sgonzo */ 2625192946Sgonzo sc->arge_intr_status = 0; 2626188808Sgonzo ARGE_UNLOCK(sc); 2627192783Sgonzo /* 2628232627Sray * re-enable all interrupts 2629192783Sgonzo */ 2630192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL); 2631188808Sgonzo} 2632188808Sgonzo 2633192783Sgonzo 2634188808Sgonzostatic void 2635188808Sgonzoarge_tick(void *xsc) 2636188808Sgonzo{ 2637188808Sgonzo struct arge_softc *sc = xsc; 2638188808Sgonzo struct mii_data *mii; 2639188808Sgonzo 2640188808Sgonzo ARGE_LOCK_ASSERT(sc); 2641188808Sgonzo 2642199234Sgonzo if (sc->arge_miibus) { 2643199234Sgonzo mii = device_get_softc(sc->arge_miibus); 2644199234Sgonzo mii_tick(mii); 2645199234Sgonzo callout_reset(&sc->arge_stat_callout, hz, arge_tick, sc); 2646199234Sgonzo } 2647188808Sgonzo} 2648199234Sgonzo 2649199234Sgonzoint 2650199234Sgonzoarge_multiphy_mediachange(struct ifnet *ifp) 2651199234Sgonzo{ 2652199234Sgonzo struct arge_softc *sc = ifp->if_softc; 2653199234Sgonzo struct ifmedia *ifm = &sc->arge_ifmedia; 2654199234Sgonzo struct ifmedia_entry *ife = ifm->ifm_cur; 2655199234Sgonzo 2656199234Sgonzo if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 2657199234Sgonzo return (EINVAL); 2658199234Sgonzo 2659199234Sgonzo if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 2660232627Sray device_printf(sc->arge_dev, 2661199234Sgonzo "AUTO is not supported for multiphy MAC"); 2662199234Sgonzo return (EINVAL); 2663199234Sgonzo } 2664199234Sgonzo 2665199234Sgonzo /* 2666199234Sgonzo * Ignore everything 2667199234Sgonzo */ 2668199234Sgonzo return (0); 2669199234Sgonzo} 2670199234Sgonzo 2671199234Sgonzovoid 2672199234Sgonzoarge_multiphy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 2673199234Sgonzo{ 2674199234Sgonzo struct arge_softc *sc = ifp->if_softc; 2675199234Sgonzo 2676199234Sgonzo ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 2677232627Sray ifmr->ifm_active = IFM_ETHER | sc->arge_media_type | 2678199234Sgonzo sc->arge_duplex_mode; 2679199234Sgonzo} 2680199234Sgonzo 2681234862Sadrian#if defined(ARGE_MDIO) 2682234862Sadrianstatic int 2683234862Sadrianargemdio_probe(device_t dev) 2684234862Sadrian{ 2685234862Sadrian device_set_desc(dev, "Atheros AR71xx built-in ethernet interface, MDIO controller"); 2686234862Sadrian return (0); 2687234862Sadrian} 2688234862Sadrian 2689234862Sadrianstatic int 2690234862Sadrianargemdio_attach(device_t dev) 2691234862Sadrian{ 2692234862Sadrian struct arge_softc *sc; 2693234862Sadrian int error = 0; 2694234862Sadrian 2695234862Sadrian sc = device_get_softc(dev); 2696234862Sadrian sc->arge_dev = dev; 2697234862Sadrian sc->arge_mac_unit = device_get_unit(dev); 2698234862Sadrian sc->arge_rid = 0; 2699234862Sadrian sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2700234862Sadrian &sc->arge_rid, RF_ACTIVE | RF_SHAREABLE); 2701234862Sadrian if (sc->arge_res == NULL) { 2702234862Sadrian device_printf(dev, "couldn't map memory\n"); 2703234862Sadrian error = ENXIO; 2704234862Sadrian goto fail; 2705234862Sadrian } 2706234862Sadrian 2707234862Sadrian /* Reset MAC - required for AR71xx MDIO to successfully occur */ 2708234862Sadrian arge_reset_mac(sc); 2709234862Sadrian /* Reset MII bus */ 2710234862Sadrian arge_reset_miibus(sc); 2711234862Sadrian 2712234862Sadrian bus_generic_probe(dev); 2713234862Sadrian bus_enumerate_hinted_children(dev); 2714234862Sadrian error = bus_generic_attach(dev); 2715234862Sadrianfail: 2716234862Sadrian return (error); 2717234862Sadrian} 2718234862Sadrian 2719234862Sadrianstatic int 2720234862Sadrianargemdio_detach(device_t dev) 2721234862Sadrian{ 2722234862Sadrian return (0); 2723234862Sadrian} 2724234862Sadrian 2725234862Sadrian#endif 2726