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 __FBSDID("$FreeBSD$"); 290aeed3e9SJustin Hibbits 300aeed3e9SJustin Hibbits #include <sys/param.h> 310aeed3e9SJustin Hibbits #include <sys/systm.h> 320aeed3e9SJustin Hibbits #include <sys/kernel.h> 330aeed3e9SJustin Hibbits #include <sys/module.h> 340aeed3e9SJustin Hibbits #include <sys/bus.h> 350aeed3e9SJustin Hibbits #include <sys/rman.h> 360aeed3e9SJustin Hibbits #include <sys/malloc.h> 370aeed3e9SJustin Hibbits #include <sys/mbuf.h> 380aeed3e9SJustin Hibbits #include <sys/socket.h> 390aeed3e9SJustin Hibbits #include <sys/sysctl.h> 400aeed3e9SJustin Hibbits #include <sys/sockio.h> 410aeed3e9SJustin Hibbits 420aeed3e9SJustin Hibbits #include <machine/bus.h> 430aeed3e9SJustin Hibbits #include <machine/resource.h> 440aeed3e9SJustin Hibbits 450aeed3e9SJustin Hibbits #include <net/ethernet.h> 460aeed3e9SJustin Hibbits #include <net/if.h> 470aeed3e9SJustin Hibbits #include <net/if_dl.h> 480aeed3e9SJustin Hibbits #include <net/if_media.h> 490aeed3e9SJustin Hibbits #include <net/if_types.h> 500aeed3e9SJustin Hibbits #include <net/if_arp.h> 510aeed3e9SJustin Hibbits 520aeed3e9SJustin Hibbits #include <dev/mii/mii.h> 530aeed3e9SJustin Hibbits #include <dev/mii/miivar.h> 540aeed3e9SJustin Hibbits #include <dev/ofw/ofw_bus.h> 550aeed3e9SJustin Hibbits #include <dev/ofw/ofw_bus_subr.h> 560aeed3e9SJustin Hibbits #include <dev/ofw/openfirm.h> 570aeed3e9SJustin Hibbits 580aeed3e9SJustin Hibbits #include "miibus_if.h" 590aeed3e9SJustin Hibbits 60852ba100SJustin Hibbits #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h> 610aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h> 620aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h> 630aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/xx_ext.h> 640aeed3e9SJustin Hibbits 650aeed3e9SJustin Hibbits #include "fman.h" 660aeed3e9SJustin Hibbits #include "if_dtsec.h" 670aeed3e9SJustin Hibbits #include "if_dtsec_im.h" 680aeed3e9SJustin Hibbits #include "if_dtsec_rm.h" 690aeed3e9SJustin Hibbits 70*c3f3cd05SJustin Hibbits #define DTSEC_MIN_FRAME_SIZE 64 71*c3f3cd05SJustin Hibbits #define DTSEC_MAX_FRAME_SIZE 9600 72*c3f3cd05SJustin Hibbits 73*c3f3cd05SJustin Hibbits #define DTSEC_REG_MAXFRM 0x110 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 328*c3f3cd05SJustin Hibbits dtsec_set_mtu(struct dtsec_softc *sc, unsigned int mtu) 329*c3f3cd05SJustin Hibbits { 330*c3f3cd05SJustin Hibbits 331*c3f3cd05SJustin Hibbits mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN; 332*c3f3cd05SJustin Hibbits 333*c3f3cd05SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 334*c3f3cd05SJustin Hibbits 335*c3f3cd05SJustin Hibbits if (mtu >= DTSEC_MIN_FRAME_SIZE && mtu <= DTSEC_MAX_FRAME_SIZE) { 336*c3f3cd05SJustin Hibbits bus_write_4(sc->sc_mem, DTSEC_REG_MAXFRM, mtu); 337*c3f3cd05SJustin Hibbits return (mtu); 338*c3f3cd05SJustin Hibbits } 339*c3f3cd05SJustin Hibbits 340*c3f3cd05SJustin Hibbits return (0); 341*c3f3cd05SJustin Hibbits } 342*c3f3cd05SJustin Hibbits 343*c3f3cd05SJustin Hibbits static int 3440aeed3e9SJustin Hibbits dtsec_if_enable_locked(struct dtsec_softc *sc) 3450aeed3e9SJustin Hibbits { 3460aeed3e9SJustin Hibbits int error; 3470aeed3e9SJustin Hibbits 3480aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 3490aeed3e9SJustin Hibbits 3500aeed3e9SJustin Hibbits error = FM_MAC_Enable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 3510aeed3e9SJustin Hibbits if (error != E_OK) 3520aeed3e9SJustin Hibbits return (EIO); 3530aeed3e9SJustin Hibbits 3540aeed3e9SJustin Hibbits error = FM_PORT_Enable(sc->sc_rxph); 3550aeed3e9SJustin Hibbits if (error != E_OK) 3560aeed3e9SJustin Hibbits return (EIO); 3570aeed3e9SJustin Hibbits 3580aeed3e9SJustin Hibbits error = FM_PORT_Enable(sc->sc_txph); 3590aeed3e9SJustin Hibbits if (error != E_OK) 3600aeed3e9SJustin Hibbits return (EIO); 3610aeed3e9SJustin Hibbits 3620aeed3e9SJustin Hibbits sc->sc_ifnet->if_drv_flags |= IFF_DRV_RUNNING; 3630aeed3e9SJustin Hibbits 3640aeed3e9SJustin Hibbits /* Refresh link state */ 3650aeed3e9SJustin Hibbits dtsec_miibus_statchg(sc->sc_dev); 3660aeed3e9SJustin Hibbits 3670aeed3e9SJustin Hibbits return (0); 3680aeed3e9SJustin Hibbits } 3690aeed3e9SJustin Hibbits 3700aeed3e9SJustin Hibbits static int 3710aeed3e9SJustin Hibbits dtsec_if_disable_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_Disable(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_Disable(sc->sc_rxph); 3820aeed3e9SJustin Hibbits if (error != E_OK) 3830aeed3e9SJustin Hibbits return (EIO); 3840aeed3e9SJustin Hibbits 3850aeed3e9SJustin Hibbits error = FM_PORT_Disable(sc->sc_txph); 3860aeed3e9SJustin Hibbits if (error != E_OK) 3870aeed3e9SJustin Hibbits return (EIO); 3880aeed3e9SJustin Hibbits 3890aeed3e9SJustin Hibbits sc->sc_ifnet->if_drv_flags &= ~IFF_DRV_RUNNING; 3900aeed3e9SJustin Hibbits 3910aeed3e9SJustin Hibbits return (0); 3920aeed3e9SJustin Hibbits } 3930aeed3e9SJustin Hibbits 3940aeed3e9SJustin Hibbits static int 3950aeed3e9SJustin Hibbits dtsec_if_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 3960aeed3e9SJustin Hibbits { 3970aeed3e9SJustin Hibbits struct dtsec_softc *sc; 3980aeed3e9SJustin Hibbits struct ifreq *ifr; 3990aeed3e9SJustin Hibbits int error; 4000aeed3e9SJustin Hibbits 4010aeed3e9SJustin Hibbits sc = ifp->if_softc; 4020aeed3e9SJustin Hibbits ifr = (struct ifreq *)data; 4030aeed3e9SJustin Hibbits error = 0; 4040aeed3e9SJustin Hibbits 4050aeed3e9SJustin Hibbits /* Basic functionality to achieve media status reports */ 4060aeed3e9SJustin Hibbits switch (command) { 407*c3f3cd05SJustin Hibbits case SIOCSIFMTU: 408*c3f3cd05SJustin Hibbits DTSEC_LOCK(sc); 409*c3f3cd05SJustin Hibbits if (dtsec_set_mtu(sc, ifr->ifr_mtu)) 410*c3f3cd05SJustin Hibbits ifp->if_mtu = ifr->ifr_mtu; 411*c3f3cd05SJustin Hibbits else 412*c3f3cd05SJustin Hibbits error = EINVAL; 413*c3f3cd05SJustin Hibbits DTSEC_UNLOCK(sc); 414*c3f3cd05SJustin Hibbits break; 4150aeed3e9SJustin Hibbits case SIOCSIFFLAGS: 4160aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4170aeed3e9SJustin Hibbits 4180aeed3e9SJustin Hibbits if (sc->sc_ifnet->if_flags & IFF_UP) 4190aeed3e9SJustin Hibbits error = dtsec_if_enable_locked(sc); 4200aeed3e9SJustin Hibbits else 4210aeed3e9SJustin Hibbits error = dtsec_if_disable_locked(sc); 4220aeed3e9SJustin Hibbits 4230aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4240aeed3e9SJustin Hibbits break; 4250aeed3e9SJustin Hibbits 4260aeed3e9SJustin Hibbits case SIOCGIFMEDIA: 4270aeed3e9SJustin Hibbits case SIOCSIFMEDIA: 4280aeed3e9SJustin Hibbits error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, 4290aeed3e9SJustin Hibbits command); 4300aeed3e9SJustin Hibbits break; 4310aeed3e9SJustin Hibbits 4320aeed3e9SJustin Hibbits default: 4330aeed3e9SJustin Hibbits error = ether_ioctl(ifp, command, data); 4340aeed3e9SJustin Hibbits } 4350aeed3e9SJustin Hibbits 4360aeed3e9SJustin Hibbits return (error); 4370aeed3e9SJustin Hibbits } 4380aeed3e9SJustin Hibbits 4390aeed3e9SJustin Hibbits static void 4400aeed3e9SJustin Hibbits dtsec_if_tick(void *arg) 4410aeed3e9SJustin Hibbits { 4420aeed3e9SJustin Hibbits struct dtsec_softc *sc; 4430aeed3e9SJustin Hibbits 4440aeed3e9SJustin Hibbits sc = arg; 4450aeed3e9SJustin Hibbits 4460aeed3e9SJustin Hibbits /* TODO */ 4470aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4480aeed3e9SJustin Hibbits 4490aeed3e9SJustin Hibbits mii_tick(sc->sc_mii); 4500aeed3e9SJustin Hibbits callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 4510aeed3e9SJustin Hibbits 4520aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4530aeed3e9SJustin Hibbits } 4540aeed3e9SJustin Hibbits 4550aeed3e9SJustin Hibbits static void 4560aeed3e9SJustin Hibbits dtsec_if_deinit_locked(struct dtsec_softc *sc) 4570aeed3e9SJustin Hibbits { 4580aeed3e9SJustin Hibbits 4590aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 4600aeed3e9SJustin Hibbits 4610aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4620aeed3e9SJustin Hibbits callout_drain(&sc->sc_tick_callout); 4630aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4640aeed3e9SJustin Hibbits } 4650aeed3e9SJustin Hibbits 4660aeed3e9SJustin Hibbits static void 4670aeed3e9SJustin Hibbits dtsec_if_init_locked(struct dtsec_softc *sc) 4680aeed3e9SJustin Hibbits { 4690aeed3e9SJustin Hibbits int error; 4700aeed3e9SJustin Hibbits 4710aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 4720aeed3e9SJustin Hibbits 4730aeed3e9SJustin Hibbits /* Set MAC address */ 4740aeed3e9SJustin Hibbits error = FM_MAC_ModifyMacAddr(sc->sc_mach, 4750aeed3e9SJustin Hibbits (t_EnetAddr *)IF_LLADDR(sc->sc_ifnet)); 4760aeed3e9SJustin Hibbits if (error != E_OK) { 4770aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't set MAC address.\n"); 4780aeed3e9SJustin Hibbits goto err; 4790aeed3e9SJustin Hibbits } 4800aeed3e9SJustin Hibbits 4810aeed3e9SJustin Hibbits /* Start MII polling */ 4820aeed3e9SJustin Hibbits if (sc->sc_mii) 4830aeed3e9SJustin Hibbits callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 4840aeed3e9SJustin Hibbits 4850aeed3e9SJustin Hibbits if (sc->sc_ifnet->if_flags & IFF_UP) { 4860aeed3e9SJustin Hibbits error = dtsec_if_enable_locked(sc); 4870aeed3e9SJustin Hibbits if (error != 0) 4880aeed3e9SJustin Hibbits goto err; 4890aeed3e9SJustin Hibbits } else { 4900aeed3e9SJustin Hibbits error = dtsec_if_disable_locked(sc); 4910aeed3e9SJustin Hibbits if (error != 0) 4920aeed3e9SJustin Hibbits goto err; 4930aeed3e9SJustin Hibbits } 4940aeed3e9SJustin Hibbits 4950aeed3e9SJustin Hibbits return; 4960aeed3e9SJustin Hibbits 4970aeed3e9SJustin Hibbits err: 4980aeed3e9SJustin Hibbits dtsec_if_deinit_locked(sc); 4990aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "initialization error.\n"); 5000aeed3e9SJustin Hibbits return; 5010aeed3e9SJustin Hibbits } 5020aeed3e9SJustin Hibbits 5030aeed3e9SJustin Hibbits static void 5040aeed3e9SJustin Hibbits dtsec_if_init(void *data) 5050aeed3e9SJustin Hibbits { 5060aeed3e9SJustin Hibbits struct dtsec_softc *sc; 5070aeed3e9SJustin Hibbits 5080aeed3e9SJustin Hibbits sc = data; 5090aeed3e9SJustin Hibbits 5100aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5110aeed3e9SJustin Hibbits dtsec_if_init_locked(sc); 5120aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5130aeed3e9SJustin Hibbits } 5140aeed3e9SJustin Hibbits 5150aeed3e9SJustin Hibbits static void 5160aeed3e9SJustin Hibbits dtsec_if_start(struct ifnet *ifp) 5170aeed3e9SJustin Hibbits { 5180aeed3e9SJustin Hibbits struct dtsec_softc *sc; 5190aeed3e9SJustin Hibbits 5200aeed3e9SJustin Hibbits sc = ifp->if_softc; 5210aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5220aeed3e9SJustin Hibbits sc->sc_start_locked(sc); 5230aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5240aeed3e9SJustin Hibbits } 5250aeed3e9SJustin Hibbits 5260aeed3e9SJustin Hibbits static void 5270aeed3e9SJustin Hibbits dtsec_if_watchdog(struct ifnet *ifp) 5280aeed3e9SJustin Hibbits { 5290aeed3e9SJustin Hibbits /* TODO */ 5300aeed3e9SJustin Hibbits } 5310aeed3e9SJustin Hibbits /** @} */ 5320aeed3e9SJustin Hibbits 5330aeed3e9SJustin Hibbits 5340aeed3e9SJustin Hibbits /** 5350aeed3e9SJustin Hibbits * @group IFmedia routines. 5360aeed3e9SJustin Hibbits * @{ 5370aeed3e9SJustin Hibbits */ 5380aeed3e9SJustin Hibbits static int 5390aeed3e9SJustin Hibbits dtsec_ifmedia_upd(struct ifnet *ifp) 5400aeed3e9SJustin Hibbits { 5410aeed3e9SJustin Hibbits struct dtsec_softc *sc = ifp->if_softc; 5420aeed3e9SJustin Hibbits 5430aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5440aeed3e9SJustin Hibbits mii_mediachg(sc->sc_mii); 5450aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5460aeed3e9SJustin Hibbits 5470aeed3e9SJustin Hibbits return (0); 5480aeed3e9SJustin Hibbits } 5490aeed3e9SJustin Hibbits 5500aeed3e9SJustin Hibbits static void 5510aeed3e9SJustin Hibbits dtsec_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 5520aeed3e9SJustin Hibbits { 5530aeed3e9SJustin Hibbits struct dtsec_softc *sc = ifp->if_softc; 5540aeed3e9SJustin Hibbits 5550aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5560aeed3e9SJustin Hibbits 5570aeed3e9SJustin Hibbits mii_pollstat(sc->sc_mii); 5580aeed3e9SJustin Hibbits 5590aeed3e9SJustin Hibbits ifmr->ifm_active = sc->sc_mii->mii_media_active; 5600aeed3e9SJustin Hibbits ifmr->ifm_status = sc->sc_mii->mii_media_status; 5610aeed3e9SJustin Hibbits 5620aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5630aeed3e9SJustin Hibbits } 5640aeed3e9SJustin Hibbits /** @} */ 5650aeed3e9SJustin Hibbits 5660aeed3e9SJustin Hibbits 5670aeed3e9SJustin Hibbits /** 5680aeed3e9SJustin Hibbits * @group dTSEC bus interface. 5690aeed3e9SJustin Hibbits * @{ 5700aeed3e9SJustin Hibbits */ 5710aeed3e9SJustin Hibbits static void 5720aeed3e9SJustin Hibbits dtsec_configure_mode(struct dtsec_softc *sc) 5730aeed3e9SJustin Hibbits { 5740aeed3e9SJustin Hibbits char tunable[64]; 5750aeed3e9SJustin Hibbits 5760aeed3e9SJustin Hibbits snprintf(tunable, sizeof(tunable), "%s.independent_mode", 5770aeed3e9SJustin Hibbits device_get_nameunit(sc->sc_dev)); 5780aeed3e9SJustin Hibbits 5790aeed3e9SJustin Hibbits sc->sc_mode = DTSEC_MODE_REGULAR; 5800aeed3e9SJustin Hibbits TUNABLE_INT_FETCH(tunable, &sc->sc_mode); 5810aeed3e9SJustin Hibbits 5820aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 5830aeed3e9SJustin Hibbits sc->sc_port_rx_init = dtsec_rm_fm_port_rx_init; 5840aeed3e9SJustin Hibbits sc->sc_port_tx_init = dtsec_rm_fm_port_tx_init; 5850aeed3e9SJustin Hibbits sc->sc_start_locked = dtsec_rm_if_start_locked; 5860aeed3e9SJustin Hibbits } else { 5870aeed3e9SJustin Hibbits sc->sc_port_rx_init = dtsec_im_fm_port_rx_init; 5880aeed3e9SJustin Hibbits sc->sc_port_tx_init = dtsec_im_fm_port_tx_init; 5890aeed3e9SJustin Hibbits sc->sc_start_locked = dtsec_im_if_start_locked; 5900aeed3e9SJustin Hibbits } 5910aeed3e9SJustin Hibbits 5920aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "Configured for %s mode.\n", 5930aeed3e9SJustin Hibbits (sc->sc_mode == DTSEC_MODE_REGULAR) ? "regular" : "independent"); 5940aeed3e9SJustin Hibbits } 5950aeed3e9SJustin Hibbits 5960aeed3e9SJustin Hibbits int 5970aeed3e9SJustin Hibbits dtsec_attach(device_t dev) 5980aeed3e9SJustin Hibbits { 5990aeed3e9SJustin Hibbits struct dtsec_softc *sc; 6001c41f28fSJustin Hibbits device_t parent; 6010aeed3e9SJustin Hibbits int error; 6020aeed3e9SJustin Hibbits struct ifnet *ifp; 6030aeed3e9SJustin Hibbits 6040aeed3e9SJustin Hibbits sc = device_get_softc(dev); 6050aeed3e9SJustin Hibbits 6061c41f28fSJustin Hibbits parent = device_get_parent(dev); 6070aeed3e9SJustin Hibbits sc->sc_dev = dev; 6080aeed3e9SJustin Hibbits sc->sc_mac_mdio_irq = NO_IRQ; 6090aeed3e9SJustin Hibbits 6100aeed3e9SJustin Hibbits /* Check if MallocSmart allocator is ready */ 6110aeed3e9SJustin Hibbits if (XX_MallocSmartInit() != E_OK) 6120aeed3e9SJustin Hibbits return (ENXIO); 6130aeed3e9SJustin Hibbits 6140aeed3e9SJustin Hibbits /* Init locks */ 6150aeed3e9SJustin Hibbits mtx_init(&sc->sc_lock, device_get_nameunit(dev), 6160aeed3e9SJustin Hibbits "DTSEC Global Lock", MTX_DEF); 6170aeed3e9SJustin Hibbits 6180aeed3e9SJustin Hibbits mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev), 6190aeed3e9SJustin Hibbits "DTSEC MII Lock", MTX_DEF); 6200aeed3e9SJustin Hibbits 6210aeed3e9SJustin Hibbits /* Init callouts */ 6220aeed3e9SJustin Hibbits callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE); 6230aeed3e9SJustin Hibbits 6240aeed3e9SJustin Hibbits /* Read configuraton */ 6251c41f28fSJustin Hibbits if ((error = fman_get_handle(parent, &sc->sc_fmh)) != 0) 6260aeed3e9SJustin Hibbits return (error); 6270aeed3e9SJustin Hibbits 6281c41f28fSJustin Hibbits if ((error = fman_get_muram_handle(parent, &sc->sc_muramh)) != 0) 6290aeed3e9SJustin Hibbits return (error); 6300aeed3e9SJustin Hibbits 6311c41f28fSJustin Hibbits if ((error = fman_get_bushandle(parent, &sc->sc_fm_base)) != 0) 6320aeed3e9SJustin Hibbits return (error); 6330aeed3e9SJustin Hibbits 6340aeed3e9SJustin Hibbits /* Configure working mode */ 6350aeed3e9SJustin Hibbits dtsec_configure_mode(sc); 6360aeed3e9SJustin Hibbits 6370aeed3e9SJustin Hibbits /* If we are working in regular mode configure BMAN and QMAN */ 6380aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 6390aeed3e9SJustin Hibbits /* Create RX buffer pool */ 6400aeed3e9SJustin Hibbits error = dtsec_rm_pool_rx_init(sc); 6410aeed3e9SJustin Hibbits if (error != 0) 6420aeed3e9SJustin Hibbits return (EIO); 6430aeed3e9SJustin Hibbits 6440aeed3e9SJustin Hibbits /* Create RX frame queue range */ 6450aeed3e9SJustin Hibbits error = dtsec_rm_fqr_rx_init(sc); 6460aeed3e9SJustin Hibbits if (error != 0) 6470aeed3e9SJustin Hibbits return (EIO); 6480aeed3e9SJustin Hibbits 6490aeed3e9SJustin Hibbits /* Create frame info pool */ 6500aeed3e9SJustin Hibbits error = dtsec_rm_fi_pool_init(sc); 6510aeed3e9SJustin Hibbits if (error != 0) 6520aeed3e9SJustin Hibbits return (EIO); 6530aeed3e9SJustin Hibbits 6540aeed3e9SJustin Hibbits /* Create TX frame queue range */ 6550aeed3e9SJustin Hibbits error = dtsec_rm_fqr_tx_init(sc); 6560aeed3e9SJustin Hibbits if (error != 0) 6570aeed3e9SJustin Hibbits return (EIO); 6580aeed3e9SJustin Hibbits } 6590aeed3e9SJustin Hibbits 6600aeed3e9SJustin Hibbits /* Init FMan MAC module. */ 6610aeed3e9SJustin Hibbits error = dtsec_fm_mac_init(sc, sc->sc_mac_addr); 6620aeed3e9SJustin Hibbits if (error != 0) { 6630aeed3e9SJustin Hibbits dtsec_detach(dev); 6640aeed3e9SJustin Hibbits return (ENXIO); 6650aeed3e9SJustin Hibbits } 6660aeed3e9SJustin Hibbits 6670aeed3e9SJustin Hibbits /* Init FMan TX port */ 6680aeed3e9SJustin Hibbits error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev)); 6690aeed3e9SJustin Hibbits if (error != 0) { 6700aeed3e9SJustin Hibbits dtsec_detach(dev); 6710aeed3e9SJustin Hibbits return (ENXIO); 6720aeed3e9SJustin Hibbits } 6730aeed3e9SJustin Hibbits 6740aeed3e9SJustin Hibbits /* Init FMan RX port */ 6750aeed3e9SJustin Hibbits error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev)); 6760aeed3e9SJustin Hibbits if (error != 0) { 6770aeed3e9SJustin Hibbits dtsec_detach(dev); 6780aeed3e9SJustin Hibbits return (ENXIO); 6790aeed3e9SJustin Hibbits } 6800aeed3e9SJustin Hibbits 6810aeed3e9SJustin Hibbits /* Create network interface for upper layers */ 6820aeed3e9SJustin Hibbits ifp = sc->sc_ifnet = if_alloc(IFT_ETHER); 6830aeed3e9SJustin Hibbits if (ifp == NULL) { 6840aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "if_alloc() failed.\n"); 6850aeed3e9SJustin Hibbits dtsec_detach(dev); 6860aeed3e9SJustin Hibbits return (ENOMEM); 6870aeed3e9SJustin Hibbits } 6880aeed3e9SJustin Hibbits 6890aeed3e9SJustin Hibbits ifp->if_softc = sc; 6900aeed3e9SJustin Hibbits ifp->if_mtu = ETHERMTU; /* TODO: Configure */ 6910aeed3e9SJustin Hibbits ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; 6920aeed3e9SJustin Hibbits ifp->if_init = dtsec_if_init; 6930aeed3e9SJustin Hibbits ifp->if_start = dtsec_if_start; 6940aeed3e9SJustin Hibbits ifp->if_ioctl = dtsec_if_ioctl; 6950aeed3e9SJustin Hibbits ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 6960aeed3e9SJustin Hibbits 6970aeed3e9SJustin Hibbits if (sc->sc_phy_addr >= 0) 6980aeed3e9SJustin Hibbits if_initname(ifp, device_get_name(sc->sc_dev), 6990aeed3e9SJustin Hibbits device_get_unit(sc->sc_dev)); 7000aeed3e9SJustin Hibbits else 7010aeed3e9SJustin Hibbits if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev)); 7020aeed3e9SJustin Hibbits 7030aeed3e9SJustin Hibbits /* TODO */ 7040aeed3e9SJustin Hibbits #if 0 7050aeed3e9SJustin Hibbits IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_TX_NUM_DESC - 1); 7060aeed3e9SJustin Hibbits ifp->if_snd.ifq_drv_maxlen = TSEC_TX_NUM_DESC - 1; 7070aeed3e9SJustin Hibbits IFQ_SET_READY(&ifp->if_snd); 7080aeed3e9SJustin Hibbits #endif 709*c3f3cd05SJustin Hibbits ifp->if_capabilities = IFCAP_JUMBO_MTU; /* TODO: HWCSUM */ 7100aeed3e9SJustin Hibbits ifp->if_capenable = ifp->if_capabilities; 7110aeed3e9SJustin Hibbits 7120aeed3e9SJustin Hibbits /* Attach PHY(s) */ 7130aeed3e9SJustin Hibbits error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd, 7140aeed3e9SJustin Hibbits dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr, 7150aeed3e9SJustin Hibbits MII_OFFSET_ANY, 0); 7160aeed3e9SJustin Hibbits if (error) { 7170aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error); 7180aeed3e9SJustin Hibbits dtsec_detach(sc->sc_dev); 7190aeed3e9SJustin Hibbits return (error); 7200aeed3e9SJustin Hibbits } 7210aeed3e9SJustin Hibbits sc->sc_mii = device_get_softc(sc->sc_mii_dev); 7220aeed3e9SJustin Hibbits 7230aeed3e9SJustin Hibbits /* Attach to stack */ 7240aeed3e9SJustin Hibbits ether_ifattach(ifp, sc->sc_mac_addr); 7250aeed3e9SJustin Hibbits 7260aeed3e9SJustin Hibbits return (0); 7270aeed3e9SJustin Hibbits } 7280aeed3e9SJustin Hibbits 7290aeed3e9SJustin Hibbits int 7300aeed3e9SJustin Hibbits dtsec_detach(device_t dev) 7310aeed3e9SJustin Hibbits { 7320aeed3e9SJustin Hibbits struct dtsec_softc *sc; 7330aeed3e9SJustin Hibbits if_t ifp; 7340aeed3e9SJustin Hibbits 7350aeed3e9SJustin Hibbits sc = device_get_softc(dev); 7360aeed3e9SJustin Hibbits ifp = sc->sc_ifnet; 7370aeed3e9SJustin Hibbits 7380aeed3e9SJustin Hibbits if (device_is_attached(dev)) { 7390aeed3e9SJustin Hibbits ether_ifdetach(ifp); 7400aeed3e9SJustin Hibbits /* Shutdown interface */ 7410aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 7420aeed3e9SJustin Hibbits dtsec_if_deinit_locked(sc); 7430aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 7440aeed3e9SJustin Hibbits } 7450aeed3e9SJustin Hibbits 7460aeed3e9SJustin Hibbits if (sc->sc_ifnet) { 7470aeed3e9SJustin Hibbits if_free(sc->sc_ifnet); 7480aeed3e9SJustin Hibbits sc->sc_ifnet = NULL; 7490aeed3e9SJustin Hibbits } 7500aeed3e9SJustin Hibbits 7510aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 7520aeed3e9SJustin Hibbits /* Free RX/TX FQRs */ 7530aeed3e9SJustin Hibbits dtsec_rm_fqr_rx_free(sc); 7540aeed3e9SJustin Hibbits dtsec_rm_fqr_tx_free(sc); 7550aeed3e9SJustin Hibbits 7560aeed3e9SJustin Hibbits /* Free frame info pool */ 7570aeed3e9SJustin Hibbits dtsec_rm_fi_pool_free(sc); 7580aeed3e9SJustin Hibbits 7590aeed3e9SJustin Hibbits /* Free RX buffer pool */ 7600aeed3e9SJustin Hibbits dtsec_rm_pool_rx_free(sc); 7610aeed3e9SJustin Hibbits } 7620aeed3e9SJustin Hibbits 7630aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 7640aeed3e9SJustin Hibbits dtsec_fm_port_free_both(sc); 7650aeed3e9SJustin Hibbits 7660aeed3e9SJustin Hibbits /* Destroy lock */ 7670aeed3e9SJustin Hibbits mtx_destroy(&sc->sc_lock); 7680aeed3e9SJustin Hibbits 7690aeed3e9SJustin Hibbits return (0); 7700aeed3e9SJustin Hibbits } 7710aeed3e9SJustin Hibbits 7720aeed3e9SJustin Hibbits int 7730aeed3e9SJustin Hibbits dtsec_suspend(device_t dev) 7740aeed3e9SJustin Hibbits { 7750aeed3e9SJustin Hibbits 7760aeed3e9SJustin Hibbits return (0); 7770aeed3e9SJustin Hibbits } 7780aeed3e9SJustin Hibbits 7790aeed3e9SJustin Hibbits int 7800aeed3e9SJustin Hibbits dtsec_resume(device_t dev) 7810aeed3e9SJustin Hibbits { 7820aeed3e9SJustin Hibbits 7830aeed3e9SJustin Hibbits return (0); 7840aeed3e9SJustin Hibbits } 7850aeed3e9SJustin Hibbits 7860aeed3e9SJustin Hibbits int 7870aeed3e9SJustin Hibbits dtsec_shutdown(device_t dev) 7880aeed3e9SJustin Hibbits { 7890aeed3e9SJustin Hibbits 7900aeed3e9SJustin Hibbits return (0); 7910aeed3e9SJustin Hibbits } 7920aeed3e9SJustin Hibbits /** @} */ 7930aeed3e9SJustin Hibbits 7940aeed3e9SJustin Hibbits 7950aeed3e9SJustin Hibbits /** 7960aeed3e9SJustin Hibbits * @group MII bus interface. 7970aeed3e9SJustin Hibbits * @{ 7980aeed3e9SJustin Hibbits */ 7990aeed3e9SJustin Hibbits int 8000aeed3e9SJustin Hibbits dtsec_miibus_readreg(device_t dev, int phy, int reg) 8010aeed3e9SJustin Hibbits { 8020aeed3e9SJustin Hibbits struct dtsec_softc *sc; 8030aeed3e9SJustin Hibbits 8040aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8050aeed3e9SJustin Hibbits 80647cabd04SJustin Hibbits return (MIIBUS_READREG(sc->sc_mdio, phy, reg)); 8070aeed3e9SJustin Hibbits } 8080aeed3e9SJustin Hibbits 8090aeed3e9SJustin Hibbits int 8100aeed3e9SJustin Hibbits dtsec_miibus_writereg(device_t dev, int phy, int reg, int value) 8110aeed3e9SJustin Hibbits { 81247cabd04SJustin Hibbits 8130aeed3e9SJustin Hibbits struct dtsec_softc *sc; 8140aeed3e9SJustin Hibbits 8150aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8160aeed3e9SJustin Hibbits 81747cabd04SJustin Hibbits return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value)); 8180aeed3e9SJustin Hibbits } 8190aeed3e9SJustin Hibbits 8200aeed3e9SJustin Hibbits void 8210aeed3e9SJustin Hibbits dtsec_miibus_statchg(device_t dev) 8220aeed3e9SJustin Hibbits { 8230aeed3e9SJustin Hibbits struct dtsec_softc *sc; 8240aeed3e9SJustin Hibbits e_EnetSpeed speed; 8250aeed3e9SJustin Hibbits bool duplex; 8260aeed3e9SJustin Hibbits int error; 8270aeed3e9SJustin Hibbits 8280aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8290aeed3e9SJustin Hibbits 8300aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 8310aeed3e9SJustin Hibbits 8320aeed3e9SJustin Hibbits duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX); 8330aeed3e9SJustin Hibbits 8340aeed3e9SJustin Hibbits switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 8350aeed3e9SJustin Hibbits case IFM_1000_T: 8360aeed3e9SJustin Hibbits case IFM_1000_SX: 8370aeed3e9SJustin Hibbits speed = e_ENET_SPEED_1000; 8380aeed3e9SJustin Hibbits break; 8390aeed3e9SJustin Hibbits 8400aeed3e9SJustin Hibbits case IFM_100_TX: 8410aeed3e9SJustin Hibbits speed = e_ENET_SPEED_100; 8420aeed3e9SJustin Hibbits break; 8430aeed3e9SJustin Hibbits 8440aeed3e9SJustin Hibbits case IFM_10_T: 8450aeed3e9SJustin Hibbits speed = e_ENET_SPEED_10; 8460aeed3e9SJustin Hibbits break; 8470aeed3e9SJustin Hibbits 8480aeed3e9SJustin Hibbits default: 8490aeed3e9SJustin Hibbits speed = e_ENET_SPEED_10; 8500aeed3e9SJustin Hibbits } 8510aeed3e9SJustin Hibbits 8520aeed3e9SJustin Hibbits error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex); 8530aeed3e9SJustin Hibbits if (error != E_OK) 8540aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "error while adjusting MAC speed.\n"); 8550aeed3e9SJustin Hibbits } 8560aeed3e9SJustin Hibbits /** @} */ 857