10aeed3e9SJustin Hibbits /*- 20aeed3e9SJustin Hibbits * Copyright (c) 2011-2012 Semihalf. 30aeed3e9SJustin Hibbits * All rights reserved. 40aeed3e9SJustin Hibbits * 50aeed3e9SJustin Hibbits * Redistribution and use in source and binary forms, with or without 60aeed3e9SJustin Hibbits * modification, are permitted provided that the following conditions 70aeed3e9SJustin Hibbits * are met: 80aeed3e9SJustin Hibbits * 1. Redistributions of source code must retain the above copyright 90aeed3e9SJustin Hibbits * notice, this list of conditions and the following disclaimer. 100aeed3e9SJustin Hibbits * 2. Redistributions in binary form must reproduce the above copyright 110aeed3e9SJustin Hibbits * notice, this list of conditions and the following disclaimer in the 120aeed3e9SJustin Hibbits * documentation and/or other materials provided with the distribution. 130aeed3e9SJustin Hibbits * 140aeed3e9SJustin Hibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 150aeed3e9SJustin Hibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160aeed3e9SJustin Hibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 170aeed3e9SJustin Hibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 180aeed3e9SJustin Hibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 190aeed3e9SJustin Hibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 200aeed3e9SJustin Hibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 210aeed3e9SJustin Hibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 220aeed3e9SJustin Hibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 230aeed3e9SJustin Hibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 240aeed3e9SJustin Hibbits * SUCH DAMAGE. 250aeed3e9SJustin Hibbits */ 260aeed3e9SJustin Hibbits 270aeed3e9SJustin Hibbits #include <sys/cdefs.h> 280aeed3e9SJustin Hibbits #include <sys/param.h> 290aeed3e9SJustin Hibbits #include <sys/systm.h> 300aeed3e9SJustin Hibbits #include <sys/kernel.h> 310aeed3e9SJustin Hibbits #include <sys/module.h> 320aeed3e9SJustin Hibbits #include <sys/bus.h> 330aeed3e9SJustin Hibbits #include <sys/rman.h> 340aeed3e9SJustin Hibbits #include <sys/malloc.h> 350aeed3e9SJustin Hibbits #include <sys/mbuf.h> 360aeed3e9SJustin Hibbits #include <sys/socket.h> 370aeed3e9SJustin Hibbits #include <sys/sysctl.h> 380aeed3e9SJustin Hibbits #include <sys/sockio.h> 390aeed3e9SJustin Hibbits 400aeed3e9SJustin Hibbits #include <machine/bus.h> 410aeed3e9SJustin Hibbits #include <machine/resource.h> 420aeed3e9SJustin Hibbits 430aeed3e9SJustin Hibbits #include <net/ethernet.h> 440aeed3e9SJustin Hibbits #include <net/if.h> 450aeed3e9SJustin Hibbits #include <net/if_dl.h> 460aeed3e9SJustin Hibbits #include <net/if_media.h> 470aeed3e9SJustin Hibbits #include <net/if_types.h> 480aeed3e9SJustin Hibbits #include <net/if_arp.h> 490aeed3e9SJustin Hibbits 500aeed3e9SJustin Hibbits #include <dev/mii/mii.h> 510aeed3e9SJustin Hibbits #include <dev/mii/miivar.h> 520aeed3e9SJustin Hibbits #include <dev/ofw/ofw_bus.h> 530aeed3e9SJustin Hibbits #include <dev/ofw/ofw_bus_subr.h> 540aeed3e9SJustin Hibbits #include <dev/ofw/openfirm.h> 550aeed3e9SJustin Hibbits 560aeed3e9SJustin Hibbits #include "miibus_if.h" 570aeed3e9SJustin Hibbits 58852ba100SJustin Hibbits #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h> 590aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h> 600aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h> 61*db550517SJustin Hibbits #include <contrib/ncsw/inc/flib/fsl_fman_dtsec.h> 620aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/xx_ext.h> 630aeed3e9SJustin Hibbits 640aeed3e9SJustin Hibbits #include "fman.h" 650aeed3e9SJustin Hibbits #include "if_dtsec.h" 660aeed3e9SJustin Hibbits #include "if_dtsec_im.h" 670aeed3e9SJustin Hibbits #include "if_dtsec_rm.h" 680aeed3e9SJustin Hibbits 69c3f3cd05SJustin Hibbits #define DTSEC_MIN_FRAME_SIZE 64 70c3f3cd05SJustin Hibbits #define DTSEC_MAX_FRAME_SIZE 9600 71c3f3cd05SJustin Hibbits 72c3f3cd05SJustin Hibbits #define DTSEC_REG_MAXFRM 0x110 73*db550517SJustin Hibbits #define DTSEC_REG_GADDR(i) (0x0a0 + 4*(i)) 740aeed3e9SJustin Hibbits 750aeed3e9SJustin Hibbits /** 760aeed3e9SJustin Hibbits * @group dTSEC private defines. 770aeed3e9SJustin Hibbits * @{ 780aeed3e9SJustin Hibbits */ 790aeed3e9SJustin Hibbits /** 800aeed3e9SJustin Hibbits * dTSEC FMan MAC exceptions info struct. 810aeed3e9SJustin Hibbits */ 820aeed3e9SJustin Hibbits struct dtsec_fm_mac_ex_str { 830aeed3e9SJustin Hibbits const int num; 840aeed3e9SJustin Hibbits const char *str; 850aeed3e9SJustin Hibbits }; 860aeed3e9SJustin Hibbits /** @} */ 870aeed3e9SJustin Hibbits 880aeed3e9SJustin Hibbits 890aeed3e9SJustin Hibbits /** 900aeed3e9SJustin Hibbits * @group FMan MAC routines. 910aeed3e9SJustin Hibbits * @{ 920aeed3e9SJustin Hibbits */ 930aeed3e9SJustin Hibbits #define DTSEC_MAC_EXCEPTIONS_END (-1) 940aeed3e9SJustin Hibbits 950aeed3e9SJustin Hibbits /** 960aeed3e9SJustin Hibbits * FMan MAC exceptions. 970aeed3e9SJustin Hibbits */ 980aeed3e9SJustin Hibbits static const struct dtsec_fm_mac_ex_str dtsec_fm_mac_exceptions[] = { 990aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO, "MDIO scan event" }, 1000aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_MDIO_CMD_CMPL, "MDIO command completion" }, 1010aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_REM_FAULT, "Remote fault" }, 1020aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_LOC_FAULT, "Local fault" }, 1030aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_1TX_ECC_ER, "Transmit frame ECC error" }, 1040aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_TX_FIFO_UNFL, "Transmit FIFO underflow" }, 1050aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_TX_FIFO_OVFL, "Receive FIFO overflow" }, 1060aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_TX_ER, "Transmit frame error" }, 1070aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_FIFO_OVFL, "Receive FIFO overflow" }, 1080aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_ECC_ER, "Receive frame ECC error" }, 1090aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_JAB_FRM, "Receive jabber frame" }, 1100aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_OVRSZ_FRM, "Receive oversized frame" }, 1110aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_RUNT_FRM, "Receive runt frame" }, 1120aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_FRAG_FRM, "Receive fragment frame" }, 1130aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_LEN_ER, "Receive payload length error" }, 1140aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_CRC_ER, "Receive CRC error" }, 1150aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_ALIGN_ER, "Receive alignment error" }, 1160aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_BAB_RX, "Babbling receive error" }, 1170aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_RX_CTL, "Receive control (pause frame) interrupt" }, 1180aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET, "Graceful transmit stop " 1190aeed3e9SJustin Hibbits "complete" }, 1200aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_BAB_TX, "Babbling transmit error" }, 1210aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_CTL, "Transmit control (pause frame) interrupt" }, 1220aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_ERR, "Transmit error" }, 1230aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_LATE_COL, "Late collision" }, 1240aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_COL_RET_LMT, "Collision retry limit" }, 1250aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_FIFO_UNDRN, "Transmit FIFO underrun" }, 1260aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_MAG_PCKT, "Magic Packet detected when dTSEC is in " 1270aeed3e9SJustin Hibbits "Magic Packet detection mode" }, 1280aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET, "MII management read completion" }, 1290aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET, "MII management write completion" }, 1300aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET, "Graceful receive stop " 1310aeed3e9SJustin Hibbits "complete" }, 1320aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_DATA_ERR, "Internal data error on transmit" }, 1330aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_RX_DATA_ERR, "Internal data error on receive" }, 1340aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_1588_TS_RX_ERR, "Time-Stamp Receive Error" }, 1350aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, "MIB counter overflow" }, 1360aeed3e9SJustin Hibbits { DTSEC_MAC_EXCEPTIONS_END, "" } 1370aeed3e9SJustin Hibbits }; 1380aeed3e9SJustin Hibbits 1390aeed3e9SJustin Hibbits static const char * 1400aeed3e9SJustin Hibbits dtsec_fm_mac_ex_to_str(e_FmMacExceptions exception) 1410aeed3e9SJustin Hibbits { 1420aeed3e9SJustin Hibbits int i; 1430aeed3e9SJustin Hibbits 1440aeed3e9SJustin Hibbits for (i = 0; dtsec_fm_mac_exceptions[i].num != exception && 1450aeed3e9SJustin Hibbits dtsec_fm_mac_exceptions[i].num != DTSEC_MAC_EXCEPTIONS_END; ++i) 1460aeed3e9SJustin Hibbits ; 1470aeed3e9SJustin Hibbits 1480aeed3e9SJustin Hibbits if (dtsec_fm_mac_exceptions[i].num == DTSEC_MAC_EXCEPTIONS_END) 1490aeed3e9SJustin Hibbits return ("<Unknown Exception>"); 1500aeed3e9SJustin Hibbits 1510aeed3e9SJustin Hibbits return (dtsec_fm_mac_exceptions[i].str); 1520aeed3e9SJustin Hibbits } 1530aeed3e9SJustin Hibbits 1540aeed3e9SJustin Hibbits static void 1550aeed3e9SJustin Hibbits dtsec_fm_mac_mdio_event_callback(t_Handle h_App, 1560aeed3e9SJustin Hibbits e_FmMacExceptions exception) 1570aeed3e9SJustin Hibbits { 1580aeed3e9SJustin Hibbits struct dtsec_softc *sc; 1590aeed3e9SJustin Hibbits 1600aeed3e9SJustin Hibbits sc = h_App; 1610aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "MDIO event %i: %s.\n", exception, 1620aeed3e9SJustin Hibbits dtsec_fm_mac_ex_to_str(exception)); 1630aeed3e9SJustin Hibbits } 1640aeed3e9SJustin Hibbits 1650aeed3e9SJustin Hibbits static void 1660aeed3e9SJustin Hibbits dtsec_fm_mac_exception_callback(t_Handle app, e_FmMacExceptions exception) 1670aeed3e9SJustin Hibbits { 1680aeed3e9SJustin Hibbits struct dtsec_softc *sc; 1690aeed3e9SJustin Hibbits 1700aeed3e9SJustin Hibbits sc = app; 1710aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "MAC exception %i: %s.\n", exception, 1720aeed3e9SJustin Hibbits dtsec_fm_mac_ex_to_str(exception)); 1730aeed3e9SJustin Hibbits } 1740aeed3e9SJustin Hibbits 1750aeed3e9SJustin Hibbits static void 1760aeed3e9SJustin Hibbits dtsec_fm_mac_free(struct dtsec_softc *sc) 1770aeed3e9SJustin Hibbits { 1780aeed3e9SJustin Hibbits if (sc->sc_mach == NULL) 1790aeed3e9SJustin Hibbits return; 1800aeed3e9SJustin Hibbits 1810aeed3e9SJustin Hibbits FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 1820aeed3e9SJustin Hibbits FM_MAC_Free(sc->sc_mach); 1830aeed3e9SJustin Hibbits sc->sc_mach = NULL; 1840aeed3e9SJustin Hibbits } 1850aeed3e9SJustin Hibbits 1860aeed3e9SJustin Hibbits static int 1870aeed3e9SJustin Hibbits dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac) 1880aeed3e9SJustin Hibbits { 1890aeed3e9SJustin Hibbits t_FmMacParams params; 1900aeed3e9SJustin Hibbits t_Error error; 1910aeed3e9SJustin Hibbits 1920aeed3e9SJustin Hibbits memset(¶ms, 0, sizeof(params)); 1930aeed3e9SJustin Hibbits memcpy(¶ms.addr, mac, sizeof(params.addr)); 1940aeed3e9SJustin Hibbits 195a32b5435SJustin Hibbits params.baseAddr = rman_get_bushandle(sc->sc_mem); 1960aeed3e9SJustin Hibbits params.enetMode = sc->sc_mac_enet_mode; 1970aeed3e9SJustin Hibbits params.macId = sc->sc_eth_id; 1980aeed3e9SJustin Hibbits params.mdioIrq = sc->sc_mac_mdio_irq; 1990aeed3e9SJustin Hibbits params.f_Event = dtsec_fm_mac_mdio_event_callback; 2000aeed3e9SJustin Hibbits params.f_Exception = dtsec_fm_mac_exception_callback; 2010aeed3e9SJustin Hibbits params.h_App = sc; 2020aeed3e9SJustin Hibbits params.h_Fm = sc->sc_fmh; 2030aeed3e9SJustin Hibbits 2040aeed3e9SJustin Hibbits sc->sc_mach = FM_MAC_Config(¶ms); 2050aeed3e9SJustin Hibbits if (sc->sc_mach == NULL) { 2060aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't configure FM_MAC module.\n" 2070aeed3e9SJustin Hibbits ); 2080aeed3e9SJustin Hibbits return (ENXIO); 2090aeed3e9SJustin Hibbits } 2100aeed3e9SJustin Hibbits 2110aeed3e9SJustin Hibbits error = FM_MAC_ConfigResetOnInit(sc->sc_mach, TRUE); 2120aeed3e9SJustin Hibbits if (error != E_OK) { 2130aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't enable reset on init " 2140aeed3e9SJustin Hibbits "feature.\n"); 2150aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 2160aeed3e9SJustin Hibbits return (ENXIO); 2170aeed3e9SJustin Hibbits } 2180aeed3e9SJustin Hibbits 2190aeed3e9SJustin Hibbits /* Do not inform about pause frames */ 2200aeed3e9SJustin Hibbits error = FM_MAC_ConfigException(sc->sc_mach, e_FM_MAC_EX_1G_RX_CTL, 2210aeed3e9SJustin Hibbits FALSE); 2220aeed3e9SJustin Hibbits if (error != E_OK) { 2230aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't disable pause frames " 2240aeed3e9SJustin Hibbits "exception.\n"); 2250aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 2260aeed3e9SJustin Hibbits return (ENXIO); 2270aeed3e9SJustin Hibbits } 2280aeed3e9SJustin Hibbits 2290aeed3e9SJustin Hibbits error = FM_MAC_Init(sc->sc_mach); 2300aeed3e9SJustin Hibbits if (error != E_OK) { 2310aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't initialize FM_MAC module." 2320aeed3e9SJustin Hibbits "\n"); 2330aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 2340aeed3e9SJustin Hibbits return (ENXIO); 2350aeed3e9SJustin Hibbits } 2360aeed3e9SJustin Hibbits 2370aeed3e9SJustin Hibbits return (0); 2380aeed3e9SJustin Hibbits } 2390aeed3e9SJustin Hibbits /** @} */ 2400aeed3e9SJustin Hibbits 2410aeed3e9SJustin Hibbits 2420aeed3e9SJustin Hibbits /** 2430aeed3e9SJustin Hibbits * @group FMan PORT routines. 2440aeed3e9SJustin Hibbits * @{ 2450aeed3e9SJustin Hibbits */ 2460aeed3e9SJustin Hibbits static const char * 2470aeed3e9SJustin Hibbits dtsec_fm_port_ex_to_str(e_FmPortExceptions exception) 2480aeed3e9SJustin Hibbits { 2490aeed3e9SJustin Hibbits 2500aeed3e9SJustin Hibbits switch (exception) { 2510aeed3e9SJustin Hibbits case e_FM_PORT_EXCEPTION_IM_BUSY: 2520aeed3e9SJustin Hibbits return ("IM: RX busy"); 2530aeed3e9SJustin Hibbits default: 2540aeed3e9SJustin Hibbits return ("<Unknown Exception>"); 2550aeed3e9SJustin Hibbits } 2560aeed3e9SJustin Hibbits } 2570aeed3e9SJustin Hibbits 2580aeed3e9SJustin Hibbits void 2590aeed3e9SJustin Hibbits dtsec_fm_port_rx_exception_callback(t_Handle app, 2600aeed3e9SJustin Hibbits e_FmPortExceptions exception) 2610aeed3e9SJustin Hibbits { 2620aeed3e9SJustin Hibbits struct dtsec_softc *sc; 2630aeed3e9SJustin Hibbits 2640aeed3e9SJustin Hibbits sc = app; 2650aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "RX exception: %i: %s.\n", exception, 2660aeed3e9SJustin Hibbits dtsec_fm_port_ex_to_str(exception)); 2670aeed3e9SJustin Hibbits } 2680aeed3e9SJustin Hibbits 2690aeed3e9SJustin Hibbits void 2700aeed3e9SJustin Hibbits dtsec_fm_port_tx_exception_callback(t_Handle app, 2710aeed3e9SJustin Hibbits e_FmPortExceptions exception) 2720aeed3e9SJustin Hibbits { 2730aeed3e9SJustin Hibbits struct dtsec_softc *sc; 2740aeed3e9SJustin Hibbits 2750aeed3e9SJustin Hibbits sc = app; 2760aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "TX exception: %i: %s.\n", exception, 2770aeed3e9SJustin Hibbits dtsec_fm_port_ex_to_str(exception)); 2780aeed3e9SJustin Hibbits } 2790aeed3e9SJustin Hibbits 2800aeed3e9SJustin Hibbits e_FmPortType 2810aeed3e9SJustin Hibbits dtsec_fm_port_rx_type(enum eth_dev_type type) 2820aeed3e9SJustin Hibbits { 2830aeed3e9SJustin Hibbits switch (type) { 2840aeed3e9SJustin Hibbits case ETH_DTSEC: 2850aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_RX); 2860aeed3e9SJustin Hibbits case ETH_10GSEC: 2870aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_RX_10G); 2880aeed3e9SJustin Hibbits default: 2890aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_DUMMY); 2900aeed3e9SJustin Hibbits } 2910aeed3e9SJustin Hibbits } 2920aeed3e9SJustin Hibbits 2930aeed3e9SJustin Hibbits e_FmPortType 2940aeed3e9SJustin Hibbits dtsec_fm_port_tx_type(enum eth_dev_type type) 2950aeed3e9SJustin Hibbits { 2960aeed3e9SJustin Hibbits 2970aeed3e9SJustin Hibbits switch (type) { 2980aeed3e9SJustin Hibbits case ETH_DTSEC: 2990aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_TX); 3000aeed3e9SJustin Hibbits case ETH_10GSEC: 3010aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_TX_10G); 3020aeed3e9SJustin Hibbits default: 3030aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_DUMMY); 3040aeed3e9SJustin Hibbits } 3050aeed3e9SJustin Hibbits } 3060aeed3e9SJustin Hibbits 3070aeed3e9SJustin Hibbits static void 3080aeed3e9SJustin Hibbits dtsec_fm_port_free_both(struct dtsec_softc *sc) 3090aeed3e9SJustin Hibbits { 3100aeed3e9SJustin Hibbits if (sc->sc_rxph) { 3110aeed3e9SJustin Hibbits FM_PORT_Free(sc->sc_rxph); 3120aeed3e9SJustin Hibbits sc->sc_rxph = NULL; 3130aeed3e9SJustin Hibbits } 3140aeed3e9SJustin Hibbits 3150aeed3e9SJustin Hibbits if (sc->sc_txph) { 3160aeed3e9SJustin Hibbits FM_PORT_Free(sc->sc_txph); 3170aeed3e9SJustin Hibbits sc->sc_txph = NULL; 3180aeed3e9SJustin Hibbits } 3190aeed3e9SJustin Hibbits } 3200aeed3e9SJustin Hibbits /** @} */ 3210aeed3e9SJustin Hibbits 3220aeed3e9SJustin Hibbits 3230aeed3e9SJustin Hibbits /** 3240aeed3e9SJustin Hibbits * @group IFnet routines. 3250aeed3e9SJustin Hibbits * @{ 3260aeed3e9SJustin Hibbits */ 3270aeed3e9SJustin Hibbits static int 328c3f3cd05SJustin Hibbits dtsec_set_mtu(struct dtsec_softc *sc, unsigned int mtu) 329c3f3cd05SJustin Hibbits { 330c3f3cd05SJustin Hibbits 331c3f3cd05SJustin Hibbits mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN; 332c3f3cd05SJustin Hibbits 333c3f3cd05SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 334c3f3cd05SJustin Hibbits 335c3f3cd05SJustin Hibbits if (mtu >= DTSEC_MIN_FRAME_SIZE && mtu <= DTSEC_MAX_FRAME_SIZE) { 336c3f3cd05SJustin Hibbits bus_write_4(sc->sc_mem, DTSEC_REG_MAXFRM, mtu); 337c3f3cd05SJustin Hibbits return (mtu); 338c3f3cd05SJustin Hibbits } 339c3f3cd05SJustin Hibbits 340c3f3cd05SJustin Hibbits return (0); 341c3f3cd05SJustin Hibbits } 342c3f3cd05SJustin Hibbits 343*db550517SJustin Hibbits static u_int 344*db550517SJustin Hibbits dtsec_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) 345*db550517SJustin Hibbits { 346*db550517SJustin Hibbits struct dtsec_softc *sc = arg; 347*db550517SJustin Hibbits 348*db550517SJustin Hibbits FM_MAC_AddHashMacAddr(sc->sc_mach, (t_EnetAddr *)LLADDR(sdl)); 349*db550517SJustin Hibbits 350*db550517SJustin Hibbits return (1); 351*db550517SJustin Hibbits } 352*db550517SJustin Hibbits 353*db550517SJustin Hibbits static void 354*db550517SJustin Hibbits dtsec_setup_multicast(struct dtsec_softc *sc) 355*db550517SJustin Hibbits { 356*db550517SJustin Hibbits int i; 357*db550517SJustin Hibbits 358*db550517SJustin Hibbits if (if_getflags(sc->sc_ifnet) & IFF_ALLMULTI) { 359*db550517SJustin Hibbits for (i = 0; i < 8; i++) 360*db550517SJustin Hibbits bus_write_4(sc->sc_mem, DTSEC_REG_GADDR(i), 0xFFFFFFFF); 361*db550517SJustin Hibbits 362*db550517SJustin Hibbits return; 363*db550517SJustin Hibbits } 364*db550517SJustin Hibbits 365*db550517SJustin Hibbits fman_dtsec_reset_filter_table(rman_get_virtual(sc->sc_mem), 366*db550517SJustin Hibbits true, false); 367*db550517SJustin Hibbits if_foreach_llmaddr(sc->sc_ifnet, dtsec_hash_maddr, sc); 368*db550517SJustin Hibbits } 369*db550517SJustin Hibbits 370c3f3cd05SJustin Hibbits static int 3710aeed3e9SJustin Hibbits dtsec_if_enable_locked(struct dtsec_softc *sc) 3720aeed3e9SJustin Hibbits { 3730aeed3e9SJustin Hibbits int error; 3740aeed3e9SJustin Hibbits 3750aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 3760aeed3e9SJustin Hibbits 3770aeed3e9SJustin Hibbits error = FM_MAC_Enable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 3780aeed3e9SJustin Hibbits if (error != E_OK) 3790aeed3e9SJustin Hibbits return (EIO); 3800aeed3e9SJustin Hibbits 3810aeed3e9SJustin Hibbits error = FM_PORT_Enable(sc->sc_rxph); 3820aeed3e9SJustin Hibbits if (error != E_OK) 3830aeed3e9SJustin Hibbits return (EIO); 3840aeed3e9SJustin Hibbits 3850aeed3e9SJustin Hibbits error = FM_PORT_Enable(sc->sc_txph); 3860aeed3e9SJustin Hibbits if (error != E_OK) 3870aeed3e9SJustin Hibbits return (EIO); 3880aeed3e9SJustin Hibbits 389*db550517SJustin Hibbits dtsec_setup_multicast(sc); 390*db550517SJustin Hibbits 3911510005cSJustin Hibbits if_setdrvflagbits(sc->sc_ifnet, IFF_DRV_RUNNING, 0); 3920aeed3e9SJustin Hibbits 3930aeed3e9SJustin Hibbits /* Refresh link state */ 3940aeed3e9SJustin Hibbits dtsec_miibus_statchg(sc->sc_dev); 3950aeed3e9SJustin Hibbits 3960aeed3e9SJustin Hibbits return (0); 3970aeed3e9SJustin Hibbits } 3980aeed3e9SJustin Hibbits 3990aeed3e9SJustin Hibbits static int 4000aeed3e9SJustin Hibbits dtsec_if_disable_locked(struct dtsec_softc *sc) 4010aeed3e9SJustin Hibbits { 4020aeed3e9SJustin Hibbits int error; 4030aeed3e9SJustin Hibbits 4040aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 4050aeed3e9SJustin Hibbits 4060aeed3e9SJustin Hibbits error = FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 4070aeed3e9SJustin Hibbits if (error != E_OK) 4080aeed3e9SJustin Hibbits return (EIO); 4090aeed3e9SJustin Hibbits 4100aeed3e9SJustin Hibbits error = FM_PORT_Disable(sc->sc_rxph); 4110aeed3e9SJustin Hibbits if (error != E_OK) 4120aeed3e9SJustin Hibbits return (EIO); 4130aeed3e9SJustin Hibbits 4140aeed3e9SJustin Hibbits error = FM_PORT_Disable(sc->sc_txph); 4150aeed3e9SJustin Hibbits if (error != E_OK) 4160aeed3e9SJustin Hibbits return (EIO); 4170aeed3e9SJustin Hibbits 4181510005cSJustin Hibbits if_setdrvflagbits(sc->sc_ifnet, 0, IFF_DRV_RUNNING); 4190aeed3e9SJustin Hibbits 4200aeed3e9SJustin Hibbits return (0); 4210aeed3e9SJustin Hibbits } 4220aeed3e9SJustin Hibbits 4230aeed3e9SJustin Hibbits static int 4240083fc5cSJustin Hibbits dtsec_if_ioctl(if_t ifp, u_long command, caddr_t data) 4250aeed3e9SJustin Hibbits { 4260aeed3e9SJustin Hibbits struct dtsec_softc *sc; 4270aeed3e9SJustin Hibbits struct ifreq *ifr; 4280aeed3e9SJustin Hibbits int error; 4290aeed3e9SJustin Hibbits 4300083fc5cSJustin Hibbits sc = if_getsoftc(ifp); 4310aeed3e9SJustin Hibbits ifr = (struct ifreq *)data; 4320aeed3e9SJustin Hibbits error = 0; 4330aeed3e9SJustin Hibbits 4340aeed3e9SJustin Hibbits /* Basic functionality to achieve media status reports */ 4350aeed3e9SJustin Hibbits switch (command) { 436c3f3cd05SJustin Hibbits case SIOCSIFMTU: 437c3f3cd05SJustin Hibbits DTSEC_LOCK(sc); 438c3f3cd05SJustin Hibbits if (dtsec_set_mtu(sc, ifr->ifr_mtu)) 4390083fc5cSJustin Hibbits if_setmtu(ifp, ifr->ifr_mtu); 440c3f3cd05SJustin Hibbits else 441c3f3cd05SJustin Hibbits error = EINVAL; 442c3f3cd05SJustin Hibbits DTSEC_UNLOCK(sc); 443c3f3cd05SJustin Hibbits break; 4440aeed3e9SJustin Hibbits case SIOCSIFFLAGS: 4450aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4460aeed3e9SJustin Hibbits 4471510005cSJustin Hibbits if (if_getflags(sc->sc_ifnet) & IFF_UP) 4480aeed3e9SJustin Hibbits error = dtsec_if_enable_locked(sc); 4490aeed3e9SJustin Hibbits else 4500aeed3e9SJustin Hibbits error = dtsec_if_disable_locked(sc); 4510aeed3e9SJustin Hibbits 4520aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4530aeed3e9SJustin Hibbits break; 4540aeed3e9SJustin Hibbits 4550aeed3e9SJustin Hibbits case SIOCGIFMEDIA: 4560aeed3e9SJustin Hibbits case SIOCSIFMEDIA: 4570aeed3e9SJustin Hibbits error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, 4580aeed3e9SJustin Hibbits command); 4590aeed3e9SJustin Hibbits break; 4600aeed3e9SJustin Hibbits 4610aeed3e9SJustin Hibbits default: 4620aeed3e9SJustin Hibbits error = ether_ioctl(ifp, command, data); 4630aeed3e9SJustin Hibbits } 4640aeed3e9SJustin Hibbits 4650aeed3e9SJustin Hibbits return (error); 4660aeed3e9SJustin Hibbits } 4670aeed3e9SJustin Hibbits 4680aeed3e9SJustin Hibbits static void 4690aeed3e9SJustin Hibbits dtsec_if_tick(void *arg) 4700aeed3e9SJustin Hibbits { 4710aeed3e9SJustin Hibbits struct dtsec_softc *sc; 4720aeed3e9SJustin Hibbits 4730aeed3e9SJustin Hibbits sc = arg; 4740aeed3e9SJustin Hibbits 4750aeed3e9SJustin Hibbits /* TODO */ 4760aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4770aeed3e9SJustin Hibbits 4780aeed3e9SJustin Hibbits mii_tick(sc->sc_mii); 4790aeed3e9SJustin Hibbits callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 4800aeed3e9SJustin Hibbits 4810aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4820aeed3e9SJustin Hibbits } 4830aeed3e9SJustin Hibbits 4840aeed3e9SJustin Hibbits static void 4850aeed3e9SJustin Hibbits dtsec_if_deinit_locked(struct dtsec_softc *sc) 4860aeed3e9SJustin Hibbits { 4870aeed3e9SJustin Hibbits 4880aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 4890aeed3e9SJustin Hibbits 4900aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4910aeed3e9SJustin Hibbits callout_drain(&sc->sc_tick_callout); 4920aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4930aeed3e9SJustin Hibbits } 4940aeed3e9SJustin Hibbits 4950aeed3e9SJustin Hibbits static void 4960aeed3e9SJustin Hibbits dtsec_if_init_locked(struct dtsec_softc *sc) 4970aeed3e9SJustin Hibbits { 4980aeed3e9SJustin Hibbits int error; 4990aeed3e9SJustin Hibbits 5000aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 5010aeed3e9SJustin Hibbits 5020aeed3e9SJustin Hibbits /* Set MAC address */ 5030aeed3e9SJustin Hibbits error = FM_MAC_ModifyMacAddr(sc->sc_mach, 5040083fc5cSJustin Hibbits (t_EnetAddr *)if_getlladdr(sc->sc_ifnet)); 5050aeed3e9SJustin Hibbits if (error != E_OK) { 5060aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't set MAC address.\n"); 5070aeed3e9SJustin Hibbits goto err; 5080aeed3e9SJustin Hibbits } 5090aeed3e9SJustin Hibbits 5100aeed3e9SJustin Hibbits /* Start MII polling */ 5110aeed3e9SJustin Hibbits if (sc->sc_mii) 5120aeed3e9SJustin Hibbits callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 5130aeed3e9SJustin Hibbits 5141510005cSJustin Hibbits if (if_getflags(sc->sc_ifnet) & IFF_UP) { 5150aeed3e9SJustin Hibbits error = dtsec_if_enable_locked(sc); 5160aeed3e9SJustin Hibbits if (error != 0) 5170aeed3e9SJustin Hibbits goto err; 5180aeed3e9SJustin Hibbits } else { 5190aeed3e9SJustin Hibbits error = dtsec_if_disable_locked(sc); 5200aeed3e9SJustin Hibbits if (error != 0) 5210aeed3e9SJustin Hibbits goto err; 5220aeed3e9SJustin Hibbits } 5230aeed3e9SJustin Hibbits 5240aeed3e9SJustin Hibbits return; 5250aeed3e9SJustin Hibbits 5260aeed3e9SJustin Hibbits err: 5270aeed3e9SJustin Hibbits dtsec_if_deinit_locked(sc); 5280aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "initialization error.\n"); 5290aeed3e9SJustin Hibbits return; 5300aeed3e9SJustin Hibbits } 5310aeed3e9SJustin Hibbits 5320aeed3e9SJustin Hibbits static void 5330aeed3e9SJustin Hibbits dtsec_if_init(void *data) 5340aeed3e9SJustin Hibbits { 5350aeed3e9SJustin Hibbits struct dtsec_softc *sc; 5360aeed3e9SJustin Hibbits 5370aeed3e9SJustin Hibbits sc = data; 5380aeed3e9SJustin Hibbits 5390aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5400aeed3e9SJustin Hibbits dtsec_if_init_locked(sc); 5410aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5420aeed3e9SJustin Hibbits } 5430aeed3e9SJustin Hibbits 5440aeed3e9SJustin Hibbits static void 5450083fc5cSJustin Hibbits dtsec_if_start(if_t ifp) 5460aeed3e9SJustin Hibbits { 5470aeed3e9SJustin Hibbits struct dtsec_softc *sc; 5480aeed3e9SJustin Hibbits 5490083fc5cSJustin Hibbits sc = if_getsoftc(ifp); 5500aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5510aeed3e9SJustin Hibbits sc->sc_start_locked(sc); 5520aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5530aeed3e9SJustin Hibbits } 5540aeed3e9SJustin Hibbits 5550aeed3e9SJustin Hibbits static void 5560083fc5cSJustin Hibbits dtsec_if_watchdog(if_t ifp) 5570aeed3e9SJustin Hibbits { 5580aeed3e9SJustin Hibbits /* TODO */ 5590aeed3e9SJustin Hibbits } 5600aeed3e9SJustin Hibbits /** @} */ 5610aeed3e9SJustin Hibbits 5620aeed3e9SJustin Hibbits 5630aeed3e9SJustin Hibbits /** 5640aeed3e9SJustin Hibbits * @group IFmedia routines. 5650aeed3e9SJustin Hibbits * @{ 5660aeed3e9SJustin Hibbits */ 5670aeed3e9SJustin Hibbits static int 5680083fc5cSJustin Hibbits dtsec_ifmedia_upd(if_t ifp) 5690aeed3e9SJustin Hibbits { 5700083fc5cSJustin Hibbits struct dtsec_softc *sc = if_getsoftc(ifp); 5710aeed3e9SJustin Hibbits 5720aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5730aeed3e9SJustin Hibbits mii_mediachg(sc->sc_mii); 5740aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5750aeed3e9SJustin Hibbits 5760aeed3e9SJustin Hibbits return (0); 5770aeed3e9SJustin Hibbits } 5780aeed3e9SJustin Hibbits 5790aeed3e9SJustin Hibbits static void 5800083fc5cSJustin Hibbits dtsec_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) 5810aeed3e9SJustin Hibbits { 5820083fc5cSJustin Hibbits struct dtsec_softc *sc = if_getsoftc(ifp); 5830aeed3e9SJustin Hibbits 5840aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5850aeed3e9SJustin Hibbits 5860aeed3e9SJustin Hibbits mii_pollstat(sc->sc_mii); 5870aeed3e9SJustin Hibbits 5880aeed3e9SJustin Hibbits ifmr->ifm_active = sc->sc_mii->mii_media_active; 5890aeed3e9SJustin Hibbits ifmr->ifm_status = sc->sc_mii->mii_media_status; 5900aeed3e9SJustin Hibbits 5910aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5920aeed3e9SJustin Hibbits } 5930aeed3e9SJustin Hibbits /** @} */ 5940aeed3e9SJustin Hibbits 5950aeed3e9SJustin Hibbits 5960aeed3e9SJustin Hibbits /** 5970aeed3e9SJustin Hibbits * @group dTSEC bus interface. 5980aeed3e9SJustin Hibbits * @{ 5990aeed3e9SJustin Hibbits */ 6000aeed3e9SJustin Hibbits static void 6010aeed3e9SJustin Hibbits dtsec_configure_mode(struct dtsec_softc *sc) 6020aeed3e9SJustin Hibbits { 6030aeed3e9SJustin Hibbits char tunable[64]; 6040aeed3e9SJustin Hibbits 6050aeed3e9SJustin Hibbits snprintf(tunable, sizeof(tunable), "%s.independent_mode", 6060aeed3e9SJustin Hibbits device_get_nameunit(sc->sc_dev)); 6070aeed3e9SJustin Hibbits 6080aeed3e9SJustin Hibbits sc->sc_mode = DTSEC_MODE_REGULAR; 6090aeed3e9SJustin Hibbits TUNABLE_INT_FETCH(tunable, &sc->sc_mode); 6100aeed3e9SJustin Hibbits 6110aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 6120aeed3e9SJustin Hibbits sc->sc_port_rx_init = dtsec_rm_fm_port_rx_init; 6130aeed3e9SJustin Hibbits sc->sc_port_tx_init = dtsec_rm_fm_port_tx_init; 6140aeed3e9SJustin Hibbits sc->sc_start_locked = dtsec_rm_if_start_locked; 6150aeed3e9SJustin Hibbits } else { 6160aeed3e9SJustin Hibbits sc->sc_port_rx_init = dtsec_im_fm_port_rx_init; 6170aeed3e9SJustin Hibbits sc->sc_port_tx_init = dtsec_im_fm_port_tx_init; 6180aeed3e9SJustin Hibbits sc->sc_start_locked = dtsec_im_if_start_locked; 6190aeed3e9SJustin Hibbits } 6200aeed3e9SJustin Hibbits 6210aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "Configured for %s mode.\n", 6220aeed3e9SJustin Hibbits (sc->sc_mode == DTSEC_MODE_REGULAR) ? "regular" : "independent"); 6230aeed3e9SJustin Hibbits } 6240aeed3e9SJustin Hibbits 6250aeed3e9SJustin Hibbits int 6260aeed3e9SJustin Hibbits dtsec_attach(device_t dev) 6270aeed3e9SJustin Hibbits { 6280aeed3e9SJustin Hibbits struct dtsec_softc *sc; 6291c41f28fSJustin Hibbits device_t parent; 6300aeed3e9SJustin Hibbits int error; 6310083fc5cSJustin Hibbits if_t ifp; 6320aeed3e9SJustin Hibbits 6330aeed3e9SJustin Hibbits sc = device_get_softc(dev); 6340aeed3e9SJustin Hibbits 6351c41f28fSJustin Hibbits parent = device_get_parent(dev); 6360aeed3e9SJustin Hibbits sc->sc_dev = dev; 6370aeed3e9SJustin Hibbits sc->sc_mac_mdio_irq = NO_IRQ; 6380aeed3e9SJustin Hibbits 6390aeed3e9SJustin Hibbits /* Check if MallocSmart allocator is ready */ 6400aeed3e9SJustin Hibbits if (XX_MallocSmartInit() != E_OK) 6410aeed3e9SJustin Hibbits return (ENXIO); 6420aeed3e9SJustin Hibbits 6430aeed3e9SJustin Hibbits /* Init locks */ 6440aeed3e9SJustin Hibbits mtx_init(&sc->sc_lock, device_get_nameunit(dev), 6450aeed3e9SJustin Hibbits "DTSEC Global Lock", MTX_DEF); 6460aeed3e9SJustin Hibbits 6470aeed3e9SJustin Hibbits mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev), 6480aeed3e9SJustin Hibbits "DTSEC MII Lock", MTX_DEF); 6490aeed3e9SJustin Hibbits 6500aeed3e9SJustin Hibbits /* Init callouts */ 6510aeed3e9SJustin Hibbits callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE); 6520aeed3e9SJustin Hibbits 6530aeed3e9SJustin Hibbits /* Read configuraton */ 6541c41f28fSJustin Hibbits if ((error = fman_get_handle(parent, &sc->sc_fmh)) != 0) 6550aeed3e9SJustin Hibbits return (error); 6560aeed3e9SJustin Hibbits 6571c41f28fSJustin Hibbits if ((error = fman_get_muram_handle(parent, &sc->sc_muramh)) != 0) 6580aeed3e9SJustin Hibbits return (error); 6590aeed3e9SJustin Hibbits 6601c41f28fSJustin Hibbits if ((error = fman_get_bushandle(parent, &sc->sc_fm_base)) != 0) 6610aeed3e9SJustin Hibbits return (error); 6620aeed3e9SJustin Hibbits 6630aeed3e9SJustin Hibbits /* Configure working mode */ 6640aeed3e9SJustin Hibbits dtsec_configure_mode(sc); 6650aeed3e9SJustin Hibbits 6660aeed3e9SJustin Hibbits /* If we are working in regular mode configure BMAN and QMAN */ 6670aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 6680aeed3e9SJustin Hibbits /* Create RX buffer pool */ 6690aeed3e9SJustin Hibbits error = dtsec_rm_pool_rx_init(sc); 6700aeed3e9SJustin Hibbits if (error != 0) 6710aeed3e9SJustin Hibbits return (EIO); 6720aeed3e9SJustin Hibbits 6730aeed3e9SJustin Hibbits /* Create RX frame queue range */ 6740aeed3e9SJustin Hibbits error = dtsec_rm_fqr_rx_init(sc); 6750aeed3e9SJustin Hibbits if (error != 0) 6760aeed3e9SJustin Hibbits return (EIO); 6770aeed3e9SJustin Hibbits 6780aeed3e9SJustin Hibbits /* Create frame info pool */ 6790aeed3e9SJustin Hibbits error = dtsec_rm_fi_pool_init(sc); 6800aeed3e9SJustin Hibbits if (error != 0) 6810aeed3e9SJustin Hibbits return (EIO); 6820aeed3e9SJustin Hibbits 6830aeed3e9SJustin Hibbits /* Create TX frame queue range */ 6840aeed3e9SJustin Hibbits error = dtsec_rm_fqr_tx_init(sc); 6850aeed3e9SJustin Hibbits if (error != 0) 6860aeed3e9SJustin Hibbits return (EIO); 6870aeed3e9SJustin Hibbits } 6880aeed3e9SJustin Hibbits 6890aeed3e9SJustin Hibbits /* Init FMan MAC module. */ 6900aeed3e9SJustin Hibbits error = dtsec_fm_mac_init(sc, sc->sc_mac_addr); 6910aeed3e9SJustin Hibbits if (error != 0) { 6920aeed3e9SJustin Hibbits dtsec_detach(dev); 6930aeed3e9SJustin Hibbits return (ENXIO); 6940aeed3e9SJustin Hibbits } 6950aeed3e9SJustin Hibbits 6960aeed3e9SJustin Hibbits /* Init FMan TX port */ 6970aeed3e9SJustin Hibbits error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev)); 6980aeed3e9SJustin Hibbits if (error != 0) { 6990aeed3e9SJustin Hibbits dtsec_detach(dev); 7000aeed3e9SJustin Hibbits return (ENXIO); 7010aeed3e9SJustin Hibbits } 7020aeed3e9SJustin Hibbits 7030aeed3e9SJustin Hibbits /* Init FMan RX port */ 7040aeed3e9SJustin Hibbits error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev)); 7050aeed3e9SJustin Hibbits if (error != 0) { 7060aeed3e9SJustin Hibbits dtsec_detach(dev); 7070aeed3e9SJustin Hibbits return (ENXIO); 7080aeed3e9SJustin Hibbits } 7090aeed3e9SJustin Hibbits 7100aeed3e9SJustin Hibbits /* Create network interface for upper layers */ 7110aeed3e9SJustin Hibbits ifp = sc->sc_ifnet = if_alloc(IFT_ETHER); 7120aeed3e9SJustin Hibbits if (ifp == NULL) { 7130aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "if_alloc() failed.\n"); 7140aeed3e9SJustin Hibbits dtsec_detach(dev); 7150aeed3e9SJustin Hibbits return (ENOMEM); 7160aeed3e9SJustin Hibbits } 7170aeed3e9SJustin Hibbits 7180083fc5cSJustin Hibbits if_setsoftc(ifp, sc); 7190083fc5cSJustin Hibbits 720*db550517SJustin Hibbits if_setflags(ifp, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST); 7210083fc5cSJustin Hibbits if_setinitfn(ifp, dtsec_if_init); 7220083fc5cSJustin Hibbits if_setstartfn(ifp, dtsec_if_start); 7230083fc5cSJustin Hibbits if_setioctlfn(ifp, dtsec_if_ioctl); 7240083fc5cSJustin Hibbits if_setsendqlen(ifp, IFQ_MAXLEN); 7250aeed3e9SJustin Hibbits 7260aeed3e9SJustin Hibbits if (sc->sc_phy_addr >= 0) 7270aeed3e9SJustin Hibbits if_initname(ifp, device_get_name(sc->sc_dev), 7280aeed3e9SJustin Hibbits device_get_unit(sc->sc_dev)); 7290aeed3e9SJustin Hibbits else 7300aeed3e9SJustin Hibbits if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev)); 7310aeed3e9SJustin Hibbits 7320aeed3e9SJustin Hibbits /* TODO */ 7330aeed3e9SJustin Hibbits #if 0 7340083fc5cSJustin Hibbits if_setsendqlen(ifp, TSEC_TX_NUM_DESC - 1); 7350083fc5cSJustin Hibbits if_setsendqready(ifp); 7360aeed3e9SJustin Hibbits #endif 7370083fc5cSJustin Hibbits 7380083fc5cSJustin Hibbits if_setcapenable(ifp, if_getcapabilities(ifp)); 7390aeed3e9SJustin Hibbits 7400aeed3e9SJustin Hibbits /* Attach PHY(s) */ 7410aeed3e9SJustin Hibbits error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd, 7420aeed3e9SJustin Hibbits dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr, 7430aeed3e9SJustin Hibbits MII_OFFSET_ANY, 0); 7440aeed3e9SJustin Hibbits if (error) { 7450aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error); 7460aeed3e9SJustin Hibbits dtsec_detach(sc->sc_dev); 7470aeed3e9SJustin Hibbits return (error); 7480aeed3e9SJustin Hibbits } 7490aeed3e9SJustin Hibbits sc->sc_mii = device_get_softc(sc->sc_mii_dev); 7500aeed3e9SJustin Hibbits 7510aeed3e9SJustin Hibbits /* Attach to stack */ 7520aeed3e9SJustin Hibbits ether_ifattach(ifp, sc->sc_mac_addr); 7530aeed3e9SJustin Hibbits 7540aeed3e9SJustin Hibbits return (0); 7550aeed3e9SJustin Hibbits } 7560aeed3e9SJustin Hibbits 7570aeed3e9SJustin Hibbits int 7580aeed3e9SJustin Hibbits dtsec_detach(device_t dev) 7590aeed3e9SJustin Hibbits { 7600aeed3e9SJustin Hibbits struct dtsec_softc *sc; 7610aeed3e9SJustin Hibbits if_t ifp; 7620aeed3e9SJustin Hibbits 7630aeed3e9SJustin Hibbits sc = device_get_softc(dev); 7640aeed3e9SJustin Hibbits ifp = sc->sc_ifnet; 7650aeed3e9SJustin Hibbits 7660aeed3e9SJustin Hibbits if (device_is_attached(dev)) { 7670aeed3e9SJustin Hibbits ether_ifdetach(ifp); 7680aeed3e9SJustin Hibbits /* Shutdown interface */ 7690aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 7700aeed3e9SJustin Hibbits dtsec_if_deinit_locked(sc); 7710aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 7720aeed3e9SJustin Hibbits } 7730aeed3e9SJustin Hibbits 7740aeed3e9SJustin Hibbits if (sc->sc_ifnet) { 7750aeed3e9SJustin Hibbits if_free(sc->sc_ifnet); 7760aeed3e9SJustin Hibbits sc->sc_ifnet = NULL; 7770aeed3e9SJustin Hibbits } 7780aeed3e9SJustin Hibbits 7790aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 7800aeed3e9SJustin Hibbits /* Free RX/TX FQRs */ 7810aeed3e9SJustin Hibbits dtsec_rm_fqr_rx_free(sc); 7820aeed3e9SJustin Hibbits dtsec_rm_fqr_tx_free(sc); 7830aeed3e9SJustin Hibbits 7840aeed3e9SJustin Hibbits /* Free frame info pool */ 7850aeed3e9SJustin Hibbits dtsec_rm_fi_pool_free(sc); 7860aeed3e9SJustin Hibbits 7870aeed3e9SJustin Hibbits /* Free RX buffer pool */ 7880aeed3e9SJustin Hibbits dtsec_rm_pool_rx_free(sc); 7890aeed3e9SJustin Hibbits } 7900aeed3e9SJustin Hibbits 7910aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 7920aeed3e9SJustin Hibbits dtsec_fm_port_free_both(sc); 7930aeed3e9SJustin Hibbits 7940aeed3e9SJustin Hibbits /* Destroy lock */ 7950aeed3e9SJustin Hibbits mtx_destroy(&sc->sc_lock); 7960aeed3e9SJustin Hibbits 7970aeed3e9SJustin Hibbits return (0); 7980aeed3e9SJustin Hibbits } 7990aeed3e9SJustin Hibbits 8000aeed3e9SJustin Hibbits int 8010aeed3e9SJustin Hibbits dtsec_suspend(device_t dev) 8020aeed3e9SJustin Hibbits { 8030aeed3e9SJustin Hibbits 8040aeed3e9SJustin Hibbits return (0); 8050aeed3e9SJustin Hibbits } 8060aeed3e9SJustin Hibbits 8070aeed3e9SJustin Hibbits int 8080aeed3e9SJustin Hibbits dtsec_resume(device_t dev) 8090aeed3e9SJustin Hibbits { 8100aeed3e9SJustin Hibbits 8110aeed3e9SJustin Hibbits return (0); 8120aeed3e9SJustin Hibbits } 8130aeed3e9SJustin Hibbits 8140aeed3e9SJustin Hibbits int 8150aeed3e9SJustin Hibbits dtsec_shutdown(device_t dev) 8160aeed3e9SJustin Hibbits { 8170aeed3e9SJustin Hibbits 8180aeed3e9SJustin Hibbits return (0); 8190aeed3e9SJustin Hibbits } 8200aeed3e9SJustin Hibbits /** @} */ 8210aeed3e9SJustin Hibbits 8220aeed3e9SJustin Hibbits 8230aeed3e9SJustin Hibbits /** 8240aeed3e9SJustin Hibbits * @group MII bus interface. 8250aeed3e9SJustin Hibbits * @{ 8260aeed3e9SJustin Hibbits */ 8270aeed3e9SJustin Hibbits int 8280aeed3e9SJustin Hibbits dtsec_miibus_readreg(device_t dev, int phy, int reg) 8290aeed3e9SJustin Hibbits { 8300aeed3e9SJustin Hibbits struct dtsec_softc *sc; 8310aeed3e9SJustin Hibbits 8320aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8330aeed3e9SJustin Hibbits 83447cabd04SJustin Hibbits return (MIIBUS_READREG(sc->sc_mdio, phy, reg)); 8350aeed3e9SJustin Hibbits } 8360aeed3e9SJustin Hibbits 8370aeed3e9SJustin Hibbits int 8380aeed3e9SJustin Hibbits dtsec_miibus_writereg(device_t dev, int phy, int reg, int value) 8390aeed3e9SJustin Hibbits { 84047cabd04SJustin Hibbits 8410aeed3e9SJustin Hibbits struct dtsec_softc *sc; 8420aeed3e9SJustin Hibbits 8430aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8440aeed3e9SJustin Hibbits 84547cabd04SJustin Hibbits return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value)); 8460aeed3e9SJustin Hibbits } 8470aeed3e9SJustin Hibbits 8480aeed3e9SJustin Hibbits void 8490aeed3e9SJustin Hibbits dtsec_miibus_statchg(device_t dev) 8500aeed3e9SJustin Hibbits { 8510aeed3e9SJustin Hibbits struct dtsec_softc *sc; 8520aeed3e9SJustin Hibbits e_EnetSpeed speed; 8530aeed3e9SJustin Hibbits bool duplex; 8540aeed3e9SJustin Hibbits int error; 8550aeed3e9SJustin Hibbits 8560aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8570aeed3e9SJustin Hibbits 8580aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 8590aeed3e9SJustin Hibbits 8600aeed3e9SJustin Hibbits duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX); 8610aeed3e9SJustin Hibbits 8620aeed3e9SJustin Hibbits switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 8630aeed3e9SJustin Hibbits case IFM_1000_T: 8640aeed3e9SJustin Hibbits case IFM_1000_SX: 8650aeed3e9SJustin Hibbits speed = e_ENET_SPEED_1000; 8660aeed3e9SJustin Hibbits break; 8670aeed3e9SJustin Hibbits 8680aeed3e9SJustin Hibbits case IFM_100_TX: 8690aeed3e9SJustin Hibbits speed = e_ENET_SPEED_100; 8700aeed3e9SJustin Hibbits break; 8710aeed3e9SJustin Hibbits 8720aeed3e9SJustin Hibbits case IFM_10_T: 8730aeed3e9SJustin Hibbits speed = e_ENET_SPEED_10; 8740aeed3e9SJustin Hibbits break; 8750aeed3e9SJustin Hibbits 8760aeed3e9SJustin Hibbits default: 8770aeed3e9SJustin Hibbits speed = e_ENET_SPEED_10; 8780aeed3e9SJustin Hibbits } 8790aeed3e9SJustin Hibbits 8800aeed3e9SJustin Hibbits error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex); 8810aeed3e9SJustin Hibbits if (error != E_OK) 8820aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "error while adjusting MAC speed.\n"); 8830aeed3e9SJustin Hibbits } 8840aeed3e9SJustin Hibbits /** @} */ 885