Home | History | Annotate | Line # | Download | only in dev
octeon_gmx.c revision 1.2
      1 /*	$NetBSD: octeon_gmx.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2007 Internet Initiative Japan, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  *  support GMX0 interface only
     31  *  take no thought for other GMX interface
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
     36 
     37 #include "opt_octeon.h"
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/types.h>
     42 #include <sys/cpu.h>
     43 #include <sys/device.h>
     44 #include <sys/lock.h>
     45 #include <sys/cdefs.h>
     46 #include <sys/malloc.h>
     47 #include <sys/syslog.h>
     48 
     49 #include <mips/locore.h>
     50 #include <mips/include/cpuregs.h>
     51 #include <sys/bus.h>
     52 
     53 #include <mips/cavium/dev/octeon_ciureg.h>
     54 #include <mips/cavium/dev/octeon_gmxreg.h>
     55 #include <mips/cavium/include/iobusvar.h>
     56 #include <mips/cavium/dev/octeon_ipdvar.h>
     57 #include <mips/cavium/dev/octeon_asxvar.h>
     58 #include <mips/cavium/dev/octeon_gmxvar.h>
     59 
     60 #define	dprintf(...)
     61 #define	OCTEON_ETH_KASSERT	KASSERT
     62 
     63 #define	ADDR2UINT64(u, a) \
     64 	do { \
     65 		u = \
     66 		    (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \
     67 		     ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \
     68 		     ((uint64_t)a[4] <<  8) | ((uint64_t)a[5] <<  0)); \
     69 	} while (0)
     70 #define	UINT642ADDR(a, u) \
     71 	do { \
     72 		a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \
     73 		a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \
     74 		a[4] = (uint8_t)((u) >>  8); a[5] = (uint8_t)((u) >>  0); \
     75 	} while (0)
     76 
     77 #define	_GMX_RD8(sc, off) \
     78 	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off))
     79 #define	_GMX_WR8(sc, off, v) \
     80 	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off), (v))
     81 #define	_GMX_PORT_RD8(sc, off) \
     82 	bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off))
     83 #define	_GMX_PORT_WR8(sc, off, v) \
     84 	bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v))
     85 
     86 struct octeon_gmx_port_ops {
     87 	int	(*port_ops_enable)(struct octeon_gmx_port_softc *, int);
     88 	int	(*port_ops_speed)(struct octeon_gmx_port_softc *);
     89 	int	(*port_ops_timing)(struct octeon_gmx_port_softc *);
     90 	int	(*port_ops_set_mac_addr)(struct octeon_gmx_port_softc *,
     91 		    uint8_t *, uint64_t);
     92 	int	(*port_ops_set_filter)(struct octeon_gmx_port_softc *);
     93 };
     94 
     95 static int	octeon_gmx_match(device_t, struct cfdata *, void *);
     96 static void	octeon_gmx_attach(device_t, device_t, void *);
     97 static int	octeon_gmx_print(void *, const char *);
     98 static int      octeon_gmx_submatch(device_t, struct cfdata *,
     99 		    const int *, void *);
    100 static int	octeon_gmx_init(struct octeon_gmx_softc *);
    101 static int	octeon_gmx_rx_frm_ctl_xable(struct octeon_gmx_port_softc *,
    102 		    uint64_t, int);
    103 
    104 static int	octeon_gmx_rgmii_enable(struct octeon_gmx_port_softc *, int);
    105 static int	octeon_gmx_rgmii_speed(struct octeon_gmx_port_softc *);
    106 static int	octeon_gmx_rgmii_speed_newlink(struct octeon_gmx_port_softc *,
    107 		    uint64_t *);
    108 static int	octeon_gmx_rgmii_speed_speed(struct octeon_gmx_port_softc *);
    109 static int	octeon_gmx_rgmii_timing(struct octeon_gmx_port_softc *);
    110 static int	octeon_gmx_rgmii_set_mac_addr(struct octeon_gmx_port_softc *,
    111 		    uint8_t *, uint64_t);
    112 static int	octeon_gmx_rgmii_set_filter(struct octeon_gmx_port_softc *);
    113 
    114 #ifdef OCTEON_ETH_DEBUG
    115 void		octeon_gmx_intr_evcnt_attach(struct octeon_gmx_softc *);
    116 void		octeon_gmx_dump(void);
    117 void		octeon_gmx_debug_reset(void);
    118 int		octeon_gmx_intr_drop(void *);
    119 #endif
    120 
    121 static const int	octeon_gmx_rx_adr_cam_regs[] = {
    122 	GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2,
    123 	GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5
    124 };
    125 
    126 struct octeon_gmx_port_ops octeon_gmx_port_ops_mii = {
    127 	/* XXX not implemented */
    128 };
    129 
    130 struct octeon_gmx_port_ops octeon_gmx_port_ops_gmii = {
    131 	.port_ops_enable = octeon_gmx_rgmii_enable,
    132 	.port_ops_speed = octeon_gmx_rgmii_speed,
    133 	.port_ops_timing = octeon_gmx_rgmii_timing,
    134 	.port_ops_set_mac_addr = octeon_gmx_rgmii_set_mac_addr,
    135 	.port_ops_set_filter = octeon_gmx_rgmii_set_filter
    136 };
    137 
    138 struct octeon_gmx_port_ops octeon_gmx_port_ops_rgmii = {
    139 	.port_ops_enable = octeon_gmx_rgmii_enable,
    140 	.port_ops_speed = octeon_gmx_rgmii_speed,
    141 	.port_ops_timing = octeon_gmx_rgmii_timing,
    142 	.port_ops_set_mac_addr = octeon_gmx_rgmii_set_mac_addr,
    143 	.port_ops_set_filter = octeon_gmx_rgmii_set_filter
    144 };
    145 
    146 struct octeon_gmx_port_ops octeon_gmx_port_ops_spi42 = {
    147 	/* XXX not implemented */
    148 };
    149 
    150 struct octeon_gmx_port_ops *octeon_gmx_port_ops[] = {
    151 	[GMX_MII_PORT] = &octeon_gmx_port_ops_mii,
    152 	[GMX_GMII_PORT] = &octeon_gmx_port_ops_gmii,
    153 	[GMX_RGMII_PORT] = &octeon_gmx_port_ops_rgmii,
    154 	[GMX_SPI42_PORT] = &octeon_gmx_port_ops_spi42
    155 };
    156 
    157 #ifdef OCTEON_ETH_DEBUG
    158 static void		*octeon_gmx_intr_drop_ih;
    159 struct evcnt		octeon_gmx_intr_drop_evcnt =
    160 			    EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "octeon",
    161 			    "gmx drop intr");
    162 struct evcnt		octeon_gmx_intr_evcnt =
    163 			    EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "octeon",
    164 			    "gmx intr");
    165 EVCNT_ATTACH_STATIC(octeon_gmx_intr_drop_evcnt);
    166 EVCNT_ATTACH_STATIC(octeon_gmx_intr_evcnt);
    167 
    168 struct octeon_gmx_port_softc *__octeon_gmx_port_softc[3/* XXX */];
    169 #endif
    170 
    171 CFATTACH_DECL_NEW(octeon_gmx, sizeof(struct octeon_gmx_softc),
    172     octeon_gmx_match, octeon_gmx_attach, NULL, NULL);
    173 
    174 static int
    175 octeon_gmx_match(device_t parent, struct cfdata *cf, void *aux)
    176 {
    177 	struct iobus_attach_args *aa = aux;
    178 
    179 	if (strcmp(cf->cf_name, aa->aa_name) != 0)
    180 		return 0;
    181 	if (cf->cf_unit != aa->aa_unitno)
    182 		return 0;
    183 	return 1;
    184 }
    185 
    186 static void
    187 octeon_gmx_attach(device_t parent, device_t self, void *aux)
    188 {
    189 	struct octeon_gmx_softc *sc = device_private(self);
    190 	struct iobus_attach_args *aa = aux;
    191 	struct octeon_gmx_attach_args gmx_aa;
    192 	int status;
    193 	int i;
    194 	struct octeon_gmx_port_softc *port_sc;
    195 
    196 	sc->sc_dev = self;
    197 	sc->sc_regt = aa->aa_bust;
    198 	sc->sc_unitno = aa->aa_unitno;
    199 
    200 	aprint_normal("\n");
    201 
    202 	status = bus_space_map(sc->sc_regt, aa->aa_unit->addr,
    203 	    GMX0_BASE_IF_SIZE, 0, &sc->sc_regh);
    204 	if (status != 0)
    205 		panic(": can't map register");
    206 
    207 	octeon_gmx_init(sc);
    208 
    209 	sc->sc_ports = malloc(sizeof(*sc->sc_ports) * sc->sc_nports, M_DEVBUF,
    210 	    M_NOWAIT | M_ZERO);
    211 
    212 	for (i = 0; i < sc->sc_nports; i++) {
    213 		port_sc = &sc->sc_ports[i];
    214 		port_sc->sc_port_gmx = sc;
    215 		port_sc->sc_port_no = i;
    216 		port_sc->sc_port_type = sc->sc_port_types[i];
    217 		port_sc->sc_port_ops = octeon_gmx_port_ops[port_sc->sc_port_type];
    218 		status = bus_space_map(sc->sc_regt,
    219 		    aa->aa_unit->addr + GMX0_BASE_PORT_SIZE * i,
    220 		    GMX0_BASE_PORT_SIZE, 0, &port_sc->sc_port_regh);
    221 		if (status != 0)
    222 			panic(": can't map port register");
    223 
    224 		(void)memset(&gmx_aa, 0, sizeof(gmx_aa));
    225 		gmx_aa.ga_regt = aa->aa_bust;
    226 		gmx_aa.ga_addr = aa->aa_unit->addr;
    227 		gmx_aa.ga_name = "cnmac";
    228 		gmx_aa.ga_portno = i;
    229 		gmx_aa.ga_port_type = sc->sc_port_types[i];
    230 		gmx_aa.ga_gmx = sc;
    231 		gmx_aa.ga_gmx_port = port_sc;
    232 		config_found_sm_loc(self, "octeon_gmx", NULL, &gmx_aa,
    233 		    octeon_gmx_print, octeon_gmx_submatch);
    234 
    235 #ifdef OCTEON_ETH_DEBUG
    236 		__octeon_gmx_port_softc[i] = port_sc;
    237 #endif
    238 	}
    239 
    240 #ifdef OCTEON_ETH_DEBUG
    241 	octeon_gmx_intr_evcnt_attach(sc);
    242 	if (octeon_gmx_intr_drop_ih == NULL)
    243 		octeon_gmx_intr_drop_ih = octeon_intr_establish(
    244 		   ffs64(CIU_INTX_SUM0_GMX_DRP) - 1, IPL_NET,
    245 		   octeon_gmx_intr_drop, NULL);
    246 #endif
    247 }
    248 
    249 static int
    250 octeon_gmx_print(void *aux, const char *pnp)
    251 {
    252 	struct octeon_gmx_attach_args *ga = aux;
    253 	static const char *types[] = {
    254 		[GMX_MII_PORT] = "MII",
    255 		[GMX_GMII_PORT] = "GMII",
    256 		[GMX_RGMII_PORT] = "RGMII"
    257 	};
    258 
    259 #if DEBUG
    260 	if (pnp)
    261 		aprint_normal("%s at %s\n", ga->ga_name, pnp);
    262 #endif
    263 
    264 	aprint_normal(": address=0x%016" PRIx64 ": %s\n", ga->ga_addr,
    265 	    types[ga->ga_port_type]);
    266 
    267 	return UNCONF;
    268 }
    269 
    270 static int
    271 octeon_gmx_submatch(device_t parent, struct cfdata *cf,
    272     const int *ldesc, void *aux)
    273 {
    274 	return config_match(parent, cf, aux);
    275 }
    276 
    277 static int
    278 octeon_gmx_init(struct octeon_gmx_softc *sc)
    279 {
    280 	int result = 0;
    281 	uint64_t inf_mode;
    282 	/* XXX */
    283 	const mips_prid_t cpu_id = mips_options.mips_cpu_id;
    284 
    285 	inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE);
    286 	if ((inf_mode & INF_MODE_EN) == 0) {
    287 		aprint_normal("port are disable\n");
    288 		sc->sc_nports = 0;
    289 		return 1;
    290 	}
    291 
    292 	if (MIPS_PRID_CID(cpu_id) != MIPS_PRID_CID_CAVIUM)
    293 		return 1;
    294 
    295 	switch (MIPS_PRID_IMPL(cpu_id)) {
    296 	case MIPS_CN31XX:
    297 		/*
    298 		 * Packet Interface Configuration
    299 		 * GMX Registers, Interface Mode Register, GMX0_INF_MODE
    300 		 */
    301 		if ((inf_mode & INF_MODE_TYPE) == 0) {
    302 			/* all three ports configured as RGMII */
    303 			sc->sc_nports = 3;
    304 			sc->sc_port_types[0] = GMX_RGMII_PORT;
    305 			sc->sc_port_types[1] = GMX_RGMII_PORT;
    306 			sc->sc_port_types[2] = GMX_RGMII_PORT;
    307 		} else {
    308 			/* port 0: RGMII, port 1: GMII, port 2: disabled */
    309 			sc->sc_nports = 2;
    310 			sc->sc_port_types[0] = GMX_RGMII_PORT;
    311 			sc->sc_port_types[1] = GMX_GMII_PORT;
    312 		}
    313 		break;
    314 	case MIPS_CN30XX:
    315 	case MIPS_CN50XX:
    316 		/*
    317 		 * Packet Interface Configuration
    318 		 * GMX Registers, Interface Mode Register, GMX0_INF_MODE
    319 		 */
    320 		if ((inf_mode & INF_MODE_P0MII) == 0)
    321 			sc->sc_port_types[0] = GMX_RGMII_PORT;
    322 		else
    323 			sc->sc_port_types[0] = GMX_MII_PORT;
    324 		if ((inf_mode & INF_MODE_TYPE) == 0) {
    325 			/* port 1 and 2 are configred as RGMII ports */
    326 			sc->sc_nports = 3;
    327 			sc->sc_port_types[1] = GMX_RGMII_PORT;
    328 			sc->sc_port_types[2] = GMX_RGMII_PORT;
    329 		} else {
    330 			/* port 1: GMII/MII, port 2: disabled */
    331 			/* GMII or MII port is slected by GMX_PRT1_CFG[SPEED] */
    332 			sc->sc_nports = 2;
    333 			sc->sc_port_types[1] = GMX_GMII_PORT;
    334 		}
    335 #if 0 /* XXX XXX XXX */
    336 		/* port 2 is in CN3010/CN5010 only */
    337 		if ((octeon_model(id) != OCTEON_MODEL_CN3010) &&
    338 		    (octeon_model(id) != OCTEON_MODEL_CN5010))
    339 			if (sc->sc_nports == 3)
    340 				sc->sc_nports = 2;
    341 #endif
    342 		break;
    343 	default:
    344 		aprint_normal("unsupported octeon model: 0x%x\n", cpu_id);
    345 		sc->sc_nports = 0;
    346 		result = 1;
    347 		break;
    348 	}
    349 
    350 	return result;
    351 }
    352 
    353 /* XXX RGMII specific */
    354 int
    355 octeon_gmx_link_enable(struct octeon_gmx_port_softc *sc, int enable)
    356 {
    357 	uint64_t prt_cfg;
    358 
    359 	octeon_gmx_tx_int_enable(sc, enable);
    360 	octeon_gmx_rx_int_enable(sc, enable);
    361 
    362 	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
    363 	if (enable) {
    364 		if (octeon_gmx_link_status(sc)) {
    365 			SET(prt_cfg, PRTN_CFG_EN);
    366 		}
    367 	} else {
    368 		CLR(prt_cfg, PRTN_CFG_EN);
    369 	}
    370 	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
    371 	/* software should read back to flush the write operation. */
    372 	(void)_GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
    373 
    374 	return 0;
    375 }
    376 
    377 /* XXX RGMII specific */
    378 int
    379 octeon_gmx_stats_init(struct octeon_gmx_port_softc *sc)
    380 {
    381         _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0x0ULL);
    382         _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0x0ULL);
    383         _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0x0ULL);
    384         _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0x0ULL);
    385         _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0x0ULL);
    386         _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0x0ULL);
    387         _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0x0ULL);
    388 
    389 	return 0;
    390 }
    391 
    392 int
    393 octeon_gmx_tx_stats_rd_clr(struct octeon_gmx_port_softc *sc, int enable)
    394 {
    395 	_GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
    396 	return 0;
    397 }
    398 
    399 int
    400 octeon_gmx_rx_stats_rd_clr(struct octeon_gmx_port_softc *sc, int enable)
    401 {
    402 	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 0x1ULL : 0x0ULL);
    403 	return 0;
    404 }
    405 
    406 void
    407 octeon_gmx_rx_stats_dec_bad(struct octeon_gmx_port_softc *sc)
    408 {
    409 	uint64_t tmp;
    410 
    411         tmp = _GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_BAD);
    412 	_GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, tmp - 1);
    413 }
    414 
    415 static int
    416 octeon_gmx_tx_ovr_bp_enable(struct octeon_gmx_port_softc *sc, int enable)
    417 {
    418 	uint64_t ovr_bp;
    419 
    420 	ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP);
    421 	if (enable) {
    422 		CLR(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_EN_SHIFT);
    423 		SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_BP_SHIFT);
    424 		/* XXX really??? */
    425 		SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_IGN_FULL_SHIFT);
    426 	} else {
    427 		SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_EN_SHIFT);
    428 		CLR(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_BP_SHIFT);
    429 		/* XXX really??? */
    430 		SET(ovr_bp, (1 << sc->sc_port_no) << TX_OVR_BP_IGN_FULL_SHIFT);
    431 	}
    432 	_GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp);
    433 	return 0;
    434 }
    435 
    436 static int
    437 octeon_gmx_rx_pause_enable(struct octeon_gmx_port_softc *sc, int enable)
    438 {
    439 	if (enable) {
    440 		octeon_gmx_rx_frm_ctl_enable(sc, RXN_FRM_CTL_CTL_BCK);
    441 	} else {
    442 		octeon_gmx_rx_frm_ctl_disable(sc, RXN_FRM_CTL_CTL_BCK);
    443 	}
    444 
    445 	return 0;
    446 }
    447 
    448 void
    449 octeon_gmx_tx_int_enable(struct octeon_gmx_port_softc *sc, int enable)
    450 {
    451 	uint64_t tx_int_xxx = 0;
    452 
    453 	SET(tx_int_xxx,
    454 	    TX_INT_REG_LATE_COL |
    455 	    TX_INT_REG_XSDEF |
    456 	    TX_INT_REG_XSCOL |
    457 	    TX_INT_REG_UNDFLW |
    458 	    TX_INT_REG_PKO_NXA);
    459 	_GMX_WR8(sc, GMX0_TX_INT_REG, tx_int_xxx);
    460 	_GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0);
    461 }
    462 
    463 void
    464 octeon_gmx_rx_int_enable(struct octeon_gmx_port_softc *sc, int enable)
    465 {
    466 	uint64_t rx_int_xxx = 0;
    467 
    468 	SET(rx_int_xxx, 0 |
    469 	    RXN_INT_REG_PHY_DUPX |
    470 	    RXN_INT_REG_PHY_SPD |
    471 	    RXN_INT_REG_PHY_LINK |
    472 	    RXN_INT_REG_IFGERR |
    473 	    RXN_INT_REG_COLDET |
    474 	    RXN_INT_REG_FALERR |
    475 	    RXN_INT_REG_RSVERR |
    476 	    RXN_INT_REG_PCTERR |
    477 	    RXN_INT_REG_OVRERR |
    478 	    RXN_INT_REG_NIBERR |
    479 	    RXN_INT_REG_SKPERR |
    480 	    RXN_INT_REG_RCVERR |
    481 	    RXN_INT_REG_LENERR |
    482 	    RXN_INT_REG_ALNERR |
    483 	    RXN_INT_REG_FCSERR |
    484 	    RXN_INT_REG_JABBER |
    485 	    RXN_INT_REG_MAXERR |
    486 	    RXN_INT_REG_CAREXT |
    487 	    RXN_INT_REG_MINERR);
    488 	_GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_xxx);
    489 	_GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0);
    490 }
    491 
    492 int
    493 octeon_gmx_rx_frm_ctl_enable(struct octeon_gmx_port_softc *sc,
    494     uint64_t rx_frm_ctl)
    495 {
    496 	/*
    497 	 * XXX Jumbo-frame Workarounds
    498 	 *     Current implementation of cnmac is required to
    499 	 *     configure GMX0_RX0_JABBER[CNT] as follows:
    500 	 *	RX0_FRM_MAX(1536) <= GMX0_RX0_JABBER <= 1536(0x600)
    501 	 */
    502 	_GMX_PORT_WR8(sc, GMX0_RX0_JABBER, GMX_FRM_MAX_SIZ);
    503 
    504 	return octeon_gmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1);
    505 }
    506 
    507 int
    508 octeon_gmx_rx_frm_ctl_disable(struct octeon_gmx_port_softc *sc,
    509     uint64_t rx_frm_ctl)
    510 {
    511 	return octeon_gmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0);
    512 }
    513 
    514 static int
    515 octeon_gmx_rx_frm_ctl_xable(struct octeon_gmx_port_softc *sc,
    516     uint64_t rx_frm_ctl, int enable)
    517 {
    518 	uint64_t tmp;
    519 
    520 	tmp = _GMX_PORT_RD8(sc, GMX0_RX0_FRM_CTL);
    521 	if (enable)
    522 		SET(tmp, rx_frm_ctl);
    523 	else
    524 		CLR(tmp, rx_frm_ctl);
    525 	_GMX_PORT_WR8(sc, GMX0_RX0_FRM_CTL, tmp);
    526 
    527 	return 0;
    528 }
    529 
    530 int
    531 octeon_gmx_tx_thresh(struct octeon_gmx_port_softc *sc, int cnt)
    532 {
    533 	_GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt);
    534 	return 0;
    535 }
    536 
    537 int
    538 octeon_gmx_set_mac_addr(struct octeon_gmx_port_softc *sc, uint8_t *addr)
    539 {
    540 	uint64_t mac = 0;
    541 
    542 	ADDR2UINT64(mac, addr);
    543 	(*sc->sc_port_ops->port_ops_set_mac_addr)(sc, addr, mac);
    544 	return 0;
    545 }
    546 
    547 int
    548 octeon_gmx_set_filter(struct octeon_gmx_port_softc *sc)
    549 {
    550 	(*sc->sc_port_ops->port_ops_set_filter)(sc);
    551 	return 0;
    552 }
    553 
    554 int
    555 octeon_gmx_port_enable(struct octeon_gmx_port_softc *sc, int enable)
    556 {
    557 	(*sc->sc_port_ops->port_ops_enable)(sc, enable);
    558 	return 0;
    559 }
    560 
    561 int
    562 octeon_gmx_reset_speed(struct octeon_gmx_port_softc *sc)
    563 {
    564 	struct ifnet *ifp = &sc->sc_port_ec->ec_if;
    565 	if (ISSET(sc->sc_port_mii->mii_flags, MIIF_DOINGAUTO)) {
    566 		log(LOG_WARNING,
    567 		    "%s: autonegotiation has not been completed yet\n",
    568 		    ifp->if_xname);
    569 		return 1;
    570 	}
    571 	(*sc->sc_port_ops->port_ops_speed)(sc);
    572 	return 0;
    573 }
    574 
    575 int
    576 octeon_gmx_reset_timing(struct octeon_gmx_port_softc *sc)
    577 {
    578 	(*sc->sc_port_ops->port_ops_timing)(sc);
    579 	return 0;
    580 }
    581 
    582 int
    583 octeon_gmx_reset_flowctl(struct octeon_gmx_port_softc *sc)
    584 {
    585 	struct ifmedia_entry *ife = sc->sc_port_mii->mii_media.ifm_cur;
    586 
    587 	/*
    588 	 * Get flow control negotiation result.
    589 	 */
    590 	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO &&
    591 	    (sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK) !=
    592 			sc->sc_port_flowflags) {
    593 		sc->sc_port_flowflags =
    594 			sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK;
    595 		sc->sc_port_mii->mii_media_active &= ~IFM_ETH_FMASK;
    596 	}
    597 
    598 	/*
    599 	 * 802.3x Flow Control Capabilities
    600 	 */
    601 	if (sc->sc_port_flowflags & IFM_ETH_TXPAUSE) {
    602 		octeon_gmx_tx_ovr_bp_enable(sc, 1);
    603 	} else {
    604 		octeon_gmx_tx_ovr_bp_enable(sc, 0);
    605 	}
    606 	if (sc->sc_port_flowflags & IFM_ETH_RXPAUSE) {
    607 		octeon_gmx_rx_pause_enable(sc, 1);
    608 	} else {
    609 		octeon_gmx_rx_pause_enable(sc, 0);
    610 	}
    611 
    612 	return 0;
    613 }
    614 
    615 static int
    616 octeon_gmx_rgmii_enable(struct octeon_gmx_port_softc *sc, int enable)
    617 {
    618 	uint64_t mode;
    619 
    620 	/* XXX XXX XXX */
    621 	mode = _GMX_RD8(sc, GMX0_INF_MODE);
    622 	if (ISSET(mode, INF_MODE_EN)) {
    623 		octeon_asx_enable(sc->sc_port_asx, 1);
    624 	}
    625 	/* XXX XXX XXX */
    626 	return 0;
    627 }
    628 
    629 static int
    630 octeon_gmx_rgmii_speed(struct octeon_gmx_port_softc *sc)
    631 {
    632 	struct ifnet *ifp = &sc->sc_port_ec->ec_if;
    633 	uint64_t newlink;
    634 	int baudrate;
    635 
    636 	/* XXX XXX XXX */
    637 	octeon_gmx_link_enable(sc, 1);
    638 
    639 	octeon_gmx_rgmii_speed_newlink(sc, &newlink);
    640 	if (sc->sc_link == newlink) {
    641 		return 0;
    642 	}
    643 	sc->sc_link = newlink;
    644 
    645 	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
    646 	case RXN_RX_INBND_SPEED_2_5:
    647 		baudrate = IF_Mbps(10);
    648 		break;
    649 	case RXN_RX_INBND_SPEED_25:
    650 		baudrate = IF_Mbps(100);
    651 		break;
    652 	case RXN_RX_INBND_SPEED_125:
    653 		baudrate = IF_Mbps(1000);
    654 		break;
    655 	default:
    656 		baudrate = 0/* XXX */;
    657 		break;
    658 	}
    659 	ifp->if_baudrate = baudrate;
    660 
    661 	/* XXX XXX XXX */
    662 
    663 	octeon_gmx_link_enable(sc, 0);
    664 
    665 	/*
    666 	 * wait a max_packet_time
    667 	 * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
    668 	 */
    669 	delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
    670 
    671 	octeon_gmx_rgmii_speed_speed(sc);
    672 
    673 	octeon_gmx_link_enable(sc, 1);
    674 	octeon_asx_enable(sc->sc_port_asx, 1);
    675 
    676 	return 0;
    677 }
    678 
    679 static int
    680 octeon_gmx_rgmii_speed_newlink(struct octeon_gmx_port_softc *sc,
    681     uint64_t *rnewlink)
    682 {
    683 	uint64_t newlink = 0;
    684 
    685 	if (sc->sc_quirks & OCTEON_ETH_QUIRKS_NO_RX_INBND) {
    686 		newlink = 0;
    687 		switch (IFM_SUBTYPE(sc->sc_port_mii->mii_media_active)) {
    688 		default:
    689 			SET(newlink, RXN_RX_INBND_SPEED_125);
    690 			break;
    691 		case IFM_100_TX:
    692 			SET(newlink, RXN_RX_INBND_SPEED_25);
    693 			break;
    694 		case IFM_10_T:
    695 			SET(newlink, RXN_RX_INBND_SPEED_2_5);
    696 			break;
    697 		}
    698 		SET(newlink,
    699 		    ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX) ?
    700 		    RXN_RX_INBND_DUPLEX : 0);
    701 		SET(newlink,
    702 		    ISSET(sc->sc_port_mii->mii_media_status, IFM_ACTIVE) ?
    703 		    RXN_RX_INBND_STATUS : 0);
    704 	} else {
    705 		newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
    706 	}
    707 
    708 	*rnewlink = newlink;
    709 	return 0;
    710 }
    711 
    712 static int
    713 octeon_gmx_rgmii_speed_speed(struct octeon_gmx_port_softc *sc)
    714 {
    715 	uint64_t prt_cfg;
    716 	uint64_t tx_clk, tx_slot, tx_burst;
    717 
    718 	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
    719 
    720 	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
    721 	case RXN_RX_INBND_SPEED_2_5:
    722 		/* 10Mbps */
    723 		/*
    724 		 * GMX Tx Clock Generation Registers
    725 		 * 8ns x 50 = 400ns (2.5MHz TXC clock)
    726 		 */
    727 		tx_clk = 50;
    728 		/*
    729 		 * TX Slottime Counter Registers
    730 		 * 10/100Mbps: set SLOT to 0x40
    731 		 */
    732 		tx_slot = 0x40;
    733 		/*
    734 		 * TX Burst-Counter Registers
    735 		 * 10/100Mbps: set BURST to 0x0
    736 		 */
    737 		tx_burst = 0;
    738 		/*
    739 		 * GMX Tx Port Configuration Registers
    740 		 * Slot time for half-duplex operation
    741 		 *   0 = 512 bittimes (10/100Mbps operation)
    742 		 */
    743 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
    744 		/*
    745 		 * GMX Port Configuration Registers
    746 		 * Link speed
    747 		 *   0 = 10/100Mbps operation
    748 		 *     in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
    749 		 */
    750 		CLR(prt_cfg, PRTN_CFG_SPEED);
    751 		break;
    752 	case RXN_RX_INBND_SPEED_25:
    753 		/* 100Mbps */
    754 		/*
    755 		 * GMX Tx Clock Generation Registers
    756 		 *  8ns x 5 = 40ns (25.0MHz TXC clock)
    757 		 */
    758 		tx_clk = 5;
    759 		/*
    760 		 * TX Slottime Counter Registers
    761 		 *  10/100Mbps: set SLOT to 0x40
    762 		 */
    763 		tx_slot = 0x40;
    764 		/*
    765 		 * TX Burst-Counter Registers
    766 		 *  10/100Mbps: set BURST to 0x0
    767 		 */
    768 		tx_burst = 0;
    769 		/*
    770 		 * GMX Tx Port Configuration Registers
    771 		 *  Slot time for half-duplex operation
    772 		 *    0 = 512 bittimes (10/100Mbps operation)
    773 		 */
    774 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
    775 		/*
    776 		 * GMX Port Configuration Registers
    777 		 *  Link speed
    778 		 *    0 = 10/100Mbps operation
    779 		 *      in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
    780 		 */
    781 		CLR(prt_cfg, PRTN_CFG_SPEED);
    782 		break;
    783 	case RXN_RX_INBND_SPEED_125:
    784 		/* 1000Mbps */
    785 		/*
    786 		 * GMX Tx Clock Generation Registers
    787 		 *  8ns x 1 = 8ns (125.0MHz TXC clock)
    788 		 */
    789 		tx_clk = 1;
    790 		/*
    791 		 * TX Slottime Counter Registers
    792 		 * > 1000Mbps: set SLOT to 0x200
    793 		 */
    794 		tx_slot = 0x200;
    795 		/*
    796 		 * "TX Burst-Counter Registers
    797 		 * > 1000Mbps: set BURST to 0x2000
    798 		 */
    799 		tx_burst = 0x2000;
    800 		/*
    801 		 * GMX Tx Port Configuration Registers
    802 		 *  Slot time for half-duplex operation
    803 		 *    1 = 4096 bittimes (1000Mbps operation)
    804 		 */
    805 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
    806 		/*
    807 		 * GMX Port Configuration Registers
    808 		 *  Link speed
    809 		 *    1 = 1000Mbps operation
    810 		 */
    811 		SET(prt_cfg, PRTN_CFG_SPEED);
    812 		break;
    813 	default:
    814 		/* NOT REACHED! */
    815 		/* Following configuration is default value of system.
    816 		*/
    817 		tx_clk = 1;
    818 		tx_slot = 0x200;
    819 		tx_burst = 0x2000;
    820 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
    821 		SET(prt_cfg, PRTN_CFG_SPEED);
    822 		break;
    823 	}
    824 
    825 	/* Setup Duplex mode(negotiated) */
    826 	/*
    827 	 * GMX Port Configuration Registers
    828 	 *  Duplex mode: 0 = half-duplex mode, 1=full-duplex
    829 	 */
    830 	if (ISSET(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
    831 		/* Full-Duplex */
    832 		SET(prt_cfg, PRTN_CFG_DUPLEX);
    833 	} else {
    834 		/* Half-Duplex */
    835 		CLR(prt_cfg, PRTN_CFG_DUPLEX);
    836 	}
    837 
    838 	_GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
    839 	_GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
    840 	_GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
    841 	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
    842 
    843 	return 0;
    844 }
    845 
    846 static int
    847 octeon_gmx_rgmii_timing(struct octeon_gmx_port_softc *sc)
    848 {
    849 	prop_dictionary_t dict = device_properties(sc->sc_port_gmx->sc_dev);
    850 	prop_object_t clk;
    851 	int clk_tx_setting, clk_rx_setting;
    852 	uint64_t rx_frm_ctl;
    853 
    854 	/* RGMII TX Threshold Registers
    855 	 * Number of 16-byte ticks to accumulate in the TX FIFO before
    856 	 * sending on the RGMII interface. This field should be large
    857 	 * enough to prevent underflow on the RGMII interface and must
    858 	 * never be set to less than 0x4. This register cannot exceed
    859 	 * the TX FIFO depth of 0x40 words.
    860 	 */
    861 	/* Default parameter of CN30XX */
    862 	octeon_gmx_tx_thresh(sc, 32);
    863 
    864 	rx_frm_ctl = 0 |
    865 	    /* RXN_FRM_CTL_NULL_DIS |	(cn5xxx only) */
    866 	    /* RXN_FRM_CTL_PRE_ALIGN |	(cn5xxx only) */
    867 	    /* RXN_FRM_CTL_PAD_LEN |	(cn3xxx only) */
    868 	    /* RXN_FRM_CTL_VLAN_LEN |	(cn3xxx only) */
    869 	    RXN_FRM_CTL_PRE_FREE |
    870 	    RXN_FRM_CTL_CTL_SMAC |
    871 	    RXN_FRM_CTL_CTL_MCST |
    872 	    RXN_FRM_CTL_CTL_DRP |
    873 	    RXN_FRM_CTL_PRE_STRP |
    874 	    RXN_FRM_CTL_PRE_CHK;
    875 	if (!(sc->sc_quirks & OCTEON_ETH_QUIRKS_NO_PRE_ALIGN))
    876 		rx_frm_ctl |= RXN_FRM_CTL_PRE_ALIGN;
    877 	octeon_gmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
    878 
    879 	/* RGMII RX Clock-Delay Registers
    880 	 * Delay setting to place n RXC (RGMII receive clock) delay line.
    881 	 * The intrinsic delay can range from 50ps to 80ps per tap,
    882 	 * which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
    883 	 * This is the best match for the RGMII specification which wants
    884 	 * 1ns - 2.6ns of skew.
    885 	 */
    886 	/* RGMII TX Clock-Delay Registers
    887 	 * Delay setting to place n TXC (RGMII transmit clock) delay line.
    888 	 */
    889 	clk = prop_dictionary_get(dict, "rgmii-tx");
    890 	KASSERT(clk != NULL);
    891 	clk_tx_setting = prop_number_integer_value(clk);
    892 	clk = prop_dictionary_get(dict, "rgmii-rx");
    893 	KASSERT(clk != NULL);
    894 	clk_rx_setting = prop_number_integer_value(clk);
    895 
    896 	octeon_asx_clk_set(sc->sc_port_asx, clk_tx_setting, clk_rx_setting);
    897 
    898 	return 0;
    899 }
    900 
    901 static int
    902 octeon_gmx_rgmii_set_mac_addr(struct octeon_gmx_port_softc *sc, uint8_t *addr,
    903     uint64_t mac)
    904 {
    905 	int i;
    906 
    907 	octeon_gmx_link_enable(sc, 0);
    908 
    909 	sc->sc_mac = mac;
    910 	_GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
    911 	for (i = 0; i < 6; i++)
    912 		_GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[i], addr[i]);
    913 
    914 	octeon_gmx_link_enable(sc, 1);
    915 
    916 	return 0;
    917 }
    918 
    919 #define	OCTEON_ETH_USE_GMX_CAM
    920 
    921 static int
    922 octeon_gmx_rgmii_set_filter(struct octeon_gmx_port_softc *sc)
    923 {
    924 	struct ifnet *ifp = &sc->sc_port_ec->ec_if;
    925 #ifdef OCTEON_ETH_USE_GMX_CAM
    926 	struct ether_multi *enm;
    927 	struct ether_multistep step;
    928 #endif
    929 	uint64_t ctl = 0;
    930 	int multi = 0;
    931 	/* XXX XXX XXX */
    932 	uint64_t cam_en = 0x01ULL;
    933 	/* XXX XXX XXX */
    934 
    935 	octeon_gmx_link_enable(sc, 0);
    936 
    937 	if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
    938 		dprintf("accept broadcast\n");
    939 		SET(ctl, RXN_ADR_CTL_BCST);
    940 	}
    941 	if (ISSET(ifp->if_flags, IFF_PROMISC)) {
    942 		dprintf("promiscas(reject cam)\n");
    943 		CLR(ctl, RXN_ADR_CTL_CAM_MODE);
    944 	} else {
    945 		dprintf("not promiscas(accept cam)\n");
    946 		SET(ctl, RXN_ADR_CTL_CAM_MODE);
    947 	}
    948 
    949 #ifdef OCTEON_ETH_USE_GMX_CAM
    950 	/*
    951 	 * Note first entry is self MAC address; other 7 entires are available
    952 	 * for multicast addresses.
    953 	 */
    954 
    955 	ETHER_FIRST_MULTI(step, sc->sc_port_ec, enm);
    956 	while (enm != NULL) {
    957 		int i;
    958 
    959 		dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - "
    960 		    "hi(%02x:%02x:%02x:%02x:%02x:%02x)\n",
    961 		    multi + 1,
    962 		    enm->enm_addrlo[0], enm->enm_addrlo[1],
    963 		    enm->enm_addrlo[2], enm->enm_addrlo[3],
    964 		    enm->enm_addrlo[4], enm->enm_addrlo[5],
    965 		    enm->enm_addrhi[0], enm->enm_addrhi[1],
    966 		    enm->enm_addrhi[2], enm->enm_addrhi[3],
    967 		    enm->enm_addrhi[4], enm->enm_addrhi[5]);
    968 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
    969 			dprintf("all multicast\n");
    970 			SET(ifp->if_flags, IFF_ALLMULTI);
    971 			goto setmulti;
    972 		}
    973 		multi++;
    974 
    975 		/* XXX XXX XXX */
    976 		if (multi >= 8) {
    977 			SET(ifp->if_flags, IFF_ALLMULTI);
    978 			goto setmulti;
    979 		}
    980 		/* XXX XXX XXX */
    981 
    982 		/* XXX XXX XXX */
    983 		SET(cam_en, 1ULL << multi);
    984 		/* XXX XXX XXX */
    985 
    986 		for (i = 0; i < 6; i++) {
    987 			uint64_t tmp;
    988 
    989 			/* XXX XXX XXX */
    990 			tmp = _GMX_PORT_RD8(sc, octeon_gmx_rx_adr_cam_regs[i]);
    991 			CLR(tmp, 0xffULL << (8 * multi));
    992 			SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi));
    993 			_GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[i], tmp);
    994 			/* XXX XXX XXX */
    995 
    996 		}
    997 		for (i = 0; i < 6; i++)
    998 			dprintf("cam%d = %016llx\n", i,
    999 			    _GMX_PORT_RD8(sc, octeon_gmx_rx_adr_cam_regs[i]));
   1000 		ETHER_NEXT_MULTI(step, enm);
   1001 	}
   1002 	CLR(ifp->if_flags, IFF_ALLMULTI);
   1003 
   1004 	OCTEON_ETH_KASSERT(enm == NULL);
   1005 #else
   1006 	/*
   1007 	 * XXX
   1008 	 * Never use DMAC filter for multicast addresses, but register only
   1009 	 * single entry for self address. FreeBSD code do so.
   1010 	 */
   1011 	SET(ifp->if_flags, IFF_ALLMULTI);
   1012 	goto setmulti;
   1013 #endif
   1014 
   1015 setmulti:
   1016 	/* XXX XXX XXX */
   1017 	if (ISSET(ifp->if_flags, IFF_ALLMULTI) ||
   1018 	    ISSET(ifp->if_flags, IFF_PROMISC)) {
   1019 		/* XXX XXX XXX */
   1020 		dprintf("accept all multicast\n");
   1021 		SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
   1022 		/* XXX XXX XXX */
   1023 	} else if (multi) {
   1024 		/* XXX XXX XXX */
   1025 		dprintf("use cam\n");
   1026 		SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
   1027 		/* XXX XXX XXX */
   1028 	} else {
   1029 		/* XXX XXX XXX */
   1030 		dprintf("reject all multicast\n");
   1031 		SET(ctl, RXN_ADR_CTL_MCST_REJECT);
   1032 		/* XXX XXX XXX */
   1033 	}
   1034 	/* XXX XXX XXX */
   1035 
   1036 	/* XXX XXX XXX */
   1037 	if (ISSET(ifp->if_flags, IFF_PROMISC)) {
   1038 		cam_en = 0x00ULL;
   1039 	} else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
   1040 		cam_en = 0x01ULL;
   1041 	}
   1042 	/* XXX XXX XXX */
   1043 
   1044 	dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en);
   1045 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
   1046 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
   1047 
   1048 	octeon_gmx_link_enable(sc, 1);
   1049 
   1050 	return 0;
   1051 }
   1052 
   1053 void
   1054 octeon_gmx_stats(struct octeon_gmx_port_softc *sc)
   1055 {
   1056 	struct ifnet *ifp = &sc->sc_port_ec->ec_if;
   1057 	uint64_t tmp;
   1058 
   1059 	/*
   1060 	 *  GMX0_RX0_STATS_PKTS is not count.
   1061          *  input packet is counted when recepted packet in if_cnmac.
   1062          */
   1063 	/*
   1064          *  GMX0_RX0_STATS_PKTS_BAD count is included
   1065          *  receive error of work queue entry.
   1066          *  this is not add to input packet errors of interface.
   1067          */
   1068 	ifp->if_iqdrops +=
   1069 	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP);
   1070 	ifp->if_opackets +=
   1071 	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3);
   1072 
   1073 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
   1074 	ifp->if_oerrors +=
   1075 	    (uint32_t)tmp + ((uint32_t)(tmp >> 32) * 16);
   1076 	ifp->if_collisions += (uint32_t)tmp;
   1077 #if IFETHER_DOT3STATS
   1078 	/* dot3StatsExcessiveCollisions */
   1079 	ifp->if_data.ifi_dot3stats.if_oexsvcols += (uint32_t)tmp;
   1080 #endif
   1081 
   1082 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
   1083 	ifp->if_collisions +=
   1084 	    (uint32_t)tmp + (uint32_t)(tmp >> 32);
   1085 #if IFETHER_DOT3STATS
   1086 	/* dot3StatsSingleCollisionFrames */
   1087 	ifp->if_data.ifi_dot3stats.if_oscols += (uint32_t)(tmp >> 32);
   1088 	/* dot3StatsMultipleCollisionFrames */
   1089 	ifp->if_data.ifi_dot3stats.if_omcols += (uint32_t)tmp;
   1090 #endif
   1091 
   1092 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
   1093 	ifp->if_oerrors += (uint32_t)(tmp >> 32);
   1094 }
   1095 
   1096 /* ---- DMAC filter */
   1097 
   1098 #ifdef notyet
   1099 /*
   1100  * DMAC filter configuration
   1101  *	accept all
   1102  *	reject 0 addrs (virtually accept all?)
   1103  *	reject N addrs
   1104  *	accept N addrs
   1105  *	accept 0 addrs (virtually reject all?)
   1106  *	reject all
   1107  */
   1108 
   1109 /* XXX local namespace */
   1110 #define	_POLICY			CN30XXGMX_FILTER_POLICY
   1111 #define	_POLICY_ACCEPT_ALL	CN30XXGMX_FILTER_POLICY_ACCEPT_ALL
   1112 #define	_POLICY_ACCEPT		CN30XXGMX_FILTER_POLICY_ACCEPT
   1113 #define	_POLICY_REJECT		CN30XXGMX_FILTER_POLICY_REJECT
   1114 #define	_POLICY_REJECT_ALL	CN30XXGMX_FILTER_POLICY_REJECT_ALL
   1115 
   1116 static int	octeon_gmx_setfilt_addrs(struct octeon_gmx_port_softc *,
   1117 		    size_t, uint8_t **);
   1118 
   1119 int
   1120 octeon_gmx_setfilt(struct octeon_gmx_port_softc *sc, enum _POLICY policy,
   1121     size_t naddrs, uint8_t **addrs)
   1122 {
   1123 	uint64_t rx_adr_ctl;
   1124 
   1125 	KASSERT(policy >= _POLICY_ACCEPT_ALL);
   1126 	KASSERT(policy <= _POLICY_REJECT_ALL);
   1127 
   1128 	rx_adr_ctl = _GMX_PORT_RD8(sc, GMX0_RX0_ADR_CTL);
   1129 	CLR(rx_adr_ctl, RXN_ADR_CTL_CAM_MODE | RXN_ADR_CTL_MCST);
   1130 
   1131 	switch (policy) {
   1132 	case _POLICY_ACCEPT_ALL:
   1133 	case _POLICY_REJECT_ALL:
   1134 		KASSERT(naddrs == 0);
   1135 		KASSERT(addrs == NULL);
   1136 
   1137 		SET(rx_adr_ctl, (policy == _POLICY_ACCEPT_ALL) ?
   1138 		    RXN_ADR_CTL_MCST_ACCEPT : RXN_ADR_CTL_MCST_REJECT);
   1139 		break;
   1140 	case _POLICY_ACCEPT:
   1141 	case _POLICY_REJECT:
   1142 		if (naddrs > CN30XXGMX_FILTER_NADDRS_MAX)
   1143 			return E2BIG;
   1144 		SET(rx_adr_ctl, (policy == _POLICY_ACCEPT) ?
   1145 		    RXN_ADR_CTL_CAM_MODE : 0);
   1146 		SET(rx_adr_ctl, RXN_ADR_CTL_MCST_AFCAM);
   1147 		/* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
   1148 		octeon_gmx_setfilt_addrs(sc, naddrs, addrs);
   1149 		break;
   1150 	}
   1151 
   1152 	/* set GMX0_RXN_ADR_CTL[MCST] */
   1153 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, rx_adr_ctl);
   1154 
   1155 	return 0;
   1156 }
   1157 
   1158 static int
   1159 octeon_gmx_setfilt_addrs(struct octeon_gmx_port_softc *sc, size_t naddrs,
   1160     uint8_t **addrs)
   1161 {
   1162 	uint64_t rx_adr_cam_en;
   1163 	uint64_t rx_adr_cam_addrs[CN30XXGMX_FILTER_NADDRS_MAX];
   1164 	int i, j;
   1165 
   1166 	KASSERT(naddrs <= CN30XXGMX_FILTER_NADDRS_MAX);
   1167 
   1168 	rx_adr_cam_en = 0;
   1169 	(void)memset(rx_adr_cam_addrs, 0, sizeof(rx_adr_cam_addrs));
   1170 
   1171 	for (i = 0; i < naddrs; i++) {
   1172 		SET(rx_adr_cam_en, 1ULL << i);
   1173 		for (j = 0; j < 6; j++)
   1174 			SET(rx_adr_cam_addrs[j],
   1175 			    (uint64_t)addrs[i][j] << (8 * i));
   1176 	}
   1177 
   1178 	/* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
   1179 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, rx_adr_cam_en);
   1180 	for (j = 0; j < 6; j++)
   1181 		_GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[j],
   1182 		    rx_adr_cam_addrs[j]);
   1183 
   1184 	return 0;
   1185 }
   1186 #endif
   1187 
   1188 /* ---- interrupt */
   1189 
   1190 #ifdef OCTEON_ETH_DEBUG
   1191 void			octeon_gmx_intr_rml_gmx0(void);
   1192 
   1193 int			octeon_gmx_intr_rml_verbose;
   1194 
   1195 /* tx - per unit (gmx0, gmx1, ...) */
   1196 static const struct octeon_evcnt_entry octeon_gmx_intr_evcnt_tx_entries[] = {
   1197 #define	_ENTRY(name, type, parent, descr) \
   1198 	OCTEON_EVCNT_ENTRY(struct octeon_gmx_softc, name, type, parent, descr)
   1199 	_ENTRY(latecol,		MISC, NULL, "tx late collision"),
   1200 	_ENTRY(xsdef,		MISC, NULL, "tx excessive deferral"),
   1201 	_ENTRY(xscol,		MISC, NULL, "tx excessive collision"),
   1202 	_ENTRY(undflw,		MISC, NULL, "tx underflow"),
   1203 	_ENTRY(pkonxa,		MISC, NULL, "tx port addr out-of-range")
   1204 #undef	_ENTRY
   1205 };
   1206 
   1207 /* rx - per port (gmx0:0, gmx0:1, ...) */
   1208 static const struct octeon_evcnt_entry octeon_gmx_intr_evcnt_rx_entries[] = {
   1209 #define	_ENTRY(name, type, parent, descr) \
   1210 	OCTEON_EVCNT_ENTRY(struct octeon_gmx_port_softc, name, type, parent, descr)
   1211 	_ENTRY(minerr,		MISC, NULL, "rx min error"),
   1212 	_ENTRY(carext,		MISC, NULL, "rx carrier error"),
   1213 	_ENTRY(maxerr,		MISC, NULL, "rx max error"),
   1214 	_ENTRY(jabber,		MISC, NULL, "rx jabber error"),
   1215 	_ENTRY(fcserr,		MISC, NULL, "rx fcs error"),
   1216 	_ENTRY(alnerr,		MISC, NULL, "rx align error"),
   1217 	_ENTRY(lenerr,		MISC, NULL, "rx length error"),
   1218 	_ENTRY(rcverr,		MISC, NULL, "rx receive error"),
   1219 	_ENTRY(skperr,		MISC, NULL, "rx skip error"),
   1220 	_ENTRY(niberr,		MISC, NULL, "rx nibble error"),
   1221 	_ENTRY(ovrerr,		MISC, NULL, "rx overflow error"),
   1222 	_ENTRY(pckterr,		MISC, NULL, "rx packet error"),
   1223 	_ENTRY(rsverr,		MISC, NULL, "rx reserved opcode error"),
   1224 	_ENTRY(falerr,		MISC, NULL, "rx false carrier error"),
   1225 	_ENTRY(coldet,		MISC, NULL, "rx collision detect"),
   1226 	_ENTRY(ifgerr,		MISC, NULL, "rx ifg error")
   1227 #undef	_ENTRY
   1228 };
   1229 
   1230 void
   1231 octeon_gmx_intr_evcnt_attach(struct octeon_gmx_softc *sc)
   1232 {
   1233 	struct octeon_gmx_port_softc *port_sc;
   1234 	int i;
   1235 
   1236 	OCTEON_EVCNT_ATTACH_EVCNTS(sc, octeon_gmx_intr_evcnt_tx_entries,
   1237 	    device_xname(sc->sc_dev));
   1238 	for (i = 0; i < sc->sc_nports; i++) {
   1239 		port_sc = &sc->sc_ports[i];
   1240 		OCTEON_EVCNT_ATTACH_EVCNTS(port_sc, octeon_gmx_intr_evcnt_rx_entries,
   1241 		    device_xname(sc->sc_dev));
   1242 	}
   1243 }
   1244 
   1245 void
   1246 octeon_gmx_intr_rml_gmx0(void)
   1247 {
   1248 	struct octeon_gmx_port_softc *sc = NULL/* XXX gcc */;
   1249 	int i;
   1250 	uint64_t reg = 0/* XXX gcc */;
   1251 
   1252 	octeon_gmx_intr_evcnt.ev_count++;
   1253 
   1254 	sc = __octeon_gmx_port_softc[0];
   1255 	if (sc == NULL)
   1256 		return;
   1257 
   1258 	/* GMX0_RXn_INT_REG or GMX0_TXn_INT_REG */
   1259 	reg = octeon_gmx_get_tx_int_reg(sc);
   1260 	if (octeon_gmx_intr_rml_verbose && reg != 0)
   1261 		printf("%s: GMX_TX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
   1262 	if (reg & TX_INT_REG_LATE_COL)
   1263 		OCTEON_EVCNT_INC(sc->sc_port_gmx, latecol);
   1264 	if (reg & TX_INT_REG_XSDEF)
   1265 		OCTEON_EVCNT_INC(sc->sc_port_gmx, xsdef);
   1266 	if (reg & TX_INT_REG_XSCOL)
   1267 		OCTEON_EVCNT_INC(sc->sc_port_gmx, xscol);
   1268 	if (reg & TX_INT_REG_UNDFLW)
   1269 		OCTEON_EVCNT_INC(sc->sc_port_gmx, undflw);
   1270 	if (reg & TX_INT_REG_PKO_NXA)
   1271 		OCTEON_EVCNT_INC(sc->sc_port_gmx, pkonxa);
   1272 
   1273 	for (i = 0; i < GMX_PORT_NUNITS; i++) {
   1274 		sc = __octeon_gmx_port_softc[i];
   1275 		if (sc == NULL)
   1276 			continue;
   1277 		reg = octeon_gmx_get_rx_int_reg(sc);
   1278 		if (octeon_gmx_intr_rml_verbose)
   1279 			printf("%s: GMX_RX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
   1280 		if (reg & RXN_INT_REG_MINERR)
   1281 			OCTEON_EVCNT_INC(sc, minerr);
   1282 		if (reg & RXN_INT_REG_CAREXT)
   1283 			OCTEON_EVCNT_INC(sc, carext);
   1284 		if (reg & RXN_INT_REG_JABBER)
   1285 			OCTEON_EVCNT_INC(sc, jabber);
   1286 		if (reg & RXN_INT_REG_FCSERR)
   1287 			OCTEON_EVCNT_INC(sc, fcserr);
   1288 		if (reg & RXN_INT_REG_ALNERR)
   1289 			OCTEON_EVCNT_INC(sc, alnerr);
   1290 		if (reg & RXN_INT_REG_LENERR)
   1291 			OCTEON_EVCNT_INC(sc, lenerr);
   1292 		if (reg & RXN_INT_REG_RCVERR)
   1293 			OCTEON_EVCNT_INC(sc, rcverr);
   1294 		if (reg & RXN_INT_REG_SKPERR)
   1295 			OCTEON_EVCNT_INC(sc, skperr);
   1296 		if (reg & RXN_INT_REG_NIBERR)
   1297 			OCTEON_EVCNT_INC(sc, niberr);
   1298 		if (reg & RXN_INT_REG_OVRERR)
   1299 			OCTEON_EVCNT_INC(sc, ovrerr);
   1300 		if (reg & RXN_INT_REG_PCTERR)
   1301 			OCTEON_EVCNT_INC(sc, pckterr);
   1302 		if (reg & RXN_INT_REG_RSVERR)
   1303 			OCTEON_EVCNT_INC(sc, rsverr);
   1304 		if (reg & RXN_INT_REG_FALERR)
   1305 			OCTEON_EVCNT_INC(sc, falerr);
   1306 		if (reg & RXN_INT_REG_COLDET)
   1307 			OCTEON_EVCNT_INC(sc, coldet);
   1308 		if (reg & RXN_INT_REG_IFGERR)
   1309 			OCTEON_EVCNT_INC(sc, ifgerr);
   1310 	}
   1311 }
   1312 
   1313 #ifdef notyet
   1314 void
   1315 octeon_gmx_intr_rml_gmx1(void)
   1316 {
   1317 	uint64_t reg = 0/* XXX gcc */;
   1318 
   1319 		/* GMX1_RXn_INT_REG or GMX1_TXn_INT_REG */
   1320 }
   1321 #endif
   1322 
   1323 int
   1324 octeon_gmx_intr_drop(void *arg)
   1325 {
   1326 	octeon_write_csr(CIU_INT0_SUM0, CIU_INTX_SUM0_GMX_DRP);
   1327 	octeon_gmx_intr_drop_evcnt.ev_count++;
   1328 	return (1);
   1329 }
   1330 
   1331 uint64_t
   1332 octeon_gmx_get_rx_int_reg(struct octeon_gmx_port_softc *sc)
   1333 {
   1334 	uint64_t reg;
   1335 	uint64_t rx_int_reg = 0;
   1336 
   1337 	reg = _GMX_PORT_RD8(sc, GMX0_RX0_INT_REG);
   1338 	/* clear */
   1339 	SET(rx_int_reg, 0 |
   1340 	    RXN_INT_REG_PHY_DUPX |
   1341 	    RXN_INT_REG_PHY_SPD |
   1342 	    RXN_INT_REG_PHY_LINK |
   1343 	    RXN_INT_REG_IFGERR |
   1344 	    RXN_INT_REG_COLDET |
   1345 	    RXN_INT_REG_FALERR |
   1346 	    RXN_INT_REG_RSVERR |
   1347 	    RXN_INT_REG_PCTERR |
   1348 	    RXN_INT_REG_OVRERR |
   1349 	    RXN_INT_REG_NIBERR |
   1350 	    RXN_INT_REG_SKPERR |
   1351 	    RXN_INT_REG_RCVERR |
   1352 	    RXN_INT_REG_LENERR |
   1353 	    RXN_INT_REG_ALNERR |
   1354 	    RXN_INT_REG_FCSERR |
   1355 	    RXN_INT_REG_JABBER |
   1356 	    RXN_INT_REG_MAXERR |
   1357 	    RXN_INT_REG_CAREXT |
   1358 	    RXN_INT_REG_MINERR);
   1359 	_GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_reg);
   1360 
   1361 	return reg;
   1362 }
   1363 
   1364 uint64_t
   1365 octeon_gmx_get_tx_int_reg(struct octeon_gmx_port_softc *sc)
   1366 {
   1367 	uint64_t reg;
   1368 	uint64_t tx_int_reg = 0;
   1369 
   1370 	reg = _GMX_PORT_RD8(sc, GMX0_TX_INT_REG);
   1371 	/* clear */
   1372 	SET(tx_int_reg, 0 |
   1373 	    TX_INT_REG_LATE_COL |
   1374 	    TX_INT_REG_XSDEF |
   1375 	    TX_INT_REG_XSCOL |
   1376 	    TX_INT_REG_UNDFLW |
   1377 	    TX_INT_REG_PKO_NXA);
   1378 	_GMX_PORT_WR8(sc, GMX0_TX_INT_REG, tx_int_reg);
   1379 
   1380 	return reg;
   1381 }
   1382 #endif	/* OCTEON_ETH_DEBUG */
   1383 
   1384 /* ---- debug */
   1385 
   1386 #ifdef OCTEON_ETH_DEBUG
   1387 #define	_ENTRY(x)	{ #x, x##_BITS, x }
   1388 
   1389 struct octeon_gmx_dump_reg_ {
   1390 	const char *name;
   1391 	const char *format;
   1392 	size_t	offset;
   1393 };
   1394 
   1395 static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_regs_[] = {
   1396 	_ENTRY(GMX0_SMAC0),
   1397 	_ENTRY(GMX0_BIST0),
   1398 	_ENTRY(GMX0_RX_PRTS),
   1399 	_ENTRY(GMX0_RX_BP_DROP0),
   1400 	_ENTRY(GMX0_RX_BP_DROP1),
   1401 	_ENTRY(GMX0_RX_BP_DROP2),
   1402 	_ENTRY(GMX0_RX_BP_ON0),
   1403 	_ENTRY(GMX0_RX_BP_ON1),
   1404 	_ENTRY(GMX0_RX_BP_ON2),
   1405 	_ENTRY(GMX0_RX_BP_OFF0),
   1406 	_ENTRY(GMX0_RX_BP_OFF1),
   1407 	_ENTRY(GMX0_RX_BP_OFF2),
   1408 	_ENTRY(GMX0_TX_PRTS),
   1409 	_ENTRY(GMX0_TX_IFG),
   1410 	_ENTRY(GMX0_TX_JAM),
   1411 	_ENTRY(GMX0_TX_COL_ATTEMPT),
   1412 	_ENTRY(GMX0_TX_PAUSE_PKT_DMAC),
   1413 	_ENTRY(GMX0_TX_PAUSE_PKT_TYPE),
   1414 	_ENTRY(GMX0_TX_OVR_BP),
   1415 	_ENTRY(GMX0_TX_BP),
   1416 	_ENTRY(GMX0_TX_CORRUPT),
   1417 	_ENTRY(GMX0_RX_PRT_INFO),
   1418 	_ENTRY(GMX0_TX_LFSR),
   1419 	_ENTRY(GMX0_TX_INT_REG),
   1420 	_ENTRY(GMX0_TX_INT_EN),
   1421 	_ENTRY(GMX0_NXA_ADR),
   1422 	_ENTRY(GMX0_BAD_REG),
   1423 	_ENTRY(GMX0_STAT_BP),
   1424 	_ENTRY(GMX0_TX_CLK_MSK0),
   1425 	_ENTRY(GMX0_TX_CLK_MSK1),
   1426 	_ENTRY(GMX0_RX_TX_STATUS),
   1427 	_ENTRY(GMX0_INF_MODE),
   1428 };
   1429 
   1430 static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_port_regs_[] = {
   1431 	_ENTRY(GMX0_RX0_INT_REG),
   1432 	_ENTRY(GMX0_RX0_INT_EN),
   1433 	_ENTRY(GMX0_PRT0_CFG),
   1434 	_ENTRY(GMX0_RX0_FRM_CTL),
   1435 	_ENTRY(GMX0_RX0_FRM_CHK),
   1436 	_ENTRY(GMX0_RX0_FRM_MIN),
   1437 	_ENTRY(GMX0_RX0_FRM_MAX),
   1438 	_ENTRY(GMX0_RX0_JABBER),
   1439 	_ENTRY(GMX0_RX0_DECISION),
   1440 	_ENTRY(GMX0_RX0_UDD_SKP),
   1441 	_ENTRY(GMX0_RX0_STATS_CTL),
   1442 	_ENTRY(GMX0_RX0_IFG),
   1443 	_ENTRY(GMX0_RX0_RX_INBND),
   1444 	_ENTRY(GMX0_RX0_ADR_CTL),
   1445 	_ENTRY(GMX0_RX0_ADR_CAM_EN),
   1446 	_ENTRY(GMX0_RX0_ADR_CAM0),
   1447 	_ENTRY(GMX0_RX0_ADR_CAM1),
   1448 	_ENTRY(GMX0_RX0_ADR_CAM2),
   1449 	_ENTRY(GMX0_RX0_ADR_CAM3),
   1450 	_ENTRY(GMX0_RX0_ADR_CAM4),
   1451 	_ENTRY(GMX0_RX0_ADR_CAM5),
   1452 	_ENTRY(GMX0_TX0_CLK),
   1453 	_ENTRY(GMX0_TX0_THRESH),
   1454 	_ENTRY(GMX0_TX0_APPEND),
   1455 	_ENTRY(GMX0_TX0_SLOT),
   1456 	_ENTRY(GMX0_TX0_BURST),
   1457 	_ENTRY(GMX0_TX0_PAUSE_PKT_TIME),
   1458 	_ENTRY(GMX0_TX0_MIN_PKT),
   1459 	_ENTRY(GMX0_TX0_PAUSE_PKT_INTERVAL),
   1460 	_ENTRY(GMX0_TX0_SOFT_PAUSE),
   1461 	_ENTRY(GMX0_TX0_PAUSE_TOGO),
   1462 	_ENTRY(GMX0_TX0_PAUSE_ZERO),
   1463 	_ENTRY(GMX0_TX0_STATS_CTL),
   1464 	_ENTRY(GMX0_TX0_CTL),
   1465 };
   1466 
   1467 static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_port_stats_[] = {
   1468 	_ENTRY(GMX0_RX0_STATS_PKTS),
   1469 	_ENTRY(GMX0_RX0_STATS_OCTS),
   1470 	_ENTRY(GMX0_RX0_STATS_PKTS_CTL),
   1471 	_ENTRY(GMX0_RX0_STATS_OCTS_CTL),
   1472 	_ENTRY(GMX0_RX0_STATS_PKTS_DMAC),
   1473 	_ENTRY(GMX0_RX0_STATS_OCTS_DMAC),
   1474 	_ENTRY(GMX0_RX0_STATS_PKTS_DRP),
   1475 	_ENTRY(GMX0_RX0_STATS_OCTS_DRP),
   1476 	_ENTRY(GMX0_RX0_STATS_PKTS_BAD),
   1477 	_ENTRY(GMX0_TX0_STAT0),
   1478 	_ENTRY(GMX0_TX0_STAT1),
   1479 	_ENTRY(GMX0_TX0_STAT2),
   1480 	_ENTRY(GMX0_TX0_STAT3),
   1481 	_ENTRY(GMX0_TX0_STAT4),
   1482 	_ENTRY(GMX0_TX0_STAT5),
   1483 	_ENTRY(GMX0_TX0_STAT6),
   1484 	_ENTRY(GMX0_TX0_STAT7),
   1485 	_ENTRY(GMX0_TX0_STAT8),
   1486 	_ENTRY(GMX0_TX0_STAT9),
   1487 };
   1488 
   1489 void		octeon_gmx_dump_common(void);
   1490 void		octeon_gmx_dump_port0(void);
   1491 void		octeon_gmx_dump_port1(void);
   1492 void		octeon_gmx_dump_port2(void);
   1493 void		octeon_gmx_dump_port0_regs(void);
   1494 void		octeon_gmx_dump_port1_regs(void);
   1495 void		octeon_gmx_dump_port2_regs(void);
   1496 void		octeon_gmx_dump_port0_stats(void);
   1497 void		octeon_gmx_dump_port1_stats(void);
   1498 void		octeon_gmx_dump_port2_stats(void);
   1499 void		octeon_gmx_dump_port_regs(int);
   1500 void		octeon_gmx_dump_port_stats(int);
   1501 void		octeon_gmx_dump_common_x(int, const struct octeon_gmx_dump_reg_ *, size_t);
   1502 void		octeon_gmx_dump_port_x(int, const struct octeon_gmx_dump_reg_ *, size_t);
   1503 void		octeon_gmx_dump_x(int, const struct octeon_gmx_dump_reg_ *, size_t, size_t, int);
   1504 void		octeon_gmx_dump_x_index(char *, size_t, int);
   1505 
   1506 void
   1507 octeon_gmx_dump(void)
   1508 {
   1509 	octeon_gmx_dump_common();
   1510 	octeon_gmx_dump_port0();
   1511 	octeon_gmx_dump_port1();
   1512 	octeon_gmx_dump_port2();
   1513 }
   1514 
   1515 void
   1516 octeon_gmx_dump_common(void)
   1517 {
   1518 	octeon_gmx_dump_common_x(0, octeon_gmx_dump_regs_,
   1519 	    __arraycount(octeon_gmx_dump_regs_));
   1520 }
   1521 
   1522 void
   1523 octeon_gmx_dump_port0(void)
   1524 {
   1525 	octeon_gmx_dump_port_regs(0);
   1526 	octeon_gmx_dump_port_stats(0);
   1527 }
   1528 
   1529 void
   1530 octeon_gmx_dump_port1(void)
   1531 {
   1532 	octeon_gmx_dump_port_regs(1);
   1533 	octeon_gmx_dump_port_stats(1);
   1534 }
   1535 
   1536 void
   1537 octeon_gmx_dump_port2(void)
   1538 {
   1539 	octeon_gmx_dump_port_regs(2);
   1540 	octeon_gmx_dump_port_stats(2);
   1541 }
   1542 
   1543 void
   1544 octeon_gmx_dump_port_regs(int portno)
   1545 {
   1546 	octeon_gmx_dump_port_x(portno, octeon_gmx_dump_port_regs_,
   1547 	    __arraycount(octeon_gmx_dump_port_regs_));
   1548 }
   1549 
   1550 void
   1551 octeon_gmx_dump_port_stats(int portno)
   1552 {
   1553 	struct octeon_gmx_port_softc *sc = __octeon_gmx_port_softc[0];
   1554 	uint64_t rx_stats_ctl;
   1555 	uint64_t tx_stats_ctl;
   1556 
   1557 	rx_stats_ctl = _GMX_RD8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL);
   1558 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL,
   1559 	    rx_stats_ctl & ~RXN_STATS_CTL_RD_CLR);
   1560 	tx_stats_ctl = _GMX_RD8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL);
   1561 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL,
   1562 	    tx_stats_ctl & ~TXN_STATS_CTL_RD_CLR);
   1563 	octeon_gmx_dump_port_x(portno, octeon_gmx_dump_port_stats_,
   1564 	    __arraycount(octeon_gmx_dump_port_stats_));
   1565 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL, rx_stats_ctl);
   1566 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL, tx_stats_ctl);
   1567 }
   1568 
   1569 void
   1570 octeon_gmx_dump_common_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size)
   1571 {
   1572 	octeon_gmx_dump_x(portno, regs, size, 0, 0);
   1573 }
   1574 
   1575 void
   1576 octeon_gmx_dump_port_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size)
   1577 {
   1578 	octeon_gmx_dump_x(portno, regs, size, GMX0_BASE_PORT_SIZE * portno, 1);
   1579 }
   1580 
   1581 void
   1582 octeon_gmx_dump_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size, size_t base, int index)
   1583 {
   1584 	struct octeon_gmx_port_softc *sc = __octeon_gmx_port_softc[0];
   1585 	const struct octeon_gmx_dump_reg_ *reg;
   1586 	uint64_t tmp;
   1587 	char name[64];
   1588 	char buf[512];
   1589 	int i;
   1590 
   1591 	for (i = 0; i < (int)size; i++) {
   1592 		reg = &regs[i];
   1593 		tmp = _GMX_RD8(sc, base + reg->offset);
   1594 
   1595 		if (reg->format == NULL)
   1596 			snprintf(buf, sizeof(buf), "%016" PRIx64, tmp);
   1597 		else
   1598 			snprintb(buf, sizeof(buf), reg->format, tmp);
   1599 
   1600 		snprintf(name, sizeof(name), "%s", reg->name);
   1601 		if (index > 0)
   1602 			octeon_gmx_dump_x_index(name, sizeof(name), portno);
   1603 
   1604 		printf("\t%-24s: %s\n", name, buf);
   1605 	}
   1606 }
   1607 
   1608 void
   1609 octeon_gmx_dump_x_index(char *buf, size_t len, int index)
   1610 {
   1611 	static const char *patterns[] = { "_TX0_", "_RX0_", "_PRT0_" };
   1612 	int i;
   1613 
   1614 	for (i = 0; i < (int)__arraycount(patterns); i++) {
   1615 		char *p;
   1616 
   1617 		p = strstr(buf, patterns[i]);
   1618 		if (p == NULL)
   1619 			continue;
   1620 		p = strchr(p, '0');
   1621 		KASSERT(p != NULL);
   1622 		*p = '0' + index;
   1623 		return;
   1624 	}
   1625 }
   1626 
   1627 void
   1628 octeon_gmx_debug_reset(void)
   1629 {
   1630 	int i;
   1631 
   1632 	for (i = 0; i < 3; i++)
   1633 		octeon_gmx_link_enable(__octeon_gmx_port_softc[i], 0);
   1634 	for (i = 0; i < 3; i++)
   1635 		octeon_gmx_link_enable(__octeon_gmx_port_softc[i], 1);
   1636 }
   1637 #endif
   1638