if_arge.c revision 290215
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: head/sys/mips/atheros/if_arge.c 290215 2015-10-30 23:18:02Z adrian $"); 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 <machine/pmap.h> 69188808Sgonzo#include <sys/bus.h> 70188808Sgonzo#include <sys/rman.h> 71188808Sgonzo 72188808Sgonzo#include <dev/mii/mii.h> 73188808Sgonzo#include <dev/mii/miivar.h> 74188808Sgonzo 75188808Sgonzo#include <dev/pci/pcireg.h> 76188808Sgonzo#include <dev/pci/pcivar.h> 77188808Sgonzo 78234862Sadrian#include "opt_arge.h" 79234862Sadrian 80234862Sadrian#if defined(ARGE_MDIO) 81234862Sadrian#include <dev/etherswitch/mdio.h> 82234862Sadrian#include <dev/etherswitch/miiproxy.h> 83234862Sadrian#include "mdio_if.h" 84234862Sadrian#endif 85234862Sadrian 86234862Sadrian 87188808SgonzoMODULE_DEPEND(arge, ether, 1, 1, 1); 88188808SgonzoMODULE_DEPEND(arge, miibus, 1, 1, 1); 89234862SadrianMODULE_VERSION(arge, 1); 90188808Sgonzo 91188808Sgonzo#include "miibus_if.h" 92188808Sgonzo 93280798Sadrian#include <net/ethernet.h> 94280798Sadrian 95188808Sgonzo#include <mips/atheros/ar71xxreg.h> 96256575Sadrian#include <mips/atheros/ar934xreg.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 } 402256575Sadrian ar71xx_device_stop(reset_reg); 403234862Sadrian DELAY(100); 404256575Sadrian ar71xx_device_start(reset_reg); 405234862Sadrian 406234862Sadrian /* Step 3. Reconfigure MAC block */ 407234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_CFG1, 408234862Sadrian MAC_CFG1_SYNC_RX | MAC_CFG1_RX_ENABLE | 409234862Sadrian MAC_CFG1_SYNC_TX | MAC_CFG1_TX_ENABLE); 410234862Sadrian 411234862Sadrian reg = ARGE_READ(sc, AR71XX_MAC_CFG2); 412234862Sadrian reg |= MAC_CFG2_ENABLE_PADCRC | MAC_CFG2_LENGTH_FIELD ; 413234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_CFG2, reg); 414234862Sadrian 415234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_MAX_FRAME_LEN, 1536); 416234862Sadrian} 417234862Sadrian 418256575Sadrian/* 419256648Sadrian * These values map to the divisor values programmed into 420256648Sadrian * AR71XX_MAC_MII_CFG. 421256648Sadrian * 422256648Sadrian * The index of each value corresponds to the divisor section 423256648Sadrian * value in AR71XX_MAC_MII_CFG (ie, table[0] means '0' in 424256648Sadrian * AR71XX_MAC_MII_CFG, table[1] means '1', etc.) 425256648Sadrian */ 426256648Sadrianstatic const uint32_t ar71xx_mdio_div_table[] = { 427256648Sadrian 4, 4, 6, 8, 10, 14, 20, 28, 428256648Sadrian}; 429256648Sadrian 430256648Sadrianstatic const uint32_t ar7240_mdio_div_table[] = { 431256648Sadrian 2, 2, 4, 6, 8, 12, 18, 26, 32, 40, 48, 56, 62, 70, 78, 96, 432256648Sadrian}; 433256648Sadrian 434256648Sadrianstatic const uint32_t ar933x_mdio_div_table[] = { 435256648Sadrian 4, 4, 6, 8, 10, 14, 20, 28, 34, 42, 50, 58, 66, 74, 82, 98, 436256648Sadrian}; 437256648Sadrian 438256648Sadrian/* 439256648Sadrian * Lookup the divisor to use based on the given frequency. 440256648Sadrian * 441256648Sadrian * Returns the divisor to use, or -ve on error. 442256648Sadrian */ 443256648Sadrianstatic int 444256648Sadrianarge_mdio_get_divider(struct arge_softc *sc, unsigned long mdio_clock) 445256648Sadrian{ 446256648Sadrian unsigned long ref_clock, t; 447256648Sadrian const uint32_t *table; 448256648Sadrian int ndivs; 449256648Sadrian int i; 450256648Sadrian 451256648Sadrian /* 452256648Sadrian * This is the base MDIO frequency on the SoC. 453256648Sadrian * The dividers .. well, divide. Duh. 454256648Sadrian */ 455256648Sadrian ref_clock = ar71xx_mdio_freq(); 456256648Sadrian 457256648Sadrian /* 458256648Sadrian * If either clock is undefined, just tell the 459256648Sadrian * caller to fall through to the defaults. 460256648Sadrian */ 461256648Sadrian if (ref_clock == 0 || mdio_clock == 0) 462256648Sadrian return (-EINVAL); 463256648Sadrian 464256648Sadrian /* 465256648Sadrian * Pick the correct table! 466256648Sadrian */ 467256648Sadrian switch (ar71xx_soc) { 468256648Sadrian case AR71XX_SOC_AR9330: 469256648Sadrian case AR71XX_SOC_AR9331: 470256648Sadrian case AR71XX_SOC_AR9341: 471256648Sadrian case AR71XX_SOC_AR9342: 472256648Sadrian case AR71XX_SOC_AR9344: 473279510Sadrian case AR71XX_SOC_QCA9556: 474279510Sadrian case AR71XX_SOC_QCA9558: 475256648Sadrian table = ar933x_mdio_div_table; 476256648Sadrian ndivs = nitems(ar933x_mdio_div_table); 477256648Sadrian break; 478256648Sadrian 479256648Sadrian case AR71XX_SOC_AR7240: 480256648Sadrian case AR71XX_SOC_AR7241: 481256648Sadrian case AR71XX_SOC_AR7242: 482256648Sadrian table = ar7240_mdio_div_table; 483256648Sadrian ndivs = nitems(ar7240_mdio_div_table); 484256648Sadrian break; 485256648Sadrian 486256648Sadrian default: 487256648Sadrian table = ar71xx_mdio_div_table; 488256648Sadrian ndivs = nitems(ar71xx_mdio_div_table); 489256648Sadrian } 490256648Sadrian 491256648Sadrian /* 492256648Sadrian * Now, walk through the list and find the first divisor 493256648Sadrian * that falls under the target MDIO frequency. 494256648Sadrian * 495256648Sadrian * The divisors go up, but the corresponding frequencies 496256648Sadrian * are actually decreasing. 497256648Sadrian */ 498256648Sadrian for (i = 0; i < ndivs; i++) { 499256648Sadrian t = ref_clock / table[i]; 500256648Sadrian if (t <= mdio_clock) { 501256648Sadrian return (i); 502256648Sadrian } 503256648Sadrian } 504256648Sadrian 505256648Sadrian ARGEDEBUG(sc, ARGE_DBG_RESET, 506256648Sadrian "No divider found; MDIO=%lu Hz; target=%lu Hz\n", 507256648Sadrian ref_clock, mdio_clock); 508256648Sadrian return (-ENOENT); 509256648Sadrian} 510256648Sadrian 511256648Sadrian/* 512256575Sadrian * Fetch the MDIO bus clock rate. 513256575Sadrian * 514256575Sadrian * For now, the default is DIV_28 for everything 515256648Sadrian * bar AR934x, which will be DIV_58. 516256575Sadrian * 517256575Sadrian * It will definitely need updating to take into account 518256575Sadrian * the MDIO bus core clock rate and the target clock 519256575Sadrian * rate for the chip. 520256575Sadrian */ 521256575Sadrianstatic uint32_t 522256575Sadrianarge_fetch_mdiobus_clock_rate(struct arge_softc *sc) 523256575Sadrian{ 524256648Sadrian int mdio_freq, div; 525256575Sadrian 526256648Sadrian /* 527256648Sadrian * Is the MDIO frequency defined? If so, find a divisor that 528256648Sadrian * makes reasonable sense. Don't overshoot the frequency. 529256648Sadrian */ 530256648Sadrian if (resource_int_value(device_get_name(sc->arge_dev), 531256648Sadrian device_get_unit(sc->arge_dev), 532256648Sadrian "mdio_freq", 533256648Sadrian &mdio_freq) == 0) { 534256648Sadrian sc->arge_mdiofreq = mdio_freq; 535256648Sadrian div = arge_mdio_get_divider(sc, sc->arge_mdiofreq); 536256648Sadrian if (bootverbose) 537256648Sadrian device_printf(sc->arge_dev, 538256648Sadrian "%s: mdio ref freq=%llu Hz, target freq=%llu Hz," 539256648Sadrian " divisor index=%d\n", 540256648Sadrian __func__, 541256648Sadrian (unsigned long long) ar71xx_mdio_freq(), 542256648Sadrian (unsigned long long) mdio_freq, 543256648Sadrian div); 544256648Sadrian if (div >= 0) 545256648Sadrian return (div); 546256648Sadrian } 547256648Sadrian 548256648Sadrian /* 549256648Sadrian * Default value(s). 550256648Sadrian * 551256648Sadrian * XXX obviously these need .. fixing. 552256648Sadrian * 553256648Sadrian * From Linux/OpenWRT: 554256648Sadrian * 555256648Sadrian * + 7240? DIV_6 556256648Sadrian * + Builtin-switch port and not 934x? DIV_10 557256648Sadrian * + Not built-in switch port and 934x? DIV_58 558256648Sadrian * + .. else DIV_28. 559256648Sadrian */ 560256575Sadrian switch (ar71xx_soc) { 561256575Sadrian case AR71XX_SOC_AR9341: 562256575Sadrian case AR71XX_SOC_AR9342: 563256575Sadrian case AR71XX_SOC_AR9344: 564279510Sadrian case AR71XX_SOC_QCA9556: 565279510Sadrian case AR71XX_SOC_QCA9558: 566256648Sadrian return (MAC_MII_CFG_CLOCK_DIV_58); 567256648Sadrian break; 568256575Sadrian default: 569256575Sadrian return (MAC_MII_CFG_CLOCK_DIV_28); 570256575Sadrian } 571256575Sadrian} 572256575Sadrian 573234862Sadrianstatic void 574234862Sadrianarge_reset_miibus(struct arge_softc *sc) 575234862Sadrian{ 576256575Sadrian uint32_t mdio_div; 577234862Sadrian 578256575Sadrian mdio_div = arge_fetch_mdiobus_clock_rate(sc); 579256575Sadrian 580256575Sadrian /* 581256575Sadrian * XXX AR934x and later; should we be also resetting the 582256575Sadrian * MDIO block(s) using the reset register block? 583256575Sadrian */ 584256575Sadrian 585256575Sadrian /* Reset MII bus; program in the default divisor */ 586256575Sadrian ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET | mdio_div); 587234862Sadrian DELAY(100); 588256575Sadrian ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, mdio_div); 589234862Sadrian DELAY(100); 590234862Sadrian} 591234862Sadrian 592234919Sadrianstatic void 593234919Sadrianarge_fetch_pll_config(struct arge_softc *sc) 594234919Sadrian{ 595234919Sadrian long int val; 596234919Sadrian 597234919Sadrian if (resource_long_value(device_get_name(sc->arge_dev), 598234919Sadrian device_get_unit(sc->arge_dev), 599234919Sadrian "pll_10", &val) == 0) { 600234919Sadrian sc->arge_pllcfg.pll_10 = val; 601234919Sadrian device_printf(sc->arge_dev, "%s: pll_10 = 0x%x\n", 602234919Sadrian __func__, (int) val); 603234919Sadrian } 604234919Sadrian if (resource_long_value(device_get_name(sc->arge_dev), 605234919Sadrian device_get_unit(sc->arge_dev), 606234919Sadrian "pll_100", &val) == 0) { 607234919Sadrian sc->arge_pllcfg.pll_100 = val; 608234919Sadrian device_printf(sc->arge_dev, "%s: pll_100 = 0x%x\n", 609234919Sadrian __func__, (int) val); 610234919Sadrian } 611234919Sadrian if (resource_long_value(device_get_name(sc->arge_dev), 612234919Sadrian device_get_unit(sc->arge_dev), 613234919Sadrian "pll_1000", &val) == 0) { 614234919Sadrian sc->arge_pllcfg.pll_1000 = val; 615234919Sadrian device_printf(sc->arge_dev, "%s: pll_1000 = 0x%x\n", 616234919Sadrian __func__, (int) val); 617234919Sadrian } 618234919Sadrian} 619234919Sadrian 620188808Sgonzostatic int 621188808Sgonzoarge_attach(device_t dev) 622188808Sgonzo{ 623188808Sgonzo struct ifnet *ifp; 624188808Sgonzo struct arge_softc *sc; 625280798Sadrian int error = 0, rid, i; 626199234Sgonzo uint32_t hint; 627220260Sadrian long eeprom_mac_addr = 0; 628234910Sadrian int miicfg = 0; 629254690Ssbruno int readascii = 0; 630263224Sadrian int local_mac = 0; 631280798Sadrian uint8_t local_macaddr[ETHER_ADDR_LEN]; 632280798Sadrian char * local_macstr; 633280798Sadrian char devid_str[32]; 634280798Sadrian int count; 635188808Sgonzo 636188808Sgonzo sc = device_get_softc(dev); 637188808Sgonzo sc->arge_dev = dev; 638188808Sgonzo sc->arge_mac_unit = device_get_unit(dev); 639188808Sgonzo 640220260Sadrian /* 641280798Sadrian * See if there's a "board" MAC address hint available for 642280798Sadrian * this particular device. 643280798Sadrian * 644280798Sadrian * This is in the environment - it'd be nice to use the resource_*() 645280798Sadrian * routines, but at the moment the system is booting, the resource hints 646280798Sadrian * are set to the 'static' map so they're not pulling from kenv. 647280798Sadrian */ 648280798Sadrian snprintf(devid_str, 32, "hint.%s.%d.macaddr", 649280798Sadrian device_get_name(dev), 650280798Sadrian device_get_unit(dev)); 651280798Sadrian if ((local_macstr = kern_getenv(devid_str)) != NULL) { 652280798Sadrian uint32_t tmpmac[ETHER_ADDR_LEN]; 653280798Sadrian 654280798Sadrian /* Have a MAC address; should use it */ 655280798Sadrian device_printf(dev, "Overriding MAC address from environment: '%s'\n", 656280798Sadrian local_macstr); 657280798Sadrian 658280798Sadrian /* Extract out the MAC address */ 659280798Sadrian /* XXX this should all be a generic method */ 660280798Sadrian count = sscanf(local_macstr, "%x%*c%x%*c%x%*c%x%*c%x%*c%x", 661280798Sadrian &tmpmac[0], &tmpmac[1], 662280798Sadrian &tmpmac[2], &tmpmac[3], 663280798Sadrian &tmpmac[4], &tmpmac[5]); 664280798Sadrian if (count == 6) { 665280798Sadrian /* Valid! */ 666280798Sadrian local_mac = 1; 667280798Sadrian for (i = 0; i < ETHER_ADDR_LEN; i++) 668280798Sadrian local_macaddr[i] = tmpmac[i]; 669280798Sadrian } 670280798Sadrian /* Done! */ 671280798Sadrian freeenv(local_macstr); 672280798Sadrian local_macstr = NULL; 673280798Sadrian } 674280798Sadrian 675280798Sadrian /* 676289476Sadrian * Hardware workarounds. 677289476Sadrian */ 678289476Sadrian switch (ar71xx_soc) { 679289744Sadrian case AR71XX_SOC_AR9330: 680289744Sadrian case AR71XX_SOC_AR9331: 681289898Sadrian case AR71XX_SOC_AR9341: 682289898Sadrian case AR71XX_SOC_AR9342: 683289898Sadrian case AR71XX_SOC_AR9344: 684289476Sadrian case AR71XX_SOC_QCA9556: 685289476Sadrian case AR71XX_SOC_QCA9558: 686289476Sadrian /* Arbitrary alignment */ 687289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_TX_DESC_ALIGN_1BYTE; 688289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE; 689289476Sadrian break; 690289476Sadrian default: 691289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE; 692289476Sadrian sc->arge_hw_flags |= ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE; 693289476Sadrian break; 694289476Sadrian } 695289476Sadrian 696289476Sadrian /* 697220260Sadrian * Some units (eg the TP-Link WR-1043ND) do not have a convenient 698220260Sadrian * EEPROM location to read the ethernet MAC address from. 699220260Sadrian * OpenWRT simply snaffles it from a fixed location. 700220260Sadrian * 701220260Sadrian * Since multiple units seem to use this feature, include 702220260Sadrian * a method of setting the MAC address based on an flash location 703220260Sadrian * in CPU address space. 704254690Ssbruno * 705254690Ssbruno * Some vendors have decided to store the mac address as a literal 706254690Ssbruno * string of 18 characters in xx:xx:xx:xx:xx:xx format instead of 707254690Ssbruno * an array of numbers. Expose a hint to turn on this conversion 708254690Ssbruno * feature via strtol() 709220260Sadrian */ 710280798Sadrian if (local_mac == 0 && resource_long_value(device_get_name(dev), 711280798Sadrian device_get_unit(dev), "eeprommac", &eeprom_mac_addr) == 0) { 712263224Sadrian local_mac = 1; 713220260Sadrian int i; 714232628Sray const char *mac = 715232628Sray (const char *) MIPS_PHYS_TO_KSEG1(eeprom_mac_addr); 716220260Sadrian device_printf(dev, "Overriding MAC from EEPROM\n"); 717254690Ssbruno if (resource_int_value(device_get_name(dev), device_get_unit(dev), 718254690Ssbruno "readascii", &readascii) == 0) { 719254690Ssbruno device_printf(dev, "Vendor stores MAC in ASCII format\n"); 720254690Ssbruno for (i = 0; i < 6; i++) { 721280798Sadrian local_macaddr[i] = strtol(&(mac[i*3]), NULL, 16); 722254690Ssbruno } 723254690Ssbruno } else { 724254690Ssbruno for (i = 0; i < 6; i++) { 725280798Sadrian local_macaddr[i] = mac[i]; 726254690Ssbruno } 727220260Sadrian } 728220260Sadrian } 729220260Sadrian 730232627Sray KASSERT(((sc->arge_mac_unit == 0) || (sc->arge_mac_unit == 1)), 731188808Sgonzo ("if_arge: Only MAC0 and MAC1 supported")); 732188808Sgonzo 733188808Sgonzo /* 734234919Sadrian * Fetch the PLL configuration. 735234919Sadrian */ 736234919Sadrian arge_fetch_pll_config(sc); 737234919Sadrian 738234919Sadrian /* 739234910Sadrian * Get the MII configuration, if applicable. 740234910Sadrian */ 741234910Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 742234910Sadrian "miimode", &miicfg) == 0) { 743234910Sadrian /* XXX bounds check? */ 744234910Sadrian device_printf(dev, "%s: overriding MII mode to '%s'\n", 745234910Sadrian __func__, arge_miicfg_str[miicfg]); 746234910Sadrian sc->arge_miicfg = miicfg; 747234910Sadrian } 748234910Sadrian 749234910Sadrian /* 750188808Sgonzo * Get which PHY of 5 available we should use for this unit 751188808Sgonzo */ 752234862Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 753234862Sadrian "phymask", &sc->arge_phymask) != 0) { 754188808Sgonzo /* 755232627Sray * Use port 4 (WAN) for GE0. For any other port use 756232627Sray * its PHY the same as its unit number 757188808Sgonzo */ 758188808Sgonzo if (sc->arge_mac_unit == 0) 759234862Sadrian sc->arge_phymask = (1 << 4); 760188808Sgonzo else 761199234Sgonzo /* Use all phys up to 4 */ 762234862Sadrian sc->arge_phymask = (1 << 4) - 1; 763188808Sgonzo 764234862Sadrian device_printf(dev, "No PHY specified, using mask %d\n", sc->arge_phymask); 765188808Sgonzo } 766188808Sgonzo 767199234Sgonzo /* 768279791Sadrian * Get default/hard-coded media & duplex mode. 769199234Sgonzo */ 770232627Sray if (resource_int_value(device_get_name(dev), device_get_unit(dev), 771199234Sgonzo "media", &hint) != 0) 772199234Sgonzo hint = 0; 773188808Sgonzo 774199234Sgonzo if (hint == 1000) 775199234Sgonzo sc->arge_media_type = IFM_1000_T; 776279791Sadrian else if (hint == 100) 777279791Sadrian sc->arge_media_type = IFM_100_TX; 778279791Sadrian else if (hint == 10) 779279791Sadrian sc->arge_media_type = IFM_10_T; 780199234Sgonzo else 781279791Sadrian sc->arge_media_type = 0; 782199234Sgonzo 783232627Sray if (resource_int_value(device_get_name(dev), device_get_unit(dev), 784199234Sgonzo "fduplex", &hint) != 0) 785199234Sgonzo hint = 1; 786199234Sgonzo 787199234Sgonzo if (hint) 788199234Sgonzo sc->arge_duplex_mode = IFM_FDX; 789199234Sgonzo else 790199234Sgonzo sc->arge_duplex_mode = 0; 791199234Sgonzo 792188808Sgonzo mtx_init(&sc->arge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 793188808Sgonzo MTX_DEF); 794188808Sgonzo callout_init_mtx(&sc->arge_stat_callout, &sc->arge_mtx, 0); 795188808Sgonzo TASK_INIT(&sc->arge_link_task, 0, arge_link_task, sc); 796188808Sgonzo 797188808Sgonzo /* Map control/status registers. */ 798188808Sgonzo sc->arge_rid = 0; 799234862Sadrian sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 800234862Sadrian &sc->arge_rid, RF_ACTIVE | RF_SHAREABLE); 801188808Sgonzo 802188808Sgonzo if (sc->arge_res == NULL) { 803188808Sgonzo device_printf(dev, "couldn't map memory\n"); 804188808Sgonzo error = ENXIO; 805188808Sgonzo goto fail; 806188808Sgonzo } 807188808Sgonzo 808188808Sgonzo /* Allocate interrupts */ 809188808Sgonzo rid = 0; 810232627Sray sc->arge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 811188808Sgonzo RF_SHAREABLE | RF_ACTIVE); 812188808Sgonzo 813188808Sgonzo if (sc->arge_irq == NULL) { 814188808Sgonzo device_printf(dev, "couldn't map interrupt\n"); 815188808Sgonzo error = ENXIO; 816188808Sgonzo goto fail; 817188808Sgonzo } 818188808Sgonzo 819188808Sgonzo /* Allocate ifnet structure. */ 820188808Sgonzo ifp = sc->arge_ifp = if_alloc(IFT_ETHER); 821188808Sgonzo 822188808Sgonzo if (ifp == NULL) { 823188808Sgonzo device_printf(dev, "couldn't allocate ifnet structure\n"); 824188808Sgonzo error = ENOSPC; 825188808Sgonzo goto fail; 826188808Sgonzo } 827188808Sgonzo 828188808Sgonzo ifp->if_softc = sc; 829188808Sgonzo if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 830188808Sgonzo ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 831188808Sgonzo ifp->if_ioctl = arge_ioctl; 832188808Sgonzo ifp->if_start = arge_start; 833188808Sgonzo ifp->if_init = arge_init; 834198932Sgonzo sc->arge_if_flags = ifp->if_flags; 835188808Sgonzo 836188808Sgonzo /* XXX: add real size */ 837207554Ssobomax IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 838207554Ssobomax ifp->if_snd.ifq_maxlen = ifqmaxlen; 839188808Sgonzo IFQ_SET_READY(&ifp->if_snd); 840188808Sgonzo 841268235Sloos /* Tell the upper layer(s) we support long frames. */ 842268235Sloos ifp->if_capabilities |= IFCAP_VLAN_MTU; 843268235Sloos 844188808Sgonzo ifp->if_capenable = ifp->if_capabilities; 845192783Sgonzo#ifdef DEVICE_POLLING 846192783Sgonzo ifp->if_capabilities |= IFCAP_POLLING; 847192783Sgonzo#endif 848188808Sgonzo 849280798Sadrian /* If there's a local mac defined, copy that in */ 850280798Sadrian if (local_mac == 1) { 851280798Sadrian (void) ar71xx_mac_addr_init(sc->arge_eaddr, 852280798Sadrian local_macaddr, 0, 0); 853280798Sadrian } else { 854192179Sgonzo /* 855192179Sgonzo * No MAC address configured. Generate the random one. 856192179Sgonzo */ 857198933Sgonzo if (bootverbose) 858232627Sray device_printf(dev, 859192179Sgonzo "Generating random ethernet address.\n"); 860280124Sadrian (void) ar71xx_mac_addr_random_init(sc->arge_eaddr); 861192179Sgonzo } 862263224Sadrian 863188808Sgonzo if (arge_dma_alloc(sc) != 0) { 864188808Sgonzo error = ENXIO; 865188808Sgonzo goto fail; 866188808Sgonzo } 867188808Sgonzo 868234862Sadrian /* 869234862Sadrian * Don't do this for the MDIO bus case - it's already done 870234862Sadrian * as part of the MDIO bus attachment. 871234862Sadrian */ 872234862Sadrian#if !defined(ARGE_MDIO) 873192569Sdwhite /* Initialize the MAC block */ 874234862Sadrian arge_reset_mac(sc); 875234862Sadrian arge_reset_miibus(sc); 876234862Sadrian#endif 877232627Sray 878234910Sadrian /* Configure MII mode, just for convienence */ 879234910Sadrian if (sc->arge_miicfg != 0) 880234910Sadrian ar71xx_device_set_mii_if(sc->arge_mac_unit, sc->arge_miicfg); 881234910Sadrian 882232627Sray /* 883188808Sgonzo * Set all Ethernet address registers to the same initial values 884232627Sray * set all four addresses to 66-88-aa-cc-dd-ee 885188808Sgonzo */ 886234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR1, (sc->arge_eaddr[2] << 24) 887234862Sadrian | (sc->arge_eaddr[3] << 16) | (sc->arge_eaddr[4] << 8) 888234862Sadrian | sc->arge_eaddr[5]); 889234862Sadrian ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR2, (sc->arge_eaddr[0] << 8) 890234862Sadrian | sc->arge_eaddr[1]); 891188808Sgonzo 892232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG0, 893188808Sgonzo FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT); 894188808Sgonzo 895289476Sadrian /* 896289476Sadrian * SoC specific bits. 897289476Sadrian */ 898219589Sadrian switch (ar71xx_soc) { 899219589Sadrian case AR71XX_SOC_AR7240: 900219589Sadrian case AR71XX_SOC_AR7241: 901219589Sadrian case AR71XX_SOC_AR7242: 902249123Sadrian case AR71XX_SOC_AR9330: 903249123Sadrian case AR71XX_SOC_AR9331: 904256575Sadrian case AR71XX_SOC_AR9341: 905256575Sadrian case AR71XX_SOC_AR9342: 906256575Sadrian case AR71XX_SOC_AR9344: 907279510Sadrian case AR71XX_SOC_QCA9556: 908279510Sadrian case AR71XX_SOC_QCA9558: 909219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0010ffff); 910219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x015500aa); 911219589Sadrian break; 912256575Sadrian /* AR71xx, AR913x */ 913219589Sadrian default: 914219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0fff0000); 915219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x00001fff); 916219589Sadrian } 917219589Sadrian 918232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMATCH, 919192783Sgonzo FIFO_RX_FILTMATCH_DEFAULT); 920188808Sgonzo 921232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK, 922192783Sgonzo FIFO_RX_FILTMASK_DEFAULT); 923188808Sgonzo 924234862Sadrian#if defined(ARGE_MDIO) 925234862Sadrian sc->arge_miiproxy = mii_attach_proxy(sc->arge_dev); 926234862Sadrian#endif 927199234Sgonzo 928234862Sadrian device_printf(sc->arge_dev, "finishing attachment, phymask %04x" 929234862Sadrian ", proxy %s \n", sc->arge_phymask, sc->arge_miiproxy == NULL ? 930234862Sadrian "null" : "set"); 931234862Sadrian for (i = 0; i < ARGE_NPHY; i++) { 932234862Sadrian if (((1 << i) & sc->arge_phymask) != 0) { 933234862Sadrian error = mii_attach(sc->arge_miiproxy != NULL ? 934234862Sadrian sc->arge_miiproxy : sc->arge_dev, 935234862Sadrian &sc->arge_miibus, sc->arge_ifp, 936234862Sadrian arge_ifmedia_upd, arge_ifmedia_sts, 937234862Sadrian BMSR_DEFCAPMASK, i, MII_OFFSET_ANY, 0); 938234862Sadrian if (error != 0) { 939234862Sadrian device_printf(sc->arge_dev, "unable to attach" 940234862Sadrian " PHY %d: %d\n", i, error); 941234862Sadrian goto fail; 942234862Sadrian } 943199234Sgonzo } 944199234Sgonzo } 945279791Sadrian 946234862Sadrian if (sc->arge_miibus == NULL) { 947234862Sadrian /* no PHY, so use hard-coded values */ 948279791Sadrian ifmedia_init(&sc->arge_ifmedia, 0, 949199234Sgonzo arge_multiphy_mediachange, 950199234Sgonzo arge_multiphy_mediastatus); 951199234Sgonzo ifmedia_add(&sc->arge_ifmedia, 952232627Sray IFM_ETHER | sc->arge_media_type | sc->arge_duplex_mode, 953199234Sgonzo 0, NULL); 954199234Sgonzo ifmedia_set(&sc->arge_ifmedia, 955199234Sgonzo IFM_ETHER | sc->arge_media_type | sc->arge_duplex_mode); 956199234Sgonzo arge_set_pll(sc, sc->arge_media_type, sc->arge_duplex_mode); 957199234Sgonzo } 958199234Sgonzo 959188808Sgonzo /* Call MI attach routine. */ 960234862Sadrian ether_ifattach(sc->arge_ifp, sc->arge_eaddr); 961188808Sgonzo 962188808Sgonzo /* Hook interrupt last to avoid having to lock softc */ 963234862Sadrian error = bus_setup_intr(sc->arge_dev, sc->arge_irq, INTR_TYPE_NET | INTR_MPSAFE, 964188808Sgonzo arge_intr_filter, arge_intr, sc, &sc->arge_intrhand); 965188808Sgonzo 966188808Sgonzo if (error) { 967234862Sadrian device_printf(sc->arge_dev, "couldn't set up irq\n"); 968234862Sadrian ether_ifdetach(sc->arge_ifp); 969188808Sgonzo goto fail; 970188808Sgonzo } 971188808Sgonzo 972209802Sadrian /* setup sysctl variables */ 973234862Sadrian arge_attach_sysctl(sc->arge_dev); 974209802Sadrian 975188808Sgonzofail: 976234862Sadrian if (error) 977188808Sgonzo arge_detach(dev); 978188808Sgonzo 979188808Sgonzo return (error); 980188808Sgonzo} 981188808Sgonzo 982188808Sgonzostatic int 983188808Sgonzoarge_detach(device_t dev) 984188808Sgonzo{ 985192783Sgonzo struct arge_softc *sc = device_get_softc(dev); 986188808Sgonzo struct ifnet *ifp = sc->arge_ifp; 987188808Sgonzo 988232628Sray KASSERT(mtx_initialized(&sc->arge_mtx), 989232628Sray ("arge mutex not initialized")); 990188808Sgonzo 991188808Sgonzo /* These should only be active if attach succeeded */ 992188808Sgonzo if (device_is_attached(dev)) { 993188808Sgonzo ARGE_LOCK(sc); 994188808Sgonzo sc->arge_detach = 1; 995192783Sgonzo#ifdef DEVICE_POLLING 996192783Sgonzo if (ifp->if_capenable & IFCAP_POLLING) 997192783Sgonzo ether_poll_deregister(ifp); 998192783Sgonzo#endif 999192783Sgonzo 1000188808Sgonzo arge_stop(sc); 1001188808Sgonzo ARGE_UNLOCK(sc); 1002188808Sgonzo taskqueue_drain(taskqueue_swi, &sc->arge_link_task); 1003188808Sgonzo ether_ifdetach(ifp); 1004188808Sgonzo } 1005188808Sgonzo 1006188808Sgonzo if (sc->arge_miibus) 1007188808Sgonzo device_delete_child(dev, sc->arge_miibus); 1008199234Sgonzo 1009234862Sadrian if (sc->arge_miiproxy) 1010234862Sadrian device_delete_child(dev, sc->arge_miiproxy); 1011234862Sadrian 1012188808Sgonzo bus_generic_detach(dev); 1013188808Sgonzo 1014188808Sgonzo if (sc->arge_intrhand) 1015188808Sgonzo bus_teardown_intr(dev, sc->arge_irq, sc->arge_intrhand); 1016188808Sgonzo 1017188808Sgonzo if (sc->arge_res) 1018232627Sray bus_release_resource(dev, SYS_RES_MEMORY, sc->arge_rid, 1019188808Sgonzo sc->arge_res); 1020188808Sgonzo 1021188808Sgonzo if (ifp) 1022188808Sgonzo if_free(ifp); 1023188808Sgonzo 1024188808Sgonzo arge_dma_free(sc); 1025188808Sgonzo 1026188808Sgonzo mtx_destroy(&sc->arge_mtx); 1027188808Sgonzo 1028188808Sgonzo return (0); 1029188808Sgonzo 1030188808Sgonzo} 1031188808Sgonzo 1032188808Sgonzostatic int 1033188808Sgonzoarge_suspend(device_t dev) 1034188808Sgonzo{ 1035188808Sgonzo 1036188808Sgonzo panic("%s", __func__); 1037188808Sgonzo return 0; 1038188808Sgonzo} 1039188808Sgonzo 1040188808Sgonzostatic int 1041188808Sgonzoarge_resume(device_t dev) 1042188808Sgonzo{ 1043188808Sgonzo 1044188808Sgonzo panic("%s", __func__); 1045188808Sgonzo return 0; 1046188808Sgonzo} 1047188808Sgonzo 1048194059Sgonzostatic int 1049188808Sgonzoarge_shutdown(device_t dev) 1050188808Sgonzo{ 1051188808Sgonzo struct arge_softc *sc; 1052188808Sgonzo 1053188808Sgonzo sc = device_get_softc(dev); 1054188808Sgonzo 1055188808Sgonzo ARGE_LOCK(sc); 1056188808Sgonzo arge_stop(sc); 1057188808Sgonzo ARGE_UNLOCK(sc); 1058194059Sgonzo 1059194059Sgonzo return (0); 1060188808Sgonzo} 1061188808Sgonzo 1062234862Sadrianstatic void 1063234862Sadrianarge_hinted_child(device_t bus, const char *dname, int dunit) 1064234862Sadrian{ 1065234862Sadrian BUS_ADD_CHILD(bus, 0, dname, dunit); 1066234862Sadrian device_printf(bus, "hinted child %s%d\n", dname, dunit); 1067234862Sadrian} 1068234862Sadrian 1069188808Sgonzostatic int 1070188808Sgonzoarge_miibus_readreg(device_t dev, int phy, int reg) 1071188808Sgonzo{ 1072188808Sgonzo struct arge_softc * sc = device_get_softc(dev); 1073188808Sgonzo int i, result; 1074232627Sray uint32_t addr = (phy << MAC_MII_PHY_ADDR_SHIFT) 1075188808Sgonzo | (reg & MAC_MII_REG_MASK); 1076188808Sgonzo 1077199038Sgonzo mtx_lock(&miibus_mtx); 1078234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE); 1079234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr); 1080234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_READ); 1081188808Sgonzo 1082188808Sgonzo i = ARGE_MII_TIMEOUT; 1083234862Sadrian while ((ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR) & 1084290212Sadrian MAC_MII_INDICATOR_BUSY) && (i--)) { 1085290212Sadrian ARGE_MDIO_BARRIER_READ(sc); 1086188808Sgonzo DELAY(5); 1087290212Sadrian } 1088188808Sgonzo 1089188808Sgonzo if (i < 0) { 1090199038Sgonzo mtx_unlock(&miibus_mtx); 1091220354Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s timedout\n", __func__); 1092188808Sgonzo /* XXX: return ERRNO istead? */ 1093188808Sgonzo return (-1); 1094188808Sgonzo } 1095188808Sgonzo 1096234862Sadrian result = ARGE_MDIO_READ(sc, AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK; 1097290212Sadrian ARGE_MDIO_BARRIER_READ(sc); 1098234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE); 1099199038Sgonzo mtx_unlock(&miibus_mtx); 1100199038Sgonzo 1101232628Sray ARGEDEBUG(sc, ARGE_DBG_MII, 1102232628Sray "%s: phy=%d, reg=%02x, value[%08x]=%04x\n", 1103232628Sray __func__, phy, reg, addr, result); 1104188808Sgonzo 1105188808Sgonzo return (result); 1106188808Sgonzo} 1107188808Sgonzo 1108188808Sgonzostatic int 1109188808Sgonzoarge_miibus_writereg(device_t dev, int phy, int reg, int data) 1110188808Sgonzo{ 1111188808Sgonzo struct arge_softc * sc = device_get_softc(dev); 1112188808Sgonzo int i; 1113232627Sray uint32_t addr = 1114196794Sgonzo (phy << MAC_MII_PHY_ADDR_SHIFT) | (reg & MAC_MII_REG_MASK); 1115188808Sgonzo 1116234862Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s: phy=%d, reg=%02x, value=%04x\n", __func__, 1117234862Sadrian phy, reg, data); 1118199038Sgonzo 1119199038Sgonzo mtx_lock(&miibus_mtx); 1120234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_ADDR, addr); 1121234862Sadrian ARGE_MDIO_WRITE(sc, AR71XX_MAC_MII_CONTROL, data); 1122188808Sgonzo 1123188808Sgonzo i = ARGE_MII_TIMEOUT; 1124234862Sadrian while ((ARGE_MDIO_READ(sc, AR71XX_MAC_MII_INDICATOR) & 1125290212Sadrian MAC_MII_INDICATOR_BUSY) && (i--)) { 1126290212Sadrian ARGE_MDIO_BARRIER_READ(sc); 1127188808Sgonzo DELAY(5); 1128290212Sadrian } 1129188808Sgonzo 1130199038Sgonzo mtx_unlock(&miibus_mtx); 1131199038Sgonzo 1132188808Sgonzo if (i < 0) { 1133220354Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s timedout\n", __func__); 1134188808Sgonzo /* XXX: return ERRNO istead? */ 1135188808Sgonzo return (-1); 1136188808Sgonzo } 1137188808Sgonzo 1138188808Sgonzo return (0); 1139188808Sgonzo} 1140188808Sgonzo 1141188808Sgonzostatic void 1142188808Sgonzoarge_miibus_statchg(device_t dev) 1143188808Sgonzo{ 1144232627Sray struct arge_softc *sc; 1145188808Sgonzo 1146188808Sgonzo sc = device_get_softc(dev); 1147188808Sgonzo taskqueue_enqueue(taskqueue_swi, &sc->arge_link_task); 1148188808Sgonzo} 1149188808Sgonzo 1150188808Sgonzostatic void 1151188808Sgonzoarge_link_task(void *arg, int pending) 1152188808Sgonzo{ 1153188808Sgonzo struct arge_softc *sc; 1154232914Sadrian sc = (struct arge_softc *)arg; 1155232914Sadrian 1156232914Sadrian ARGE_LOCK(sc); 1157232914Sadrian arge_update_link_locked(sc); 1158232914Sadrian ARGE_UNLOCK(sc); 1159232914Sadrian} 1160232914Sadrian 1161232914Sadrianstatic void 1162232914Sadrianarge_update_link_locked(struct arge_softc *sc) 1163232914Sadrian{ 1164188808Sgonzo struct mii_data *mii; 1165188808Sgonzo struct ifnet *ifp; 1166199234Sgonzo uint32_t media, duplex; 1167188808Sgonzo 1168188808Sgonzo mii = device_get_softc(sc->arge_miibus); 1169188808Sgonzo ifp = sc->arge_ifp; 1170188808Sgonzo if (mii == NULL || ifp == NULL || 1171188808Sgonzo (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1172188808Sgonzo return; 1173188808Sgonzo } 1174188808Sgonzo 1175279791Sadrian /* 1176279791Sadrian * If we have a static media type configured, then 1177279791Sadrian * use that. Some PHY configurations (eg QCA955x -> AR8327) 1178279791Sadrian * use a static speed/duplex between the SoC and switch, 1179279791Sadrian * even though the front-facing PHY speed changes. 1180279791Sadrian */ 1181279791Sadrian if (sc->arge_media_type != 0) { 1182279791Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s: fixed; media=%d, duplex=%d\n", 1183279791Sadrian __func__, 1184279791Sadrian sc->arge_media_type, 1185279791Sadrian sc->arge_duplex_mode); 1186279791Sadrian if (mii->mii_media_status & IFM_ACTIVE) { 1187279791Sadrian sc->arge_link_status = 1; 1188279791Sadrian } else { 1189279791Sadrian sc->arge_link_status = 0; 1190279791Sadrian } 1191279791Sadrian arge_set_pll(sc, sc->arge_media_type, sc->arge_duplex_mode); 1192279791Sadrian } 1193279791Sadrian 1194188808Sgonzo if (mii->mii_media_status & IFM_ACTIVE) { 1195188808Sgonzo 1196188808Sgonzo media = IFM_SUBTYPE(mii->mii_media_active); 1197188808Sgonzo if (media != IFM_NONE) { 1198188808Sgonzo sc->arge_link_status = 1; 1199199234Sgonzo duplex = mii->mii_media_active & IFM_GMASK; 1200234907Sadrian ARGEDEBUG(sc, ARGE_DBG_MII, "%s: media=%d, duplex=%d\n", 1201234907Sadrian __func__, 1202234907Sadrian media, 1203234907Sadrian duplex); 1204199234Sgonzo arge_set_pll(sc, media, duplex); 1205199234Sgonzo } 1206232914Sadrian } else { 1207199234Sgonzo sc->arge_link_status = 0; 1208232914Sadrian } 1209199234Sgonzo} 1210192783Sgonzo 1211199234Sgonzostatic void 1212199234Sgonzoarge_set_pll(struct arge_softc *sc, int media, int duplex) 1213199234Sgonzo{ 1214211511Sadrian uint32_t cfg, ifcontrol, rx_filtmask; 1215234907Sadrian uint32_t fifo_tx, pll; 1216211511Sadrian int if_speed; 1217192783Sgonzo 1218279791Sadrian /* 1219279791Sadrian * XXX Verify - is this valid for all chips? 1220279791Sadrian * QCA955x (and likely some of the earlier chips!) define 1221279791Sadrian * this as nibble mode and byte mode, and those have to do 1222279791Sadrian * with the interface type (MII/SMII versus GMII/RGMII.) 1223279791Sadrian */ 1224234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "set_pll(%04x, %s)\n", media, 1225234862Sadrian duplex == IFM_FDX ? "full" : "half"); 1226199234Sgonzo cfg = ARGE_READ(sc, AR71XX_MAC_CFG2); 1227232627Sray cfg &= ~(MAC_CFG2_IFACE_MODE_1000 1228232627Sray | MAC_CFG2_IFACE_MODE_10_100 1229199234Sgonzo | MAC_CFG2_FULL_DUPLEX); 1230188808Sgonzo 1231199234Sgonzo if (duplex == IFM_FDX) 1232199234Sgonzo cfg |= MAC_CFG2_FULL_DUPLEX; 1233188808Sgonzo 1234199234Sgonzo ifcontrol = ARGE_READ(sc, AR71XX_MAC_IFCONTROL); 1235199234Sgonzo ifcontrol &= ~MAC_IFCONTROL_SPEED; 1236232627Sray rx_filtmask = 1237199234Sgonzo ARGE_READ(sc, AR71XX_MAC_FIFO_RX_FILTMASK); 1238199234Sgonzo rx_filtmask &= ~FIFO_RX_MASK_BYTE_MODE; 1239188808Sgonzo 1240199234Sgonzo switch(media) { 1241199234Sgonzo case IFM_10_T: 1242199234Sgonzo cfg |= MAC_CFG2_IFACE_MODE_10_100; 1243211511Sadrian if_speed = 10; 1244199234Sgonzo break; 1245199234Sgonzo case IFM_100_TX: 1246199234Sgonzo cfg |= MAC_CFG2_IFACE_MODE_10_100; 1247199234Sgonzo ifcontrol |= MAC_IFCONTROL_SPEED; 1248211511Sadrian if_speed = 100; 1249199234Sgonzo break; 1250199234Sgonzo case IFM_1000_T: 1251199234Sgonzo case IFM_1000_SX: 1252199234Sgonzo cfg |= MAC_CFG2_IFACE_MODE_1000; 1253199234Sgonzo rx_filtmask |= FIFO_RX_MASK_BYTE_MODE; 1254211511Sadrian if_speed = 1000; 1255199234Sgonzo break; 1256199234Sgonzo default: 1257211511Sadrian if_speed = 100; 1258232627Sray device_printf(sc->arge_dev, 1259199234Sgonzo "Unknown media %d\n", media); 1260199234Sgonzo } 1261188808Sgonzo 1262234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: if_speed=%d\n", __func__, if_speed); 1263234907Sadrian 1264219589Sadrian switch (ar71xx_soc) { 1265219589Sadrian case AR71XX_SOC_AR7240: 1266219589Sadrian case AR71XX_SOC_AR7241: 1267219589Sadrian case AR71XX_SOC_AR7242: 1268249123Sadrian case AR71XX_SOC_AR9330: 1269249123Sadrian case AR71XX_SOC_AR9331: 1270256575Sadrian case AR71XX_SOC_AR9341: 1271256575Sadrian case AR71XX_SOC_AR9342: 1272256575Sadrian case AR71XX_SOC_AR9344: 1273279510Sadrian case AR71XX_SOC_QCA9556: 1274279510Sadrian case AR71XX_SOC_QCA9558: 1275219589Sadrian fifo_tx = 0x01f00140; 1276219589Sadrian break; 1277219589Sadrian case AR71XX_SOC_AR9130: 1278219589Sadrian case AR71XX_SOC_AR9132: 1279219589Sadrian fifo_tx = 0x00780fff; 1280219589Sadrian break; 1281256575Sadrian /* AR71xx */ 1282219589Sadrian default: 1283219589Sadrian fifo_tx = 0x008001ff; 1284219589Sadrian } 1285188808Sgonzo 1286199234Sgonzo ARGE_WRITE(sc, AR71XX_MAC_CFG2, cfg); 1287199234Sgonzo ARGE_WRITE(sc, AR71XX_MAC_IFCONTROL, ifcontrol); 1288232627Sray ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK, 1289199234Sgonzo rx_filtmask); 1290219589Sadrian ARGE_WRITE(sc, AR71XX_MAC_FIFO_TX_THRESHOLD, fifo_tx); 1291188808Sgonzo 1292234919Sadrian /* fetch PLL registers */ 1293234907Sadrian pll = ar71xx_device_get_eth_pll(sc->arge_mac_unit, if_speed); 1294234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: pll=0x%x\n", __func__, pll); 1295234907Sadrian 1296234919Sadrian /* Override if required by platform data */ 1297234919Sadrian if (if_speed == 10 && sc->arge_pllcfg.pll_10 != 0) 1298234919Sadrian pll = sc->arge_pllcfg.pll_10; 1299234919Sadrian else if (if_speed == 100 && sc->arge_pllcfg.pll_100 != 0) 1300234919Sadrian pll = sc->arge_pllcfg.pll_100; 1301234919Sadrian else if (if_speed == 1000 && sc->arge_pllcfg.pll_1000 != 0) 1302234919Sadrian pll = sc->arge_pllcfg.pll_1000; 1303234919Sadrian ARGEDEBUG(sc, ARGE_DBG_PLL, "%s: final pll=0x%x\n", __func__, pll); 1304234919Sadrian 1305234907Sadrian /* XXX ensure pll != 0 */ 1306234907Sadrian ar71xx_device_set_pll_ge(sc->arge_mac_unit, if_speed, pll); 1307234907Sadrian 1308234907Sadrian /* set MII registers */ 1309234992Sadrian /* 1310234992Sadrian * This was introduced to match what the Linux ag71xx ethernet 1311234992Sadrian * driver does. For the AR71xx case, it does set the port 1312234992Sadrian * MII speed. However, if this is done, non-gigabit speeds 1313234992Sadrian * are not at all reliable when speaking via RGMII through 1314234992Sadrian * 'bridge' PHY port that's pretending to be a local PHY. 1315234992Sadrian * 1316234992Sadrian * Until that gets root caused, and until an AR71xx + normal 1317234992Sadrian * PHY board is tested, leave this disabled. 1318234992Sadrian */ 1319234992Sadrian#if 0 1320234907Sadrian ar71xx_device_set_mii_speed(sc->arge_mac_unit, if_speed); 1321234992Sadrian#endif 1322188808Sgonzo} 1323188808Sgonzo 1324199234Sgonzo 1325188808Sgonzostatic void 1326188808Sgonzoarge_reset_dma(struct arge_softc *sc) 1327188808Sgonzo{ 1328279791Sadrian 1329279791Sadrian ARGEDEBUG(sc, ARGE_DBG_RESET, "%s: called\n", __func__); 1330279791Sadrian 1331188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, 0); 1332188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, 0); 1333188808Sgonzo 1334188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_DESC, 0); 1335188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_DESC, 0); 1336188808Sgonzo 1337188808Sgonzo /* Clear all possible RX interrupts */ 1338192569Sdwhite while(ARGE_READ(sc, AR71XX_DMA_RX_STATUS) & DMA_RX_STATUS_PKT_RECVD) 1339188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_PKT_RECVD); 1340188808Sgonzo 1341232627Sray /* 1342188808Sgonzo * Clear all possible TX interrupts 1343188808Sgonzo */ 1344192569Sdwhite while(ARGE_READ(sc, AR71XX_DMA_TX_STATUS) & DMA_TX_STATUS_PKT_SENT) 1345188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_PKT_SENT); 1346188808Sgonzo 1347232627Sray /* 1348188808Sgonzo * Now Rx/Tx errors 1349188808Sgonzo */ 1350232627Sray ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, 1351188808Sgonzo DMA_RX_STATUS_BUS_ERROR | DMA_RX_STATUS_OVERFLOW); 1352232627Sray ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, 1353188808Sgonzo DMA_TX_STATUS_BUS_ERROR | DMA_TX_STATUS_UNDERRUN); 1354232912Sadrian 1355232912Sadrian /* 1356232912Sadrian * Force a DDR flush so any pending data is properly 1357232912Sadrian * flushed to RAM before underlying buffers are freed. 1358232912Sadrian */ 1359232912Sadrian arge_flush_ddr(sc); 1360188808Sgonzo} 1361188808Sgonzo 1362188808Sgonzostatic void 1363188808Sgonzoarge_init(void *xsc) 1364188808Sgonzo{ 1365188808Sgonzo struct arge_softc *sc = xsc; 1366188808Sgonzo 1367188808Sgonzo ARGE_LOCK(sc); 1368188808Sgonzo arge_init_locked(sc); 1369188808Sgonzo ARGE_UNLOCK(sc); 1370188808Sgonzo} 1371188808Sgonzo 1372188808Sgonzostatic void 1373188808Sgonzoarge_init_locked(struct arge_softc *sc) 1374188808Sgonzo{ 1375188808Sgonzo struct ifnet *ifp = sc->arge_ifp; 1376188808Sgonzo struct mii_data *mii; 1377188808Sgonzo 1378188808Sgonzo ARGE_LOCK_ASSERT(sc); 1379188808Sgonzo 1380255021Sloos if ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) 1381255021Sloos return; 1382188808Sgonzo 1383188808Sgonzo /* Init circular RX list. */ 1384188808Sgonzo if (arge_rx_ring_init(sc) != 0) { 1385188808Sgonzo device_printf(sc->arge_dev, 1386188808Sgonzo "initialization failed: no memory for rx buffers\n"); 1387188808Sgonzo arge_stop(sc); 1388188808Sgonzo return; 1389188808Sgonzo } 1390188808Sgonzo 1391188808Sgonzo /* Init tx descriptors. */ 1392188808Sgonzo arge_tx_ring_init(sc); 1393188808Sgonzo 1394188808Sgonzo arge_reset_dma(sc); 1395188808Sgonzo 1396199234Sgonzo if (sc->arge_miibus) { 1397199234Sgonzo mii = device_get_softc(sc->arge_miibus); 1398199234Sgonzo mii_mediachg(mii); 1399199234Sgonzo } 1400199234Sgonzo else { 1401199234Sgonzo /* 1402199234Sgonzo * Sun always shines over multiPHY interface 1403199234Sgonzo */ 1404199234Sgonzo sc->arge_link_status = 1; 1405199234Sgonzo } 1406199234Sgonzo 1407188808Sgonzo ifp->if_drv_flags |= IFF_DRV_RUNNING; 1408188808Sgonzo ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1409188808Sgonzo 1410232914Sadrian if (sc->arge_miibus) { 1411199234Sgonzo callout_reset(&sc->arge_stat_callout, hz, arge_tick, sc); 1412232914Sadrian arge_update_link_locked(sc); 1413232914Sadrian } 1414192783Sgonzo 1415188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_DESC, ARGE_TX_RING_ADDR(sc, 0)); 1416188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_DESC, ARGE_RX_RING_ADDR(sc, 0)); 1417188808Sgonzo 1418188808Sgonzo /* Start listening */ 1419188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, DMA_RX_CONTROL_EN); 1420188808Sgonzo 1421188808Sgonzo /* Enable interrupts */ 1422188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL); 1423188808Sgonzo} 1424188808Sgonzo 1425188808Sgonzo/* 1426209807Sadrian * Return whether the mbuf chain is correctly aligned 1427209807Sadrian * for the arge TX engine. 1428209807Sadrian * 1429289476Sadrian * All the MACs have a length requirement: any non-final 1430289476Sadrian * fragment (ie, descriptor with MORE bit set) needs to have 1431289476Sadrian * a length divisible by 4. 1432256649Sadrian * 1433289476Sadrian * The AR71xx, AR913x require the start address also be 1434289476Sadrian * DWORD aligned. The later MACs don't. 1435209807Sadrian */ 1436209807Sadrianstatic int 1437289476Sadrianarge_mbuf_chain_is_tx_aligned(struct arge_softc *sc, struct mbuf *m0) 1438209807Sadrian{ 1439209807Sadrian struct mbuf *m; 1440209807Sadrian 1441209807Sadrian for (m = m0; m != NULL; m = m->m_next) { 1442289476Sadrian /* 1443289476Sadrian * Only do this for chips that require it. 1444289476Sadrian */ 1445289476Sadrian if ((sc->arge_hw_flags & ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE) && 1446289476Sadrian (mtod(m, intptr_t) & 3) != 0) { 1447289476Sadrian sc->stats.tx_pkts_unaligned_start++; 1448209807Sadrian return 0; 1449289476Sadrian } 1450289476Sadrian 1451289476Sadrian /* 1452289476Sadrian * All chips have this requirement for length. 1453289476Sadrian */ 1454289476Sadrian if ((m->m_next != NULL) && ((m->m_len & 0x03) != 0)) { 1455289476Sadrian sc->stats.tx_pkts_unaligned_len++; 1456209807Sadrian return 0; 1457289476Sadrian } 1458209807Sadrian } 1459209807Sadrian return 1; 1460209807Sadrian} 1461209807Sadrian 1462209807Sadrian/* 1463188808Sgonzo * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 1464188808Sgonzo * pointers to the fragment pointers. 1465188808Sgonzo */ 1466188808Sgonzostatic int 1467188808Sgonzoarge_encap(struct arge_softc *sc, struct mbuf **m_head) 1468188808Sgonzo{ 1469188808Sgonzo struct arge_txdesc *txd; 1470188808Sgonzo struct arge_desc *desc, *prev_desc; 1471188808Sgonzo bus_dma_segment_t txsegs[ARGE_MAXFRAGS]; 1472192569Sdwhite int error, i, nsegs, prod, prev_prod; 1473192783Sgonzo struct mbuf *m; 1474188808Sgonzo 1475188808Sgonzo ARGE_LOCK_ASSERT(sc); 1476188808Sgonzo 1477192783Sgonzo /* 1478289476Sadrian * Fix mbuf chain based on hardware alignment constraints. 1479192783Sgonzo */ 1480192783Sgonzo m = *m_head; 1481289476Sadrian if (! arge_mbuf_chain_is_tx_aligned(sc, m)) { 1482209809Sadrian sc->stats.tx_pkts_unaligned++; 1483243882Sglebius m = m_defrag(*m_head, M_NOWAIT); 1484192783Sgonzo if (m == NULL) { 1485192783Sgonzo *m_head = NULL; 1486192783Sgonzo return (ENOBUFS); 1487192783Sgonzo } 1488192783Sgonzo *m_head = m; 1489209809Sadrian } else 1490209809Sadrian sc->stats.tx_pkts_aligned++; 1491192783Sgonzo 1492188808Sgonzo prod = sc->arge_cdata.arge_tx_prod; 1493188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[prod]; 1494232627Sray error = bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_tx_tag, 1495188808Sgonzo txd->tx_dmamap, *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1496188808Sgonzo 1497188808Sgonzo if (error == EFBIG) { 1498188808Sgonzo panic("EFBIG"); 1499188808Sgonzo } else if (error != 0) 1500188808Sgonzo return (error); 1501188808Sgonzo 1502188808Sgonzo if (nsegs == 0) { 1503188808Sgonzo m_freem(*m_head); 1504188808Sgonzo *m_head = NULL; 1505188808Sgonzo return (EIO); 1506188808Sgonzo } 1507188808Sgonzo 1508188808Sgonzo /* Check number of available descriptors. */ 1509290211Sadrian if (sc->arge_cdata.arge_tx_cnt + nsegs >= (ARGE_TX_RING_COUNT - 2)) { 1510188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap); 1511289476Sadrian sc->stats.tx_pkts_nosegs++; 1512188808Sgonzo return (ENOBUFS); 1513188808Sgonzo } 1514188808Sgonzo 1515188808Sgonzo txd->tx_m = *m_head; 1516188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap, 1517188808Sgonzo BUS_DMASYNC_PREWRITE); 1518188808Sgonzo 1519232627Sray /* 1520188808Sgonzo * Make a list of descriptors for this packet. DMA controller will 1521188808Sgonzo * walk through it while arge_link is not zero. 1522290215Sadrian * 1523290215Sadrian * Since we're in a endless circular buffer, ensure that 1524290215Sadrian * the first descriptor in a multi-descriptor ring is always 1525290215Sadrian * set to EMPTY, then un-do it when we're done populating. 1526188808Sgonzo */ 1527188808Sgonzo prev_prod = prod; 1528188808Sgonzo desc = prev_desc = NULL; 1529188808Sgonzo for (i = 0; i < nsegs; i++) { 1530290215Sadrian uint32_t tmp; 1531290215Sadrian 1532188808Sgonzo desc = &sc->arge_rdata.arge_tx_ring[prod]; 1533188808Sgonzo 1534290215Sadrian /* 1535290215Sadrian * Set DESC_EMPTY so the hardware (hopefully) stops at this 1536290215Sadrian * point. We don't want it to start transmitting descriptors 1537290215Sadrian * before we've finished fleshing this out. 1538290215Sadrian */ 1539290215Sadrian tmp = ARGE_DMASIZE(txsegs[i].ds_len); 1540290215Sadrian if (i == 0) 1541290215Sadrian tmp |= ARGE_DESC_EMPTY; 1542290215Sadrian desc->packet_ctrl = tmp; 1543290215Sadrian 1544289476Sadrian /* XXX Note: only relevant for older MACs; but check length! */ 1545289476Sadrian if ((sc->arge_hw_flags & ARGE_HW_FLG_TX_DESC_ALIGN_4BYTE) && 1546289476Sadrian (txsegs[i].ds_addr & 3)) 1547192783Sgonzo panic("TX packet address unaligned\n"); 1548192783Sgonzo 1549188808Sgonzo desc->packet_addr = txsegs[i].ds_addr; 1550232627Sray 1551188808Sgonzo /* link with previous descriptor */ 1552188808Sgonzo if (prev_desc) 1553188808Sgonzo prev_desc->packet_ctrl |= ARGE_DESC_MORE; 1554188808Sgonzo 1555188808Sgonzo sc->arge_cdata.arge_tx_cnt++; 1556188808Sgonzo prev_desc = desc; 1557188808Sgonzo ARGE_INC(prod, ARGE_TX_RING_COUNT); 1558188808Sgonzo } 1559188808Sgonzo 1560188808Sgonzo /* Update producer index. */ 1561188808Sgonzo sc->arge_cdata.arge_tx_prod = prod; 1562188808Sgonzo 1563290215Sadrian /* 1564290215Sadrian * The descriptors are updated, so enable the first one. 1565290215Sadrian */ 1566290215Sadrian desc = &sc->arge_rdata.arge_tx_ring[prev_prod]; 1567290215Sadrian desc->packet_ctrl &= ~ ARGE_DESC_EMPTY; 1568290215Sadrian 1569188808Sgonzo /* Sync descriptors. */ 1570188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 1571188808Sgonzo sc->arge_cdata.arge_tx_ring_map, 1572188808Sgonzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1573188808Sgonzo 1574290213Sadrian /* Flush writes */ 1575290213Sadrian ARGE_BARRIER_WRITE(sc); 1576290213Sadrian 1577188808Sgonzo /* Start transmitting */ 1578232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: setting DMA_TX_CONTROL_EN\n", 1579232628Sray __func__); 1580188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, DMA_TX_CONTROL_EN); 1581188808Sgonzo return (0); 1582188808Sgonzo} 1583188808Sgonzo 1584188808Sgonzostatic void 1585188808Sgonzoarge_start(struct ifnet *ifp) 1586188808Sgonzo{ 1587188808Sgonzo struct arge_softc *sc; 1588188808Sgonzo 1589188808Sgonzo sc = ifp->if_softc; 1590188808Sgonzo 1591188808Sgonzo ARGE_LOCK(sc); 1592188808Sgonzo arge_start_locked(ifp); 1593188808Sgonzo ARGE_UNLOCK(sc); 1594188808Sgonzo} 1595188808Sgonzo 1596188808Sgonzostatic void 1597188808Sgonzoarge_start_locked(struct ifnet *ifp) 1598188808Sgonzo{ 1599188808Sgonzo struct arge_softc *sc; 1600188808Sgonzo struct mbuf *m_head; 1601220356Sadrian int enq = 0; 1602188808Sgonzo 1603188808Sgonzo sc = ifp->if_softc; 1604188808Sgonzo 1605188808Sgonzo ARGE_LOCK_ASSERT(sc); 1606188808Sgonzo 1607220356Sadrian ARGEDEBUG(sc, ARGE_DBG_TX, "%s: beginning\n", __func__); 1608220356Sadrian 1609188808Sgonzo if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1610188808Sgonzo IFF_DRV_RUNNING || sc->arge_link_status == 0 ) 1611188808Sgonzo return; 1612188808Sgonzo 1613220356Sadrian /* 1614220356Sadrian * Before we go any further, check whether we're already full. 1615220356Sadrian * The below check errors out immediately if the ring is full 1616220356Sadrian * and never gets a chance to set this flag. Although it's 1617220356Sadrian * likely never needed, this at least avoids an unexpected 1618220356Sadrian * situation. 1619220356Sadrian */ 1620220356Sadrian if (sc->arge_cdata.arge_tx_cnt >= ARGE_TX_RING_COUNT - 2) { 1621220356Sadrian ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1622232628Sray ARGEDEBUG(sc, ARGE_DBG_ERR, 1623232628Sray "%s: tx_cnt %d >= max %d; setting IFF_DRV_OACTIVE\n", 1624232628Sray __func__, sc->arge_cdata.arge_tx_cnt, 1625232628Sray ARGE_TX_RING_COUNT - 2); 1626220356Sadrian return; 1627220356Sadrian } 1628220356Sadrian 1629188808Sgonzo arge_flush_ddr(sc); 1630188808Sgonzo 1631188808Sgonzo for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && 1632188808Sgonzo sc->arge_cdata.arge_tx_cnt < ARGE_TX_RING_COUNT - 2; ) { 1633188808Sgonzo IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1634188808Sgonzo if (m_head == NULL) 1635188808Sgonzo break; 1636188808Sgonzo 1637188808Sgonzo 1638188808Sgonzo /* 1639188808Sgonzo * Pack the data into the transmit ring. 1640188808Sgonzo */ 1641188808Sgonzo if (arge_encap(sc, &m_head)) { 1642188808Sgonzo if (m_head == NULL) 1643188808Sgonzo break; 1644188808Sgonzo IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1645188808Sgonzo ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1646188808Sgonzo break; 1647188808Sgonzo } 1648188808Sgonzo 1649188808Sgonzo enq++; 1650188808Sgonzo /* 1651188808Sgonzo * If there's a BPF listener, bounce a copy of this frame 1652188808Sgonzo * to him. 1653188808Sgonzo */ 1654188808Sgonzo ETHER_BPF_MTAP(ifp, m_head); 1655188808Sgonzo } 1656232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: finished; queued %d packets\n", 1657232628Sray __func__, enq); 1658188808Sgonzo} 1659188808Sgonzo 1660188808Sgonzostatic void 1661188808Sgonzoarge_stop(struct arge_softc *sc) 1662188808Sgonzo{ 1663188808Sgonzo struct ifnet *ifp; 1664188808Sgonzo 1665188808Sgonzo ARGE_LOCK_ASSERT(sc); 1666188808Sgonzo 1667188808Sgonzo ifp = sc->arge_ifp; 1668188808Sgonzo ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1669199234Sgonzo if (sc->arge_miibus) 1670199234Sgonzo callout_stop(&sc->arge_stat_callout); 1671188808Sgonzo 1672188808Sgonzo /* mask out interrupts */ 1673188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, 0); 1674188808Sgonzo 1675188808Sgonzo arge_reset_dma(sc); 1676232912Sadrian 1677232912Sadrian /* Flush FIFO and free any existing mbufs */ 1678232912Sadrian arge_flush_ddr(sc); 1679232912Sadrian arge_rx_ring_free(sc); 1680255300Sloos arge_tx_ring_free(sc); 1681188808Sgonzo} 1682188808Sgonzo 1683188808Sgonzo 1684188808Sgonzostatic int 1685188808Sgonzoarge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 1686188808Sgonzo{ 1687188808Sgonzo struct arge_softc *sc = ifp->if_softc; 1688188808Sgonzo struct ifreq *ifr = (struct ifreq *) data; 1689188808Sgonzo struct mii_data *mii; 1690188808Sgonzo int error; 1691192783Sgonzo#ifdef DEVICE_POLLING 1692192783Sgonzo int mask; 1693192783Sgonzo#endif 1694188808Sgonzo 1695188808Sgonzo switch (command) { 1696188808Sgonzo case SIOCSIFFLAGS: 1697198932Sgonzo ARGE_LOCK(sc); 1698198932Sgonzo if ((ifp->if_flags & IFF_UP) != 0) { 1699198932Sgonzo if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1700198932Sgonzo if (((ifp->if_flags ^ sc->arge_if_flags) 1701198939Sgonzo & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 1702198939Sgonzo /* XXX: handle promisc & multi flags */ 1703198939Sgonzo } 1704232627Sray 1705198932Sgonzo } else { 1706198932Sgonzo if (!sc->arge_detach) 1707198932Sgonzo arge_init_locked(sc); 1708198932Sgonzo } 1709198932Sgonzo } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1710198932Sgonzo ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1711198932Sgonzo arge_stop(sc); 1712198932Sgonzo } 1713198932Sgonzo sc->arge_if_flags = ifp->if_flags; 1714198932Sgonzo ARGE_UNLOCK(sc); 1715188808Sgonzo error = 0; 1716188808Sgonzo break; 1717188808Sgonzo case SIOCADDMULTI: 1718188808Sgonzo case SIOCDELMULTI: 1719198932Sgonzo /* XXX: implement SIOCDELMULTI */ 1720188808Sgonzo error = 0; 1721188808Sgonzo break; 1722188808Sgonzo case SIOCGIFMEDIA: 1723188808Sgonzo case SIOCSIFMEDIA: 1724199234Sgonzo if (sc->arge_miibus) { 1725199234Sgonzo mii = device_get_softc(sc->arge_miibus); 1726232628Sray error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, 1727232628Sray command); 1728199234Sgonzo } 1729232627Sray else 1730232628Sray error = ifmedia_ioctl(ifp, ifr, &sc->arge_ifmedia, 1731232628Sray command); 1732188808Sgonzo break; 1733198933Sgonzo case SIOCSIFCAP: 1734198932Sgonzo /* XXX: Check other capabilities */ 1735192783Sgonzo#ifdef DEVICE_POLLING 1736198933Sgonzo mask = ifp->if_capenable ^ ifr->ifr_reqcap; 1737198933Sgonzo if (mask & IFCAP_POLLING) { 1738198933Sgonzo if (ifr->ifr_reqcap & IFCAP_POLLING) { 1739192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, 0); 1740198933Sgonzo error = ether_poll_register(arge_poll, ifp); 1741198933Sgonzo if (error) 1742198933Sgonzo return error; 1743198933Sgonzo ARGE_LOCK(sc); 1744198933Sgonzo ifp->if_capenable |= IFCAP_POLLING; 1745198933Sgonzo ARGE_UNLOCK(sc); 1746198933Sgonzo } else { 1747192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL); 1748198933Sgonzo error = ether_poll_deregister(ifp); 1749198933Sgonzo ARGE_LOCK(sc); 1750198933Sgonzo ifp->if_capenable &= ~IFCAP_POLLING; 1751198933Sgonzo ARGE_UNLOCK(sc); 1752198933Sgonzo } 1753198933Sgonzo } 1754198932Sgonzo error = 0; 1755198933Sgonzo break; 1756192783Sgonzo#endif 1757188808Sgonzo default: 1758188808Sgonzo error = ether_ioctl(ifp, command, data); 1759188808Sgonzo break; 1760188808Sgonzo } 1761188808Sgonzo 1762188808Sgonzo return (error); 1763188808Sgonzo} 1764188808Sgonzo 1765188808Sgonzo/* 1766188808Sgonzo * Set media options. 1767188808Sgonzo */ 1768188808Sgonzostatic int 1769188808Sgonzoarge_ifmedia_upd(struct ifnet *ifp) 1770188808Sgonzo{ 1771188808Sgonzo struct arge_softc *sc; 1772188808Sgonzo struct mii_data *mii; 1773188808Sgonzo struct mii_softc *miisc; 1774188808Sgonzo int error; 1775188808Sgonzo 1776188808Sgonzo sc = ifp->if_softc; 1777188808Sgonzo ARGE_LOCK(sc); 1778188808Sgonzo mii = device_get_softc(sc->arge_miibus); 1779221407Smarius LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1780221407Smarius PHY_RESET(miisc); 1781188808Sgonzo error = mii_mediachg(mii); 1782188808Sgonzo ARGE_UNLOCK(sc); 1783188808Sgonzo 1784188808Sgonzo return (error); 1785188808Sgonzo} 1786188808Sgonzo 1787188808Sgonzo/* 1788188808Sgonzo * Report current media status. 1789188808Sgonzo */ 1790188808Sgonzostatic void 1791188808Sgonzoarge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1792188808Sgonzo{ 1793188808Sgonzo struct arge_softc *sc = ifp->if_softc; 1794188808Sgonzo struct mii_data *mii; 1795188808Sgonzo 1796188808Sgonzo mii = device_get_softc(sc->arge_miibus); 1797188808Sgonzo ARGE_LOCK(sc); 1798188808Sgonzo mii_pollstat(mii); 1799188808Sgonzo ifmr->ifm_active = mii->mii_media_active; 1800188808Sgonzo ifmr->ifm_status = mii->mii_media_status; 1801226478Syongari ARGE_UNLOCK(sc); 1802188808Sgonzo} 1803188808Sgonzo 1804188808Sgonzostruct arge_dmamap_arg { 1805188808Sgonzo bus_addr_t arge_busaddr; 1806188808Sgonzo}; 1807188808Sgonzo 1808188808Sgonzostatic void 1809188808Sgonzoarge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1810188808Sgonzo{ 1811188808Sgonzo struct arge_dmamap_arg *ctx; 1812188808Sgonzo 1813188808Sgonzo if (error != 0) 1814188808Sgonzo return; 1815188808Sgonzo ctx = arg; 1816188808Sgonzo ctx->arge_busaddr = segs[0].ds_addr; 1817188808Sgonzo} 1818188808Sgonzo 1819188808Sgonzostatic int 1820188808Sgonzoarge_dma_alloc(struct arge_softc *sc) 1821188808Sgonzo{ 1822188808Sgonzo struct arge_dmamap_arg ctx; 1823188808Sgonzo struct arge_txdesc *txd; 1824188808Sgonzo struct arge_rxdesc *rxd; 1825188808Sgonzo int error, i; 1826289476Sadrian int arge_tx_align, arge_rx_align; 1827188808Sgonzo 1828289476Sadrian /* Assume 4 byte alignment by default */ 1829289476Sadrian arge_tx_align = 4; 1830289476Sadrian arge_rx_align = 4; 1831289476Sadrian 1832289476Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_TX_DESC_ALIGN_1BYTE) 1833289476Sadrian arge_tx_align = 1; 1834289476Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE) 1835289476Sadrian arge_rx_align = 1; 1836289476Sadrian 1837188808Sgonzo /* Create parent DMA tag. */ 1838188808Sgonzo error = bus_dma_tag_create( 1839188808Sgonzo bus_get_dma_tag(sc->arge_dev), /* parent */ 1840188808Sgonzo 1, 0, /* alignment, boundary */ 1841188808Sgonzo BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1842188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1843188808Sgonzo NULL, NULL, /* filter, filterarg */ 1844188808Sgonzo BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1845188808Sgonzo 0, /* nsegments */ 1846188808Sgonzo BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1847188808Sgonzo 0, /* flags */ 1848188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1849188808Sgonzo &sc->arge_cdata.arge_parent_tag); 1850188808Sgonzo if (error != 0) { 1851232628Sray device_printf(sc->arge_dev, 1852232628Sray "failed to create parent DMA tag\n"); 1853188808Sgonzo goto fail; 1854188808Sgonzo } 1855188808Sgonzo /* Create tag for Tx ring. */ 1856188808Sgonzo error = bus_dma_tag_create( 1857188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1858188808Sgonzo ARGE_RING_ALIGN, 0, /* alignment, boundary */ 1859188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1860188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1861188808Sgonzo NULL, NULL, /* filter, filterarg */ 1862188808Sgonzo ARGE_TX_DMA_SIZE, /* maxsize */ 1863188808Sgonzo 1, /* nsegments */ 1864188808Sgonzo ARGE_TX_DMA_SIZE, /* maxsegsize */ 1865188808Sgonzo 0, /* flags */ 1866188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1867188808Sgonzo &sc->arge_cdata.arge_tx_ring_tag); 1868188808Sgonzo if (error != 0) { 1869232628Sray device_printf(sc->arge_dev, 1870232628Sray "failed to create Tx ring DMA tag\n"); 1871188808Sgonzo goto fail; 1872188808Sgonzo } 1873188808Sgonzo 1874188808Sgonzo /* Create tag for Rx ring. */ 1875188808Sgonzo error = bus_dma_tag_create( 1876188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1877188808Sgonzo ARGE_RING_ALIGN, 0, /* alignment, boundary */ 1878188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1879188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1880188808Sgonzo NULL, NULL, /* filter, filterarg */ 1881188808Sgonzo ARGE_RX_DMA_SIZE, /* maxsize */ 1882188808Sgonzo 1, /* nsegments */ 1883188808Sgonzo ARGE_RX_DMA_SIZE, /* maxsegsize */ 1884188808Sgonzo 0, /* flags */ 1885188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1886188808Sgonzo &sc->arge_cdata.arge_rx_ring_tag); 1887188808Sgonzo if (error != 0) { 1888232628Sray device_printf(sc->arge_dev, 1889232628Sray "failed to create Rx ring DMA tag\n"); 1890188808Sgonzo goto fail; 1891188808Sgonzo } 1892188808Sgonzo 1893188808Sgonzo /* Create tag for Tx buffers. */ 1894188808Sgonzo error = bus_dma_tag_create( 1895188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1896289476Sadrian arge_tx_align, 0, /* alignment, boundary */ 1897188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1898188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1899188808Sgonzo NULL, NULL, /* filter, filterarg */ 1900188808Sgonzo MCLBYTES * ARGE_MAXFRAGS, /* maxsize */ 1901188808Sgonzo ARGE_MAXFRAGS, /* nsegments */ 1902188808Sgonzo MCLBYTES, /* maxsegsize */ 1903188808Sgonzo 0, /* flags */ 1904188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1905188808Sgonzo &sc->arge_cdata.arge_tx_tag); 1906188808Sgonzo if (error != 0) { 1907188808Sgonzo device_printf(sc->arge_dev, "failed to create Tx DMA tag\n"); 1908188808Sgonzo goto fail; 1909188808Sgonzo } 1910188808Sgonzo 1911188808Sgonzo /* Create tag for Rx buffers. */ 1912188808Sgonzo error = bus_dma_tag_create( 1913188808Sgonzo sc->arge_cdata.arge_parent_tag, /* parent */ 1914289476Sadrian arge_rx_align, 0, /* alignment, boundary */ 1915188808Sgonzo BUS_SPACE_MAXADDR, /* lowaddr */ 1916188808Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 1917188808Sgonzo NULL, NULL, /* filter, filterarg */ 1918188808Sgonzo MCLBYTES, /* maxsize */ 1919192821Sgonzo ARGE_MAXFRAGS, /* nsegments */ 1920188808Sgonzo MCLBYTES, /* maxsegsize */ 1921188808Sgonzo 0, /* flags */ 1922188808Sgonzo NULL, NULL, /* lockfunc, lockarg */ 1923188808Sgonzo &sc->arge_cdata.arge_rx_tag); 1924188808Sgonzo if (error != 0) { 1925188808Sgonzo device_printf(sc->arge_dev, "failed to create Rx DMA tag\n"); 1926188808Sgonzo goto fail; 1927188808Sgonzo } 1928188808Sgonzo 1929188808Sgonzo /* Allocate DMA'able memory and load the DMA map for Tx ring. */ 1930188808Sgonzo error = bus_dmamem_alloc(sc->arge_cdata.arge_tx_ring_tag, 1931188808Sgonzo (void **)&sc->arge_rdata.arge_tx_ring, BUS_DMA_WAITOK | 1932232628Sray BUS_DMA_COHERENT | BUS_DMA_ZERO, 1933232628Sray &sc->arge_cdata.arge_tx_ring_map); 1934188808Sgonzo if (error != 0) { 1935188808Sgonzo device_printf(sc->arge_dev, 1936188808Sgonzo "failed to allocate DMA'able memory for Tx ring\n"); 1937188808Sgonzo goto fail; 1938188808Sgonzo } 1939188808Sgonzo 1940188808Sgonzo ctx.arge_busaddr = 0; 1941188808Sgonzo error = bus_dmamap_load(sc->arge_cdata.arge_tx_ring_tag, 1942188808Sgonzo sc->arge_cdata.arge_tx_ring_map, sc->arge_rdata.arge_tx_ring, 1943188808Sgonzo ARGE_TX_DMA_SIZE, arge_dmamap_cb, &ctx, 0); 1944188808Sgonzo if (error != 0 || ctx.arge_busaddr == 0) { 1945188808Sgonzo device_printf(sc->arge_dev, 1946188808Sgonzo "failed to load DMA'able memory for Tx ring\n"); 1947188808Sgonzo goto fail; 1948188808Sgonzo } 1949188808Sgonzo sc->arge_rdata.arge_tx_ring_paddr = ctx.arge_busaddr; 1950188808Sgonzo 1951188808Sgonzo /* Allocate DMA'able memory and load the DMA map for Rx ring. */ 1952188808Sgonzo error = bus_dmamem_alloc(sc->arge_cdata.arge_rx_ring_tag, 1953188808Sgonzo (void **)&sc->arge_rdata.arge_rx_ring, BUS_DMA_WAITOK | 1954232628Sray BUS_DMA_COHERENT | BUS_DMA_ZERO, 1955232628Sray &sc->arge_cdata.arge_rx_ring_map); 1956188808Sgonzo if (error != 0) { 1957188808Sgonzo device_printf(sc->arge_dev, 1958188808Sgonzo "failed to allocate DMA'able memory for Rx ring\n"); 1959188808Sgonzo goto fail; 1960188808Sgonzo } 1961188808Sgonzo 1962188808Sgonzo ctx.arge_busaddr = 0; 1963188808Sgonzo error = bus_dmamap_load(sc->arge_cdata.arge_rx_ring_tag, 1964188808Sgonzo sc->arge_cdata.arge_rx_ring_map, sc->arge_rdata.arge_rx_ring, 1965188808Sgonzo ARGE_RX_DMA_SIZE, arge_dmamap_cb, &ctx, 0); 1966188808Sgonzo if (error != 0 || ctx.arge_busaddr == 0) { 1967188808Sgonzo device_printf(sc->arge_dev, 1968188808Sgonzo "failed to load DMA'able memory for Rx ring\n"); 1969188808Sgonzo goto fail; 1970188808Sgonzo } 1971188808Sgonzo sc->arge_rdata.arge_rx_ring_paddr = ctx.arge_busaddr; 1972188808Sgonzo 1973188808Sgonzo /* Create DMA maps for Tx buffers. */ 1974188808Sgonzo for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 1975188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[i]; 1976188808Sgonzo txd->tx_m = NULL; 1977188808Sgonzo txd->tx_dmamap = NULL; 1978188808Sgonzo error = bus_dmamap_create(sc->arge_cdata.arge_tx_tag, 0, 1979188808Sgonzo &txd->tx_dmamap); 1980188808Sgonzo if (error != 0) { 1981188808Sgonzo device_printf(sc->arge_dev, 1982188808Sgonzo "failed to create Tx dmamap\n"); 1983188808Sgonzo goto fail; 1984188808Sgonzo } 1985188808Sgonzo } 1986188808Sgonzo /* Create DMA maps for Rx buffers. */ 1987188808Sgonzo if ((error = bus_dmamap_create(sc->arge_cdata.arge_rx_tag, 0, 1988188808Sgonzo &sc->arge_cdata.arge_rx_sparemap)) != 0) { 1989188808Sgonzo device_printf(sc->arge_dev, 1990188808Sgonzo "failed to create spare Rx dmamap\n"); 1991188808Sgonzo goto fail; 1992188808Sgonzo } 1993188808Sgonzo for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 1994188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[i]; 1995188808Sgonzo rxd->rx_m = NULL; 1996188808Sgonzo rxd->rx_dmamap = NULL; 1997188808Sgonzo error = bus_dmamap_create(sc->arge_cdata.arge_rx_tag, 0, 1998188808Sgonzo &rxd->rx_dmamap); 1999188808Sgonzo if (error != 0) { 2000188808Sgonzo device_printf(sc->arge_dev, 2001188808Sgonzo "failed to create Rx dmamap\n"); 2002188808Sgonzo goto fail; 2003188808Sgonzo } 2004188808Sgonzo } 2005188808Sgonzo 2006188808Sgonzofail: 2007188808Sgonzo return (error); 2008188808Sgonzo} 2009188808Sgonzo 2010188808Sgonzostatic void 2011188808Sgonzoarge_dma_free(struct arge_softc *sc) 2012188808Sgonzo{ 2013188808Sgonzo struct arge_txdesc *txd; 2014188808Sgonzo struct arge_rxdesc *rxd; 2015188808Sgonzo int i; 2016188808Sgonzo 2017188808Sgonzo /* Tx ring. */ 2018188808Sgonzo if (sc->arge_cdata.arge_tx_ring_tag) { 2019267363Sjhb if (sc->arge_rdata.arge_tx_ring_paddr) 2020188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_tx_ring_tag, 2021188808Sgonzo sc->arge_cdata.arge_tx_ring_map); 2022267363Sjhb if (sc->arge_rdata.arge_tx_ring) 2023188808Sgonzo bus_dmamem_free(sc->arge_cdata.arge_tx_ring_tag, 2024188808Sgonzo sc->arge_rdata.arge_tx_ring, 2025188808Sgonzo sc->arge_cdata.arge_tx_ring_map); 2026188808Sgonzo sc->arge_rdata.arge_tx_ring = NULL; 2027267363Sjhb sc->arge_rdata.arge_tx_ring_paddr = 0; 2028188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_tx_ring_tag); 2029188808Sgonzo sc->arge_cdata.arge_tx_ring_tag = NULL; 2030188808Sgonzo } 2031188808Sgonzo /* Rx ring. */ 2032188808Sgonzo if (sc->arge_cdata.arge_rx_ring_tag) { 2033267363Sjhb if (sc->arge_rdata.arge_rx_ring_paddr) 2034188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_rx_ring_tag, 2035188808Sgonzo sc->arge_cdata.arge_rx_ring_map); 2036267363Sjhb if (sc->arge_rdata.arge_rx_ring) 2037188808Sgonzo bus_dmamem_free(sc->arge_cdata.arge_rx_ring_tag, 2038188808Sgonzo sc->arge_rdata.arge_rx_ring, 2039188808Sgonzo sc->arge_cdata.arge_rx_ring_map); 2040188808Sgonzo sc->arge_rdata.arge_rx_ring = NULL; 2041267363Sjhb sc->arge_rdata.arge_rx_ring_paddr = 0; 2042188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_rx_ring_tag); 2043188808Sgonzo sc->arge_cdata.arge_rx_ring_tag = NULL; 2044188808Sgonzo } 2045188808Sgonzo /* Tx buffers. */ 2046188808Sgonzo if (sc->arge_cdata.arge_tx_tag) { 2047188808Sgonzo for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2048188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[i]; 2049188808Sgonzo if (txd->tx_dmamap) { 2050188808Sgonzo bus_dmamap_destroy(sc->arge_cdata.arge_tx_tag, 2051188808Sgonzo txd->tx_dmamap); 2052188808Sgonzo txd->tx_dmamap = NULL; 2053188808Sgonzo } 2054188808Sgonzo } 2055188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_tx_tag); 2056188808Sgonzo sc->arge_cdata.arge_tx_tag = NULL; 2057188808Sgonzo } 2058188808Sgonzo /* Rx buffers. */ 2059188808Sgonzo if (sc->arge_cdata.arge_rx_tag) { 2060188808Sgonzo for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2061188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[i]; 2062188808Sgonzo if (rxd->rx_dmamap) { 2063188808Sgonzo bus_dmamap_destroy(sc->arge_cdata.arge_rx_tag, 2064188808Sgonzo rxd->rx_dmamap); 2065188808Sgonzo rxd->rx_dmamap = NULL; 2066188808Sgonzo } 2067188808Sgonzo } 2068188808Sgonzo if (sc->arge_cdata.arge_rx_sparemap) { 2069188808Sgonzo bus_dmamap_destroy(sc->arge_cdata.arge_rx_tag, 2070188808Sgonzo sc->arge_cdata.arge_rx_sparemap); 2071188808Sgonzo sc->arge_cdata.arge_rx_sparemap = 0; 2072188808Sgonzo } 2073188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_rx_tag); 2074188808Sgonzo sc->arge_cdata.arge_rx_tag = NULL; 2075188808Sgonzo } 2076188808Sgonzo 2077188808Sgonzo if (sc->arge_cdata.arge_parent_tag) { 2078188808Sgonzo bus_dma_tag_destroy(sc->arge_cdata.arge_parent_tag); 2079188808Sgonzo sc->arge_cdata.arge_parent_tag = NULL; 2080188808Sgonzo } 2081188808Sgonzo} 2082188808Sgonzo 2083188808Sgonzo/* 2084188808Sgonzo * Initialize the transmit descriptors. 2085188808Sgonzo */ 2086188808Sgonzostatic int 2087188808Sgonzoarge_tx_ring_init(struct arge_softc *sc) 2088188808Sgonzo{ 2089188808Sgonzo struct arge_ring_data *rd; 2090188808Sgonzo struct arge_txdesc *txd; 2091188808Sgonzo bus_addr_t addr; 2092188808Sgonzo int i; 2093188808Sgonzo 2094188808Sgonzo sc->arge_cdata.arge_tx_prod = 0; 2095188808Sgonzo sc->arge_cdata.arge_tx_cons = 0; 2096188808Sgonzo sc->arge_cdata.arge_tx_cnt = 0; 2097188808Sgonzo 2098188808Sgonzo rd = &sc->arge_rdata; 2099188808Sgonzo bzero(rd->arge_tx_ring, sizeof(rd->arge_tx_ring)); 2100188808Sgonzo for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2101188808Sgonzo if (i == ARGE_TX_RING_COUNT - 1) 2102188808Sgonzo addr = ARGE_TX_RING_ADDR(sc, 0); 2103188808Sgonzo else 2104188808Sgonzo addr = ARGE_TX_RING_ADDR(sc, i + 1); 2105188808Sgonzo rd->arge_tx_ring[i].packet_ctrl = ARGE_DESC_EMPTY; 2106188808Sgonzo rd->arge_tx_ring[i].next_desc = addr; 2107188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[i]; 2108188808Sgonzo txd->tx_m = NULL; 2109188808Sgonzo } 2110188808Sgonzo 2111188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 2112188808Sgonzo sc->arge_cdata.arge_tx_ring_map, 2113188808Sgonzo BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2114188808Sgonzo 2115188808Sgonzo return (0); 2116188808Sgonzo} 2117188808Sgonzo 2118188808Sgonzo/* 2119255300Sloos * Free the Tx ring, unload any pending dma transaction and free the mbuf. 2120255300Sloos */ 2121255300Sloosstatic void 2122255300Sloosarge_tx_ring_free(struct arge_softc *sc) 2123255300Sloos{ 2124255300Sloos struct arge_txdesc *txd; 2125255300Sloos int i; 2126255300Sloos 2127255300Sloos /* Free the Tx buffers. */ 2128255300Sloos for (i = 0; i < ARGE_TX_RING_COUNT; i++) { 2129255300Sloos txd = &sc->arge_cdata.arge_txdesc[i]; 2130255300Sloos if (txd->tx_dmamap) { 2131255300Sloos bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, 2132255300Sloos txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); 2133255300Sloos bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, 2134255300Sloos txd->tx_dmamap); 2135255300Sloos } 2136255300Sloos if (txd->tx_m) 2137255300Sloos m_freem(txd->tx_m); 2138255300Sloos txd->tx_m = NULL; 2139255300Sloos } 2140255300Sloos} 2141255300Sloos 2142255300Sloos/* 2143188808Sgonzo * Initialize the RX descriptors and allocate mbufs for them. Note that 2144188808Sgonzo * we arrange the descriptors in a closed ring, so that the last descriptor 2145188808Sgonzo * points back to the first. 2146188808Sgonzo */ 2147188808Sgonzostatic int 2148188808Sgonzoarge_rx_ring_init(struct arge_softc *sc) 2149188808Sgonzo{ 2150188808Sgonzo struct arge_ring_data *rd; 2151188808Sgonzo struct arge_rxdesc *rxd; 2152188808Sgonzo bus_addr_t addr; 2153188808Sgonzo int i; 2154188808Sgonzo 2155188808Sgonzo sc->arge_cdata.arge_rx_cons = 0; 2156188808Sgonzo 2157188808Sgonzo rd = &sc->arge_rdata; 2158188808Sgonzo bzero(rd->arge_rx_ring, sizeof(rd->arge_rx_ring)); 2159188808Sgonzo for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2160188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[i]; 2161232912Sadrian if (rxd->rx_m != NULL) { 2162232912Sadrian device_printf(sc->arge_dev, 2163232912Sadrian "%s: ring[%d] rx_m wasn't free?\n", 2164232912Sadrian __func__, 2165232912Sadrian i); 2166232912Sadrian } 2167188808Sgonzo rxd->rx_m = NULL; 2168188808Sgonzo rxd->desc = &rd->arge_rx_ring[i]; 2169188808Sgonzo if (i == ARGE_RX_RING_COUNT - 1) 2170188808Sgonzo addr = ARGE_RX_RING_ADDR(sc, 0); 2171188808Sgonzo else 2172188808Sgonzo addr = ARGE_RX_RING_ADDR(sc, i + 1); 2173188808Sgonzo rd->arge_rx_ring[i].next_desc = addr; 2174192783Sgonzo if (arge_newbuf(sc, i) != 0) { 2175188808Sgonzo return (ENOBUFS); 2176192783Sgonzo } 2177188808Sgonzo } 2178188808Sgonzo 2179188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2180188808Sgonzo sc->arge_cdata.arge_rx_ring_map, 2181195434Sgonzo BUS_DMASYNC_PREWRITE); 2182188808Sgonzo 2183188808Sgonzo return (0); 2184188808Sgonzo} 2185188808Sgonzo 2186188808Sgonzo/* 2187232912Sadrian * Free all the buffers in the RX ring. 2188232912Sadrian * 2189232912Sadrian * TODO: ensure that DMA is disabled and no pending DMA 2190232912Sadrian * is lurking in the FIFO. 2191232912Sadrian */ 2192232912Sadrianstatic void 2193232912Sadrianarge_rx_ring_free(struct arge_softc *sc) 2194232912Sadrian{ 2195232912Sadrian int i; 2196232912Sadrian struct arge_rxdesc *rxd; 2197232912Sadrian 2198232912Sadrian ARGE_LOCK_ASSERT(sc); 2199232912Sadrian 2200232912Sadrian for (i = 0; i < ARGE_RX_RING_COUNT; i++) { 2201232912Sadrian rxd = &sc->arge_cdata.arge_rxdesc[i]; 2202232912Sadrian /* Unmap the mbuf */ 2203232912Sadrian if (rxd->rx_m != NULL) { 2204232912Sadrian bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, 2205232912Sadrian rxd->rx_dmamap); 2206232912Sadrian m_free(rxd->rx_m); 2207232912Sadrian rxd->rx_m = NULL; 2208232912Sadrian } 2209232912Sadrian } 2210232912Sadrian} 2211232912Sadrian 2212232912Sadrian/* 2213188808Sgonzo * Initialize an RX descriptor and attach an MBUF cluster. 2214188808Sgonzo */ 2215188808Sgonzostatic int 2216188808Sgonzoarge_newbuf(struct arge_softc *sc, int idx) 2217188808Sgonzo{ 2218188808Sgonzo struct arge_desc *desc; 2219188808Sgonzo struct arge_rxdesc *rxd; 2220188808Sgonzo struct mbuf *m; 2221188808Sgonzo bus_dma_segment_t segs[1]; 2222188808Sgonzo bus_dmamap_t map; 2223188808Sgonzo int nsegs; 2224188808Sgonzo 2225289671Sadrian /* XXX TODO: should just allocate an explicit 2KiB buffer */ 2226243882Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 2227188808Sgonzo if (m == NULL) 2228188808Sgonzo return (ENOBUFS); 2229188808Sgonzo m->m_len = m->m_pkthdr.len = MCLBYTES; 2230289476Sadrian 2231289476Sadrian /* 2232289476Sadrian * Add extra space to "adjust" (copy) the packet back to be aligned 2233289476Sadrian * for purposes of IPv4/IPv6 header contents. 2234289476Sadrian */ 2235289671Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) 2236289671Sadrian m_adj(m, sizeof(uint64_t)); 2237289671Sadrian /* 2238289671Sadrian * If it's a 1-byte aligned buffer, then just offset it two bytes 2239289671Sadrian * and that will give us a hopefully correctly DWORD aligned 2240289671Sadrian * L3 payload - and we won't have to undo it afterwards. 2241289671Sadrian */ 2242289671Sadrian else if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE) 2243289671Sadrian m_adj(m, sizeof(uint16_t)); 2244188808Sgonzo 2245188808Sgonzo if (bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_rx_tag, 2246188808Sgonzo sc->arge_cdata.arge_rx_sparemap, m, segs, &nsegs, 0) != 0) { 2247188808Sgonzo m_freem(m); 2248188808Sgonzo return (ENOBUFS); 2249188808Sgonzo } 2250188808Sgonzo KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2251188808Sgonzo 2252188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[idx]; 2253188808Sgonzo if (rxd->rx_m != NULL) { 2254188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap); 2255188808Sgonzo } 2256188808Sgonzo map = rxd->rx_dmamap; 2257188808Sgonzo rxd->rx_dmamap = sc->arge_cdata.arge_rx_sparemap; 2258188808Sgonzo sc->arge_cdata.arge_rx_sparemap = map; 2259188808Sgonzo rxd->rx_m = m; 2260188808Sgonzo desc = rxd->desc; 2261289476Sadrian if ((sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) && 2262289476Sadrian segs[0].ds_addr & 3) 2263192783Sgonzo panic("RX packet address unaligned"); 2264188808Sgonzo desc->packet_addr = segs[0].ds_addr; 2265192783Sgonzo desc->packet_ctrl = ARGE_DESC_EMPTY | ARGE_DMASIZE(segs[0].ds_len); 2266188808Sgonzo 2267195434Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2268195434Sgonzo sc->arge_cdata.arge_rx_ring_map, 2269195434Sgonzo BUS_DMASYNC_PREWRITE); 2270195434Sgonzo 2271188808Sgonzo return (0); 2272188808Sgonzo} 2273188808Sgonzo 2274289671Sadrian/* 2275289671Sadrian * Move the data backwards 16 bits to (hopefully!) ensure the 2276289671Sadrian * IPv4/IPv6 payload is aligned. 2277289671Sadrian * 2278289671Sadrian * This is required for earlier hardware where the RX path 2279289671Sadrian * requires DWORD aligned buffers. 2280289671Sadrian */ 2281188808Sgonzostatic __inline void 2282188808Sgonzoarge_fixup_rx(struct mbuf *m) 2283188808Sgonzo{ 2284198933Sgonzo int i; 2285198933Sgonzo uint16_t *src, *dst; 2286188808Sgonzo 2287188808Sgonzo src = mtod(m, uint16_t *); 2288188808Sgonzo dst = src - 1; 2289188808Sgonzo 2290195434Sgonzo for (i = 0; i < m->m_len / sizeof(uint16_t); i++) { 2291188808Sgonzo *dst++ = *src++; 2292195434Sgonzo } 2293188808Sgonzo 2294195434Sgonzo if (m->m_len % sizeof(uint16_t)) 2295195434Sgonzo *(uint8_t *)dst = *(uint8_t *)src; 2296195434Sgonzo 2297188808Sgonzo m->m_data -= ETHER_ALIGN; 2298188808Sgonzo} 2299188808Sgonzo 2300192783Sgonzo#ifdef DEVICE_POLLING 2301198667Sgonzostatic int 2302192783Sgonzoarge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 2303192783Sgonzo{ 2304192783Sgonzo struct arge_softc *sc = ifp->if_softc; 2305198667Sgonzo int rx_npkts = 0; 2306188808Sgonzo 2307198933Sgonzo if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2308192783Sgonzo ARGE_LOCK(sc); 2309192783Sgonzo arge_tx_locked(sc); 2310198667Sgonzo rx_npkts = arge_rx_locked(sc); 2311192783Sgonzo ARGE_UNLOCK(sc); 2312198933Sgonzo } 2313198667Sgonzo 2314198667Sgonzo return (rx_npkts); 2315192783Sgonzo} 2316192783Sgonzo#endif /* DEVICE_POLLING */ 2317192783Sgonzo 2318192783Sgonzo 2319188808Sgonzostatic void 2320188808Sgonzoarge_tx_locked(struct arge_softc *sc) 2321188808Sgonzo{ 2322188808Sgonzo struct arge_txdesc *txd; 2323188808Sgonzo struct arge_desc *cur_tx; 2324188808Sgonzo struct ifnet *ifp; 2325188808Sgonzo uint32_t ctrl; 2326188808Sgonzo int cons, prod; 2327188808Sgonzo 2328188808Sgonzo ARGE_LOCK_ASSERT(sc); 2329188808Sgonzo 2330188808Sgonzo cons = sc->arge_cdata.arge_tx_cons; 2331188808Sgonzo prod = sc->arge_cdata.arge_tx_prod; 2332220356Sadrian 2333232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: cons=%d, prod=%d\n", __func__, cons, 2334232628Sray prod); 2335220356Sadrian 2336188808Sgonzo if (cons == prod) 2337188808Sgonzo return; 2338188808Sgonzo 2339188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 2340188808Sgonzo sc->arge_cdata.arge_tx_ring_map, 2341188808Sgonzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2342188808Sgonzo 2343188808Sgonzo ifp = sc->arge_ifp; 2344188808Sgonzo /* 2345188808Sgonzo * Go through our tx list and free mbufs for those 2346188808Sgonzo * frames that have been transmitted. 2347188808Sgonzo */ 2348188808Sgonzo for (; cons != prod; ARGE_INC(cons, ARGE_TX_RING_COUNT)) { 2349188808Sgonzo cur_tx = &sc->arge_rdata.arge_tx_ring[cons]; 2350188808Sgonzo ctrl = cur_tx->packet_ctrl; 2351188808Sgonzo /* Check if descriptor has "finished" flag */ 2352188808Sgonzo if ((ctrl & ARGE_DESC_EMPTY) == 0) 2353188808Sgonzo break; 2354188808Sgonzo 2355188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_PKT_SENT); 2356188808Sgonzo 2357188808Sgonzo sc->arge_cdata.arge_tx_cnt--; 2358188808Sgonzo ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2359188808Sgonzo 2360188808Sgonzo txd = &sc->arge_cdata.arge_txdesc[cons]; 2361188808Sgonzo 2362271858Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 2363188808Sgonzo 2364188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap, 2365188808Sgonzo BUS_DMASYNC_POSTWRITE); 2366188808Sgonzo bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap); 2367188808Sgonzo 2368188808Sgonzo /* Free only if it's first descriptor in list */ 2369188808Sgonzo if (txd->tx_m) 2370188808Sgonzo m_freem(txd->tx_m); 2371188808Sgonzo txd->tx_m = NULL; 2372188808Sgonzo 2373188808Sgonzo /* reset descriptor */ 2374188808Sgonzo cur_tx->packet_addr = 0; 2375188808Sgonzo } 2376188808Sgonzo 2377188808Sgonzo sc->arge_cdata.arge_tx_cons = cons; 2378188808Sgonzo 2379188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag, 2380188808Sgonzo sc->arge_cdata.arge_tx_ring_map, BUS_DMASYNC_PREWRITE); 2381188808Sgonzo} 2382188808Sgonzo 2383188808Sgonzo 2384198667Sgonzostatic int 2385188808Sgonzoarge_rx_locked(struct arge_softc *sc) 2386188808Sgonzo{ 2387188808Sgonzo struct arge_rxdesc *rxd; 2388188808Sgonzo struct ifnet *ifp = sc->arge_ifp; 2389192783Sgonzo int cons, prog, packet_len, i; 2390188808Sgonzo struct arge_desc *cur_rx; 2391188808Sgonzo struct mbuf *m; 2392198667Sgonzo int rx_npkts = 0; 2393188808Sgonzo 2394188808Sgonzo ARGE_LOCK_ASSERT(sc); 2395188808Sgonzo 2396188808Sgonzo cons = sc->arge_cdata.arge_rx_cons; 2397188808Sgonzo 2398188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2399188808Sgonzo sc->arge_cdata.arge_rx_ring_map, 2400188808Sgonzo BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2401188808Sgonzo 2402232627Sray for (prog = 0; prog < ARGE_RX_RING_COUNT; 2403188808Sgonzo ARGE_INC(cons, ARGE_RX_RING_COUNT)) { 2404188808Sgonzo cur_rx = &sc->arge_rdata.arge_rx_ring[cons]; 2405188808Sgonzo rxd = &sc->arge_cdata.arge_rxdesc[cons]; 2406188808Sgonzo m = rxd->rx_m; 2407188808Sgonzo 2408188808Sgonzo if ((cur_rx->packet_ctrl & ARGE_DESC_EMPTY) != 0) 2409232627Sray break; 2410188808Sgonzo 2411188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_PKT_RECVD); 2412188808Sgonzo 2413188808Sgonzo prog++; 2414188808Sgonzo 2415188808Sgonzo packet_len = ARGE_DMASIZE(cur_rx->packet_ctrl); 2416188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap, 2417195434Sgonzo BUS_DMASYNC_POSTREAD); 2418188808Sgonzo m = rxd->rx_m; 2419188808Sgonzo 2420289671Sadrian /* 2421289671Sadrian * If the MAC requires 4 byte alignment then the RX setup 2422289671Sadrian * routine will have pre-offset things; so un-offset it here. 2423289671Sadrian */ 2424289671Sadrian if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) 2425289671Sadrian arge_fixup_rx(m); 2426289671Sadrian 2427188808Sgonzo m->m_pkthdr.rcvif = ifp; 2428188808Sgonzo /* Skip 4 bytes of CRC */ 2429188808Sgonzo m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN; 2430271858Sglebius if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 2431198667Sgonzo rx_npkts++; 2432188808Sgonzo 2433188808Sgonzo ARGE_UNLOCK(sc); 2434188808Sgonzo (*ifp->if_input)(ifp, m); 2435188808Sgonzo ARGE_LOCK(sc); 2436192783Sgonzo cur_rx->packet_addr = 0; 2437192783Sgonzo } 2438188808Sgonzo 2439192783Sgonzo if (prog > 0) { 2440192783Sgonzo 2441192783Sgonzo i = sc->arge_cdata.arge_rx_cons; 2442192783Sgonzo for (; prog > 0 ; prog--) { 2443192783Sgonzo if (arge_newbuf(sc, i) != 0) { 2444232627Sray device_printf(sc->arge_dev, 2445192783Sgonzo "Failed to allocate buffer\n"); 2446192783Sgonzo break; 2447192783Sgonzo } 2448192783Sgonzo ARGE_INC(i, ARGE_RX_RING_COUNT); 2449188808Sgonzo } 2450188808Sgonzo 2451188808Sgonzo bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2452188808Sgonzo sc->arge_cdata.arge_rx_ring_map, 2453195434Sgonzo BUS_DMASYNC_PREWRITE); 2454188808Sgonzo 2455188808Sgonzo sc->arge_cdata.arge_rx_cons = cons; 2456188808Sgonzo } 2457198667Sgonzo 2458198667Sgonzo return (rx_npkts); 2459188808Sgonzo} 2460188808Sgonzo 2461188808Sgonzostatic int 2462188808Sgonzoarge_intr_filter(void *arg) 2463188808Sgonzo{ 2464188808Sgonzo struct arge_softc *sc = arg; 2465188808Sgonzo uint32_t status, ints; 2466188808Sgonzo 2467188808Sgonzo status = ARGE_READ(sc, AR71XX_DMA_INTR_STATUS); 2468188808Sgonzo ints = ARGE_READ(sc, AR71XX_DMA_INTR); 2469188808Sgonzo 2470220354Sadrian ARGEDEBUG(sc, ARGE_DBG_INTR, "int mask(filter) = %b\n", ints, 2471188808Sgonzo "\20\10RX_BUS_ERROR\7RX_OVERFLOW\5RX_PKT_RCVD" 2472188808Sgonzo "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT"); 2473232627Sray ARGEDEBUG(sc, ARGE_DBG_INTR, "status(filter) = %b\n", status, 2474188808Sgonzo "\20\10RX_BUS_ERROR\7RX_OVERFLOW\5RX_PKT_RCVD" 2475188808Sgonzo "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT"); 2476188808Sgonzo 2477188808Sgonzo if (status & DMA_INTR_ALL) { 2478191644Sgonzo sc->arge_intr_status |= status; 2479192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, 0); 2480289476Sadrian sc->stats.intr_ok++; 2481188808Sgonzo return (FILTER_SCHEDULE_THREAD); 2482232627Sray } 2483188808Sgonzo 2484188808Sgonzo sc->arge_intr_status = 0; 2485289476Sadrian sc->stats.intr_stray++; 2486188808Sgonzo return (FILTER_STRAY); 2487188808Sgonzo} 2488188808Sgonzo 2489188808Sgonzostatic void 2490188808Sgonzoarge_intr(void *arg) 2491188808Sgonzo{ 2492188808Sgonzo struct arge_softc *sc = arg; 2493188808Sgonzo uint32_t status; 2494220356Sadrian struct ifnet *ifp = sc->arge_ifp; 2495290090Sadrian#ifdef ARGE_DEBUG 2496290090Sadrian int i; 2497290090Sadrian#endif 2498188808Sgonzo 2499192783Sgonzo status = ARGE_READ(sc, AR71XX_DMA_INTR_STATUS); 2500192783Sgonzo status |= sc->arge_intr_status; 2501188808Sgonzo 2502232627Sray ARGEDEBUG(sc, ARGE_DBG_INTR, "int status(intr) = %b\n", status, 2503188808Sgonzo "\20\10\7RX_OVERFLOW\5RX_PKT_RCVD" 2504188808Sgonzo "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT"); 2505188808Sgonzo 2506232627Sray /* 2507232627Sray * Is it our interrupt at all? 2508188808Sgonzo */ 2509289476Sadrian if (status == 0) { 2510289476Sadrian sc->stats.intr_stray2++; 2511188808Sgonzo return; 2512289476Sadrian } 2513188808Sgonzo 2514290090Sadrian#ifdef ARGE_DEBUG 2515290090Sadrian for (i = 0; i < 32; i++) { 2516290214Sadrian if (status & (1U << i)) { 2517290123Sadrian sc->intr_stats.count[i]++; 2518290090Sadrian } 2519290090Sadrian } 2520290090Sadrian#endif 2521290090Sadrian 2522188808Sgonzo if (status & DMA_INTR_RX_BUS_ERROR) { 2523188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_BUS_ERROR); 2524188808Sgonzo device_printf(sc->arge_dev, "RX bus error"); 2525188808Sgonzo return; 2526188808Sgonzo } 2527188808Sgonzo 2528188808Sgonzo if (status & DMA_INTR_TX_BUS_ERROR) { 2529188808Sgonzo ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_BUS_ERROR); 2530188808Sgonzo device_printf(sc->arge_dev, "TX bus error"); 2531188808Sgonzo return; 2532188808Sgonzo } 2533188808Sgonzo 2534192783Sgonzo ARGE_LOCK(sc); 2535285121Sadrian arge_flush_ddr(sc); 2536188808Sgonzo 2537192783Sgonzo if (status & DMA_INTR_RX_PKT_RCVD) 2538192783Sgonzo arge_rx_locked(sc); 2539188808Sgonzo 2540232627Sray /* 2541232627Sray * RX overrun disables the receiver. 2542232627Sray * Clear indication and re-enable rx. 2543192783Sgonzo */ 2544192783Sgonzo if ( status & DMA_INTR_RX_OVERFLOW) { 2545192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_OVERFLOW); 2546192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, DMA_RX_CONTROL_EN); 2547220356Sadrian sc->stats.rx_overflow++; 2548192783Sgonzo } 2549188808Sgonzo 2550192783Sgonzo if (status & DMA_INTR_TX_PKT_SENT) 2551192783Sgonzo arge_tx_locked(sc); 2552232627Sray /* 2553232627Sray * Underrun turns off TX. Clear underrun indication. 2554232627Sray * If there's anything left in the ring, reactivate the tx. 2555192783Sgonzo */ 2556192569Sdwhite if (status & DMA_INTR_TX_UNDERRUN) { 2557192569Sdwhite ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_UNDERRUN); 2558220356Sadrian sc->stats.tx_underflow++; 2559232628Sray ARGEDEBUG(sc, ARGE_DBG_TX, "%s: TX underrun; tx_cnt=%d\n", 2560232628Sray __func__, sc->arge_cdata.arge_tx_cnt); 2561219590Sadrian if (sc->arge_cdata.arge_tx_cnt > 0 ) { 2562232627Sray ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, 2563192783Sgonzo DMA_TX_CONTROL_EN); 2564192783Sgonzo } 2565192569Sdwhite } 2566192569Sdwhite 2567192946Sgonzo /* 2568220357Sadrian * If we've finished TXing and there's space for more packets 2569220357Sadrian * to be queued for TX, do so. Otherwise we may end up in a 2570220357Sadrian * situation where the interface send queue was filled 2571220357Sadrian * whilst the hardware queue was full, then the hardware 2572220357Sadrian * queue was drained by the interface send queue wasn't, 2573220357Sadrian * and thus if_start() is never called to kick-start 2574220357Sadrian * the send process (and all subsequent packets are simply 2575220357Sadrian * discarded. 2576220357Sadrian * 2577220357Sadrian * XXX TODO: make sure that the hardware deals nicely 2578220357Sadrian * with the possibility of the queue being enabled above 2579220357Sadrian * after a TX underrun, then having the hardware queue added 2580220357Sadrian * to below. 2581220357Sadrian */ 2582220357Sadrian if (status & (DMA_INTR_TX_PKT_SENT | DMA_INTR_TX_UNDERRUN) && 2583220357Sadrian (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { 2584220357Sadrian if (!IFQ_IS_EMPTY(&ifp->if_snd)) 2585220357Sadrian arge_start_locked(ifp); 2586220357Sadrian } 2587220357Sadrian 2588220357Sadrian /* 2589192946Sgonzo * We handled all bits, clear status 2590192946Sgonzo */ 2591192946Sgonzo sc->arge_intr_status = 0; 2592188808Sgonzo ARGE_UNLOCK(sc); 2593192783Sgonzo /* 2594232627Sray * re-enable all interrupts 2595192783Sgonzo */ 2596192783Sgonzo ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL); 2597188808Sgonzo} 2598188808Sgonzo 2599192783Sgonzo 2600188808Sgonzostatic void 2601188808Sgonzoarge_tick(void *xsc) 2602188808Sgonzo{ 2603188808Sgonzo struct arge_softc *sc = xsc; 2604188808Sgonzo struct mii_data *mii; 2605188808Sgonzo 2606188808Sgonzo ARGE_LOCK_ASSERT(sc); 2607188808Sgonzo 2608199234Sgonzo if (sc->arge_miibus) { 2609199234Sgonzo mii = device_get_softc(sc->arge_miibus); 2610199234Sgonzo mii_tick(mii); 2611199234Sgonzo callout_reset(&sc->arge_stat_callout, hz, arge_tick, sc); 2612199234Sgonzo } 2613188808Sgonzo} 2614199234Sgonzo 2615199234Sgonzoint 2616199234Sgonzoarge_multiphy_mediachange(struct ifnet *ifp) 2617199234Sgonzo{ 2618199234Sgonzo struct arge_softc *sc = ifp->if_softc; 2619199234Sgonzo struct ifmedia *ifm = &sc->arge_ifmedia; 2620199234Sgonzo struct ifmedia_entry *ife = ifm->ifm_cur; 2621199234Sgonzo 2622199234Sgonzo if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 2623199234Sgonzo return (EINVAL); 2624199234Sgonzo 2625199234Sgonzo if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 2626232627Sray device_printf(sc->arge_dev, 2627199234Sgonzo "AUTO is not supported for multiphy MAC"); 2628199234Sgonzo return (EINVAL); 2629199234Sgonzo } 2630199234Sgonzo 2631199234Sgonzo /* 2632199234Sgonzo * Ignore everything 2633199234Sgonzo */ 2634199234Sgonzo return (0); 2635199234Sgonzo} 2636199234Sgonzo 2637199234Sgonzovoid 2638199234Sgonzoarge_multiphy_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 2639199234Sgonzo{ 2640199234Sgonzo struct arge_softc *sc = ifp->if_softc; 2641199234Sgonzo 2642199234Sgonzo ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 2643232627Sray ifmr->ifm_active = IFM_ETHER | sc->arge_media_type | 2644199234Sgonzo sc->arge_duplex_mode; 2645199234Sgonzo} 2646199234Sgonzo 2647234862Sadrian#if defined(ARGE_MDIO) 2648234862Sadrianstatic int 2649234862Sadrianargemdio_probe(device_t dev) 2650234862Sadrian{ 2651234862Sadrian device_set_desc(dev, "Atheros AR71xx built-in ethernet interface, MDIO controller"); 2652234862Sadrian return (0); 2653234862Sadrian} 2654234862Sadrian 2655234862Sadrianstatic int 2656234862Sadrianargemdio_attach(device_t dev) 2657234862Sadrian{ 2658234862Sadrian struct arge_softc *sc; 2659234862Sadrian int error = 0; 2660234862Sadrian 2661234862Sadrian sc = device_get_softc(dev); 2662234862Sadrian sc->arge_dev = dev; 2663234862Sadrian sc->arge_mac_unit = device_get_unit(dev); 2664234862Sadrian sc->arge_rid = 0; 2665234862Sadrian sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 2666234862Sadrian &sc->arge_rid, RF_ACTIVE | RF_SHAREABLE); 2667234862Sadrian if (sc->arge_res == NULL) { 2668234862Sadrian device_printf(dev, "couldn't map memory\n"); 2669234862Sadrian error = ENXIO; 2670234862Sadrian goto fail; 2671234862Sadrian } 2672234862Sadrian 2673234862Sadrian /* Reset MAC - required for AR71xx MDIO to successfully occur */ 2674234862Sadrian arge_reset_mac(sc); 2675234862Sadrian /* Reset MII bus */ 2676234862Sadrian arge_reset_miibus(sc); 2677234862Sadrian 2678234862Sadrian bus_generic_probe(dev); 2679234862Sadrian bus_enumerate_hinted_children(dev); 2680234862Sadrian error = bus_generic_attach(dev); 2681234862Sadrianfail: 2682234862Sadrian return (error); 2683234862Sadrian} 2684234862Sadrian 2685234862Sadrianstatic int 2686234862Sadrianargemdio_detach(device_t dev) 2687234862Sadrian{ 2688234862Sadrian return (0); 2689234862Sadrian} 2690234862Sadrian 2691234862Sadrian#endif 2692