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