xref: /freebsd/sys/dev/dpaa/if_dtsec.c (revision 852ba100814e41898dc6e673fe0af017084e411d)
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(&params, 0, sizeof(params));
1890aeed3e9SJustin Hibbits 	memcpy(&params.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(&params);
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