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