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 60*852ba100SJustin 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 700aeed3e9SJustin Hibbits 710aeed3e9SJustin Hibbits /** 720aeed3e9SJustin Hibbits * @group dTSEC private defines. 730aeed3e9SJustin Hibbits * @{ 740aeed3e9SJustin Hibbits */ 750aeed3e9SJustin Hibbits /** 760aeed3e9SJustin Hibbits * dTSEC FMan MAC exceptions info struct. 770aeed3e9SJustin Hibbits */ 780aeed3e9SJustin Hibbits struct dtsec_fm_mac_ex_str { 790aeed3e9SJustin Hibbits const int num; 800aeed3e9SJustin Hibbits const char *str; 810aeed3e9SJustin Hibbits }; 820aeed3e9SJustin Hibbits /** @} */ 830aeed3e9SJustin Hibbits 840aeed3e9SJustin Hibbits 850aeed3e9SJustin Hibbits /** 860aeed3e9SJustin Hibbits * @group FMan MAC routines. 870aeed3e9SJustin Hibbits * @{ 880aeed3e9SJustin Hibbits */ 890aeed3e9SJustin Hibbits #define DTSEC_MAC_EXCEPTIONS_END (-1) 900aeed3e9SJustin Hibbits 910aeed3e9SJustin Hibbits /** 920aeed3e9SJustin Hibbits * FMan MAC exceptions. 930aeed3e9SJustin Hibbits */ 940aeed3e9SJustin Hibbits static const struct dtsec_fm_mac_ex_str dtsec_fm_mac_exceptions[] = { 950aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO, "MDIO scan event" }, 960aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_MDIO_CMD_CMPL, "MDIO command completion" }, 970aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_REM_FAULT, "Remote fault" }, 980aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_LOC_FAULT, "Local fault" }, 990aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_1TX_ECC_ER, "Transmit frame ECC error" }, 1000aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_TX_FIFO_UNFL, "Transmit FIFO underflow" }, 1010aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_TX_FIFO_OVFL, "Receive FIFO overflow" }, 1020aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_TX_ER, "Transmit frame error" }, 1030aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_FIFO_OVFL, "Receive FIFO overflow" }, 1040aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_ECC_ER, "Receive frame ECC error" }, 1050aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_JAB_FRM, "Receive jabber frame" }, 1060aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_OVRSZ_FRM, "Receive oversized frame" }, 1070aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_RUNT_FRM, "Receive runt frame" }, 1080aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_FRAG_FRM, "Receive fragment frame" }, 1090aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_LEN_ER, "Receive payload length error" }, 1100aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_CRC_ER, "Receive CRC error" }, 1110aeed3e9SJustin Hibbits { e_FM_MAC_EX_10G_RX_ALIGN_ER, "Receive alignment error" }, 1120aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_BAB_RX, "Babbling receive error" }, 1130aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_RX_CTL, "Receive control (pause frame) interrupt" }, 1140aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET, "Graceful transmit stop " 1150aeed3e9SJustin Hibbits "complete" }, 1160aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_BAB_TX, "Babbling transmit error" }, 1170aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_CTL, "Transmit control (pause frame) interrupt" }, 1180aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_ERR, "Transmit error" }, 1190aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_LATE_COL, "Late collision" }, 1200aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_COL_RET_LMT, "Collision retry limit" }, 1210aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_FIFO_UNDRN, "Transmit FIFO underrun" }, 1220aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_MAG_PCKT, "Magic Packet detected when dTSEC is in " 1230aeed3e9SJustin Hibbits "Magic Packet detection mode" }, 1240aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET, "MII management read completion" }, 1250aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET, "MII management write completion" }, 1260aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET, "Graceful receive stop " 1270aeed3e9SJustin Hibbits "complete" }, 1280aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_TX_DATA_ERR, "Internal data error on transmit" }, 1290aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_RX_DATA_ERR, "Internal data error on receive" }, 1300aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_1588_TS_RX_ERR, "Time-Stamp Receive Error" }, 1310aeed3e9SJustin Hibbits { e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, "MIB counter overflow" }, 1320aeed3e9SJustin Hibbits { DTSEC_MAC_EXCEPTIONS_END, "" } 1330aeed3e9SJustin Hibbits }; 1340aeed3e9SJustin Hibbits 1350aeed3e9SJustin Hibbits static const char * 1360aeed3e9SJustin Hibbits dtsec_fm_mac_ex_to_str(e_FmMacExceptions exception) 1370aeed3e9SJustin Hibbits { 1380aeed3e9SJustin Hibbits int i; 1390aeed3e9SJustin Hibbits 1400aeed3e9SJustin Hibbits for (i = 0; dtsec_fm_mac_exceptions[i].num != exception && 1410aeed3e9SJustin Hibbits dtsec_fm_mac_exceptions[i].num != DTSEC_MAC_EXCEPTIONS_END; ++i) 1420aeed3e9SJustin Hibbits ; 1430aeed3e9SJustin Hibbits 1440aeed3e9SJustin Hibbits if (dtsec_fm_mac_exceptions[i].num == DTSEC_MAC_EXCEPTIONS_END) 1450aeed3e9SJustin Hibbits return ("<Unknown Exception>"); 1460aeed3e9SJustin Hibbits 1470aeed3e9SJustin Hibbits return (dtsec_fm_mac_exceptions[i].str); 1480aeed3e9SJustin Hibbits } 1490aeed3e9SJustin Hibbits 1500aeed3e9SJustin Hibbits static void 1510aeed3e9SJustin Hibbits dtsec_fm_mac_mdio_event_callback(t_Handle h_App, 1520aeed3e9SJustin Hibbits e_FmMacExceptions exception) 1530aeed3e9SJustin Hibbits { 1540aeed3e9SJustin Hibbits struct dtsec_softc *sc; 1550aeed3e9SJustin Hibbits 1560aeed3e9SJustin Hibbits sc = h_App; 1570aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "MDIO event %i: %s.\n", exception, 1580aeed3e9SJustin Hibbits dtsec_fm_mac_ex_to_str(exception)); 1590aeed3e9SJustin Hibbits } 1600aeed3e9SJustin Hibbits 1610aeed3e9SJustin Hibbits static void 1620aeed3e9SJustin Hibbits dtsec_fm_mac_exception_callback(t_Handle app, e_FmMacExceptions exception) 1630aeed3e9SJustin Hibbits { 1640aeed3e9SJustin Hibbits struct dtsec_softc *sc; 1650aeed3e9SJustin Hibbits 1660aeed3e9SJustin Hibbits sc = app; 1670aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "MAC exception %i: %s.\n", exception, 1680aeed3e9SJustin Hibbits dtsec_fm_mac_ex_to_str(exception)); 1690aeed3e9SJustin Hibbits } 1700aeed3e9SJustin Hibbits 1710aeed3e9SJustin Hibbits static void 1720aeed3e9SJustin Hibbits dtsec_fm_mac_free(struct dtsec_softc *sc) 1730aeed3e9SJustin Hibbits { 1740aeed3e9SJustin Hibbits if (sc->sc_mach == NULL) 1750aeed3e9SJustin Hibbits return; 1760aeed3e9SJustin Hibbits 1770aeed3e9SJustin Hibbits FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 1780aeed3e9SJustin Hibbits FM_MAC_Free(sc->sc_mach); 1790aeed3e9SJustin Hibbits sc->sc_mach = NULL; 1800aeed3e9SJustin Hibbits } 1810aeed3e9SJustin Hibbits 1820aeed3e9SJustin Hibbits static int 1830aeed3e9SJustin Hibbits dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac) 1840aeed3e9SJustin Hibbits { 1850aeed3e9SJustin Hibbits t_FmMacParams params; 1860aeed3e9SJustin Hibbits t_Error error; 1870aeed3e9SJustin Hibbits 1880aeed3e9SJustin Hibbits memset(¶ms, 0, sizeof(params)); 1890aeed3e9SJustin Hibbits memcpy(¶ms.addr, mac, sizeof(params.addr)); 1900aeed3e9SJustin Hibbits 1910aeed3e9SJustin Hibbits params.baseAddr = sc->sc_fm_base + sc->sc_mac_mem_offset; 1920aeed3e9SJustin Hibbits params.enetMode = sc->sc_mac_enet_mode; 1930aeed3e9SJustin Hibbits params.macId = sc->sc_eth_id; 1940aeed3e9SJustin Hibbits params.mdioIrq = sc->sc_mac_mdio_irq; 1950aeed3e9SJustin Hibbits params.f_Event = dtsec_fm_mac_mdio_event_callback; 1960aeed3e9SJustin Hibbits params.f_Exception = dtsec_fm_mac_exception_callback; 1970aeed3e9SJustin Hibbits params.h_App = sc; 1980aeed3e9SJustin Hibbits params.h_Fm = sc->sc_fmh; 1990aeed3e9SJustin Hibbits 2000aeed3e9SJustin Hibbits sc->sc_mach = FM_MAC_Config(¶ms); 2010aeed3e9SJustin Hibbits if (sc->sc_mach == NULL) { 2020aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't configure FM_MAC module.\n" 2030aeed3e9SJustin Hibbits ); 2040aeed3e9SJustin Hibbits return (ENXIO); 2050aeed3e9SJustin Hibbits } 2060aeed3e9SJustin Hibbits 2070aeed3e9SJustin Hibbits error = FM_MAC_ConfigResetOnInit(sc->sc_mach, TRUE); 2080aeed3e9SJustin Hibbits if (error != E_OK) { 2090aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't enable reset on init " 2100aeed3e9SJustin Hibbits "feature.\n"); 2110aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 2120aeed3e9SJustin Hibbits return (ENXIO); 2130aeed3e9SJustin Hibbits } 2140aeed3e9SJustin Hibbits 2150aeed3e9SJustin Hibbits /* Do not inform about pause frames */ 2160aeed3e9SJustin Hibbits error = FM_MAC_ConfigException(sc->sc_mach, e_FM_MAC_EX_1G_RX_CTL, 2170aeed3e9SJustin Hibbits FALSE); 2180aeed3e9SJustin Hibbits if (error != E_OK) { 2190aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't disable pause frames " 2200aeed3e9SJustin Hibbits "exception.\n"); 2210aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 2220aeed3e9SJustin Hibbits return (ENXIO); 2230aeed3e9SJustin Hibbits } 2240aeed3e9SJustin Hibbits 2250aeed3e9SJustin Hibbits error = FM_MAC_Init(sc->sc_mach); 2260aeed3e9SJustin Hibbits if (error != E_OK) { 2270aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't initialize FM_MAC module." 2280aeed3e9SJustin Hibbits "\n"); 2290aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 2300aeed3e9SJustin Hibbits return (ENXIO); 2310aeed3e9SJustin Hibbits } 2320aeed3e9SJustin Hibbits 2330aeed3e9SJustin Hibbits return (0); 2340aeed3e9SJustin Hibbits } 2350aeed3e9SJustin Hibbits /** @} */ 2360aeed3e9SJustin Hibbits 2370aeed3e9SJustin Hibbits 2380aeed3e9SJustin Hibbits /** 2390aeed3e9SJustin Hibbits * @group FMan PORT routines. 2400aeed3e9SJustin Hibbits * @{ 2410aeed3e9SJustin Hibbits */ 2420aeed3e9SJustin Hibbits static const char * 2430aeed3e9SJustin Hibbits dtsec_fm_port_ex_to_str(e_FmPortExceptions exception) 2440aeed3e9SJustin Hibbits { 2450aeed3e9SJustin Hibbits 2460aeed3e9SJustin Hibbits switch (exception) { 2470aeed3e9SJustin Hibbits case e_FM_PORT_EXCEPTION_IM_BUSY: 2480aeed3e9SJustin Hibbits return ("IM: RX busy"); 2490aeed3e9SJustin Hibbits default: 2500aeed3e9SJustin Hibbits return ("<Unknown Exception>"); 2510aeed3e9SJustin Hibbits } 2520aeed3e9SJustin Hibbits } 2530aeed3e9SJustin Hibbits 2540aeed3e9SJustin Hibbits void 2550aeed3e9SJustin Hibbits dtsec_fm_port_rx_exception_callback(t_Handle app, 2560aeed3e9SJustin Hibbits e_FmPortExceptions exception) 2570aeed3e9SJustin Hibbits { 2580aeed3e9SJustin Hibbits struct dtsec_softc *sc; 2590aeed3e9SJustin Hibbits 2600aeed3e9SJustin Hibbits sc = app; 2610aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "RX exception: %i: %s.\n", exception, 2620aeed3e9SJustin Hibbits dtsec_fm_port_ex_to_str(exception)); 2630aeed3e9SJustin Hibbits } 2640aeed3e9SJustin Hibbits 2650aeed3e9SJustin Hibbits void 2660aeed3e9SJustin Hibbits dtsec_fm_port_tx_exception_callback(t_Handle app, 2670aeed3e9SJustin Hibbits e_FmPortExceptions exception) 2680aeed3e9SJustin Hibbits { 2690aeed3e9SJustin Hibbits struct dtsec_softc *sc; 2700aeed3e9SJustin Hibbits 2710aeed3e9SJustin Hibbits sc = app; 2720aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "TX exception: %i: %s.\n", exception, 2730aeed3e9SJustin Hibbits dtsec_fm_port_ex_to_str(exception)); 2740aeed3e9SJustin Hibbits } 2750aeed3e9SJustin Hibbits 2760aeed3e9SJustin Hibbits e_FmPortType 2770aeed3e9SJustin Hibbits dtsec_fm_port_rx_type(enum eth_dev_type type) 2780aeed3e9SJustin Hibbits { 2790aeed3e9SJustin Hibbits switch (type) { 2800aeed3e9SJustin Hibbits case ETH_DTSEC: 2810aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_RX); 2820aeed3e9SJustin Hibbits case ETH_10GSEC: 2830aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_RX_10G); 2840aeed3e9SJustin Hibbits default: 2850aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_DUMMY); 2860aeed3e9SJustin Hibbits } 2870aeed3e9SJustin Hibbits } 2880aeed3e9SJustin Hibbits 2890aeed3e9SJustin Hibbits e_FmPortType 2900aeed3e9SJustin Hibbits dtsec_fm_port_tx_type(enum eth_dev_type type) 2910aeed3e9SJustin Hibbits { 2920aeed3e9SJustin Hibbits 2930aeed3e9SJustin Hibbits switch (type) { 2940aeed3e9SJustin Hibbits case ETH_DTSEC: 2950aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_TX); 2960aeed3e9SJustin Hibbits case ETH_10GSEC: 2970aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_TX_10G); 2980aeed3e9SJustin Hibbits default: 2990aeed3e9SJustin Hibbits return (e_FM_PORT_TYPE_DUMMY); 3000aeed3e9SJustin Hibbits } 3010aeed3e9SJustin Hibbits } 3020aeed3e9SJustin Hibbits 3030aeed3e9SJustin Hibbits static void 3040aeed3e9SJustin Hibbits dtsec_fm_port_free_both(struct dtsec_softc *sc) 3050aeed3e9SJustin Hibbits { 3060aeed3e9SJustin Hibbits if (sc->sc_rxph) { 3070aeed3e9SJustin Hibbits FM_PORT_Free(sc->sc_rxph); 3080aeed3e9SJustin Hibbits sc->sc_rxph = NULL; 3090aeed3e9SJustin Hibbits } 3100aeed3e9SJustin Hibbits 3110aeed3e9SJustin Hibbits if (sc->sc_txph) { 3120aeed3e9SJustin Hibbits FM_PORT_Free(sc->sc_txph); 3130aeed3e9SJustin Hibbits sc->sc_txph = NULL; 3140aeed3e9SJustin Hibbits } 3150aeed3e9SJustin Hibbits } 3160aeed3e9SJustin Hibbits /** @} */ 3170aeed3e9SJustin Hibbits 3180aeed3e9SJustin Hibbits 3190aeed3e9SJustin Hibbits /** 3200aeed3e9SJustin Hibbits * @group IFnet routines. 3210aeed3e9SJustin Hibbits * @{ 3220aeed3e9SJustin Hibbits */ 3230aeed3e9SJustin Hibbits static int 3240aeed3e9SJustin Hibbits dtsec_if_enable_locked(struct dtsec_softc *sc) 3250aeed3e9SJustin Hibbits { 3260aeed3e9SJustin Hibbits int error; 3270aeed3e9SJustin Hibbits 3280aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 3290aeed3e9SJustin Hibbits 3300aeed3e9SJustin Hibbits error = FM_MAC_Enable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 3310aeed3e9SJustin Hibbits if (error != E_OK) 3320aeed3e9SJustin Hibbits return (EIO); 3330aeed3e9SJustin Hibbits 3340aeed3e9SJustin Hibbits error = FM_PORT_Enable(sc->sc_rxph); 3350aeed3e9SJustin Hibbits if (error != E_OK) 3360aeed3e9SJustin Hibbits return (EIO); 3370aeed3e9SJustin Hibbits 3380aeed3e9SJustin Hibbits error = FM_PORT_Enable(sc->sc_txph); 3390aeed3e9SJustin Hibbits if (error != E_OK) 3400aeed3e9SJustin Hibbits return (EIO); 3410aeed3e9SJustin Hibbits 3420aeed3e9SJustin Hibbits sc->sc_ifnet->if_drv_flags |= IFF_DRV_RUNNING; 3430aeed3e9SJustin Hibbits 3440aeed3e9SJustin Hibbits /* Refresh link state */ 3450aeed3e9SJustin Hibbits dtsec_miibus_statchg(sc->sc_dev); 3460aeed3e9SJustin Hibbits 3470aeed3e9SJustin Hibbits return (0); 3480aeed3e9SJustin Hibbits } 3490aeed3e9SJustin Hibbits 3500aeed3e9SJustin Hibbits static int 3510aeed3e9SJustin Hibbits dtsec_if_disable_locked(struct dtsec_softc *sc) 3520aeed3e9SJustin Hibbits { 3530aeed3e9SJustin Hibbits int error; 3540aeed3e9SJustin Hibbits 3550aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 3560aeed3e9SJustin Hibbits 3570aeed3e9SJustin Hibbits error = FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 3580aeed3e9SJustin Hibbits if (error != E_OK) 3590aeed3e9SJustin Hibbits return (EIO); 3600aeed3e9SJustin Hibbits 3610aeed3e9SJustin Hibbits error = FM_PORT_Disable(sc->sc_rxph); 3620aeed3e9SJustin Hibbits if (error != E_OK) 3630aeed3e9SJustin Hibbits return (EIO); 3640aeed3e9SJustin Hibbits 3650aeed3e9SJustin Hibbits error = FM_PORT_Disable(sc->sc_txph); 3660aeed3e9SJustin Hibbits if (error != E_OK) 3670aeed3e9SJustin Hibbits return (EIO); 3680aeed3e9SJustin Hibbits 3690aeed3e9SJustin Hibbits sc->sc_ifnet->if_drv_flags &= ~IFF_DRV_RUNNING; 3700aeed3e9SJustin Hibbits 3710aeed3e9SJustin Hibbits return (0); 3720aeed3e9SJustin Hibbits } 3730aeed3e9SJustin Hibbits 3740aeed3e9SJustin Hibbits static int 3750aeed3e9SJustin Hibbits dtsec_if_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 3760aeed3e9SJustin Hibbits { 3770aeed3e9SJustin Hibbits struct dtsec_softc *sc; 3780aeed3e9SJustin Hibbits struct ifreq *ifr; 3790aeed3e9SJustin Hibbits int error; 3800aeed3e9SJustin Hibbits 3810aeed3e9SJustin Hibbits sc = ifp->if_softc; 3820aeed3e9SJustin Hibbits ifr = (struct ifreq *)data; 3830aeed3e9SJustin Hibbits error = 0; 3840aeed3e9SJustin Hibbits 3850aeed3e9SJustin Hibbits /* Basic functionality to achieve media status reports */ 3860aeed3e9SJustin Hibbits switch (command) { 3870aeed3e9SJustin Hibbits case SIOCSIFFLAGS: 3880aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 3890aeed3e9SJustin Hibbits 3900aeed3e9SJustin Hibbits if (sc->sc_ifnet->if_flags & IFF_UP) 3910aeed3e9SJustin Hibbits error = dtsec_if_enable_locked(sc); 3920aeed3e9SJustin Hibbits else 3930aeed3e9SJustin Hibbits error = dtsec_if_disable_locked(sc); 3940aeed3e9SJustin Hibbits 3950aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 3960aeed3e9SJustin Hibbits break; 3970aeed3e9SJustin Hibbits 3980aeed3e9SJustin Hibbits case SIOCGIFMEDIA: 3990aeed3e9SJustin Hibbits case SIOCSIFMEDIA: 4000aeed3e9SJustin Hibbits error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, 4010aeed3e9SJustin Hibbits command); 4020aeed3e9SJustin Hibbits break; 4030aeed3e9SJustin Hibbits 4040aeed3e9SJustin Hibbits default: 4050aeed3e9SJustin Hibbits error = ether_ioctl(ifp, command, data); 4060aeed3e9SJustin Hibbits } 4070aeed3e9SJustin Hibbits 4080aeed3e9SJustin Hibbits return (error); 4090aeed3e9SJustin Hibbits } 4100aeed3e9SJustin Hibbits 4110aeed3e9SJustin Hibbits static void 4120aeed3e9SJustin Hibbits dtsec_if_tick(void *arg) 4130aeed3e9SJustin Hibbits { 4140aeed3e9SJustin Hibbits struct dtsec_softc *sc; 4150aeed3e9SJustin Hibbits 4160aeed3e9SJustin Hibbits sc = arg; 4170aeed3e9SJustin Hibbits 4180aeed3e9SJustin Hibbits /* TODO */ 4190aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4200aeed3e9SJustin Hibbits 4210aeed3e9SJustin Hibbits mii_tick(sc->sc_mii); 4220aeed3e9SJustin Hibbits callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 4230aeed3e9SJustin Hibbits 4240aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4250aeed3e9SJustin Hibbits } 4260aeed3e9SJustin Hibbits 4270aeed3e9SJustin Hibbits static void 4280aeed3e9SJustin Hibbits dtsec_if_deinit_locked(struct dtsec_softc *sc) 4290aeed3e9SJustin Hibbits { 4300aeed3e9SJustin Hibbits 4310aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 4320aeed3e9SJustin Hibbits 4330aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4340aeed3e9SJustin Hibbits callout_drain(&sc->sc_tick_callout); 4350aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4360aeed3e9SJustin Hibbits } 4370aeed3e9SJustin Hibbits 4380aeed3e9SJustin Hibbits static void 4390aeed3e9SJustin Hibbits dtsec_if_init_locked(struct dtsec_softc *sc) 4400aeed3e9SJustin Hibbits { 4410aeed3e9SJustin Hibbits int error; 4420aeed3e9SJustin Hibbits 4430aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 4440aeed3e9SJustin Hibbits 4450aeed3e9SJustin Hibbits /* Set MAC address */ 4460aeed3e9SJustin Hibbits error = FM_MAC_ModifyMacAddr(sc->sc_mach, 4470aeed3e9SJustin Hibbits (t_EnetAddr *)IF_LLADDR(sc->sc_ifnet)); 4480aeed3e9SJustin Hibbits if (error != E_OK) { 4490aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "couldn't set MAC address.\n"); 4500aeed3e9SJustin Hibbits goto err; 4510aeed3e9SJustin Hibbits } 4520aeed3e9SJustin Hibbits 4530aeed3e9SJustin Hibbits /* Start MII polling */ 4540aeed3e9SJustin Hibbits if (sc->sc_mii) 4550aeed3e9SJustin Hibbits callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 4560aeed3e9SJustin Hibbits 4570aeed3e9SJustin Hibbits if (sc->sc_ifnet->if_flags & IFF_UP) { 4580aeed3e9SJustin Hibbits error = dtsec_if_enable_locked(sc); 4590aeed3e9SJustin Hibbits if (error != 0) 4600aeed3e9SJustin Hibbits goto err; 4610aeed3e9SJustin Hibbits } else { 4620aeed3e9SJustin Hibbits error = dtsec_if_disable_locked(sc); 4630aeed3e9SJustin Hibbits if (error != 0) 4640aeed3e9SJustin Hibbits goto err; 4650aeed3e9SJustin Hibbits } 4660aeed3e9SJustin Hibbits 4670aeed3e9SJustin Hibbits return; 4680aeed3e9SJustin Hibbits 4690aeed3e9SJustin Hibbits err: 4700aeed3e9SJustin Hibbits dtsec_if_deinit_locked(sc); 4710aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "initialization error.\n"); 4720aeed3e9SJustin Hibbits return; 4730aeed3e9SJustin Hibbits } 4740aeed3e9SJustin Hibbits 4750aeed3e9SJustin Hibbits static void 4760aeed3e9SJustin Hibbits dtsec_if_init(void *data) 4770aeed3e9SJustin Hibbits { 4780aeed3e9SJustin Hibbits struct dtsec_softc *sc; 4790aeed3e9SJustin Hibbits 4800aeed3e9SJustin Hibbits sc = data; 4810aeed3e9SJustin Hibbits 4820aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4830aeed3e9SJustin Hibbits dtsec_if_init_locked(sc); 4840aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4850aeed3e9SJustin Hibbits } 4860aeed3e9SJustin Hibbits 4870aeed3e9SJustin Hibbits static void 4880aeed3e9SJustin Hibbits dtsec_if_start(struct ifnet *ifp) 4890aeed3e9SJustin Hibbits { 4900aeed3e9SJustin Hibbits struct dtsec_softc *sc; 4910aeed3e9SJustin Hibbits 4920aeed3e9SJustin Hibbits sc = ifp->if_softc; 4930aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 4940aeed3e9SJustin Hibbits sc->sc_start_locked(sc); 4950aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 4960aeed3e9SJustin Hibbits } 4970aeed3e9SJustin Hibbits 4980aeed3e9SJustin Hibbits static void 4990aeed3e9SJustin Hibbits dtsec_if_watchdog(struct ifnet *ifp) 5000aeed3e9SJustin Hibbits { 5010aeed3e9SJustin Hibbits /* TODO */ 5020aeed3e9SJustin Hibbits } 5030aeed3e9SJustin Hibbits /** @} */ 5040aeed3e9SJustin Hibbits 5050aeed3e9SJustin Hibbits 5060aeed3e9SJustin Hibbits /** 5070aeed3e9SJustin Hibbits * @group IFmedia routines. 5080aeed3e9SJustin Hibbits * @{ 5090aeed3e9SJustin Hibbits */ 5100aeed3e9SJustin Hibbits static int 5110aeed3e9SJustin Hibbits dtsec_ifmedia_upd(struct ifnet *ifp) 5120aeed3e9SJustin Hibbits { 5130aeed3e9SJustin Hibbits struct dtsec_softc *sc = ifp->if_softc; 5140aeed3e9SJustin Hibbits 5150aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5160aeed3e9SJustin Hibbits mii_mediachg(sc->sc_mii); 5170aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5180aeed3e9SJustin Hibbits 5190aeed3e9SJustin Hibbits return (0); 5200aeed3e9SJustin Hibbits } 5210aeed3e9SJustin Hibbits 5220aeed3e9SJustin Hibbits static void 5230aeed3e9SJustin Hibbits dtsec_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 5240aeed3e9SJustin Hibbits { 5250aeed3e9SJustin Hibbits struct dtsec_softc *sc = ifp->if_softc; 5260aeed3e9SJustin Hibbits 5270aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 5280aeed3e9SJustin Hibbits 5290aeed3e9SJustin Hibbits mii_pollstat(sc->sc_mii); 5300aeed3e9SJustin Hibbits 5310aeed3e9SJustin Hibbits ifmr->ifm_active = sc->sc_mii->mii_media_active; 5320aeed3e9SJustin Hibbits ifmr->ifm_status = sc->sc_mii->mii_media_status; 5330aeed3e9SJustin Hibbits 5340aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 5350aeed3e9SJustin Hibbits } 5360aeed3e9SJustin Hibbits /** @} */ 5370aeed3e9SJustin Hibbits 5380aeed3e9SJustin Hibbits 5390aeed3e9SJustin Hibbits /** 5400aeed3e9SJustin Hibbits * @group dTSEC bus interface. 5410aeed3e9SJustin Hibbits * @{ 5420aeed3e9SJustin Hibbits */ 5430aeed3e9SJustin Hibbits static void 5440aeed3e9SJustin Hibbits dtsec_configure_mode(struct dtsec_softc *sc) 5450aeed3e9SJustin Hibbits { 5460aeed3e9SJustin Hibbits char tunable[64]; 5470aeed3e9SJustin Hibbits 5480aeed3e9SJustin Hibbits snprintf(tunable, sizeof(tunable), "%s.independent_mode", 5490aeed3e9SJustin Hibbits device_get_nameunit(sc->sc_dev)); 5500aeed3e9SJustin Hibbits 5510aeed3e9SJustin Hibbits sc->sc_mode = DTSEC_MODE_REGULAR; 5520aeed3e9SJustin Hibbits TUNABLE_INT_FETCH(tunable, &sc->sc_mode); 5530aeed3e9SJustin Hibbits 5540aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 5550aeed3e9SJustin Hibbits sc->sc_port_rx_init = dtsec_rm_fm_port_rx_init; 5560aeed3e9SJustin Hibbits sc->sc_port_tx_init = dtsec_rm_fm_port_tx_init; 5570aeed3e9SJustin Hibbits sc->sc_start_locked = dtsec_rm_if_start_locked; 5580aeed3e9SJustin Hibbits } else { 5590aeed3e9SJustin Hibbits sc->sc_port_rx_init = dtsec_im_fm_port_rx_init; 5600aeed3e9SJustin Hibbits sc->sc_port_tx_init = dtsec_im_fm_port_tx_init; 5610aeed3e9SJustin Hibbits sc->sc_start_locked = dtsec_im_if_start_locked; 5620aeed3e9SJustin Hibbits } 5630aeed3e9SJustin Hibbits 5640aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "Configured for %s mode.\n", 5650aeed3e9SJustin Hibbits (sc->sc_mode == DTSEC_MODE_REGULAR) ? "regular" : "independent"); 5660aeed3e9SJustin Hibbits } 5670aeed3e9SJustin Hibbits 5680aeed3e9SJustin Hibbits int 5690aeed3e9SJustin Hibbits dtsec_attach(device_t dev) 5700aeed3e9SJustin Hibbits { 5710aeed3e9SJustin Hibbits struct dtsec_softc *sc; 5720aeed3e9SJustin Hibbits int error; 5730aeed3e9SJustin Hibbits struct ifnet *ifp; 5740aeed3e9SJustin Hibbits 5750aeed3e9SJustin Hibbits sc = device_get_softc(dev); 5760aeed3e9SJustin Hibbits 5770aeed3e9SJustin Hibbits sc->sc_dev = dev; 5780aeed3e9SJustin Hibbits sc->sc_mac_mdio_irq = NO_IRQ; 5790aeed3e9SJustin Hibbits sc->sc_eth_id = device_get_unit(dev); 5800aeed3e9SJustin Hibbits 5810aeed3e9SJustin Hibbits 5820aeed3e9SJustin Hibbits /* Check if MallocSmart allocator is ready */ 5830aeed3e9SJustin Hibbits if (XX_MallocSmartInit() != E_OK) 5840aeed3e9SJustin Hibbits return (ENXIO); 5850aeed3e9SJustin Hibbits 5860aeed3e9SJustin Hibbits /* Init locks */ 5870aeed3e9SJustin Hibbits mtx_init(&sc->sc_lock, device_get_nameunit(dev), 5880aeed3e9SJustin Hibbits "DTSEC Global Lock", MTX_DEF); 5890aeed3e9SJustin Hibbits 5900aeed3e9SJustin Hibbits mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev), 5910aeed3e9SJustin Hibbits "DTSEC MII Lock", MTX_DEF); 5920aeed3e9SJustin Hibbits 5930aeed3e9SJustin Hibbits /* Init callouts */ 5940aeed3e9SJustin Hibbits callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE); 5950aeed3e9SJustin Hibbits 5960aeed3e9SJustin Hibbits /* Read configuraton */ 5970aeed3e9SJustin Hibbits if ((error = fman_get_handle(&sc->sc_fmh)) != 0) 5980aeed3e9SJustin Hibbits return (error); 5990aeed3e9SJustin Hibbits 6000aeed3e9SJustin Hibbits if ((error = fman_get_muram_handle(&sc->sc_muramh)) != 0) 6010aeed3e9SJustin Hibbits return (error); 6020aeed3e9SJustin Hibbits 6030aeed3e9SJustin Hibbits if ((error = fman_get_bushandle(&sc->sc_fm_base)) != 0) 6040aeed3e9SJustin Hibbits return (error); 6050aeed3e9SJustin Hibbits 6060aeed3e9SJustin Hibbits /* Configure working mode */ 6070aeed3e9SJustin Hibbits dtsec_configure_mode(sc); 6080aeed3e9SJustin Hibbits 6090aeed3e9SJustin Hibbits /* If we are working in regular mode configure BMAN and QMAN */ 6100aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 6110aeed3e9SJustin Hibbits /* Create RX buffer pool */ 6120aeed3e9SJustin Hibbits error = dtsec_rm_pool_rx_init(sc); 6130aeed3e9SJustin Hibbits if (error != 0) 6140aeed3e9SJustin Hibbits return (EIO); 6150aeed3e9SJustin Hibbits 6160aeed3e9SJustin Hibbits /* Create RX frame queue range */ 6170aeed3e9SJustin Hibbits error = dtsec_rm_fqr_rx_init(sc); 6180aeed3e9SJustin Hibbits if (error != 0) 6190aeed3e9SJustin Hibbits return (EIO); 6200aeed3e9SJustin Hibbits 6210aeed3e9SJustin Hibbits /* Create frame info pool */ 6220aeed3e9SJustin Hibbits error = dtsec_rm_fi_pool_init(sc); 6230aeed3e9SJustin Hibbits if (error != 0) 6240aeed3e9SJustin Hibbits return (EIO); 6250aeed3e9SJustin Hibbits 6260aeed3e9SJustin Hibbits /* Create TX frame queue range */ 6270aeed3e9SJustin Hibbits error = dtsec_rm_fqr_tx_init(sc); 6280aeed3e9SJustin Hibbits if (error != 0) 6290aeed3e9SJustin Hibbits return (EIO); 6300aeed3e9SJustin Hibbits } 6310aeed3e9SJustin Hibbits 6320aeed3e9SJustin Hibbits /* Init FMan MAC module. */ 6330aeed3e9SJustin Hibbits error = dtsec_fm_mac_init(sc, sc->sc_mac_addr); 6340aeed3e9SJustin Hibbits if (error != 0) { 6350aeed3e9SJustin Hibbits dtsec_detach(dev); 6360aeed3e9SJustin Hibbits return (ENXIO); 6370aeed3e9SJustin Hibbits } 6380aeed3e9SJustin Hibbits 6390aeed3e9SJustin Hibbits /* Init FMan TX port */ 6400aeed3e9SJustin Hibbits error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev)); 6410aeed3e9SJustin Hibbits if (error != 0) { 6420aeed3e9SJustin Hibbits dtsec_detach(dev); 6430aeed3e9SJustin Hibbits return (ENXIO); 6440aeed3e9SJustin Hibbits } 6450aeed3e9SJustin Hibbits 6460aeed3e9SJustin Hibbits /* Init FMan RX port */ 6470aeed3e9SJustin Hibbits error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev)); 6480aeed3e9SJustin Hibbits if (error != 0) { 6490aeed3e9SJustin Hibbits dtsec_detach(dev); 6500aeed3e9SJustin Hibbits return (ENXIO); 6510aeed3e9SJustin Hibbits } 6520aeed3e9SJustin Hibbits 6530aeed3e9SJustin Hibbits /* Create network interface for upper layers */ 6540aeed3e9SJustin Hibbits ifp = sc->sc_ifnet = if_alloc(IFT_ETHER); 6550aeed3e9SJustin Hibbits if (ifp == NULL) { 6560aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "if_alloc() failed.\n"); 6570aeed3e9SJustin Hibbits dtsec_detach(dev); 6580aeed3e9SJustin Hibbits return (ENOMEM); 6590aeed3e9SJustin Hibbits } 6600aeed3e9SJustin Hibbits 6610aeed3e9SJustin Hibbits ifp->if_softc = sc; 6620aeed3e9SJustin Hibbits ifp->if_mtu = ETHERMTU; /* TODO: Configure */ 6630aeed3e9SJustin Hibbits ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; 6640aeed3e9SJustin Hibbits ifp->if_init = dtsec_if_init; 6650aeed3e9SJustin Hibbits ifp->if_start = dtsec_if_start; 6660aeed3e9SJustin Hibbits ifp->if_ioctl = dtsec_if_ioctl; 6670aeed3e9SJustin Hibbits ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 6680aeed3e9SJustin Hibbits 6690aeed3e9SJustin Hibbits if (sc->sc_phy_addr >= 0) 6700aeed3e9SJustin Hibbits if_initname(ifp, device_get_name(sc->sc_dev), 6710aeed3e9SJustin Hibbits device_get_unit(sc->sc_dev)); 6720aeed3e9SJustin Hibbits else 6730aeed3e9SJustin Hibbits if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev)); 6740aeed3e9SJustin Hibbits 6750aeed3e9SJustin Hibbits /* TODO */ 6760aeed3e9SJustin Hibbits #if 0 6770aeed3e9SJustin Hibbits IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_TX_NUM_DESC - 1); 6780aeed3e9SJustin Hibbits ifp->if_snd.ifq_drv_maxlen = TSEC_TX_NUM_DESC - 1; 6790aeed3e9SJustin Hibbits IFQ_SET_READY(&ifp->if_snd); 6800aeed3e9SJustin Hibbits #endif 6810aeed3e9SJustin Hibbits ifp->if_capabilities = 0; /* TODO: Check */ 6820aeed3e9SJustin Hibbits ifp->if_capenable = ifp->if_capabilities; 6830aeed3e9SJustin Hibbits 6840aeed3e9SJustin Hibbits /* Attach PHY(s) */ 6850aeed3e9SJustin Hibbits error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd, 6860aeed3e9SJustin Hibbits dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr, 6870aeed3e9SJustin Hibbits MII_OFFSET_ANY, 0); 6880aeed3e9SJustin Hibbits if (error) { 6890aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error); 6900aeed3e9SJustin Hibbits dtsec_detach(sc->sc_dev); 6910aeed3e9SJustin Hibbits return (error); 6920aeed3e9SJustin Hibbits } 6930aeed3e9SJustin Hibbits sc->sc_mii = device_get_softc(sc->sc_mii_dev); 6940aeed3e9SJustin Hibbits 6950aeed3e9SJustin Hibbits /* Attach to stack */ 6960aeed3e9SJustin Hibbits ether_ifattach(ifp, sc->sc_mac_addr); 6970aeed3e9SJustin Hibbits 6980aeed3e9SJustin Hibbits return (0); 6990aeed3e9SJustin Hibbits } 7000aeed3e9SJustin Hibbits 7010aeed3e9SJustin Hibbits int 7020aeed3e9SJustin Hibbits dtsec_detach(device_t dev) 7030aeed3e9SJustin Hibbits { 7040aeed3e9SJustin Hibbits struct dtsec_softc *sc; 7050aeed3e9SJustin Hibbits if_t ifp; 7060aeed3e9SJustin Hibbits 7070aeed3e9SJustin Hibbits sc = device_get_softc(dev); 7080aeed3e9SJustin Hibbits ifp = sc->sc_ifnet; 7090aeed3e9SJustin Hibbits 7100aeed3e9SJustin Hibbits if (device_is_attached(dev)) { 7110aeed3e9SJustin Hibbits ether_ifdetach(ifp); 7120aeed3e9SJustin Hibbits /* Shutdown interface */ 7130aeed3e9SJustin Hibbits DTSEC_LOCK(sc); 7140aeed3e9SJustin Hibbits dtsec_if_deinit_locked(sc); 7150aeed3e9SJustin Hibbits DTSEC_UNLOCK(sc); 7160aeed3e9SJustin Hibbits } 7170aeed3e9SJustin Hibbits 7180aeed3e9SJustin Hibbits if (sc->sc_ifnet) { 7190aeed3e9SJustin Hibbits if_free(sc->sc_ifnet); 7200aeed3e9SJustin Hibbits sc->sc_ifnet = NULL; 7210aeed3e9SJustin Hibbits } 7220aeed3e9SJustin Hibbits 7230aeed3e9SJustin Hibbits if (sc->sc_mode == DTSEC_MODE_REGULAR) { 7240aeed3e9SJustin Hibbits /* Free RX/TX FQRs */ 7250aeed3e9SJustin Hibbits dtsec_rm_fqr_rx_free(sc); 7260aeed3e9SJustin Hibbits dtsec_rm_fqr_tx_free(sc); 7270aeed3e9SJustin Hibbits 7280aeed3e9SJustin Hibbits /* Free frame info pool */ 7290aeed3e9SJustin Hibbits dtsec_rm_fi_pool_free(sc); 7300aeed3e9SJustin Hibbits 7310aeed3e9SJustin Hibbits /* Free RX buffer pool */ 7320aeed3e9SJustin Hibbits dtsec_rm_pool_rx_free(sc); 7330aeed3e9SJustin Hibbits } 7340aeed3e9SJustin Hibbits 7350aeed3e9SJustin Hibbits dtsec_fm_mac_free(sc); 7360aeed3e9SJustin Hibbits dtsec_fm_port_free_both(sc); 7370aeed3e9SJustin Hibbits 7380aeed3e9SJustin Hibbits /* Destroy lock */ 7390aeed3e9SJustin Hibbits mtx_destroy(&sc->sc_lock); 7400aeed3e9SJustin Hibbits 7410aeed3e9SJustin Hibbits return (0); 7420aeed3e9SJustin Hibbits } 7430aeed3e9SJustin Hibbits 7440aeed3e9SJustin Hibbits int 7450aeed3e9SJustin Hibbits dtsec_suspend(device_t dev) 7460aeed3e9SJustin Hibbits { 7470aeed3e9SJustin Hibbits 7480aeed3e9SJustin Hibbits return (0); 7490aeed3e9SJustin Hibbits } 7500aeed3e9SJustin Hibbits 7510aeed3e9SJustin Hibbits int 7520aeed3e9SJustin Hibbits dtsec_resume(device_t dev) 7530aeed3e9SJustin Hibbits { 7540aeed3e9SJustin Hibbits 7550aeed3e9SJustin Hibbits return (0); 7560aeed3e9SJustin Hibbits } 7570aeed3e9SJustin Hibbits 7580aeed3e9SJustin Hibbits int 7590aeed3e9SJustin Hibbits dtsec_shutdown(device_t dev) 7600aeed3e9SJustin Hibbits { 7610aeed3e9SJustin Hibbits 7620aeed3e9SJustin Hibbits return (0); 7630aeed3e9SJustin Hibbits } 7640aeed3e9SJustin Hibbits /** @} */ 7650aeed3e9SJustin Hibbits 7660aeed3e9SJustin Hibbits 7670aeed3e9SJustin Hibbits /** 7680aeed3e9SJustin Hibbits * @group MII bus interface. 7690aeed3e9SJustin Hibbits * @{ 7700aeed3e9SJustin Hibbits */ 7710aeed3e9SJustin Hibbits int 7720aeed3e9SJustin Hibbits dtsec_miibus_readreg(device_t dev, int phy, int reg) 7730aeed3e9SJustin Hibbits { 7740aeed3e9SJustin Hibbits struct dtsec_softc *sc; 7750aeed3e9SJustin Hibbits 7760aeed3e9SJustin Hibbits sc = device_get_softc(dev); 7770aeed3e9SJustin Hibbits 77847cabd04SJustin Hibbits return (MIIBUS_READREG(sc->sc_mdio, phy, reg)); 7790aeed3e9SJustin Hibbits } 7800aeed3e9SJustin Hibbits 7810aeed3e9SJustin Hibbits int 7820aeed3e9SJustin Hibbits dtsec_miibus_writereg(device_t dev, int phy, int reg, int value) 7830aeed3e9SJustin Hibbits { 78447cabd04SJustin Hibbits 7850aeed3e9SJustin Hibbits struct dtsec_softc *sc; 7860aeed3e9SJustin Hibbits 7870aeed3e9SJustin Hibbits sc = device_get_softc(dev); 7880aeed3e9SJustin Hibbits 78947cabd04SJustin Hibbits return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value)); 7900aeed3e9SJustin Hibbits } 7910aeed3e9SJustin Hibbits 7920aeed3e9SJustin Hibbits void 7930aeed3e9SJustin Hibbits dtsec_miibus_statchg(device_t dev) 7940aeed3e9SJustin Hibbits { 7950aeed3e9SJustin Hibbits struct dtsec_softc *sc; 7960aeed3e9SJustin Hibbits e_EnetSpeed speed; 7970aeed3e9SJustin Hibbits bool duplex; 7980aeed3e9SJustin Hibbits int error; 7990aeed3e9SJustin Hibbits 8000aeed3e9SJustin Hibbits sc = device_get_softc(dev); 8010aeed3e9SJustin Hibbits 8020aeed3e9SJustin Hibbits DTSEC_LOCK_ASSERT(sc); 8030aeed3e9SJustin Hibbits 8040aeed3e9SJustin Hibbits duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX); 8050aeed3e9SJustin Hibbits 8060aeed3e9SJustin Hibbits switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 8070aeed3e9SJustin Hibbits case IFM_1000_T: 8080aeed3e9SJustin Hibbits case IFM_1000_SX: 8090aeed3e9SJustin Hibbits speed = e_ENET_SPEED_1000; 8100aeed3e9SJustin Hibbits break; 8110aeed3e9SJustin Hibbits 8120aeed3e9SJustin Hibbits case IFM_100_TX: 8130aeed3e9SJustin Hibbits speed = e_ENET_SPEED_100; 8140aeed3e9SJustin Hibbits break; 8150aeed3e9SJustin Hibbits 8160aeed3e9SJustin Hibbits case IFM_10_T: 8170aeed3e9SJustin Hibbits speed = e_ENET_SPEED_10; 8180aeed3e9SJustin Hibbits break; 8190aeed3e9SJustin Hibbits 8200aeed3e9SJustin Hibbits default: 8210aeed3e9SJustin Hibbits speed = e_ENET_SPEED_10; 8220aeed3e9SJustin Hibbits } 8230aeed3e9SJustin Hibbits 8240aeed3e9SJustin Hibbits error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex); 8250aeed3e9SJustin Hibbits if (error != E_OK) 8260aeed3e9SJustin Hibbits device_printf(sc->sc_dev, "error while adjusting MAC speed.\n"); 8270aeed3e9SJustin Hibbits } 8280aeed3e9SJustin Hibbits /** @} */ 829