Home | History | Annotate | Line # | Download | only in dev
octeon_gmx.c revision 1.9
      1 /*	$NetBSD: octeon_gmx.c,v 1.9 2020/04/24 09:29:26 mrg 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.9 2020/04/24 09:29:26 mrg 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_WAITOK | 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 		panic("unable to get baudrate");
    658 		break;
    659 	}
    660 	ifp->if_baudrate = baudrate;
    661 
    662 	/* XXX XXX XXX */
    663 
    664 	octeon_gmx_link_enable(sc, 0);
    665 
    666 	/*
    667 	 * wait a max_packet_time
    668 	 * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps)
    669 	 */
    670 	delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000));
    671 
    672 	octeon_gmx_rgmii_speed_speed(sc);
    673 
    674 	octeon_gmx_link_enable(sc, 1);
    675 	octeon_asx_enable(sc->sc_port_asx, 1);
    676 
    677 	return 0;
    678 }
    679 
    680 static int
    681 octeon_gmx_rgmii_speed_newlink(struct octeon_gmx_port_softc *sc,
    682     uint64_t *rnewlink)
    683 {
    684 	uint64_t newlink = 0;
    685 
    686 	if (sc->sc_quirks & OCTEON_ETH_QUIRKS_NO_RX_INBND) {
    687 		newlink = 0;
    688 		switch (IFM_SUBTYPE(sc->sc_port_mii->mii_media_active)) {
    689 		default:
    690 			SET(newlink, RXN_RX_INBND_SPEED_125);
    691 			break;
    692 		case IFM_100_TX:
    693 			SET(newlink, RXN_RX_INBND_SPEED_25);
    694 			break;
    695 		case IFM_10_T:
    696 			SET(newlink, RXN_RX_INBND_SPEED_2_5);
    697 			break;
    698 		}
    699 		SET(newlink,
    700 		    ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX) ?
    701 		    RXN_RX_INBND_DUPLEX : 0);
    702 		SET(newlink,
    703 		    ISSET(sc->sc_port_mii->mii_media_status, IFM_ACTIVE) ?
    704 		    RXN_RX_INBND_STATUS : 0);
    705 	} else {
    706 		newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND);
    707 	}
    708 
    709 	*rnewlink = newlink;
    710 	return 0;
    711 }
    712 
    713 static int
    714 octeon_gmx_rgmii_speed_speed(struct octeon_gmx_port_softc *sc)
    715 {
    716 	uint64_t prt_cfg;
    717 	uint64_t tx_clk, tx_slot, tx_burst;
    718 
    719 	prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG);
    720 
    721 	switch (sc->sc_link & RXN_RX_INBND_SPEED) {
    722 	case RXN_RX_INBND_SPEED_2_5:
    723 		/* 10Mbps */
    724 		/*
    725 		 * GMX Tx Clock Generation Registers
    726 		 * 8ns x 50 = 400ns (2.5MHz TXC clock)
    727 		 */
    728 		tx_clk = 50;
    729 		/*
    730 		 * TX Slottime Counter Registers
    731 		 * 10/100Mbps: set SLOT to 0x40
    732 		 */
    733 		tx_slot = 0x40;
    734 		/*
    735 		 * TX Burst-Counter Registers
    736 		 * 10/100Mbps: set BURST to 0x0
    737 		 */
    738 		tx_burst = 0;
    739 		/*
    740 		 * GMX Tx Port Configuration Registers
    741 		 * Slot time for half-duplex operation
    742 		 *   0 = 512 bittimes (10/100Mbps operation)
    743 		 */
    744 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
    745 		/*
    746 		 * GMX Port Configuration Registers
    747 		 * Link speed
    748 		 *   0 = 10/100Mbps operation
    749 		 *     in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
    750 		 */
    751 		CLR(prt_cfg, PRTN_CFG_SPEED);
    752 		break;
    753 	case RXN_RX_INBND_SPEED_25:
    754 		/* 100Mbps */
    755 		/*
    756 		 * GMX Tx Clock Generation Registers
    757 		 *  8ns x 5 = 40ns (25.0MHz TXC clock)
    758 		 */
    759 		tx_clk = 5;
    760 		/*
    761 		 * TX Slottime Counter Registers
    762 		 *  10/100Mbps: set SLOT to 0x40
    763 		 */
    764 		tx_slot = 0x40;
    765 		/*
    766 		 * TX Burst-Counter Registers
    767 		 *  10/100Mbps: set BURST to 0x0
    768 		 */
    769 		tx_burst = 0;
    770 		/*
    771 		 * GMX Tx Port Configuration Registers
    772 		 *  Slot time for half-duplex operation
    773 		 *    0 = 512 bittimes (10/100Mbps operation)
    774 		 */
    775 		CLR(prt_cfg, PRTN_CFG_SLOTTIME);
    776 		/*
    777 		 * GMX Port Configuration Registers
    778 		 *  Link speed
    779 		 *    0 = 10/100Mbps operation
    780 		 *      in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1
    781 		 */
    782 		CLR(prt_cfg, PRTN_CFG_SPEED);
    783 		break;
    784 	case RXN_RX_INBND_SPEED_125:
    785 		/* 1000Mbps */
    786 		/*
    787 		 * GMX Tx Clock Generation Registers
    788 		 *  8ns x 1 = 8ns (125.0MHz TXC clock)
    789 		 */
    790 		tx_clk = 1;
    791 		/*
    792 		 * TX Slottime Counter Registers
    793 		 * > 1000Mbps: set SLOT to 0x200
    794 		 */
    795 		tx_slot = 0x200;
    796 		/*
    797 		 * "TX Burst-Counter Registers
    798 		 * > 1000Mbps: set BURST to 0x2000
    799 		 */
    800 		tx_burst = 0x2000;
    801 		/*
    802 		 * GMX Tx Port Configuration Registers
    803 		 *  Slot time for half-duplex operation
    804 		 *    1 = 4096 bittimes (1000Mbps operation)
    805 		 */
    806 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
    807 		/*
    808 		 * GMX Port Configuration Registers
    809 		 *  Link speed
    810 		 *    1 = 1000Mbps operation
    811 		 */
    812 		SET(prt_cfg, PRTN_CFG_SPEED);
    813 		break;
    814 	default:
    815 		/* NOT REACHED! */
    816 		/* Following configuration is default value of system.
    817 		*/
    818 		tx_clk = 1;
    819 		tx_slot = 0x200;
    820 		tx_burst = 0x2000;
    821 		SET(prt_cfg, PRTN_CFG_SLOTTIME);
    822 		SET(prt_cfg, PRTN_CFG_SPEED);
    823 		break;
    824 	}
    825 
    826 	/* Setup Duplex mode(negotiated) */
    827 	/*
    828 	 * GMX Port Configuration Registers
    829 	 *  Duplex mode: 0 = half-duplex mode, 1=full-duplex
    830 	 */
    831 	if (ISSET(sc->sc_link, RXN_RX_INBND_DUPLEX)) {
    832 		/* Full-Duplex */
    833 		SET(prt_cfg, PRTN_CFG_DUPLEX);
    834 	} else {
    835 		/* Half-Duplex */
    836 		CLR(prt_cfg, PRTN_CFG_DUPLEX);
    837 	}
    838 
    839 	_GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk);
    840 	_GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot);
    841 	_GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst);
    842 	_GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg);
    843 
    844 	return 0;
    845 }
    846 
    847 static int
    848 octeon_gmx_rgmii_timing(struct octeon_gmx_port_softc *sc)
    849 {
    850 	uint64_t rx_frm_ctl;
    851 
    852 	/* RGMII TX Threshold Registers
    853 	 * Number of 16-byte ticks to accumulate in the TX FIFO before
    854 	 * sending on the RGMII interface. This field should be large
    855 	 * enough to prevent underflow on the RGMII interface and must
    856 	 * never be set to less than 0x4. This register cannot exceed
    857 	 * the TX FIFO depth of 0x40 words.
    858 	 */
    859 	/* Default parameter of CN30XX */
    860 	octeon_gmx_tx_thresh(sc, 32);
    861 
    862 	rx_frm_ctl = 0 |
    863 	    /* RXN_FRM_CTL_NULL_DIS |	(cn5xxx only) */
    864 	    /* RXN_FRM_CTL_PRE_ALIGN |	(cn5xxx only) */
    865 	    /* RXN_FRM_CTL_PAD_LEN |	(cn3xxx only) */
    866 	    /* RXN_FRM_CTL_VLAN_LEN |	(cn3xxx only) */
    867 	    RXN_FRM_CTL_PRE_FREE |
    868 	    RXN_FRM_CTL_CTL_SMAC |
    869 	    RXN_FRM_CTL_CTL_MCST |
    870 	    RXN_FRM_CTL_CTL_DRP |
    871 	    RXN_FRM_CTL_PRE_STRP |
    872 	    RXN_FRM_CTL_PRE_CHK;
    873 	if (!(sc->sc_quirks & OCTEON_ETH_QUIRKS_NO_PRE_ALIGN))
    874 		rx_frm_ctl |= RXN_FRM_CTL_PRE_ALIGN;
    875 	octeon_gmx_rx_frm_ctl_enable(sc, rx_frm_ctl);
    876 
    877 	/* RGMII RX Clock-Delay Registers
    878 	 * Delay setting to place n RXC (RGMII receive clock) delay line.
    879 	 * The intrinsic delay can range from 50ps to 80ps per tap,
    880 	 * which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1).
    881 	 * This is the best match for the RGMII specification which wants
    882 	 * 1ns - 2.6ns of skew.
    883 	 */
    884 	/* RGMII TX Clock-Delay Registers
    885 	 * Delay setting to place n TXC (RGMII transmit clock) delay line.
    886 	 */
    887 
    888 	octeon_asx_clk_set(sc->sc_port_asx,
    889 			   sc->sc_clk_tx_setting, sc->sc_clk_rx_setting);
    890 
    891 	return 0;
    892 }
    893 
    894 static int
    895 octeon_gmx_rgmii_set_mac_addr(struct octeon_gmx_port_softc *sc, uint8_t *addr,
    896     uint64_t mac)
    897 {
    898 	int i;
    899 
    900 	octeon_gmx_link_enable(sc, 0);
    901 
    902 	sc->sc_mac = mac;
    903 	_GMX_PORT_WR8(sc, GMX0_SMAC0, mac);
    904 	for (i = 0; i < 6; i++)
    905 		_GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[i], addr[i]);
    906 
    907 	octeon_gmx_link_enable(sc, 1);
    908 
    909 	return 0;
    910 }
    911 
    912 #define	OCTEON_ETH_USE_GMX_CAM
    913 
    914 static int
    915 octeon_gmx_rgmii_set_filter(struct octeon_gmx_port_softc *sc)
    916 {
    917 	struct ethercom *ec = sc->sc_port_ec;
    918 	struct ifnet *ifp = &ec->ec_if;
    919 #ifdef OCTEON_ETH_USE_GMX_CAM
    920 	struct ether_multi *enm;
    921 	struct ether_multistep step;
    922 #endif
    923 	uint64_t ctl = 0;
    924 	int multi = 0;
    925 	/* XXX XXX XXX */
    926 	uint64_t cam_en = 0x01ULL;
    927 	/* XXX XXX XXX */
    928 
    929 	octeon_gmx_link_enable(sc, 0);
    930 
    931 	if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
    932 		dprintf("accept broadcast\n");
    933 		SET(ctl, RXN_ADR_CTL_BCST);
    934 	}
    935 	if (ISSET(ifp->if_flags, IFF_PROMISC)) {
    936 		dprintf("promiscas(reject cam)\n");
    937 		CLR(ctl, RXN_ADR_CTL_CAM_MODE);
    938 	} else {
    939 		dprintf("not promiscas(accept cam)\n");
    940 		SET(ctl, RXN_ADR_CTL_CAM_MODE);
    941 	}
    942 
    943 #ifdef OCTEON_ETH_USE_GMX_CAM
    944 	/*
    945 	 * Note first entry is self MAC address; other 7 entires are available
    946 	 * for multicast addresses.
    947 	 */
    948 
    949 	ETHER_LOCK(ec);
    950 	ETHER_FIRST_MULTI(step, ec, enm);
    951 	while (enm != NULL) {
    952 		int i;
    953 
    954 		dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - "
    955 		    "hi(%02x:%02x:%02x:%02x:%02x:%02x)\n",
    956 		    multi + 1,
    957 		    enm->enm_addrlo[0], enm->enm_addrlo[1],
    958 		    enm->enm_addrlo[2], enm->enm_addrlo[3],
    959 		    enm->enm_addrlo[4], enm->enm_addrlo[5],
    960 		    enm->enm_addrhi[0], enm->enm_addrhi[1],
    961 		    enm->enm_addrhi[2], enm->enm_addrhi[3],
    962 		    enm->enm_addrhi[4], enm->enm_addrhi[5]);
    963 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
    964 			dprintf("all multicast\n");
    965 			SET(ifp->if_flags, IFF_ALLMULTI);
    966 			ETHER_UNLOCK(ec);
    967 			goto setmulti;
    968 		}
    969 		multi++;
    970 
    971 		/* XXX XXX XXX */
    972 		if (multi >= 8) {
    973 			SET(ifp->if_flags, IFF_ALLMULTI);
    974 			ETHER_UNLOCK(ec);
    975 			goto setmulti;
    976 		}
    977 		/* XXX XXX XXX */
    978 
    979 		/* XXX XXX XXX */
    980 		SET(cam_en, 1ULL << multi);
    981 		/* XXX XXX XXX */
    982 
    983 		for (i = 0; i < 6; i++) {
    984 			uint64_t tmp;
    985 
    986 			/* XXX XXX XXX */
    987 			tmp = _GMX_PORT_RD8(sc, octeon_gmx_rx_adr_cam_regs[i]);
    988 			CLR(tmp, 0xffULL << (8 * multi));
    989 			SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi));
    990 			_GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[i], tmp);
    991 			/* XXX XXX XXX */
    992 
    993 		}
    994 		for (i = 0; i < 6; i++)
    995 			dprintf("cam%d = %016llx\n", i,
    996 			    _GMX_PORT_RD8(sc, octeon_gmx_rx_adr_cam_regs[i]));
    997 		ETHER_NEXT_MULTI(step, enm);
    998 	}
    999 	ETHER_UNLOCK(ec);
   1000 	CLR(ifp->if_flags, IFF_ALLMULTI);
   1001 
   1002 	OCTEON_ETH_KASSERT(enm == NULL);
   1003 #else
   1004 	/*
   1005 	 * XXX
   1006 	 * Never use DMAC filter for multicast addresses, but register only
   1007 	 * single entry for self address. FreeBSD code do so.
   1008 	 */
   1009 	SET(ifp->if_flags, IFF_ALLMULTI);
   1010 	goto setmulti;
   1011 #endif
   1012 
   1013 setmulti:
   1014 	/* XXX XXX XXX */
   1015 	if (ISSET(ifp->if_flags, IFF_ALLMULTI) ||
   1016 	    ISSET(ifp->if_flags, IFF_PROMISC)) {
   1017 		/* XXX XXX XXX */
   1018 		dprintf("accept all multicast\n");
   1019 		SET(ctl, RXN_ADR_CTL_MCST_ACCEPT);
   1020 		/* XXX XXX XXX */
   1021 	} else if (multi) {
   1022 		/* XXX XXX XXX */
   1023 		dprintf("use cam\n");
   1024 		SET(ctl, RXN_ADR_CTL_MCST_AFCAM);
   1025 		/* XXX XXX XXX */
   1026 	} else {
   1027 		/* XXX XXX XXX */
   1028 		dprintf("reject all multicast\n");
   1029 		SET(ctl, RXN_ADR_CTL_MCST_REJECT);
   1030 		/* XXX XXX XXX */
   1031 	}
   1032 	/* XXX XXX XXX */
   1033 
   1034 	/* XXX XXX XXX */
   1035 	if (ISSET(ifp->if_flags, IFF_PROMISC)) {
   1036 		cam_en = 0x00ULL;
   1037 	} else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) {
   1038 		cam_en = 0x01ULL;
   1039 	}
   1040 	/* XXX XXX XXX */
   1041 
   1042 	dprintf("ctl = %llx, cam_en = %llx\n", ctl, cam_en);
   1043 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl);
   1044 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en);
   1045 
   1046 	octeon_gmx_link_enable(sc, 1);
   1047 
   1048 	return 0;
   1049 }
   1050 
   1051 void
   1052 octeon_gmx_stats(struct octeon_gmx_port_softc *sc)
   1053 {
   1054 	struct ifnet *ifp = &sc->sc_port_ec->ec_if;
   1055 	uint64_t tmp;
   1056 
   1057 	/*
   1058 	 *  GMX0_RX0_STATS_PKTS is not count.
   1059          *  input packet is counted when recepted packet in if_cnmac.
   1060          */
   1061 	/*
   1062          *  GMX0_RX0_STATS_PKTS_BAD count is included
   1063          *  receive error of work queue entry.
   1064          *  this is not add to input packet errors of interface.
   1065          */
   1066 	net_stat_ref_t nsr = IF_STAT_GETREF(ifp);
   1067 	if_statadd_ref(nsr, if_iqdrops,
   1068 	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP));
   1069 	if_statadd_ref(nsr, if_opackets,
   1070 	    (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3));
   1071 
   1072 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0);
   1073 	if_statadd_ref(nsr, if_oerrors,
   1074 	    (uint32_t)tmp + ((uint32_t)(tmp >> 32) * 16));
   1075 	if_statadd_ref(nsr, if_collisions, (uint32_t)tmp);
   1076 
   1077 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1);
   1078 	if_statadd_ref(nsr, if_collisions,
   1079 	    (uint32_t)tmp + (uint32_t)(tmp >> 32));
   1080 
   1081 	tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9);
   1082 	if_statadd_ref(nsr, if_oerrors, (uint32_t)(tmp >> 32));
   1083 	IF_STAT_PUTREF(ifp);
   1084 }
   1085 
   1086 /* ---- DMAC filter */
   1087 
   1088 #ifdef notyet
   1089 /*
   1090  * DMAC filter configuration
   1091  *	accept all
   1092  *	reject 0 addrs (virtually accept all?)
   1093  *	reject N addrs
   1094  *	accept N addrs
   1095  *	accept 0 addrs (virtually reject all?)
   1096  *	reject all
   1097  */
   1098 
   1099 /* XXX local namespace */
   1100 #define	_POLICY			CN30XXGMX_FILTER_POLICY
   1101 #define	_POLICY_ACCEPT_ALL	CN30XXGMX_FILTER_POLICY_ACCEPT_ALL
   1102 #define	_POLICY_ACCEPT		CN30XXGMX_FILTER_POLICY_ACCEPT
   1103 #define	_POLICY_REJECT		CN30XXGMX_FILTER_POLICY_REJECT
   1104 #define	_POLICY_REJECT_ALL	CN30XXGMX_FILTER_POLICY_REJECT_ALL
   1105 
   1106 static int	octeon_gmx_setfilt_addrs(struct octeon_gmx_port_softc *,
   1107 		    size_t, uint8_t **);
   1108 
   1109 int
   1110 octeon_gmx_setfilt(struct octeon_gmx_port_softc *sc, enum _POLICY policy,
   1111     size_t naddrs, uint8_t **addrs)
   1112 {
   1113 	uint64_t rx_adr_ctl;
   1114 
   1115 	KASSERT(policy >= _POLICY_ACCEPT_ALL);
   1116 	KASSERT(policy <= _POLICY_REJECT_ALL);
   1117 
   1118 	rx_adr_ctl = _GMX_PORT_RD8(sc, GMX0_RX0_ADR_CTL);
   1119 	CLR(rx_adr_ctl, RXN_ADR_CTL_CAM_MODE | RXN_ADR_CTL_MCST);
   1120 
   1121 	switch (policy) {
   1122 	case _POLICY_ACCEPT_ALL:
   1123 	case _POLICY_REJECT_ALL:
   1124 		KASSERT(naddrs == 0);
   1125 		KASSERT(addrs == NULL);
   1126 
   1127 		SET(rx_adr_ctl, (policy == _POLICY_ACCEPT_ALL) ?
   1128 		    RXN_ADR_CTL_MCST_ACCEPT : RXN_ADR_CTL_MCST_REJECT);
   1129 		break;
   1130 	case _POLICY_ACCEPT:
   1131 	case _POLICY_REJECT:
   1132 		if (naddrs > CN30XXGMX_FILTER_NADDRS_MAX)
   1133 			return E2BIG;
   1134 		SET(rx_adr_ctl, (policy == _POLICY_ACCEPT) ?
   1135 		    RXN_ADR_CTL_CAM_MODE : 0);
   1136 		SET(rx_adr_ctl, RXN_ADR_CTL_MCST_AFCAM);
   1137 		/* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
   1138 		octeon_gmx_setfilt_addrs(sc, naddrs, addrs);
   1139 		break;
   1140 	}
   1141 
   1142 	/* set GMX0_RXN_ADR_CTL[MCST] */
   1143 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, rx_adr_ctl);
   1144 
   1145 	return 0;
   1146 }
   1147 
   1148 static int
   1149 octeon_gmx_setfilt_addrs(struct octeon_gmx_port_softc *sc, size_t naddrs,
   1150     uint8_t **addrs)
   1151 {
   1152 	uint64_t rx_adr_cam_en;
   1153 	uint64_t rx_adr_cam_addrs[CN30XXGMX_FILTER_NADDRS_MAX];
   1154 	int i, j;
   1155 
   1156 	KASSERT(naddrs <= CN30XXGMX_FILTER_NADDRS_MAX);
   1157 
   1158 	rx_adr_cam_en = 0;
   1159 	(void)memset(rx_adr_cam_addrs, 0, sizeof(rx_adr_cam_addrs));
   1160 
   1161 	for (i = 0; i < naddrs; i++) {
   1162 		SET(rx_adr_cam_en, 1ULL << i);
   1163 		for (j = 0; j < 6; j++)
   1164 			SET(rx_adr_cam_addrs[j],
   1165 			    (uint64_t)addrs[i][j] << (8 * i));
   1166 	}
   1167 
   1168 	/* set GMX0_RXN_ADR_CAM_EN, GMX0_RXN_ADR_CAM[0-5] */
   1169 	_GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, rx_adr_cam_en);
   1170 	for (j = 0; j < 6; j++)
   1171 		_GMX_PORT_WR8(sc, octeon_gmx_rx_adr_cam_regs[j],
   1172 		    rx_adr_cam_addrs[j]);
   1173 
   1174 	return 0;
   1175 }
   1176 #endif
   1177 
   1178 /* ---- interrupt */
   1179 
   1180 #ifdef OCTEON_ETH_DEBUG
   1181 void			octeon_gmx_intr_rml_gmx0(void);
   1182 
   1183 int			octeon_gmx_intr_rml_verbose;
   1184 
   1185 /* tx - per unit (gmx0, gmx1, ...) */
   1186 static const struct octeon_evcnt_entry octeon_gmx_intr_evcnt_tx_entries[] = {
   1187 #define	_ENTRY(name, type, parent, descr) \
   1188 	OCTEON_EVCNT_ENTRY(struct octeon_gmx_softc, name, type, parent, descr)
   1189 	_ENTRY(latecol,		MISC, NULL, "tx late collision"),
   1190 	_ENTRY(xsdef,		MISC, NULL, "tx excessive deferral"),
   1191 	_ENTRY(xscol,		MISC, NULL, "tx excessive collision"),
   1192 	_ENTRY(undflw,		MISC, NULL, "tx underflow"),
   1193 	_ENTRY(pkonxa,		MISC, NULL, "tx port addr out-of-range")
   1194 #undef	_ENTRY
   1195 };
   1196 
   1197 /* rx - per port (gmx0:0, gmx0:1, ...) */
   1198 static const struct octeon_evcnt_entry octeon_gmx_intr_evcnt_rx_entries[] = {
   1199 #define	_ENTRY(name, type, parent, descr) \
   1200 	OCTEON_EVCNT_ENTRY(struct octeon_gmx_port_softc, name, type, parent, descr)
   1201 	_ENTRY(minerr,		MISC, NULL, "rx min error"),
   1202 	_ENTRY(carext,		MISC, NULL, "rx carrier error"),
   1203 	_ENTRY(maxerr,		MISC, NULL, "rx max error"),
   1204 	_ENTRY(jabber,		MISC, NULL, "rx jabber error"),
   1205 	_ENTRY(fcserr,		MISC, NULL, "rx fcs error"),
   1206 	_ENTRY(alnerr,		MISC, NULL, "rx align error"),
   1207 	_ENTRY(lenerr,		MISC, NULL, "rx length error"),
   1208 	_ENTRY(rcverr,		MISC, NULL, "rx receive error"),
   1209 	_ENTRY(skperr,		MISC, NULL, "rx skip error"),
   1210 	_ENTRY(niberr,		MISC, NULL, "rx nibble error"),
   1211 	_ENTRY(ovrerr,		MISC, NULL, "rx overflow error"),
   1212 	_ENTRY(pckterr,		MISC, NULL, "rx packet error"),
   1213 	_ENTRY(rsverr,		MISC, NULL, "rx reserved opcode error"),
   1214 	_ENTRY(falerr,		MISC, NULL, "rx false carrier error"),
   1215 	_ENTRY(coldet,		MISC, NULL, "rx collision detect"),
   1216 	_ENTRY(ifgerr,		MISC, NULL, "rx ifg error")
   1217 #undef	_ENTRY
   1218 };
   1219 
   1220 void
   1221 octeon_gmx_intr_evcnt_attach(struct octeon_gmx_softc *sc)
   1222 {
   1223 	struct octeon_gmx_port_softc *port_sc;
   1224 	int i;
   1225 
   1226 	OCTEON_EVCNT_ATTACH_EVCNTS(sc, octeon_gmx_intr_evcnt_tx_entries,
   1227 	    device_xname(sc->sc_dev));
   1228 	for (i = 0; i < sc->sc_nports; i++) {
   1229 		port_sc = &sc->sc_ports[i];
   1230 		OCTEON_EVCNT_ATTACH_EVCNTS(port_sc, octeon_gmx_intr_evcnt_rx_entries,
   1231 		    device_xname(sc->sc_dev));
   1232 	}
   1233 }
   1234 
   1235 void
   1236 octeon_gmx_intr_rml_gmx0(void)
   1237 {
   1238 	struct octeon_gmx_port_softc *sc = NULL/* XXX gcc */;
   1239 	int i;
   1240 	uint64_t reg = 0/* XXX gcc */;
   1241 
   1242 	octeon_gmx_intr_evcnt.ev_count++;
   1243 
   1244 	sc = __octeon_gmx_port_softc[0];
   1245 	if (sc == NULL)
   1246 		return;
   1247 
   1248 	/* GMX0_RXn_INT_REG or GMX0_TXn_INT_REG */
   1249 	reg = octeon_gmx_get_tx_int_reg(sc);
   1250 	if (octeon_gmx_intr_rml_verbose && reg != 0)
   1251 		printf("%s: GMX_TX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
   1252 	if (reg & TX_INT_REG_LATE_COL)
   1253 		OCTEON_EVCNT_INC(sc->sc_port_gmx, latecol);
   1254 	if (reg & TX_INT_REG_XSDEF)
   1255 		OCTEON_EVCNT_INC(sc->sc_port_gmx, xsdef);
   1256 	if (reg & TX_INT_REG_XSCOL)
   1257 		OCTEON_EVCNT_INC(sc->sc_port_gmx, xscol);
   1258 	if (reg & TX_INT_REG_UNDFLW)
   1259 		OCTEON_EVCNT_INC(sc->sc_port_gmx, undflw);
   1260 	if (reg & TX_INT_REG_PKO_NXA)
   1261 		OCTEON_EVCNT_INC(sc->sc_port_gmx, pkonxa);
   1262 
   1263 	for (i = 0; i < GMX_PORT_NUNITS; i++) {
   1264 		sc = __octeon_gmx_port_softc[i];
   1265 		if (sc == NULL)
   1266 			continue;
   1267 		reg = octeon_gmx_get_rx_int_reg(sc);
   1268 		if (octeon_gmx_intr_rml_verbose)
   1269 			printf("%s: GMX_RX_INT_REG=0x%016" PRIx64 "\n", __func__, reg);
   1270 		if (reg & RXN_INT_REG_MINERR)
   1271 			OCTEON_EVCNT_INC(sc, minerr);
   1272 		if (reg & RXN_INT_REG_CAREXT)
   1273 			OCTEON_EVCNT_INC(sc, carext);
   1274 		if (reg & RXN_INT_REG_JABBER)
   1275 			OCTEON_EVCNT_INC(sc, jabber);
   1276 		if (reg & RXN_INT_REG_FCSERR)
   1277 			OCTEON_EVCNT_INC(sc, fcserr);
   1278 		if (reg & RXN_INT_REG_ALNERR)
   1279 			OCTEON_EVCNT_INC(sc, alnerr);
   1280 		if (reg & RXN_INT_REG_LENERR)
   1281 			OCTEON_EVCNT_INC(sc, lenerr);
   1282 		if (reg & RXN_INT_REG_RCVERR)
   1283 			OCTEON_EVCNT_INC(sc, rcverr);
   1284 		if (reg & RXN_INT_REG_SKPERR)
   1285 			OCTEON_EVCNT_INC(sc, skperr);
   1286 		if (reg & RXN_INT_REG_NIBERR)
   1287 			OCTEON_EVCNT_INC(sc, niberr);
   1288 		if (reg & RXN_INT_REG_OVRERR)
   1289 			OCTEON_EVCNT_INC(sc, ovrerr);
   1290 		if (reg & RXN_INT_REG_PCTERR)
   1291 			OCTEON_EVCNT_INC(sc, pckterr);
   1292 		if (reg & RXN_INT_REG_RSVERR)
   1293 			OCTEON_EVCNT_INC(sc, rsverr);
   1294 		if (reg & RXN_INT_REG_FALERR)
   1295 			OCTEON_EVCNT_INC(sc, falerr);
   1296 		if (reg & RXN_INT_REG_COLDET)
   1297 			OCTEON_EVCNT_INC(sc, coldet);
   1298 		if (reg & RXN_INT_REG_IFGERR)
   1299 			OCTEON_EVCNT_INC(sc, ifgerr);
   1300 	}
   1301 }
   1302 
   1303 #ifdef notyet
   1304 void
   1305 octeon_gmx_intr_rml_gmx1(void)
   1306 {
   1307 	uint64_t reg = 0/* XXX gcc */;
   1308 
   1309 		/* GMX1_RXn_INT_REG or GMX1_TXn_INT_REG */
   1310 }
   1311 #endif
   1312 
   1313 int
   1314 octeon_gmx_intr_drop(void *arg)
   1315 {
   1316 	octeon_write_csr(CIU_INT0_SUM0, CIU_INTX_SUM0_GMX_DRP);
   1317 	octeon_gmx_intr_drop_evcnt.ev_count++;
   1318 	return (1);
   1319 }
   1320 
   1321 uint64_t
   1322 octeon_gmx_get_rx_int_reg(struct octeon_gmx_port_softc *sc)
   1323 {
   1324 	uint64_t reg;
   1325 	uint64_t rx_int_reg = 0;
   1326 
   1327 	reg = _GMX_PORT_RD8(sc, GMX0_RX0_INT_REG);
   1328 	/* clear */
   1329 	SET(rx_int_reg, 0 |
   1330 	    RXN_INT_REG_PHY_DUPX |
   1331 	    RXN_INT_REG_PHY_SPD |
   1332 	    RXN_INT_REG_PHY_LINK |
   1333 	    RXN_INT_REG_IFGERR |
   1334 	    RXN_INT_REG_COLDET |
   1335 	    RXN_INT_REG_FALERR |
   1336 	    RXN_INT_REG_RSVERR |
   1337 	    RXN_INT_REG_PCTERR |
   1338 	    RXN_INT_REG_OVRERR |
   1339 	    RXN_INT_REG_NIBERR |
   1340 	    RXN_INT_REG_SKPERR |
   1341 	    RXN_INT_REG_RCVERR |
   1342 	    RXN_INT_REG_LENERR |
   1343 	    RXN_INT_REG_ALNERR |
   1344 	    RXN_INT_REG_FCSERR |
   1345 	    RXN_INT_REG_JABBER |
   1346 	    RXN_INT_REG_MAXERR |
   1347 	    RXN_INT_REG_CAREXT |
   1348 	    RXN_INT_REG_MINERR);
   1349 	_GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_reg);
   1350 
   1351 	return reg;
   1352 }
   1353 
   1354 uint64_t
   1355 octeon_gmx_get_tx_int_reg(struct octeon_gmx_port_softc *sc)
   1356 {
   1357 	uint64_t reg;
   1358 	uint64_t tx_int_reg = 0;
   1359 
   1360 	reg = _GMX_PORT_RD8(sc, GMX0_TX_INT_REG);
   1361 	/* clear */
   1362 	SET(tx_int_reg, 0 |
   1363 	    TX_INT_REG_LATE_COL |
   1364 	    TX_INT_REG_XSDEF |
   1365 	    TX_INT_REG_XSCOL |
   1366 	    TX_INT_REG_UNDFLW |
   1367 	    TX_INT_REG_PKO_NXA);
   1368 	_GMX_PORT_WR8(sc, GMX0_TX_INT_REG, tx_int_reg);
   1369 
   1370 	return reg;
   1371 }
   1372 #endif	/* OCTEON_ETH_DEBUG */
   1373 
   1374 /* ---- debug */
   1375 
   1376 #ifdef OCTEON_ETH_DEBUG
   1377 #define	_ENTRY(x)	{ #x, x##_BITS, x }
   1378 
   1379 struct octeon_gmx_dump_reg_ {
   1380 	const char *name;
   1381 	const char *format;
   1382 	size_t	offset;
   1383 };
   1384 
   1385 static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_regs_[] = {
   1386 	_ENTRY(GMX0_SMAC0),
   1387 	_ENTRY(GMX0_BIST0),
   1388 	_ENTRY(GMX0_RX_PRTS),
   1389 	_ENTRY(GMX0_RX_BP_DROP0),
   1390 	_ENTRY(GMX0_RX_BP_DROP1),
   1391 	_ENTRY(GMX0_RX_BP_DROP2),
   1392 	_ENTRY(GMX0_RX_BP_ON0),
   1393 	_ENTRY(GMX0_RX_BP_ON1),
   1394 	_ENTRY(GMX0_RX_BP_ON2),
   1395 	_ENTRY(GMX0_RX_BP_OFF0),
   1396 	_ENTRY(GMX0_RX_BP_OFF1),
   1397 	_ENTRY(GMX0_RX_BP_OFF2),
   1398 	_ENTRY(GMX0_TX_PRTS),
   1399 	_ENTRY(GMX0_TX_IFG),
   1400 	_ENTRY(GMX0_TX_JAM),
   1401 	_ENTRY(GMX0_TX_COL_ATTEMPT),
   1402 	_ENTRY(GMX0_TX_PAUSE_PKT_DMAC),
   1403 	_ENTRY(GMX0_TX_PAUSE_PKT_TYPE),
   1404 	_ENTRY(GMX0_TX_OVR_BP),
   1405 	_ENTRY(GMX0_TX_BP),
   1406 	_ENTRY(GMX0_TX_CORRUPT),
   1407 	_ENTRY(GMX0_RX_PRT_INFO),
   1408 	_ENTRY(GMX0_TX_LFSR),
   1409 	_ENTRY(GMX0_TX_INT_REG),
   1410 	_ENTRY(GMX0_TX_INT_EN),
   1411 	_ENTRY(GMX0_NXA_ADR),
   1412 	_ENTRY(GMX0_BAD_REG),
   1413 	_ENTRY(GMX0_STAT_BP),
   1414 	_ENTRY(GMX0_TX_CLK_MSK0),
   1415 	_ENTRY(GMX0_TX_CLK_MSK1),
   1416 	_ENTRY(GMX0_RX_TX_STATUS),
   1417 	_ENTRY(GMX0_INF_MODE),
   1418 };
   1419 
   1420 static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_port_regs_[] = {
   1421 	_ENTRY(GMX0_RX0_INT_REG),
   1422 	_ENTRY(GMX0_RX0_INT_EN),
   1423 	_ENTRY(GMX0_PRT0_CFG),
   1424 	_ENTRY(GMX0_RX0_FRM_CTL),
   1425 	_ENTRY(GMX0_RX0_FRM_CHK),
   1426 	_ENTRY(GMX0_RX0_FRM_MIN),
   1427 	_ENTRY(GMX0_RX0_FRM_MAX),
   1428 	_ENTRY(GMX0_RX0_JABBER),
   1429 	_ENTRY(GMX0_RX0_DECISION),
   1430 	_ENTRY(GMX0_RX0_UDD_SKP),
   1431 	_ENTRY(GMX0_RX0_STATS_CTL),
   1432 	_ENTRY(GMX0_RX0_IFG),
   1433 	_ENTRY(GMX0_RX0_RX_INBND),
   1434 	_ENTRY(GMX0_RX0_ADR_CTL),
   1435 	_ENTRY(GMX0_RX0_ADR_CAM_EN),
   1436 	_ENTRY(GMX0_RX0_ADR_CAM0),
   1437 	_ENTRY(GMX0_RX0_ADR_CAM1),
   1438 	_ENTRY(GMX0_RX0_ADR_CAM2),
   1439 	_ENTRY(GMX0_RX0_ADR_CAM3),
   1440 	_ENTRY(GMX0_RX0_ADR_CAM4),
   1441 	_ENTRY(GMX0_RX0_ADR_CAM5),
   1442 	_ENTRY(GMX0_TX0_CLK),
   1443 	_ENTRY(GMX0_TX0_THRESH),
   1444 	_ENTRY(GMX0_TX0_APPEND),
   1445 	_ENTRY(GMX0_TX0_SLOT),
   1446 	_ENTRY(GMX0_TX0_BURST),
   1447 	_ENTRY(GMX0_TX0_PAUSE_PKT_TIME),
   1448 	_ENTRY(GMX0_TX0_MIN_PKT),
   1449 	_ENTRY(GMX0_TX0_PAUSE_PKT_INTERVAL),
   1450 	_ENTRY(GMX0_TX0_SOFT_PAUSE),
   1451 	_ENTRY(GMX0_TX0_PAUSE_TOGO),
   1452 	_ENTRY(GMX0_TX0_PAUSE_ZERO),
   1453 	_ENTRY(GMX0_TX0_STATS_CTL),
   1454 	_ENTRY(GMX0_TX0_CTL),
   1455 };
   1456 
   1457 static const struct octeon_gmx_dump_reg_ octeon_gmx_dump_port_stats_[] = {
   1458 	_ENTRY(GMX0_RX0_STATS_PKTS),
   1459 	_ENTRY(GMX0_RX0_STATS_OCTS),
   1460 	_ENTRY(GMX0_RX0_STATS_PKTS_CTL),
   1461 	_ENTRY(GMX0_RX0_STATS_OCTS_CTL),
   1462 	_ENTRY(GMX0_RX0_STATS_PKTS_DMAC),
   1463 	_ENTRY(GMX0_RX0_STATS_OCTS_DMAC),
   1464 	_ENTRY(GMX0_RX0_STATS_PKTS_DRP),
   1465 	_ENTRY(GMX0_RX0_STATS_OCTS_DRP),
   1466 	_ENTRY(GMX0_RX0_STATS_PKTS_BAD),
   1467 	_ENTRY(GMX0_TX0_STAT0),
   1468 	_ENTRY(GMX0_TX0_STAT1),
   1469 	_ENTRY(GMX0_TX0_STAT2),
   1470 	_ENTRY(GMX0_TX0_STAT3),
   1471 	_ENTRY(GMX0_TX0_STAT4),
   1472 	_ENTRY(GMX0_TX0_STAT5),
   1473 	_ENTRY(GMX0_TX0_STAT6),
   1474 	_ENTRY(GMX0_TX0_STAT7),
   1475 	_ENTRY(GMX0_TX0_STAT8),
   1476 	_ENTRY(GMX0_TX0_STAT9),
   1477 };
   1478 
   1479 void		octeon_gmx_dump_common(void);
   1480 void		octeon_gmx_dump_port0(void);
   1481 void		octeon_gmx_dump_port1(void);
   1482 void		octeon_gmx_dump_port2(void);
   1483 void		octeon_gmx_dump_port0_regs(void);
   1484 void		octeon_gmx_dump_port1_regs(void);
   1485 void		octeon_gmx_dump_port2_regs(void);
   1486 void		octeon_gmx_dump_port0_stats(void);
   1487 void		octeon_gmx_dump_port1_stats(void);
   1488 void		octeon_gmx_dump_port2_stats(void);
   1489 void		octeon_gmx_dump_port_regs(int);
   1490 void		octeon_gmx_dump_port_stats(int);
   1491 void		octeon_gmx_dump_common_x(int, const struct octeon_gmx_dump_reg_ *, size_t);
   1492 void		octeon_gmx_dump_port_x(int, const struct octeon_gmx_dump_reg_ *, size_t);
   1493 void		octeon_gmx_dump_x(int, const struct octeon_gmx_dump_reg_ *, size_t, size_t, int);
   1494 void		octeon_gmx_dump_x_index(char *, size_t, int);
   1495 
   1496 void
   1497 octeon_gmx_dump(void)
   1498 {
   1499 	octeon_gmx_dump_common();
   1500 	octeon_gmx_dump_port0();
   1501 	octeon_gmx_dump_port1();
   1502 	octeon_gmx_dump_port2();
   1503 }
   1504 
   1505 void
   1506 octeon_gmx_dump_common(void)
   1507 {
   1508 	octeon_gmx_dump_common_x(0, octeon_gmx_dump_regs_,
   1509 	    __arraycount(octeon_gmx_dump_regs_));
   1510 }
   1511 
   1512 void
   1513 octeon_gmx_dump_port0(void)
   1514 {
   1515 	octeon_gmx_dump_port_regs(0);
   1516 	octeon_gmx_dump_port_stats(0);
   1517 }
   1518 
   1519 void
   1520 octeon_gmx_dump_port1(void)
   1521 {
   1522 	octeon_gmx_dump_port_regs(1);
   1523 	octeon_gmx_dump_port_stats(1);
   1524 }
   1525 
   1526 void
   1527 octeon_gmx_dump_port2(void)
   1528 {
   1529 	octeon_gmx_dump_port_regs(2);
   1530 	octeon_gmx_dump_port_stats(2);
   1531 }
   1532 
   1533 void
   1534 octeon_gmx_dump_port_regs(int portno)
   1535 {
   1536 	octeon_gmx_dump_port_x(portno, octeon_gmx_dump_port_regs_,
   1537 	    __arraycount(octeon_gmx_dump_port_regs_));
   1538 }
   1539 
   1540 void
   1541 octeon_gmx_dump_port_stats(int portno)
   1542 {
   1543 	struct octeon_gmx_port_softc *sc = __octeon_gmx_port_softc[0];
   1544 	uint64_t rx_stats_ctl;
   1545 	uint64_t tx_stats_ctl;
   1546 
   1547 	rx_stats_ctl = _GMX_RD8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL);
   1548 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL,
   1549 	    rx_stats_ctl & ~RXN_STATS_CTL_RD_CLR);
   1550 	tx_stats_ctl = _GMX_RD8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL);
   1551 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL,
   1552 	    tx_stats_ctl & ~TXN_STATS_CTL_RD_CLR);
   1553 	octeon_gmx_dump_port_x(portno, octeon_gmx_dump_port_stats_,
   1554 	    __arraycount(octeon_gmx_dump_port_stats_));
   1555 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_RX0_STATS_CTL, rx_stats_ctl);
   1556 	_GMX_WR8(sc, GMX0_BASE_PORT_SIZE * portno + GMX0_TX0_STATS_CTL, tx_stats_ctl);
   1557 }
   1558 
   1559 void
   1560 octeon_gmx_dump_common_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size)
   1561 {
   1562 	octeon_gmx_dump_x(portno, regs, size, 0, 0);
   1563 }
   1564 
   1565 void
   1566 octeon_gmx_dump_port_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size)
   1567 {
   1568 	octeon_gmx_dump_x(portno, regs, size, GMX0_BASE_PORT_SIZE * portno, 1);
   1569 }
   1570 
   1571 void
   1572 octeon_gmx_dump_x(int portno, const struct octeon_gmx_dump_reg_ *regs, size_t size, size_t base, int index)
   1573 {
   1574 	struct octeon_gmx_port_softc *sc = __octeon_gmx_port_softc[0];
   1575 	const struct octeon_gmx_dump_reg_ *reg;
   1576 	uint64_t tmp;
   1577 	char name[64];
   1578 	char buf[512];
   1579 	int i;
   1580 
   1581 	for (i = 0; i < (int)size; i++) {
   1582 		reg = &regs[i];
   1583 		tmp = _GMX_RD8(sc, base + reg->offset);
   1584 
   1585 		if (reg->format == NULL)
   1586 			snprintf(buf, sizeof(buf), "%016" PRIx64, tmp);
   1587 		else
   1588 			snprintb(buf, sizeof(buf), reg->format, tmp);
   1589 
   1590 		snprintf(name, sizeof(name), "%s", reg->name);
   1591 		if (index > 0)
   1592 			octeon_gmx_dump_x_index(name, sizeof(name), portno);
   1593 
   1594 		printf("\t%-24s: %s\n", name, buf);
   1595 	}
   1596 }
   1597 
   1598 void
   1599 octeon_gmx_dump_x_index(char *buf, size_t len, int index)
   1600 {
   1601 	static const char *patterns[] = { "_TX0_", "_RX0_", "_PRT0_" };
   1602 	int i;
   1603 
   1604 	for (i = 0; i < (int)__arraycount(patterns); i++) {
   1605 		char *p;
   1606 
   1607 		p = strstr(buf, patterns[i]);
   1608 		if (p == NULL)
   1609 			continue;
   1610 		p = strchr(p, '0');
   1611 		KASSERT(p != NULL);
   1612 		*p = '0' + index;
   1613 		return;
   1614 	}
   1615 }
   1616 
   1617 void
   1618 octeon_gmx_debug_reset(void)
   1619 {
   1620 	int i;
   1621 
   1622 	for (i = 0; i < 3; i++)
   1623 		octeon_gmx_link_enable(__octeon_gmx_port_softc[i], 0);
   1624 	for (i = 0; i < 3; i++)
   1625 		octeon_gmx_link_enable(__octeon_gmx_port_softc[i], 1);
   1626 }
   1627 #endif
   1628