Home | History | Annotate | Line # | Download | only in marvell
if_mvxpe.c revision 1.17.16.2
      1  1.17.16.2  pgoyette /*	$NetBSD: if_mvxpe.c,v 1.17.16.2 2018/07/28 04:37:45 pgoyette Exp $	*/
      2        1.1  hsuenaga /*
      3        1.1  hsuenaga  * Copyright (c) 2015 Internet Initiative Japan Inc.
      4        1.1  hsuenaga  * All rights reserved.
      5        1.1  hsuenaga  *
      6        1.1  hsuenaga  * Redistribution and use in source and binary forms, with or without
      7        1.1  hsuenaga  * modification, are permitted provided that the following conditions
      8        1.1  hsuenaga  * are met:
      9        1.1  hsuenaga  * 1. Redistributions of source code must retain the above copyright
     10        1.1  hsuenaga  *    notice, this list of conditions and the following disclaimer.
     11        1.1  hsuenaga  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1  hsuenaga  *    notice, this list of conditions and the following disclaimer in the
     13        1.1  hsuenaga  *    documentation and/or other materials provided with the distribution.
     14        1.1  hsuenaga  *
     15        1.1  hsuenaga  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16        1.1  hsuenaga  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17        1.1  hsuenaga  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18        1.1  hsuenaga  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     19        1.1  hsuenaga  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     20        1.1  hsuenaga  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21        1.1  hsuenaga  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22        1.1  hsuenaga  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     23        1.1  hsuenaga  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     24        1.1  hsuenaga  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25        1.1  hsuenaga  * POSSIBILITY OF SUCH DAMAGE.
     26        1.1  hsuenaga  */
     27        1.1  hsuenaga #include <sys/cdefs.h>
     28  1.17.16.2  pgoyette __KERNEL_RCSID(0, "$NetBSD: if_mvxpe.c,v 1.17.16.2 2018/07/28 04:37:45 pgoyette Exp $");
     29        1.1  hsuenaga 
     30        1.1  hsuenaga #include "opt_multiprocessor.h"
     31        1.1  hsuenaga 
     32        1.1  hsuenaga #include <sys/param.h>
     33        1.1  hsuenaga #include <sys/bus.h>
     34        1.1  hsuenaga #include <sys/callout.h>
     35        1.1  hsuenaga #include <sys/device.h>
     36        1.1  hsuenaga #include <sys/endian.h>
     37        1.1  hsuenaga #include <sys/errno.h>
     38        1.1  hsuenaga #include <sys/evcnt.h>
     39        1.1  hsuenaga #include <sys/kernel.h>
     40        1.1  hsuenaga #include <sys/kmem.h>
     41        1.1  hsuenaga #include <sys/mutex.h>
     42        1.1  hsuenaga #include <sys/sockio.h>
     43        1.1  hsuenaga #include <sys/sysctl.h>
     44        1.1  hsuenaga #include <sys/syslog.h>
     45        1.1  hsuenaga #include <sys/rndsource.h>
     46        1.1  hsuenaga 
     47        1.1  hsuenaga #include <net/if.h>
     48        1.1  hsuenaga #include <net/if_ether.h>
     49        1.1  hsuenaga #include <net/if_media.h>
     50        1.1  hsuenaga #include <net/bpf.h>
     51        1.1  hsuenaga 
     52        1.1  hsuenaga #include <netinet/in.h>
     53        1.1  hsuenaga #include <netinet/in_systm.h>
     54        1.1  hsuenaga #include <netinet/ip.h>
     55        1.1  hsuenaga 
     56        1.1  hsuenaga #include <dev/mii/mii.h>
     57        1.1  hsuenaga #include <dev/mii/miivar.h>
     58        1.1  hsuenaga 
     59        1.1  hsuenaga #include <dev/marvell/marvellreg.h>
     60        1.1  hsuenaga #include <dev/marvell/marvellvar.h>
     61        1.2  hsuenaga #include <dev/marvell/mvxpbmvar.h>
     62        1.1  hsuenaga #include <dev/marvell/if_mvxpereg.h>
     63        1.1  hsuenaga #include <dev/marvell/if_mvxpevar.h>
     64        1.1  hsuenaga 
     65        1.1  hsuenaga #include "locators.h"
     66        1.1  hsuenaga 
     67        1.1  hsuenaga #if BYTE_ORDER == BIG_ENDIAN
     68        1.1  hsuenaga #error "BIG ENDIAN not supported"
     69        1.1  hsuenaga #endif
     70        1.1  hsuenaga 
     71        1.1  hsuenaga #ifdef MVXPE_DEBUG
     72        1.1  hsuenaga #define STATIC /* nothing */
     73        1.1  hsuenaga #else
     74        1.1  hsuenaga #define STATIC static
     75        1.1  hsuenaga #endif
     76        1.1  hsuenaga 
     77        1.1  hsuenaga /* autoconf(9) */
     78        1.1  hsuenaga STATIC int mvxpe_match(device_t, struct cfdata *, void *);
     79        1.1  hsuenaga STATIC void mvxpe_attach(device_t, device_t, void *);
     80        1.1  hsuenaga STATIC int mvxpe_evcnt_attach(struct mvxpe_softc *);
     81        1.1  hsuenaga CFATTACH_DECL_NEW(mvxpe_mbus, sizeof(struct mvxpe_softc),
     82        1.1  hsuenaga     mvxpe_match, mvxpe_attach, NULL, NULL);
     83        1.1  hsuenaga STATIC void mvxpe_sc_lock(struct mvxpe_softc *);
     84        1.1  hsuenaga STATIC void mvxpe_sc_unlock(struct mvxpe_softc *);
     85        1.1  hsuenaga 
     86        1.1  hsuenaga /* MII */
     87        1.1  hsuenaga STATIC int mvxpe_miibus_readreg(device_t, int, int);
     88        1.1  hsuenaga STATIC void mvxpe_miibus_writereg(device_t, int, int, int);
     89        1.1  hsuenaga STATIC void mvxpe_miibus_statchg(struct ifnet *);
     90        1.1  hsuenaga 
     91        1.1  hsuenaga /* Addres Decoding Window */
     92        1.1  hsuenaga STATIC void mvxpe_wininit(struct mvxpe_softc *, enum marvell_tags *);
     93        1.1  hsuenaga 
     94        1.1  hsuenaga /* Device Register Initialization */
     95        1.1  hsuenaga STATIC int mvxpe_initreg(struct ifnet *);
     96        1.1  hsuenaga 
     97        1.1  hsuenaga /* Descriptor Ring Control for each of queues */
     98        1.1  hsuenaga STATIC void *mvxpe_dma_memalloc(struct mvxpe_softc *, bus_dmamap_t *, size_t);
     99        1.1  hsuenaga STATIC int mvxpe_ring_alloc_queue(struct mvxpe_softc *, int);
    100        1.1  hsuenaga STATIC void mvxpe_ring_dealloc_queue(struct mvxpe_softc *, int);
    101        1.1  hsuenaga STATIC void mvxpe_ring_init_queue(struct mvxpe_softc *, int);
    102        1.1  hsuenaga STATIC void mvxpe_ring_flush_queue(struct mvxpe_softc *, int);
    103        1.1  hsuenaga STATIC void mvxpe_ring_sync_rx(struct mvxpe_softc *, int, int, int, int);
    104        1.1  hsuenaga STATIC void mvxpe_ring_sync_tx(struct mvxpe_softc *, int, int, int, int);
    105        1.1  hsuenaga 
    106        1.1  hsuenaga /* Rx/Tx Queue Control */
    107        1.1  hsuenaga STATIC int mvxpe_rx_queue_init(struct ifnet *, int);
    108        1.1  hsuenaga STATIC int mvxpe_tx_queue_init(struct ifnet *, int);
    109        1.1  hsuenaga STATIC int mvxpe_rx_queue_enable(struct ifnet *, int);
    110        1.1  hsuenaga STATIC int mvxpe_tx_queue_enable(struct ifnet *, int);
    111        1.1  hsuenaga STATIC void mvxpe_rx_lockq(struct mvxpe_softc *, int);
    112        1.1  hsuenaga STATIC void mvxpe_rx_unlockq(struct mvxpe_softc *, int);
    113        1.1  hsuenaga STATIC void mvxpe_tx_lockq(struct mvxpe_softc *, int);
    114        1.1  hsuenaga STATIC void mvxpe_tx_unlockq(struct mvxpe_softc *, int);
    115        1.1  hsuenaga 
    116        1.1  hsuenaga /* Interrupt Handlers */
    117        1.1  hsuenaga STATIC void mvxpe_disable_intr(struct mvxpe_softc *);
    118        1.1  hsuenaga STATIC void mvxpe_enable_intr(struct mvxpe_softc *);
    119        1.1  hsuenaga STATIC int mvxpe_rxtxth_intr(void *);
    120        1.1  hsuenaga STATIC int mvxpe_misc_intr(void *);
    121        1.1  hsuenaga STATIC int mvxpe_rxtx_intr(void *);
    122        1.1  hsuenaga STATIC void mvxpe_tick(void *);
    123        1.1  hsuenaga 
    124        1.1  hsuenaga /* struct ifnet and mii callbacks*/
    125        1.1  hsuenaga STATIC void mvxpe_start(struct ifnet *);
    126        1.1  hsuenaga STATIC int mvxpe_ioctl(struct ifnet *, u_long, void *);
    127        1.1  hsuenaga STATIC int mvxpe_init(struct ifnet *);
    128        1.1  hsuenaga STATIC void mvxpe_stop(struct ifnet *, int);
    129        1.1  hsuenaga STATIC void mvxpe_watchdog(struct ifnet *);
    130        1.1  hsuenaga STATIC int mvxpe_ifflags_cb(struct ethercom *);
    131        1.1  hsuenaga STATIC int mvxpe_mediachange(struct ifnet *);
    132        1.1  hsuenaga STATIC void mvxpe_mediastatus(struct ifnet *, struct ifmediareq *);
    133        1.1  hsuenaga 
    134        1.1  hsuenaga /* Link State Notify */
    135        1.1  hsuenaga STATIC void mvxpe_linkupdate(struct mvxpe_softc *sc);
    136        1.1  hsuenaga STATIC void mvxpe_linkup(struct mvxpe_softc *);
    137        1.1  hsuenaga STATIC void mvxpe_linkdown(struct mvxpe_softc *);
    138        1.1  hsuenaga STATIC void mvxpe_linkreset(struct mvxpe_softc *);
    139        1.1  hsuenaga 
    140        1.1  hsuenaga /* Tx Subroutines */
    141        1.1  hsuenaga STATIC int mvxpe_tx_queue_select(struct mvxpe_softc *, struct mbuf *);
    142        1.1  hsuenaga STATIC int mvxpe_tx_queue(struct mvxpe_softc *, struct mbuf *, int);
    143        1.1  hsuenaga STATIC void mvxpe_tx_set_csumflag(struct ifnet *,
    144        1.1  hsuenaga     struct mvxpe_tx_desc *, struct mbuf *);
    145        1.2  hsuenaga STATIC void mvxpe_tx_complete(struct mvxpe_softc *, uint32_t);
    146        1.2  hsuenaga STATIC void mvxpe_tx_queue_complete(struct mvxpe_softc *, int);
    147        1.1  hsuenaga 
    148        1.1  hsuenaga /* Rx Subroutines */
    149        1.2  hsuenaga STATIC void mvxpe_rx(struct mvxpe_softc *, uint32_t);
    150        1.1  hsuenaga STATIC void mvxpe_rx_queue(struct mvxpe_softc *, int, int);
    151        1.2  hsuenaga STATIC int mvxpe_rx_queue_select(struct mvxpe_softc *, uint32_t, int *);
    152        1.2  hsuenaga STATIC void mvxpe_rx_refill(struct mvxpe_softc *, uint32_t);
    153        1.2  hsuenaga STATIC void mvxpe_rx_queue_refill(struct mvxpe_softc *, int);
    154        1.1  hsuenaga STATIC int mvxpe_rx_queue_add(struct mvxpe_softc *, int);
    155        1.1  hsuenaga STATIC void mvxpe_rx_set_csumflag(struct ifnet *,
    156        1.1  hsuenaga     struct mvxpe_rx_desc *, struct mbuf *);
    157        1.1  hsuenaga 
    158        1.1  hsuenaga /* MAC address filter */
    159        1.1  hsuenaga STATIC uint8_t mvxpe_crc8(const uint8_t *, size_t);
    160        1.1  hsuenaga STATIC void mvxpe_filter_setup(struct mvxpe_softc *);
    161        1.1  hsuenaga 
    162        1.1  hsuenaga /* sysctl(9) */
    163        1.1  hsuenaga STATIC int sysctl_read_mib(SYSCTLFN_PROTO);
    164        1.1  hsuenaga STATIC int sysctl_clear_mib(SYSCTLFN_PROTO);
    165        1.1  hsuenaga STATIC int sysctl_set_queue_length(SYSCTLFN_PROTO);
    166        1.1  hsuenaga STATIC int sysctl_set_queue_rxthtime(SYSCTLFN_PROTO);
    167        1.1  hsuenaga STATIC void sysctl_mvxpe_init(struct mvxpe_softc *);
    168        1.1  hsuenaga 
    169        1.1  hsuenaga /* MIB */
    170        1.1  hsuenaga STATIC void mvxpe_clear_mib(struct mvxpe_softc *);
    171        1.1  hsuenaga STATIC void mvxpe_update_mib(struct mvxpe_softc *);
    172        1.1  hsuenaga 
    173        1.1  hsuenaga /* for Debug */
    174        1.1  hsuenaga STATIC void mvxpe_dump_txdesc(struct mvxpe_tx_desc *, int) __attribute__((__unused__));
    175        1.1  hsuenaga STATIC void mvxpe_dump_rxdesc(struct mvxpe_rx_desc *, int) __attribute__((__unused__));
    176        1.1  hsuenaga 
    177        1.1  hsuenaga STATIC int mvxpe_root_num;
    178        1.1  hsuenaga STATIC kmutex_t mii_mutex;
    179        1.1  hsuenaga STATIC int mii_init = 0;
    180        1.1  hsuenaga #ifdef MVXPE_DEBUG
    181        1.1  hsuenaga STATIC int mvxpe_debug = MVXPE_DEBUG;
    182        1.1  hsuenaga #endif
    183        1.1  hsuenaga 
    184        1.1  hsuenaga /*
    185        1.1  hsuenaga  * List of MIB register and names
    186        1.1  hsuenaga  */
    187        1.1  hsuenaga STATIC struct mvxpe_mib_def {
    188        1.1  hsuenaga 	uint32_t regnum;
    189        1.1  hsuenaga 	int reg64;
    190        1.1  hsuenaga 	const char *sysctl_name;
    191        1.1  hsuenaga 	const char *desc;
    192       1.10    hikaru 	int ext;
    193       1.10    hikaru #define MVXPE_MIBEXT_IF_OERRORS	1
    194       1.10    hikaru #define MVXPE_MIBEXT_IF_IERRORS	2
    195       1.10    hikaru #define MVXPE_MIBEXT_IF_COLLISIONS	3
    196        1.1  hsuenaga } mvxpe_mib_list[] = {
    197        1.1  hsuenaga 	{MVXPE_MIB_RX_GOOD_OCT, 1,	"rx_good_oct",
    198       1.10    hikaru 	    "Good Octets Rx", 0},
    199        1.1  hsuenaga 	{MVXPE_MIB_RX_BAD_OCT, 0,	"rx_bad_oct",
    200       1.10    hikaru 	    "Bad  Octets Rx", 0},
    201       1.10    hikaru 	{MVXPE_MIB_TX_MAC_TRNS_ERR, 0,	"tx_mac_err",
    202       1.10    hikaru 	    "MAC Transmit Error", MVXPE_MIBEXT_IF_OERRORS},
    203        1.1  hsuenaga 	{MVXPE_MIB_RX_GOOD_FRAME, 0,	"rx_good_frame",
    204       1.10    hikaru 	    "Good Frames Rx", 0},
    205        1.1  hsuenaga 	{MVXPE_MIB_RX_BAD_FRAME, 0,	"rx_bad_frame",
    206       1.10    hikaru 	    "Bad Frames Rx", 0},
    207        1.1  hsuenaga 	{MVXPE_MIB_RX_BCAST_FRAME, 0,	"rx_bcast_frame",
    208       1.10    hikaru 	    "Broadcast Frames Rx", 0},
    209        1.1  hsuenaga 	{MVXPE_MIB_RX_MCAST_FRAME, 0,	"rx_mcast_frame",
    210       1.10    hikaru 	    "Multicast Frames Rx", 0},
    211        1.1  hsuenaga 	{MVXPE_MIB_RX_FRAME64_OCT, 0,	"rx_frame_1_64",
    212       1.10    hikaru 	    "Frame Size    1 -   64", 0},
    213        1.1  hsuenaga 	{MVXPE_MIB_RX_FRAME127_OCT, 0,	"rx_frame_65_127",
    214       1.10    hikaru 	    "Frame Size   65 -  127", 0},
    215        1.1  hsuenaga 	{MVXPE_MIB_RX_FRAME255_OCT, 0,	"rx_frame_128_255",
    216       1.10    hikaru 	    "Frame Size  128 -  255", 0},
    217        1.1  hsuenaga 	{MVXPE_MIB_RX_FRAME511_OCT, 0,	"rx_frame_256_511",
    218        1.1  hsuenaga 	    "Frame Size  256 -  511"},
    219        1.1  hsuenaga 	{MVXPE_MIB_RX_FRAME1023_OCT, 0,	"rx_frame_512_1023",
    220       1.10    hikaru 	    "Frame Size  512 - 1023", 0},
    221        1.1  hsuenaga 	{MVXPE_MIB_RX_FRAMEMAX_OCT, 0,	"rx_fame_1024_max",
    222       1.10    hikaru 	    "Frame Size 1024 -  Max", 0},
    223        1.1  hsuenaga 	{MVXPE_MIB_TX_GOOD_OCT, 1,	"tx_good_oct",
    224       1.10    hikaru 	    "Good Octets Tx", 0},
    225        1.1  hsuenaga 	{MVXPE_MIB_TX_GOOD_FRAME, 0,	"tx_good_frame",
    226       1.10    hikaru 	    "Good Frames Tx", 0},
    227        1.1  hsuenaga 	{MVXPE_MIB_TX_EXCES_COL, 0,	"tx_exces_collision",
    228       1.10    hikaru 	    "Excessive Collision", MVXPE_MIBEXT_IF_OERRORS},
    229        1.1  hsuenaga 	{MVXPE_MIB_TX_MCAST_FRAME, 0,	"tx_mcast_frame",
    230        1.1  hsuenaga 	    "Multicast Frames Tx"},
    231        1.1  hsuenaga 	{MVXPE_MIB_TX_BCAST_FRAME, 0,	"tx_bcast_frame",
    232        1.1  hsuenaga 	    "Broadcast Frames Tx"},
    233        1.1  hsuenaga 	{MVXPE_MIB_TX_MAC_CTL_ERR, 0,	"tx_mac_err",
    234       1.10    hikaru 	    "Unknown MAC Control", 0},
    235        1.1  hsuenaga 	{MVXPE_MIB_FC_SENT, 0,		"fc_tx",
    236       1.10    hikaru 	    "Flow Control Tx", 0},
    237        1.1  hsuenaga 	{MVXPE_MIB_FC_GOOD, 0,		"fc_rx_good",
    238       1.10    hikaru 	    "Good Flow Control Rx", 0},
    239        1.1  hsuenaga 	{MVXPE_MIB_FC_BAD, 0,		"fc_rx_bad",
    240       1.10    hikaru 	    "Bad Flow Control Rx", 0},
    241        1.1  hsuenaga 	{MVXPE_MIB_PKT_UNDERSIZE, 0,	"pkt_undersize",
    242       1.10    hikaru 	    "Undersized Packets Rx", MVXPE_MIBEXT_IF_IERRORS},
    243        1.1  hsuenaga 	{MVXPE_MIB_PKT_FRAGMENT, 0,	"pkt_fragment",
    244       1.10    hikaru 	    "Fragmented Packets Rx", MVXPE_MIBEXT_IF_IERRORS},
    245        1.1  hsuenaga 	{MVXPE_MIB_PKT_OVERSIZE, 0,	"pkt_oversize",
    246       1.10    hikaru 	    "Oversized Packets Rx", MVXPE_MIBEXT_IF_IERRORS},
    247        1.1  hsuenaga 	{MVXPE_MIB_PKT_JABBER, 0,	"pkt_jabber",
    248       1.10    hikaru 	    "Jabber Packets Rx", MVXPE_MIBEXT_IF_IERRORS},
    249        1.1  hsuenaga 	{MVXPE_MIB_MAC_RX_ERR, 0,	"mac_rx_err",
    250       1.10    hikaru 	    "MAC Rx Errors", MVXPE_MIBEXT_IF_IERRORS},
    251        1.1  hsuenaga 	{MVXPE_MIB_MAC_CRC_ERR, 0,	"mac_crc_err",
    252       1.10    hikaru 	    "MAC CRC Errors", MVXPE_MIBEXT_IF_IERRORS},
    253        1.1  hsuenaga 	{MVXPE_MIB_MAC_COL, 0,		"mac_collision",
    254       1.10    hikaru 	    "MAC Collision", MVXPE_MIBEXT_IF_COLLISIONS},
    255        1.1  hsuenaga 	{MVXPE_MIB_MAC_LATE_COL, 0,	"mac_late_collision",
    256       1.10    hikaru 	    "MAC Late Collision", MVXPE_MIBEXT_IF_OERRORS},
    257        1.1  hsuenaga };
    258        1.1  hsuenaga 
    259        1.1  hsuenaga /*
    260        1.1  hsuenaga  * autoconf(9)
    261        1.1  hsuenaga  */
    262        1.1  hsuenaga /* ARGSUSED */
    263        1.1  hsuenaga STATIC int
    264        1.1  hsuenaga mvxpe_match(device_t parent, cfdata_t match, void *aux)
    265        1.1  hsuenaga {
    266        1.1  hsuenaga 	struct marvell_attach_args *mva = aux;
    267        1.1  hsuenaga 	bus_size_t pv_off;
    268        1.1  hsuenaga 	uint32_t pv;
    269        1.1  hsuenaga 
    270        1.1  hsuenaga 	if (strcmp(mva->mva_name, match->cf_name) != 0)
    271        1.1  hsuenaga 		return 0;
    272        1.1  hsuenaga 	if (mva->mva_offset == MVA_OFFSET_DEFAULT)
    273        1.1  hsuenaga 		return 0;
    274        1.1  hsuenaga 
    275        1.1  hsuenaga 	/* check port version */
    276        1.1  hsuenaga 	pv_off = mva->mva_offset + MVXPE_PV;
    277        1.1  hsuenaga 	pv = bus_space_read_4(mva->mva_iot, mva->mva_ioh, pv_off);
    278        1.1  hsuenaga 	if (MVXPE_PV_GET_VERSION(pv) < 0x10)
    279        1.1  hsuenaga 		return 0; /* old version is not supported */
    280        1.1  hsuenaga 
    281        1.1  hsuenaga 	return 1;
    282        1.1  hsuenaga }
    283        1.1  hsuenaga 
    284        1.1  hsuenaga /* ARGSUSED */
    285        1.1  hsuenaga STATIC void
    286        1.1  hsuenaga mvxpe_attach(device_t parent, device_t self, void *aux)
    287        1.1  hsuenaga {
    288        1.1  hsuenaga 	struct mvxpe_softc *sc = device_private(self);
    289        1.1  hsuenaga 	struct mii_softc *mii;
    290        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    291        1.1  hsuenaga 	struct marvell_attach_args *mva = aux;
    292        1.1  hsuenaga 	prop_dictionary_t dict;
    293        1.1  hsuenaga 	prop_data_t enaddrp = NULL;
    294        1.1  hsuenaga 	uint32_t phyaddr, maddrh, maddrl;
    295        1.1  hsuenaga 	uint8_t enaddr[ETHER_ADDR_LEN];
    296        1.1  hsuenaga 	int q;
    297        1.1  hsuenaga 
    298        1.1  hsuenaga 	aprint_naive("\n");
    299        1.1  hsuenaga 	aprint_normal(": Marvell ARMADA GbE Controller\n");
    300        1.1  hsuenaga 	memset(sc, 0, sizeof(*sc));
    301        1.1  hsuenaga 	sc->sc_dev = self;
    302        1.1  hsuenaga 	sc->sc_port = mva->mva_unit;
    303        1.1  hsuenaga 	sc->sc_iot = mva->mva_iot;
    304        1.1  hsuenaga 	sc->sc_dmat = mva->mva_dmat;
    305        1.1  hsuenaga 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET);
    306        1.1  hsuenaga 	callout_init(&sc->sc_tick_ch, 0);
    307        1.1  hsuenaga 	callout_setfunc(&sc->sc_tick_ch, mvxpe_tick, sc);
    308        1.1  hsuenaga 
    309        1.1  hsuenaga 	/*
    310        1.1  hsuenaga 	 * BUS space
    311        1.1  hsuenaga 	 */
    312        1.1  hsuenaga 	if (bus_space_subregion(mva->mva_iot, mva->mva_ioh,
    313        1.1  hsuenaga 	    mva->mva_offset, mva->mva_size, &sc->sc_ioh)) {
    314        1.1  hsuenaga 		aprint_error_dev(self, "Cannot map registers\n");
    315        1.1  hsuenaga 		goto fail;
    316        1.1  hsuenaga 	}
    317        1.1  hsuenaga 	if (bus_space_subregion(mva->mva_iot, mva->mva_ioh,
    318        1.1  hsuenaga 	    mva->mva_offset + MVXPE_PORTMIB_BASE, MVXPE_PORTMIB_SIZE,
    319        1.1  hsuenaga 	    &sc->sc_mibh)) {
    320        1.1  hsuenaga 		aprint_error_dev(self,
    321        1.1  hsuenaga 		    "Cannot map destination address filter registers\n");
    322        1.1  hsuenaga 		goto fail;
    323        1.1  hsuenaga 	}
    324        1.1  hsuenaga 	sc->sc_version = MVXPE_READ(sc, MVXPE_PV);
    325        1.1  hsuenaga 	aprint_normal_dev(self, "Port Version %#x\n", sc->sc_version);
    326        1.1  hsuenaga 
    327        1.1  hsuenaga 	/*
    328        1.2  hsuenaga 	 * Buffer Manager(BM) subsystem.
    329        1.1  hsuenaga 	 */
    330        1.2  hsuenaga 	sc->sc_bm = mvxpbm_device(mva);
    331        1.2  hsuenaga 	if (sc->sc_bm == NULL) {
    332        1.2  hsuenaga 		aprint_error_dev(self, "no Buffer Manager.\n");
    333        1.1  hsuenaga 		goto fail;
    334        1.1  hsuenaga 	}
    335        1.2  hsuenaga 	aprint_normal_dev(self,
    336        1.2  hsuenaga 	    "Using Buffer Manager: %s\n", mvxpbm_xname(sc->sc_bm));
    337        1.2  hsuenaga 	aprint_normal_dev(sc->sc_dev,
    338        1.2  hsuenaga 	    "%zu kbytes managed buffer, %zu bytes * %u entries allocated.\n",
    339        1.2  hsuenaga 	    mvxpbm_buf_size(sc->sc_bm) / 1024,
    340        1.2  hsuenaga 	    mvxpbm_chunk_size(sc->sc_bm), mvxpbm_chunk_count(sc->sc_bm));
    341        1.1  hsuenaga 
    342        1.1  hsuenaga 	/*
    343        1.1  hsuenaga 	 * make sure DMA engines are in reset state
    344        1.1  hsuenaga 	 */
    345        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000001);
    346        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000001);
    347        1.1  hsuenaga 
    348        1.1  hsuenaga 	/*
    349        1.1  hsuenaga 	 * Address decoding window
    350        1.1  hsuenaga 	 */
    351        1.1  hsuenaga 	mvxpe_wininit(sc, mva->mva_tags);
    352        1.1  hsuenaga 
    353        1.1  hsuenaga 	/*
    354        1.1  hsuenaga 	 * MAC address
    355        1.1  hsuenaga 	 */
    356        1.1  hsuenaga 	dict = device_properties(self);
    357        1.1  hsuenaga 	if (dict)
    358        1.1  hsuenaga 		enaddrp = prop_dictionary_get(dict, "mac-address");
    359        1.1  hsuenaga 	if (enaddrp) {
    360        1.1  hsuenaga 		memcpy(enaddr, prop_data_data_nocopy(enaddrp), ETHER_ADDR_LEN);
    361        1.1  hsuenaga 		maddrh  = enaddr[0] << 24;
    362        1.1  hsuenaga 		maddrh |= enaddr[1] << 16;
    363        1.1  hsuenaga 		maddrh |= enaddr[2] << 8;
    364        1.1  hsuenaga 		maddrh |= enaddr[3];
    365        1.1  hsuenaga 		maddrl  = enaddr[4] << 8;
    366        1.1  hsuenaga 		maddrl |= enaddr[5];
    367        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_MACAH, maddrh);
    368        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_MACAL, maddrl);
    369        1.1  hsuenaga 	}
    370        1.1  hsuenaga 	else {
    371        1.1  hsuenaga 		/*
    372        1.1  hsuenaga 		 * even if enaddr is not found in dictionary,
    373        1.1  hsuenaga 		 * the port may be initialized by IPL program such as U-BOOT.
    374        1.1  hsuenaga 		 */
    375        1.1  hsuenaga 		maddrh = MVXPE_READ(sc, MVXPE_MACAH);
    376        1.1  hsuenaga 		maddrl = MVXPE_READ(sc, MVXPE_MACAL);
    377        1.1  hsuenaga 		if ((maddrh | maddrl) == 0) {
    378        1.1  hsuenaga 			aprint_error_dev(self, "No Ethernet address\n");
    379        1.1  hsuenaga 			return;
    380        1.1  hsuenaga 		}
    381        1.1  hsuenaga 	}
    382        1.1  hsuenaga 	sc->sc_enaddr[0] = maddrh >> 24;
    383        1.1  hsuenaga 	sc->sc_enaddr[1] = maddrh >> 16;
    384        1.1  hsuenaga 	sc->sc_enaddr[2] = maddrh >> 8;
    385        1.1  hsuenaga 	sc->sc_enaddr[3] = maddrh >> 0;
    386        1.1  hsuenaga 	sc->sc_enaddr[4] = maddrl >> 8;
    387        1.1  hsuenaga 	sc->sc_enaddr[5] = maddrl >> 0;
    388        1.1  hsuenaga 	aprint_normal_dev(self, "Ethernet address %s\n",
    389        1.1  hsuenaga 	    ether_sprintf(sc->sc_enaddr));
    390        1.1  hsuenaga 
    391        1.1  hsuenaga 	/*
    392        1.1  hsuenaga 	 * Register interrupt handlers
    393        1.1  hsuenaga 	 * XXX: handle Ethernet unit intr. and Error intr.
    394        1.1  hsuenaga 	 */
    395        1.1  hsuenaga 	mvxpe_disable_intr(sc);
    396        1.1  hsuenaga 	marvell_intr_establish(mva->mva_irq, IPL_NET, mvxpe_rxtxth_intr, sc);
    397        1.1  hsuenaga 
    398        1.1  hsuenaga 	/*
    399        1.1  hsuenaga 	 * MIB buffer allocation
    400        1.1  hsuenaga 	 */
    401        1.1  hsuenaga 	sc->sc_sysctl_mib_size =
    402        1.1  hsuenaga 	    __arraycount(mvxpe_mib_list) * sizeof(struct mvxpe_sysctl_mib);
    403        1.1  hsuenaga 	sc->sc_sysctl_mib = kmem_alloc(sc->sc_sysctl_mib_size, KM_NOSLEEP);
    404        1.1  hsuenaga 	if (sc->sc_sysctl_mib == NULL)
    405        1.1  hsuenaga 		goto fail;
    406        1.1  hsuenaga 	memset(sc->sc_sysctl_mib, 0, sc->sc_sysctl_mib_size);
    407        1.1  hsuenaga 
    408        1.1  hsuenaga 	/*
    409        1.1  hsuenaga 	 * Device DMA Buffer allocation
    410        1.1  hsuenaga 	 */
    411        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
    412        1.1  hsuenaga 		if (mvxpe_ring_alloc_queue(sc, q) != 0)
    413        1.1  hsuenaga 			goto fail;
    414        1.1  hsuenaga 		mvxpe_ring_init_queue(sc, q);
    415        1.1  hsuenaga 	}
    416        1.1  hsuenaga 
    417        1.1  hsuenaga 	/*
    418        1.1  hsuenaga 	 * We can support 802.1Q VLAN-sized frames and jumbo
    419        1.1  hsuenaga 	 * Ethernet frames.
    420        1.1  hsuenaga 	 */
    421        1.1  hsuenaga 	sc->sc_ethercom.ec_capabilities |=
    422        1.1  hsuenaga 	    ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;
    423        1.1  hsuenaga 	ifp->if_softc = sc;
    424        1.1  hsuenaga 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    425        1.1  hsuenaga 	ifp->if_start = mvxpe_start;
    426        1.1  hsuenaga 	ifp->if_ioctl = mvxpe_ioctl;
    427        1.1  hsuenaga 	ifp->if_init = mvxpe_init;
    428        1.1  hsuenaga 	ifp->if_stop = mvxpe_stop;
    429        1.1  hsuenaga 	ifp->if_watchdog = mvxpe_watchdog;
    430        1.1  hsuenaga 
    431        1.1  hsuenaga 	/*
    432        1.1  hsuenaga 	 * We can do IPv4/TCPv4/UDPv4/TCPv6/UDPv6 checksums in hardware.
    433        1.1  hsuenaga 	 */
    434        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_IPv4_Tx;
    435        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_IPv4_Rx;
    436        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Tx;
    437        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Rx;
    438        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_UDPv4_Tx;
    439        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_UDPv4_Rx;
    440        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_TCPv6_Tx;
    441        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_TCPv6_Rx;
    442        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_UDPv6_Tx;
    443        1.1  hsuenaga 	ifp->if_capabilities |= IFCAP_CSUM_UDPv6_Rx;
    444        1.1  hsuenaga 
    445        1.1  hsuenaga 	/*
    446        1.1  hsuenaga 	 * Initialize struct ifnet
    447        1.1  hsuenaga 	 */
    448        1.1  hsuenaga 	IFQ_SET_MAXLEN(&ifp->if_snd, max(MVXPE_TX_RING_CNT - 1, IFQ_MAXLEN));
    449        1.1  hsuenaga 	IFQ_SET_READY(&ifp->if_snd);
    450        1.1  hsuenaga 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), sizeof(ifp->if_xname));
    451        1.1  hsuenaga 
    452        1.1  hsuenaga 	/*
    453       1.15     skrll 	 * Enable DMA engines and Initiazlie Device Registers.
    454        1.1  hsuenaga 	 */
    455        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000000);
    456        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000000);
    457        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PACC, MVXPE_PACC_ACCELERATIONMODE_EDM);
    458        1.1  hsuenaga 	mvxpe_sc_lock(sc); /* XXX */
    459        1.1  hsuenaga 	mvxpe_filter_setup(sc);
    460        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
    461        1.1  hsuenaga 	mvxpe_initreg(ifp);
    462        1.1  hsuenaga 
    463        1.1  hsuenaga 	/*
    464        1.1  hsuenaga 	 * Now MAC is working, setup MII.
    465        1.1  hsuenaga 	 */
    466        1.1  hsuenaga 	if (mii_init == 0) {
    467        1.1  hsuenaga 		/*
    468        1.1  hsuenaga 		 * MII bus is shared by all MACs and all PHYs in SoC.
    469        1.1  hsuenaga 		 * serializing the bus access should be safe.
    470        1.1  hsuenaga 		 */
    471        1.1  hsuenaga 		mutex_init(&mii_mutex, MUTEX_DEFAULT, IPL_NET);
    472        1.1  hsuenaga 		mii_init = 1;
    473        1.1  hsuenaga 	}
    474        1.1  hsuenaga 	sc->sc_mii.mii_ifp = ifp;
    475        1.1  hsuenaga 	sc->sc_mii.mii_readreg = mvxpe_miibus_readreg;
    476        1.1  hsuenaga 	sc->sc_mii.mii_writereg = mvxpe_miibus_writereg;
    477        1.1  hsuenaga 	sc->sc_mii.mii_statchg = mvxpe_miibus_statchg;
    478        1.1  hsuenaga 
    479        1.1  hsuenaga 	sc->sc_ethercom.ec_mii = &sc->sc_mii;
    480        1.1  hsuenaga 	ifmedia_init(&sc->sc_mii.mii_media, 0,
    481        1.1  hsuenaga 	    mvxpe_mediachange, mvxpe_mediastatus);
    482        1.1  hsuenaga 	/*
    483        1.1  hsuenaga 	 * XXX: phy addressing highly depends on Board Design.
    484        1.1  hsuenaga 	 * we assume phyaddress == MAC unit number here,
    485        1.1  hsuenaga 	 * but some boards may not.
    486        1.1  hsuenaga 	 */
    487        1.1  hsuenaga 	mii_attach(self, &sc->sc_mii, 0xffffffff,
    488        1.1  hsuenaga 	    MII_PHY_ANY, sc->sc_dev->dv_unit, 0);
    489        1.1  hsuenaga 	mii = LIST_FIRST(&sc->sc_mii.mii_phys);
    490        1.1  hsuenaga 	if (mii == NULL) {
    491        1.1  hsuenaga 		aprint_error_dev(self, "no PHY found!\n");
    492        1.1  hsuenaga 		ifmedia_add(&sc->sc_mii.mii_media,
    493        1.1  hsuenaga 		    IFM_ETHER|IFM_MANUAL, 0, NULL);
    494        1.1  hsuenaga 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL);
    495        1.1  hsuenaga 	} else {
    496        1.1  hsuenaga 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
    497        1.1  hsuenaga 		phyaddr = MVXPE_PHYADDR_PHYAD(mii->mii_phy);
    498        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PHYADDR, phyaddr);
    499        1.1  hsuenaga 		DPRINTSC(sc, 1, "PHYADDR: %#x\n", MVXPE_READ(sc, MVXPE_PHYADDR));
    500        1.1  hsuenaga 	}
    501        1.1  hsuenaga 
    502        1.1  hsuenaga 	/*
    503        1.1  hsuenaga 	 * Call MI attach routines.
    504        1.1  hsuenaga 	 */
    505        1.1  hsuenaga 	if_attach(ifp);
    506       1.16     ozaki 	if_deferred_start_init(ifp, NULL);
    507        1.1  hsuenaga 
    508        1.1  hsuenaga 	ether_ifattach(ifp, sc->sc_enaddr);
    509        1.1  hsuenaga 	ether_set_ifflags_cb(&sc->sc_ethercom, mvxpe_ifflags_cb);
    510        1.1  hsuenaga 
    511        1.1  hsuenaga 	sysctl_mvxpe_init(sc);
    512        1.1  hsuenaga 	mvxpe_evcnt_attach(sc);
    513        1.1  hsuenaga 	rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
    514        1.1  hsuenaga 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
    515        1.1  hsuenaga 
    516        1.1  hsuenaga 	return;
    517        1.1  hsuenaga 
    518        1.1  hsuenaga fail:
    519        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++)
    520        1.1  hsuenaga 		mvxpe_ring_dealloc_queue(sc, q);
    521        1.1  hsuenaga 	if (sc->sc_sysctl_mib)
    522        1.1  hsuenaga 		kmem_free(sc->sc_sysctl_mib, sc->sc_sysctl_mib_size);
    523        1.1  hsuenaga 
    524        1.1  hsuenaga 	return;
    525        1.1  hsuenaga }
    526        1.1  hsuenaga 
    527        1.1  hsuenaga STATIC int
    528        1.1  hsuenaga mvxpe_evcnt_attach(struct mvxpe_softc *sc)
    529        1.1  hsuenaga {
    530        1.2  hsuenaga #ifdef MVXPE_EVENT_COUNTERS
    531        1.1  hsuenaga 	int q;
    532        1.1  hsuenaga 
    533        1.1  hsuenaga 	/* Master Interrupt Handler */
    534        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_i_rxtxth, EVCNT_TYPE_INTR,
    535        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTxTH Intr.");
    536        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_i_rxtx, EVCNT_TYPE_INTR,
    537        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx Intr.");
    538        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_i_misc, EVCNT_TYPE_INTR,
    539        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC Intr.");
    540        1.1  hsuenaga 
    541        1.1  hsuenaga 	/* RXTXTH Interrupt */
    542        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtxth_txerr, EVCNT_TYPE_INTR,
    543        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTxTH Tx error summary");
    544        1.1  hsuenaga 
    545        1.1  hsuenaga 	/* MISC Interrupt */
    546        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_phystatuschng, EVCNT_TYPE_INTR,
    547        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC phy status changed");
    548        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_linkchange, EVCNT_TYPE_INTR,
    549        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC link status changed");
    550        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_iae, EVCNT_TYPE_INTR,
    551        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC internal address error");
    552        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_rxoverrun, EVCNT_TYPE_INTR,
    553        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC Rx FIFO overrun");
    554        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_rxcrc, EVCNT_TYPE_INTR,
    555        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC Rx CRC error");
    556        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_rxlargepacket, EVCNT_TYPE_INTR,
    557        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC Rx too large frame");
    558        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_txunderrun, EVCNT_TYPE_INTR,
    559        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC Tx FIFO underrun");
    560        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_prbserr, EVCNT_TYPE_INTR,
    561        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC SERDES loopback test err");
    562        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_srse, EVCNT_TYPE_INTR,
    563        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC SERDES sync error");
    564        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_misc_txreq, EVCNT_TYPE_INTR,
    565        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "MISC Tx resource erorr");
    566        1.1  hsuenaga 
    567        1.1  hsuenaga 	/* RxTx Interrupt */
    568        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_rreq, EVCNT_TYPE_INTR,
    569        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx Rx resource erorr");
    570        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_rpq, EVCNT_TYPE_INTR,
    571        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx Rx pakcet");
    572        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_tbrq, EVCNT_TYPE_INTR,
    573        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx Tx complete");
    574        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_rxtxth, EVCNT_TYPE_INTR,
    575        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx RxTxTH summary");
    576        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_txerr, EVCNT_TYPE_INTR,
    577        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx Tx error summary");
    578        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_misc, EVCNT_TYPE_INTR,
    579        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "RxTx MISC summary");
    580        1.1  hsuenaga 
    581        1.1  hsuenaga 	/* Link */
    582        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_link_up, EVCNT_TYPE_MISC,
    583        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "link up");
    584        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_link_down, EVCNT_TYPE_MISC,
    585        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "link down");
    586        1.1  hsuenaga 
    587        1.1  hsuenaga 	/* Rx Descriptor */
    588        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_ce, EVCNT_TYPE_MISC,
    589        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx CRC error counter");
    590        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_or, EVCNT_TYPE_MISC,
    591        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx FIFO overrun counter");
    592        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_mf, EVCNT_TYPE_MISC,
    593        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx too large frame counter");
    594        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_re, EVCNT_TYPE_MISC,
    595        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx resource error counter");
    596        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_scat, EVCNT_TYPE_MISC,
    597        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx unexpected scatter bufs");
    598        1.1  hsuenaga 
    599        1.1  hsuenaga 	/* Tx Descriptor */
    600        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_txd_lc, EVCNT_TYPE_MISC,
    601        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx late collision counter");
    602        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_txd_rl, EVCNT_TYPE_MISC,
    603        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx excess. collision counter");
    604        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_txd_ur, EVCNT_TYPE_MISC,
    605        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx FIFO underrun counter");
    606        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_txd_oth, EVCNT_TYPE_MISC,
    607        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx unkonwn erorr counter");
    608        1.1  hsuenaga 
    609        1.1  hsuenaga 	/* Status Registers */
    610        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_reg_pdfc, EVCNT_TYPE_MISC,
    611        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx discard counter");
    612        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_reg_pofc, EVCNT_TYPE_MISC,
    613        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Rx overrun counter");
    614        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_reg_txbadfcs, EVCNT_TYPE_MISC,
    615        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx bad FCS counter");
    616        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_reg_txdropped, EVCNT_TYPE_MISC,
    617        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx dorpped counter");
    618        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_reg_lpic, EVCNT_TYPE_MISC,
    619        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "LP_IDLE counter");
    620        1.1  hsuenaga 
    621        1.1  hsuenaga 	/* Device Driver Errors */
    622        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_drv_wdogsoft, EVCNT_TYPE_MISC,
    623        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "watchdog timer expired");
    624        1.1  hsuenaga 	evcnt_attach_dynamic(&sc->sc_ev.ev_drv_txerr, EVCNT_TYPE_MISC,
    625        1.1  hsuenaga 	    NULL, device_xname(sc->sc_dev), "Tx descriptor alloc failed");
    626        1.1  hsuenaga #define MVXPE_QUEUE_DESC(q) "Rx success in queue " # q
    627        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
    628        1.1  hsuenaga 		static const char *rxq_desc[] = {
    629        1.1  hsuenaga 			MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1),
    630        1.1  hsuenaga 			MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3),
    631        1.1  hsuenaga 			MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5),
    632        1.1  hsuenaga 			MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7),
    633        1.1  hsuenaga 		};
    634        1.1  hsuenaga 		evcnt_attach_dynamic(&sc->sc_ev.ev_drv_rxq[q], EVCNT_TYPE_MISC,
    635        1.1  hsuenaga 		    NULL, device_xname(sc->sc_dev), rxq_desc[q]);
    636        1.1  hsuenaga 	}
    637        1.1  hsuenaga #undef MVXPE_QUEUE_DESC
    638        1.1  hsuenaga #define MVXPE_QUEUE_DESC(q) "Tx success in queue " # q
    639        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
    640        1.1  hsuenaga 		static const char *txq_desc[] = {
    641        1.1  hsuenaga 			MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1),
    642        1.1  hsuenaga 			MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3),
    643        1.1  hsuenaga 			MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5),
    644        1.1  hsuenaga 			MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7),
    645        1.1  hsuenaga 		};
    646        1.1  hsuenaga 		evcnt_attach_dynamic(&sc->sc_ev.ev_drv_txq[q], EVCNT_TYPE_MISC,
    647        1.1  hsuenaga 		    NULL, device_xname(sc->sc_dev), txq_desc[q]);
    648        1.1  hsuenaga 	}
    649        1.1  hsuenaga #undef MVXPE_QUEUE_DESC
    650        1.1  hsuenaga #define MVXPE_QUEUE_DESC(q) "Rx error in queue " # q
    651        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
    652        1.1  hsuenaga 		static const char *rxqe_desc[] = {
    653        1.1  hsuenaga 			MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1),
    654        1.1  hsuenaga 			MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3),
    655        1.1  hsuenaga 			MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5),
    656        1.1  hsuenaga 			MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7),
    657        1.1  hsuenaga 		};
    658        1.1  hsuenaga 		evcnt_attach_dynamic(&sc->sc_ev.ev_drv_rxqe[q], EVCNT_TYPE_MISC,
    659        1.1  hsuenaga 		    NULL, device_xname(sc->sc_dev), rxqe_desc[q]);
    660        1.1  hsuenaga 	}
    661        1.1  hsuenaga #undef MVXPE_QUEUE_DESC
    662        1.1  hsuenaga #define MVXPE_QUEUE_DESC(q) "Tx error in queue " # q
    663        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
    664        1.1  hsuenaga 		static const char *txqe_desc[] = {
    665        1.1  hsuenaga 			MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1),
    666        1.1  hsuenaga 			MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3),
    667        1.1  hsuenaga 			MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5),
    668        1.1  hsuenaga 			MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7),
    669        1.1  hsuenaga 		};
    670        1.1  hsuenaga 		evcnt_attach_dynamic(&sc->sc_ev.ev_drv_txqe[q], EVCNT_TYPE_MISC,
    671        1.1  hsuenaga 		    NULL, device_xname(sc->sc_dev), txqe_desc[q]);
    672        1.1  hsuenaga 	}
    673        1.1  hsuenaga #undef MVXPE_QUEUE_DESC
    674        1.1  hsuenaga 
    675        1.1  hsuenaga #endif /* MVXPE_EVENT_COUNTERS */
    676        1.1  hsuenaga 	return 0;
    677        1.1  hsuenaga }
    678        1.1  hsuenaga 
    679        1.1  hsuenaga STATIC void
    680        1.1  hsuenaga mvxpe_sc_lock(struct mvxpe_softc *sc)
    681        1.1  hsuenaga {
    682        1.1  hsuenaga 	mutex_enter(&sc->sc_mtx);
    683        1.1  hsuenaga }
    684        1.1  hsuenaga 
    685        1.1  hsuenaga STATIC void
    686        1.1  hsuenaga mvxpe_sc_unlock(struct mvxpe_softc *sc)
    687        1.1  hsuenaga {
    688        1.1  hsuenaga 	mutex_exit(&sc->sc_mtx);
    689        1.1  hsuenaga }
    690        1.1  hsuenaga 
    691        1.1  hsuenaga /*
    692        1.1  hsuenaga  * MII
    693        1.1  hsuenaga  */
    694        1.1  hsuenaga STATIC int
    695        1.1  hsuenaga mvxpe_miibus_readreg(device_t dev, int phy, int reg)
    696        1.1  hsuenaga {
    697        1.1  hsuenaga 	struct mvxpe_softc *sc = device_private(dev);
    698        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    699        1.1  hsuenaga 	uint32_t smi, val;
    700        1.1  hsuenaga 	int i;
    701        1.1  hsuenaga 
    702        1.1  hsuenaga 	mutex_enter(&mii_mutex);
    703        1.1  hsuenaga 
    704        1.1  hsuenaga 	for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) {
    705        1.1  hsuenaga 		DELAY(1);
    706        1.1  hsuenaga 		if (!(MVXPE_READ(sc, MVXPE_SMI) & MVXPE_SMI_BUSY))
    707        1.1  hsuenaga 			break;
    708        1.1  hsuenaga 	}
    709        1.1  hsuenaga 	if (i == MVXPE_PHY_TIMEOUT) {
    710        1.1  hsuenaga 		aprint_error_ifnet(ifp, "SMI busy timeout\n");
    711        1.1  hsuenaga 		mutex_exit(&mii_mutex);
    712        1.1  hsuenaga 		return -1;
    713        1.1  hsuenaga 	}
    714        1.1  hsuenaga 
    715        1.1  hsuenaga 	smi =
    716        1.1  hsuenaga 	    MVXPE_SMI_PHYAD(phy) | MVXPE_SMI_REGAD(reg) | MVXPE_SMI_OPCODE_READ;
    717        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_SMI, smi);
    718        1.1  hsuenaga 
    719        1.1  hsuenaga 	for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) {
    720        1.1  hsuenaga 		DELAY(1);
    721        1.1  hsuenaga 		smi = MVXPE_READ(sc, MVXPE_SMI);
    722        1.1  hsuenaga 		if (smi & MVXPE_SMI_READVALID)
    723        1.1  hsuenaga 			break;
    724        1.1  hsuenaga 	}
    725        1.1  hsuenaga 
    726        1.1  hsuenaga 	mutex_exit(&mii_mutex);
    727        1.1  hsuenaga 
    728        1.1  hsuenaga 	DPRINTDEV(dev, 9, "i=%d, timeout=%d\n", i, MVXPE_PHY_TIMEOUT);
    729        1.1  hsuenaga 
    730        1.1  hsuenaga 	val = smi & MVXPE_SMI_DATA_MASK;
    731        1.1  hsuenaga 
    732        1.1  hsuenaga 	DPRINTDEV(dev, 9, "phy=%d, reg=%#x, val=%#x\n", phy, reg, val);
    733        1.1  hsuenaga 
    734        1.1  hsuenaga 	return val;
    735        1.1  hsuenaga }
    736        1.1  hsuenaga 
    737        1.1  hsuenaga STATIC void
    738        1.1  hsuenaga mvxpe_miibus_writereg(device_t dev, int phy, int reg, int val)
    739        1.1  hsuenaga {
    740        1.1  hsuenaga 	struct mvxpe_softc *sc = device_private(dev);
    741        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    742        1.1  hsuenaga 	uint32_t smi;
    743        1.1  hsuenaga 	int i;
    744        1.1  hsuenaga 
    745        1.1  hsuenaga 	DPRINTDEV(dev, 9, "phy=%d reg=%#x val=%#x\n", phy, reg, val);
    746        1.1  hsuenaga 
    747        1.1  hsuenaga 	mutex_enter(&mii_mutex);
    748        1.1  hsuenaga 
    749        1.1  hsuenaga 	for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) {
    750        1.1  hsuenaga 		DELAY(1);
    751        1.1  hsuenaga 		if (!(MVXPE_READ(sc, MVXPE_SMI) & MVXPE_SMI_BUSY))
    752        1.1  hsuenaga 			break;
    753        1.1  hsuenaga 	}
    754        1.1  hsuenaga 	if (i == MVXPE_PHY_TIMEOUT) {
    755        1.1  hsuenaga 		aprint_error_ifnet(ifp, "SMI busy timeout\n");
    756        1.1  hsuenaga 		mutex_exit(&mii_mutex);
    757        1.1  hsuenaga 		return;
    758        1.1  hsuenaga 	}
    759        1.1  hsuenaga 
    760        1.1  hsuenaga 	smi = MVXPE_SMI_PHYAD(phy) | MVXPE_SMI_REGAD(reg) |
    761        1.1  hsuenaga 	    MVXPE_SMI_OPCODE_WRITE | (val & MVXPE_SMI_DATA_MASK);
    762        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_SMI, smi);
    763        1.1  hsuenaga 
    764        1.1  hsuenaga 	for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) {
    765        1.1  hsuenaga 		DELAY(1);
    766        1.1  hsuenaga 		if (!(MVXPE_READ(sc, MVXPE_SMI) & MVXPE_SMI_BUSY))
    767        1.1  hsuenaga 			break;
    768        1.1  hsuenaga 	}
    769        1.1  hsuenaga 
    770        1.1  hsuenaga 	mutex_exit(&mii_mutex);
    771        1.1  hsuenaga 
    772        1.1  hsuenaga 	if (i == MVXPE_PHY_TIMEOUT)
    773        1.1  hsuenaga 		aprint_error_ifnet(ifp, "phy write timed out\n");
    774        1.1  hsuenaga }
    775        1.1  hsuenaga 
    776        1.1  hsuenaga STATIC void
    777        1.1  hsuenaga mvxpe_miibus_statchg(struct ifnet *ifp)
    778        1.1  hsuenaga {
    779        1.1  hsuenaga 
    780        1.1  hsuenaga 	/* nothing to do */
    781        1.1  hsuenaga }
    782        1.1  hsuenaga 
    783        1.1  hsuenaga /*
    784        1.1  hsuenaga  * Address Decoding Window
    785        1.1  hsuenaga  */
    786        1.1  hsuenaga STATIC void
    787        1.1  hsuenaga mvxpe_wininit(struct mvxpe_softc *sc, enum marvell_tags *tags)
    788        1.1  hsuenaga {
    789        1.1  hsuenaga 	device_t pdev = device_parent(sc->sc_dev);
    790        1.1  hsuenaga 	uint64_t base;
    791        1.1  hsuenaga 	uint32_t en, ac, size;
    792        1.1  hsuenaga 	int window, target, attr, rv, i;
    793        1.1  hsuenaga 
    794        1.1  hsuenaga 	/* First disable all address decode windows */
    795        1.1  hsuenaga 	en = MVXPE_BARE_EN_MASK;
    796        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_BARE, en);
    797        1.1  hsuenaga 
    798        1.1  hsuenaga 	ac = 0;
    799        1.1  hsuenaga 	for (window = 0, i = 0;
    800        1.1  hsuenaga 	    tags[i] != MARVELL_TAG_UNDEFINED && window < MVXPE_NWINDOW; i++) {
    801        1.1  hsuenaga 		rv = marvell_winparams_by_tag(pdev, tags[i],
    802        1.1  hsuenaga 		    &target, &attr, &base, &size);
    803        1.1  hsuenaga 		if (rv != 0 || size == 0)
    804        1.1  hsuenaga 			continue;
    805        1.1  hsuenaga 
    806        1.1  hsuenaga 		if (base > 0xffffffffULL) {
    807        1.1  hsuenaga 			if (window >= MVXPE_NREMAP) {
    808        1.1  hsuenaga 				aprint_error_dev(sc->sc_dev,
    809        1.1  hsuenaga 				    "can't remap window %d\n", window);
    810        1.1  hsuenaga 				continue;
    811        1.1  hsuenaga 			}
    812        1.1  hsuenaga 			MVXPE_WRITE(sc, MVXPE_HA(window),
    813        1.1  hsuenaga 			    (base >> 32) & 0xffffffff);
    814        1.1  hsuenaga 		}
    815        1.1  hsuenaga 
    816        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_BASEADDR(window),
    817        1.1  hsuenaga 		    MVXPE_BASEADDR_TARGET(target)	|
    818        1.1  hsuenaga 		    MVXPE_BASEADDR_ATTR(attr)		|
    819        1.1  hsuenaga 		    MVXPE_BASEADDR_BASE(base));
    820        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_S(window), MVXPE_S_SIZE(size));
    821        1.1  hsuenaga 
    822        1.1  hsuenaga 		DPRINTSC(sc, 1, "Window %d Base 0x%016llx: Size 0x%08x\n",
    823        1.1  hsuenaga 				window, base, size);
    824        1.1  hsuenaga 
    825        1.1  hsuenaga 		en &= ~(1 << window);
    826        1.1  hsuenaga 		/* set full access (r/w) */
    827        1.1  hsuenaga 		ac |= MVXPE_EPAP_EPAR(window, MVXPE_EPAP_AC_FA);
    828        1.1  hsuenaga 		window++;
    829        1.1  hsuenaga 	}
    830        1.1  hsuenaga 	/* allow to access decode window */
    831        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_EPAP, ac);
    832        1.1  hsuenaga 
    833        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_BARE, en);
    834        1.1  hsuenaga }
    835        1.1  hsuenaga 
    836        1.1  hsuenaga /*
    837        1.1  hsuenaga  * Device Register Initialization
    838        1.1  hsuenaga  *  reset device registers to device driver default value.
    839        1.1  hsuenaga  *  the device is not enabled here.
    840        1.1  hsuenaga  */
    841        1.1  hsuenaga STATIC int
    842        1.1  hsuenaga mvxpe_initreg(struct ifnet *ifp)
    843        1.1  hsuenaga {
    844        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
    845        1.1  hsuenaga 	int serdes = 0;
    846        1.1  hsuenaga 	uint32_t reg;
    847        1.1  hsuenaga 	int q, i;
    848        1.1  hsuenaga 
    849        1.1  hsuenaga 	DPRINTIFNET(ifp, 1, "initializing device register\n");
    850        1.1  hsuenaga 
    851        1.1  hsuenaga 	/* Init TX/RX Queue Registers */
    852        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
    853        1.1  hsuenaga 		mvxpe_rx_lockq(sc, q);
    854        1.1  hsuenaga 		if (mvxpe_rx_queue_init(ifp, q) != 0) {
    855        1.1  hsuenaga 			aprint_error_ifnet(ifp,
    856        1.1  hsuenaga 			    "initialization failed: cannot initialize queue\n");
    857        1.1  hsuenaga 			mvxpe_rx_unlockq(sc, q);
    858        1.1  hsuenaga 			return ENOBUFS;
    859        1.1  hsuenaga 		}
    860        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, q);
    861        1.1  hsuenaga 
    862        1.1  hsuenaga 		mvxpe_tx_lockq(sc, q);
    863        1.1  hsuenaga 		if (mvxpe_tx_queue_init(ifp, q) != 0) {
    864        1.1  hsuenaga 			aprint_error_ifnet(ifp,
    865        1.1  hsuenaga 			    "initialization failed: cannot initialize queue\n");
    866        1.1  hsuenaga 			mvxpe_tx_unlockq(sc, q);
    867        1.1  hsuenaga 			return ENOBUFS;
    868        1.1  hsuenaga 		}
    869        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, q);
    870        1.1  hsuenaga 	}
    871        1.1  hsuenaga 
    872        1.1  hsuenaga 	/* Tx MTU Limit */
    873        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_TXMTU, MVXPE_MTU);
    874        1.1  hsuenaga 
    875        1.1  hsuenaga 	/* Check SGMII or SERDES(asume IPL/U-BOOT initialize this) */
    876        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_PMACC0);
    877        1.1  hsuenaga 	if ((reg & MVXPE_PMACC0_PORTTYPE) != 0)
    878        1.1  hsuenaga 		serdes = 1;
    879        1.1  hsuenaga 
    880        1.1  hsuenaga 	/* Ethernet Unit Control */
    881        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_EUC);
    882        1.1  hsuenaga 	reg |= MVXPE_EUC_POLLING;
    883        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_EUC, reg);
    884        1.1  hsuenaga 
    885        1.1  hsuenaga 	/* Auto Negotiation */
    886        1.1  hsuenaga 	reg  = MVXPE_PANC_MUSTSET;	/* must write 0x1 */
    887        1.1  hsuenaga 	reg |= MVXPE_PANC_FORCELINKFAIL;/* force link state down */
    888        1.1  hsuenaga 	reg |= MVXPE_PANC_ANSPEEDEN;	/* interface speed negotiation */
    889        1.1  hsuenaga 	reg |= MVXPE_PANC_ANDUPLEXEN;	/* negotiate duplex mode */
    890        1.1  hsuenaga 	if (serdes) {
    891        1.1  hsuenaga 		reg |= MVXPE_PANC_INBANDANEN; /* In Band negotiation */
    892        1.1  hsuenaga 		reg |= MVXPE_PANC_INBANDANBYPASSEN; /* bypass negotiation */
    893        1.1  hsuenaga 		reg |= MVXPE_PANC_SETFULLDX; /* set full-duplex on failure */
    894        1.1  hsuenaga 	}
    895        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PANC, reg);
    896        1.1  hsuenaga 
    897        1.1  hsuenaga 	/* EEE: Low Power Idle */
    898        1.1  hsuenaga 	reg  = MVXPE_LPIC0_LILIMIT(MVXPE_LPI_LI);
    899        1.1  hsuenaga 	reg |= MVXPE_LPIC0_TSLIMIT(MVXPE_LPI_TS);
    900        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_LPIC0, reg);
    901        1.1  hsuenaga 
    902        1.1  hsuenaga 	reg  = MVXPE_LPIC1_TWLIMIT(MVXPE_LPI_TS);
    903        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_LPIC1, reg);
    904        1.1  hsuenaga 
    905        1.1  hsuenaga 	reg = MVXPE_LPIC2_MUSTSET;
    906        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_LPIC2, reg);
    907        1.1  hsuenaga 
    908        1.1  hsuenaga 	/* Port MAC Control set 0 */
    909        1.1  hsuenaga 	reg  = MVXPE_PMACC0_MUSTSET;	/* must write 0x1 */
    910        1.1  hsuenaga 	reg &= ~MVXPE_PMACC0_PORTEN;	/* port is still disabled */
    911        1.1  hsuenaga 	reg |= MVXPE_PMACC0_FRAMESIZELIMIT(MVXPE_MRU);
    912        1.1  hsuenaga 	if (serdes)
    913        1.1  hsuenaga 		reg |= MVXPE_PMACC0_PORTTYPE;
    914        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMACC0, reg);
    915        1.1  hsuenaga 
    916        1.1  hsuenaga 	/* Port MAC Control set 1 is only used for loop-back test */
    917        1.1  hsuenaga 
    918        1.1  hsuenaga 	/* Port MAC Control set 2 */
    919        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_PMACC2);
    920        1.1  hsuenaga 	reg &= (MVXPE_PMACC2_PCSEN | MVXPE_PMACC2_RGMIIEN);
    921        1.1  hsuenaga 	reg |= MVXPE_PMACC2_MUSTSET;
    922        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMACC2, reg);
    923        1.1  hsuenaga 
    924        1.1  hsuenaga 	/* Port MAC Control set 3 is used for IPG tune */
    925        1.1  hsuenaga 
    926        1.1  hsuenaga 	/* Port MAC Control set 4 is not used */
    927        1.1  hsuenaga 
    928       1.12    hikaru 	/* Port Configuration */
    929       1.12    hikaru 	/* Use queue 0 only */
    930       1.12    hikaru 	reg = MVXPE_READ(sc, MVXPE_PXC);
    931       1.12    hikaru 	reg &= ~(MVXPE_PXC_RXQ_MASK | MVXPE_PXC_RXQARP_MASK |
    932       1.12    hikaru 	    MVXPE_PXC_TCPQ_MASK | MVXPE_PXC_UDPQ_MASK | MVXPE_PXC_BPDUQ_MASK);
    933       1.12    hikaru 	MVXPE_WRITE(sc, MVXPE_PXC, reg);
    934       1.12    hikaru 
    935        1.1  hsuenaga 	/* Port Configuration Extended: enable Tx CRC generation */
    936        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_PXCX);
    937        1.1  hsuenaga 	reg &= ~MVXPE_PXCX_TXCRCDIS;
    938        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PXCX, reg);
    939        1.1  hsuenaga 
    940        1.1  hsuenaga 	/* clear MIB counter registers(clear by read) */
    941        1.1  hsuenaga 	for (i = 0; i < __arraycount(mvxpe_mib_list); i++)
    942        1.1  hsuenaga 		MVXPE_READ_MIB(sc, (mvxpe_mib_list[i].regnum));
    943        1.1  hsuenaga 
    944        1.1  hsuenaga 	/* Set SDC register except IPGINT bits */
    945        1.1  hsuenaga 	reg  = MVXPE_SDC_RXBSZ_16_64BITWORDS;
    946        1.1  hsuenaga 	reg |= MVXPE_SDC_TXBSZ_16_64BITWORDS;
    947        1.1  hsuenaga 	reg |= MVXPE_SDC_BLMR;
    948        1.1  hsuenaga 	reg |= MVXPE_SDC_BLMT;
    949        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_SDC, reg);
    950        1.1  hsuenaga 
    951        1.1  hsuenaga 	return 0;
    952        1.1  hsuenaga }
    953        1.1  hsuenaga 
    954        1.1  hsuenaga /*
    955        1.1  hsuenaga  * Descriptor Ring Controls for each of queues
    956        1.1  hsuenaga  */
    957        1.1  hsuenaga STATIC void *
    958        1.1  hsuenaga mvxpe_dma_memalloc(struct mvxpe_softc *sc, bus_dmamap_t *map, size_t size)
    959        1.1  hsuenaga {
    960        1.1  hsuenaga 	bus_dma_segment_t segs;
    961        1.1  hsuenaga 	void *kva = NULL;
    962        1.1  hsuenaga 	int nsegs;
    963        1.1  hsuenaga 
    964        1.1  hsuenaga 	/*
    965        1.1  hsuenaga 	 * Allocate the descriptor queues.
    966        1.1  hsuenaga 	 * struct mvxpe_ring_data contians array of descriptor per queue.
    967        1.1  hsuenaga 	 */
    968        1.1  hsuenaga 	if (bus_dmamem_alloc(sc->sc_dmat,
    969        1.1  hsuenaga 	    size, PAGE_SIZE, 0, &segs, 1, &nsegs, BUS_DMA_NOWAIT)) {
    970        1.1  hsuenaga 		aprint_error_dev(sc->sc_dev,
    971        1.1  hsuenaga 		    "can't alloc device memory (%zu bytes)\n", size);
    972        1.1  hsuenaga 		return NULL;
    973        1.1  hsuenaga 	}
    974        1.1  hsuenaga 	if (bus_dmamem_map(sc->sc_dmat,
    975        1.1  hsuenaga 	    &segs, nsegs, size, &kva, BUS_DMA_NOWAIT)) {
    976        1.1  hsuenaga 		aprint_error_dev(sc->sc_dev,
    977        1.1  hsuenaga 		    "can't map dma buffers (%zu bytes)\n", size);
    978        1.1  hsuenaga 		goto fail1;
    979        1.1  hsuenaga 	}
    980        1.1  hsuenaga 
    981        1.1  hsuenaga 	if (bus_dmamap_create(sc->sc_dmat,
    982        1.1  hsuenaga 	    size, 1, size, 0, BUS_DMA_NOWAIT, map)) {
    983        1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "can't create dma map\n");
    984        1.1  hsuenaga 		goto fail2;
    985        1.1  hsuenaga 	}
    986        1.1  hsuenaga 	if (bus_dmamap_load(sc->sc_dmat,
    987        1.1  hsuenaga 	    *map, kva, size, NULL, BUS_DMA_NOWAIT)) {
    988        1.1  hsuenaga 		aprint_error_dev(sc->sc_dev, "can't load dma map\n");
    989        1.1  hsuenaga 		goto fail3;
    990        1.1  hsuenaga 	}
    991        1.1  hsuenaga 	memset(kva, 0, size);
    992        1.1  hsuenaga 	return kva;
    993        1.1  hsuenaga 
    994        1.1  hsuenaga fail3:
    995        1.1  hsuenaga 	bus_dmamap_destroy(sc->sc_dmat, *map);
    996        1.1  hsuenaga 	memset(map, 0, sizeof(*map));
    997        1.1  hsuenaga fail2:
    998        1.1  hsuenaga 	bus_dmamem_unmap(sc->sc_dmat, kva, size);
    999        1.1  hsuenaga fail1:
   1000        1.1  hsuenaga 	bus_dmamem_free(sc->sc_dmat, &segs, nsegs);
   1001        1.1  hsuenaga 	return NULL;
   1002        1.1  hsuenaga }
   1003        1.1  hsuenaga 
   1004        1.1  hsuenaga STATIC int
   1005        1.1  hsuenaga mvxpe_ring_alloc_queue(struct mvxpe_softc *sc, int q)
   1006        1.1  hsuenaga {
   1007        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   1008        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1009        1.1  hsuenaga 
   1010        1.1  hsuenaga 	/*
   1011        1.1  hsuenaga 	 * MVXPE_RX_RING_CNT and MVXPE_TX_RING_CNT is a hard limit of
   1012        1.1  hsuenaga 	 * queue length. real queue length is limited by
   1013        1.1  hsuenaga 	 * sc->sc_rx_ring[q].rx_queue_len and sc->sc_tx_ring[q].tx_queue_len.
   1014        1.1  hsuenaga 	 *
   1015        1.1  hsuenaga 	 * because descriptor ring reallocation needs reprogramming of
   1016        1.1  hsuenaga 	 * DMA registers, we allocate enough descriptor for hard limit
   1017        1.1  hsuenaga 	 * of queue length.
   1018        1.1  hsuenaga 	 */
   1019        1.1  hsuenaga 	rx->rx_descriptors =
   1020        1.1  hsuenaga 	    mvxpe_dma_memalloc(sc, &rx->rx_descriptors_map,
   1021        1.1  hsuenaga 		(sizeof(struct mvxpe_rx_desc) * MVXPE_RX_RING_CNT));
   1022        1.1  hsuenaga 	if (rx->rx_descriptors == NULL)
   1023        1.1  hsuenaga 		goto fail;
   1024        1.1  hsuenaga 
   1025        1.1  hsuenaga 	tx->tx_descriptors =
   1026        1.1  hsuenaga 	    mvxpe_dma_memalloc(sc, &tx->tx_descriptors_map,
   1027        1.1  hsuenaga 		(sizeof(struct mvxpe_tx_desc) * MVXPE_TX_RING_CNT));
   1028        1.1  hsuenaga 	if (tx->tx_descriptors == NULL)
   1029        1.1  hsuenaga 		goto fail;
   1030        1.1  hsuenaga 
   1031        1.1  hsuenaga 	return 0;
   1032        1.1  hsuenaga fail:
   1033        1.1  hsuenaga 	mvxpe_ring_dealloc_queue(sc, q);
   1034        1.1  hsuenaga 	aprint_error_dev(sc->sc_dev, "DMA Ring buffer allocation failure.\n");
   1035        1.1  hsuenaga 	return ENOMEM;
   1036        1.1  hsuenaga }
   1037        1.1  hsuenaga 
   1038        1.1  hsuenaga STATIC void
   1039        1.1  hsuenaga mvxpe_ring_dealloc_queue(struct mvxpe_softc *sc, int q)
   1040        1.1  hsuenaga {
   1041        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   1042        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1043        1.1  hsuenaga 	bus_dma_segment_t *segs;
   1044        1.1  hsuenaga 	bus_size_t size;
   1045        1.1  hsuenaga 	void *kva;
   1046        1.1  hsuenaga 	int nsegs;
   1047        1.1  hsuenaga 
   1048        1.1  hsuenaga 	/* Rx */
   1049        1.1  hsuenaga 	kva = (void *)MVXPE_RX_RING_MEM_VA(sc, q);
   1050        1.1  hsuenaga 	if (kva) {
   1051        1.1  hsuenaga 		segs = MVXPE_RX_RING_MEM_MAP(sc, q)->dm_segs;
   1052        1.1  hsuenaga 		nsegs = MVXPE_RX_RING_MEM_MAP(sc, q)->dm_nsegs;
   1053        1.1  hsuenaga 		size = MVXPE_RX_RING_MEM_MAP(sc, q)->dm_mapsize;
   1054        1.1  hsuenaga 
   1055        1.1  hsuenaga 		bus_dmamap_unload(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q));
   1056        1.1  hsuenaga 		bus_dmamap_destroy(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q));
   1057        1.1  hsuenaga 		bus_dmamem_unmap(sc->sc_dmat, kva, size);
   1058        1.1  hsuenaga 		bus_dmamem_free(sc->sc_dmat, segs, nsegs);
   1059        1.1  hsuenaga 	}
   1060        1.1  hsuenaga 
   1061        1.1  hsuenaga 	/* Tx */
   1062        1.1  hsuenaga 	kva = (void *)MVXPE_TX_RING_MEM_VA(sc, q);
   1063        1.1  hsuenaga 	if (kva) {
   1064        1.1  hsuenaga 		segs = MVXPE_TX_RING_MEM_MAP(sc, q)->dm_segs;
   1065        1.1  hsuenaga 		nsegs = MVXPE_TX_RING_MEM_MAP(sc, q)->dm_nsegs;
   1066        1.1  hsuenaga 		size = MVXPE_TX_RING_MEM_MAP(sc, q)->dm_mapsize;
   1067        1.1  hsuenaga 
   1068        1.1  hsuenaga 		bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q));
   1069        1.1  hsuenaga 		bus_dmamap_destroy(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q));
   1070        1.1  hsuenaga 		bus_dmamem_unmap(sc->sc_dmat, kva, size);
   1071        1.1  hsuenaga 		bus_dmamem_free(sc->sc_dmat, segs, nsegs);
   1072        1.1  hsuenaga 	}
   1073        1.1  hsuenaga 
   1074        1.1  hsuenaga 	/* Clear doungling pointers all */
   1075        1.1  hsuenaga 	memset(rx, 0, sizeof(*rx));
   1076        1.1  hsuenaga 	memset(tx, 0, sizeof(*tx));
   1077        1.1  hsuenaga }
   1078        1.1  hsuenaga 
   1079        1.1  hsuenaga STATIC void
   1080        1.1  hsuenaga mvxpe_ring_init_queue(struct mvxpe_softc *sc, int q)
   1081        1.1  hsuenaga {
   1082        1.1  hsuenaga 	struct mvxpe_rx_desc *rxd = MVXPE_RX_RING_MEM_VA(sc, q);
   1083        1.1  hsuenaga 	struct mvxpe_tx_desc *txd = MVXPE_TX_RING_MEM_VA(sc, q);
   1084        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   1085        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1086        1.1  hsuenaga 	static const int rx_default_queue_len[] = {
   1087        1.1  hsuenaga 		MVXPE_RX_QUEUE_LIMIT_0, MVXPE_RX_QUEUE_LIMIT_1,
   1088        1.1  hsuenaga 		MVXPE_RX_QUEUE_LIMIT_2, MVXPE_RX_QUEUE_LIMIT_3,
   1089        1.1  hsuenaga 		MVXPE_RX_QUEUE_LIMIT_4, MVXPE_RX_QUEUE_LIMIT_5,
   1090        1.1  hsuenaga 		MVXPE_RX_QUEUE_LIMIT_6, MVXPE_RX_QUEUE_LIMIT_7,
   1091        1.1  hsuenaga 	};
   1092        1.1  hsuenaga 	static const int tx_default_queue_len[] = {
   1093        1.1  hsuenaga 		MVXPE_TX_QUEUE_LIMIT_0, MVXPE_TX_QUEUE_LIMIT_1,
   1094        1.1  hsuenaga 		MVXPE_TX_QUEUE_LIMIT_2, MVXPE_TX_QUEUE_LIMIT_3,
   1095        1.1  hsuenaga 		MVXPE_TX_QUEUE_LIMIT_4, MVXPE_TX_QUEUE_LIMIT_5,
   1096        1.1  hsuenaga 		MVXPE_TX_QUEUE_LIMIT_6, MVXPE_TX_QUEUE_LIMIT_7,
   1097        1.1  hsuenaga 	};
   1098        1.1  hsuenaga 	extern uint32_t mvTclk;
   1099        1.1  hsuenaga 	int i;
   1100        1.1  hsuenaga 
   1101        1.1  hsuenaga 	/* Rx handle */
   1102        1.1  hsuenaga 	for (i = 0; i < MVXPE_RX_RING_CNT; i++) {
   1103        1.1  hsuenaga 		MVXPE_RX_DESC(sc, q, i) = &rxd[i];
   1104        1.1  hsuenaga 		MVXPE_RX_DESC_OFF(sc, q, i) = sizeof(struct mvxpe_rx_desc) * i;
   1105        1.1  hsuenaga 		MVXPE_RX_PKTBUF(sc, q, i) = NULL;
   1106        1.1  hsuenaga 	}
   1107        1.1  hsuenaga 	mutex_init(&rx->rx_ring_mtx, MUTEX_DEFAULT, IPL_NET);
   1108        1.1  hsuenaga 	rx->rx_dma = rx->rx_cpu = 0;
   1109        1.1  hsuenaga 	rx->rx_queue_len = rx_default_queue_len[q];
   1110        1.1  hsuenaga 	if (rx->rx_queue_len > MVXPE_RX_RING_CNT)
   1111        1.1  hsuenaga 		rx->rx_queue_len = MVXPE_RX_RING_CNT;
   1112        1.2  hsuenaga 	rx->rx_queue_th_received = rx->rx_queue_len / MVXPE_RXTH_RATIO;
   1113        1.2  hsuenaga 	rx->rx_queue_th_free = rx->rx_queue_len / MVXPE_RXTH_REFILL_RATIO;
   1114        1.1  hsuenaga 	rx->rx_queue_th_time = (mvTclk / 1000) / 2; /* 0.5 [ms] */
   1115        1.1  hsuenaga 
   1116        1.1  hsuenaga 	/* Tx handle */
   1117        1.1  hsuenaga 	for (i = 0; i < MVXPE_TX_RING_CNT; i++) {
   1118        1.1  hsuenaga 		MVXPE_TX_DESC(sc, q, i) = &txd[i];
   1119        1.1  hsuenaga 		MVXPE_TX_DESC_OFF(sc, q, i) = sizeof(struct mvxpe_tx_desc) * i;
   1120        1.1  hsuenaga 		MVXPE_TX_MBUF(sc, q, i) = NULL;
   1121        1.1  hsuenaga 		/* Tx handle needs DMA map for busdma_load_mbuf() */
   1122        1.2  hsuenaga 		if (bus_dmamap_create(sc->sc_dmat,
   1123        1.2  hsuenaga 		    mvxpbm_chunk_size(sc->sc_bm),
   1124        1.2  hsuenaga 		    MVXPE_TX_SEGLIMIT, mvxpbm_chunk_size(sc->sc_bm), 0,
   1125        1.1  hsuenaga 		    BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
   1126        1.1  hsuenaga 		    &MVXPE_TX_MAP(sc, q, i))) {
   1127        1.1  hsuenaga 			aprint_error_dev(sc->sc_dev,
   1128        1.1  hsuenaga 			    "can't create dma map (tx ring %d)\n", i);
   1129        1.1  hsuenaga 		}
   1130        1.1  hsuenaga 	}
   1131        1.1  hsuenaga 	mutex_init(&tx->tx_ring_mtx, MUTEX_DEFAULT, IPL_NET);
   1132        1.1  hsuenaga 	tx->tx_dma = tx->tx_cpu = 0;
   1133        1.1  hsuenaga 	tx->tx_queue_len = tx_default_queue_len[q];
   1134        1.1  hsuenaga 	if (tx->tx_queue_len > MVXPE_TX_RING_CNT)
   1135        1.1  hsuenaga 		tx->tx_queue_len = MVXPE_TX_RING_CNT;
   1136        1.2  hsuenaga        	tx->tx_used = 0;
   1137        1.2  hsuenaga 	tx->tx_queue_th_free = tx->tx_queue_len / MVXPE_TXTH_RATIO;
   1138        1.1  hsuenaga }
   1139        1.1  hsuenaga 
   1140        1.1  hsuenaga STATIC void
   1141        1.1  hsuenaga mvxpe_ring_flush_queue(struct mvxpe_softc *sc, int q)
   1142        1.1  hsuenaga {
   1143        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   1144        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1145       1.14  kiyohara 	struct mbuf *m;
   1146        1.1  hsuenaga 	int i;
   1147        1.1  hsuenaga 
   1148        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   1149        1.1  hsuenaga 	KASSERT_TX_MTX(sc, q);
   1150        1.1  hsuenaga 
   1151        1.1  hsuenaga 	/* Rx handle */
   1152        1.1  hsuenaga 	for (i = 0; i < MVXPE_RX_RING_CNT; i++) {
   1153        1.1  hsuenaga 		if (MVXPE_RX_PKTBUF(sc, q, i) == NULL)
   1154        1.1  hsuenaga 			continue;
   1155        1.2  hsuenaga 		mvxpbm_free_chunk(MVXPE_RX_PKTBUF(sc, q, i));
   1156        1.1  hsuenaga 		MVXPE_RX_PKTBUF(sc, q, i) = NULL;
   1157        1.1  hsuenaga 	}
   1158        1.1  hsuenaga 	rx->rx_dma = rx->rx_cpu = 0;
   1159        1.1  hsuenaga 
   1160        1.1  hsuenaga 	/* Tx handle */
   1161        1.1  hsuenaga 	for (i = 0; i < MVXPE_TX_RING_CNT; i++) {
   1162       1.14  kiyohara 		m = MVXPE_TX_MBUF(sc, q, i);
   1163       1.14  kiyohara 		if (m == NULL)
   1164        1.1  hsuenaga 			continue;
   1165       1.14  kiyohara 		MVXPE_TX_MBUF(sc, q, i) = NULL;
   1166       1.14  kiyohara 		bus_dmamap_sync(sc->sc_dmat,
   1167       1.14  kiyohara 		    MVXPE_TX_MAP(sc, q, i), 0, m->m_pkthdr.len,
   1168       1.14  kiyohara 		    BUS_DMASYNC_POSTWRITE);
   1169        1.1  hsuenaga 		bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_MAP(sc, q, i));
   1170       1.14  kiyohara 		m_freem(m);
   1171        1.1  hsuenaga 	}
   1172        1.1  hsuenaga 	tx->tx_dma = tx->tx_cpu = 0;
   1173        1.2  hsuenaga        	tx->tx_used = 0;
   1174        1.1  hsuenaga }
   1175        1.1  hsuenaga 
   1176        1.1  hsuenaga STATIC void
   1177        1.1  hsuenaga mvxpe_ring_sync_rx(struct mvxpe_softc *sc, int q, int idx, int count, int ops)
   1178        1.1  hsuenaga {
   1179        1.1  hsuenaga 	int wrap;
   1180        1.1  hsuenaga 
   1181        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   1182        1.1  hsuenaga 	KASSERT(count > 0 && count <= MVXPE_RX_RING_CNT);
   1183        1.1  hsuenaga 	KASSERT(idx >= 0 && idx < MVXPE_RX_RING_CNT);
   1184        1.1  hsuenaga 
   1185        1.1  hsuenaga 	wrap = (idx + count) - MVXPE_RX_RING_CNT;
   1186        1.1  hsuenaga 	if (wrap > 0) {
   1187        1.1  hsuenaga 		count -= wrap;
   1188        1.1  hsuenaga 		KASSERT(count > 0);
   1189        1.1  hsuenaga 		bus_dmamap_sync(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q),
   1190        1.1  hsuenaga 		    0, sizeof(struct mvxpe_rx_desc) * wrap, ops);
   1191        1.1  hsuenaga 	}
   1192        1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q),
   1193        1.1  hsuenaga 	    MVXPE_RX_DESC_OFF(sc, q, idx),
   1194        1.1  hsuenaga 	    sizeof(struct mvxpe_rx_desc) * count, ops);
   1195        1.1  hsuenaga }
   1196        1.1  hsuenaga 
   1197        1.1  hsuenaga STATIC void
   1198        1.1  hsuenaga mvxpe_ring_sync_tx(struct mvxpe_softc *sc, int q, int idx, int count, int ops)
   1199        1.1  hsuenaga {
   1200        1.1  hsuenaga 	int wrap = 0;
   1201        1.1  hsuenaga 
   1202        1.1  hsuenaga 	KASSERT_TX_MTX(sc, q);
   1203        1.1  hsuenaga 	KASSERT(count > 0 && count <= MVXPE_TX_RING_CNT);
   1204        1.1  hsuenaga 	KASSERT(idx >= 0 && idx < MVXPE_TX_RING_CNT);
   1205        1.1  hsuenaga 
   1206        1.1  hsuenaga 	wrap = (idx + count) - MVXPE_TX_RING_CNT;
   1207        1.1  hsuenaga 	if (wrap > 0)  {
   1208        1.1  hsuenaga 		count -= wrap;
   1209        1.1  hsuenaga 		bus_dmamap_sync(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q),
   1210        1.1  hsuenaga 		    0, sizeof(struct mvxpe_tx_desc) * wrap, ops);
   1211        1.1  hsuenaga 	}
   1212        1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q),
   1213        1.1  hsuenaga 	    MVXPE_TX_DESC_OFF(sc, q, idx),
   1214        1.1  hsuenaga 	    sizeof(struct mvxpe_tx_desc) * count, ops);
   1215        1.1  hsuenaga }
   1216        1.1  hsuenaga 
   1217        1.1  hsuenaga /*
   1218        1.1  hsuenaga  * Rx/Tx Queue Control
   1219        1.1  hsuenaga  */
   1220        1.1  hsuenaga STATIC int
   1221        1.1  hsuenaga mvxpe_rx_queue_init(struct ifnet *ifp, int q)
   1222        1.1  hsuenaga {
   1223        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1224        1.1  hsuenaga 	uint32_t reg;
   1225        1.1  hsuenaga 
   1226        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   1227        1.1  hsuenaga 	KASSERT(MVXPE_RX_RING_MEM_PA(sc, q) != 0);
   1228        1.1  hsuenaga 
   1229        1.1  hsuenaga 	/* descriptor address */
   1230        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXDQA(q), MVXPE_RX_RING_MEM_PA(sc, q));
   1231        1.1  hsuenaga 
   1232        1.1  hsuenaga 	/* Rx buffer size and descriptor ring size */
   1233        1.2  hsuenaga 	reg  = MVXPE_PRXDQS_BUFFERSIZE(mvxpbm_chunk_size(sc->sc_bm) >> 3);
   1234        1.1  hsuenaga 	reg |= MVXPE_PRXDQS_DESCRIPTORSQUEUESIZE(MVXPE_RX_RING_CNT);
   1235        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXDQS(q), reg);
   1236        1.1  hsuenaga 	DPRINTIFNET(ifp, 1, "PRXDQS(%d): %#x\n",
   1237        1.1  hsuenaga 	    q, MVXPE_READ(sc, MVXPE_PRXDQS(q)));
   1238        1.1  hsuenaga 
   1239        1.1  hsuenaga 	/* Rx packet offset address */
   1240        1.2  hsuenaga 	reg = MVXPE_PRXC_PACKETOFFSET(mvxpbm_packet_offset(sc->sc_bm) >> 3);
   1241        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXC(q), reg);
   1242        1.1  hsuenaga 	DPRINTIFNET(ifp, 1, "PRXC(%d): %#x\n",
   1243        1.1  hsuenaga 	    q, MVXPE_READ(sc, MVXPE_PRXC(q)));
   1244        1.1  hsuenaga 
   1245        1.2  hsuenaga 	/* Rx DMA SNOOP */
   1246        1.2  hsuenaga 	reg  = MVXPE_PRXSNP_SNOOPNOOFBYTES(MVXPE_MRU);
   1247        1.2  hsuenaga 	reg |= MVXPE_PRXSNP_L2DEPOSITNOOFBYTES(MVXPE_MRU);
   1248        1.2  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXSNP(q), reg);
   1249        1.2  hsuenaga 
   1250        1.1  hsuenaga 	/* if DMA is not working, register is not updated */
   1251        1.1  hsuenaga 	KASSERT(MVXPE_READ(sc, MVXPE_PRXDQA(q)) == MVXPE_RX_RING_MEM_PA(sc, q));
   1252        1.1  hsuenaga 	return 0;
   1253        1.1  hsuenaga }
   1254        1.1  hsuenaga 
   1255        1.1  hsuenaga STATIC int
   1256        1.1  hsuenaga mvxpe_tx_queue_init(struct ifnet *ifp, int q)
   1257        1.1  hsuenaga {
   1258        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1259        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1260        1.1  hsuenaga 	uint32_t reg;
   1261        1.1  hsuenaga 
   1262        1.1  hsuenaga 	KASSERT_TX_MTX(sc, q);
   1263        1.1  hsuenaga 	KASSERT(MVXPE_TX_RING_MEM_PA(sc, q) != 0);
   1264        1.1  hsuenaga 
   1265        1.1  hsuenaga 	/* descriptor address */
   1266        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PTXDQA(q), MVXPE_TX_RING_MEM_PA(sc, q));
   1267        1.1  hsuenaga 
   1268        1.1  hsuenaga 	/* Tx threshold, and descriptor ring size */
   1269        1.1  hsuenaga 	reg  = MVXPE_PTXDQS_TBT(tx->tx_queue_th_free);
   1270        1.1  hsuenaga 	reg |= MVXPE_PTXDQS_DQS(MVXPE_TX_RING_CNT);
   1271        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PTXDQS(q), reg);
   1272        1.1  hsuenaga 	DPRINTIFNET(ifp, 1, "PTXDQS(%d): %#x\n",
   1273        1.1  hsuenaga 	    q, MVXPE_READ(sc, MVXPE_PTXDQS(q)));
   1274        1.1  hsuenaga 
   1275        1.1  hsuenaga 	/* if DMA is not working, register is not updated */
   1276        1.1  hsuenaga 	KASSERT(MVXPE_READ(sc, MVXPE_PTXDQA(q)) == MVXPE_TX_RING_MEM_PA(sc, q));
   1277        1.1  hsuenaga 	return 0;
   1278        1.1  hsuenaga }
   1279        1.1  hsuenaga 
   1280        1.1  hsuenaga STATIC int
   1281        1.1  hsuenaga mvxpe_rx_queue_enable(struct ifnet *ifp, int q)
   1282        1.1  hsuenaga {
   1283        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1284        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   1285        1.1  hsuenaga 	uint32_t reg;
   1286        1.1  hsuenaga 
   1287        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   1288        1.1  hsuenaga 
   1289        1.1  hsuenaga 	/* Set Rx interrupt threshold */
   1290        1.1  hsuenaga 	reg  = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received);
   1291        1.1  hsuenaga 	reg |= MVXPE_PRXDQTH_NODT(rx->rx_queue_th_free);
   1292        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXDQTH(q), reg);
   1293        1.1  hsuenaga 
   1294        1.1  hsuenaga 	reg  = MVXPE_PRXITTH_RITT(rx->rx_queue_th_time);
   1295        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXITTH(q), reg);
   1296        1.1  hsuenaga 
   1297        1.1  hsuenaga 	/* Unmask RXTX_TH Intr. */
   1298        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_PRXTXTIM);
   1299        1.1  hsuenaga 	reg |= MVXPE_PRXTXTI_RBICTAPQ(q); /* Rx Buffer Interrupt Coalese */
   1300        1.1  hsuenaga 	reg |= MVXPE_PRXTXTI_RDTAQ(q); /* Rx Descriptor Alart */
   1301        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg);
   1302        1.1  hsuenaga 
   1303        1.1  hsuenaga 	/* Enable Rx queue */
   1304        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_RQC) & MVXPE_RQC_EN_MASK;
   1305        1.1  hsuenaga 	reg |= MVXPE_RQC_ENQ(q);
   1306        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_RQC, reg);
   1307        1.1  hsuenaga 
   1308        1.1  hsuenaga 	return 0;
   1309        1.1  hsuenaga }
   1310        1.1  hsuenaga 
   1311        1.1  hsuenaga STATIC int
   1312        1.1  hsuenaga mvxpe_tx_queue_enable(struct ifnet *ifp, int q)
   1313        1.1  hsuenaga {
   1314        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1315        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1316        1.1  hsuenaga 	uint32_t reg;
   1317        1.1  hsuenaga 
   1318        1.1  hsuenaga 	KASSERT_TX_MTX(sc, q);
   1319        1.1  hsuenaga 
   1320        1.1  hsuenaga 	/* Set Tx interrupt threshold */
   1321        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PTXDQS(q));
   1322        1.1  hsuenaga 	reg &= ~MVXPE_PTXDQS_TBT_MASK; /* keep queue size */
   1323        1.1  hsuenaga 	reg |= MVXPE_PTXDQS_TBT(tx->tx_queue_th_free);
   1324        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PTXDQS(q), reg);
   1325        1.1  hsuenaga 
   1326        1.1  hsuenaga 	/* Unmask RXTX_TH Intr. */
   1327        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_PRXTXTIM);
   1328        1.1  hsuenaga 	reg |= MVXPE_PRXTXTI_TBTCQ(q); /* Tx Threshold cross */
   1329        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg);
   1330        1.1  hsuenaga 
   1331        1.1  hsuenaga 	/* Don't update MVXPE_TQC here, there is no packet yet. */
   1332        1.1  hsuenaga 	return 0;
   1333        1.1  hsuenaga }
   1334        1.1  hsuenaga 
   1335        1.1  hsuenaga STATIC void
   1336        1.1  hsuenaga mvxpe_rx_lockq(struct mvxpe_softc *sc, int q)
   1337        1.1  hsuenaga {
   1338        1.1  hsuenaga 	KASSERT(q >= 0);
   1339        1.1  hsuenaga 	KASSERT(q < MVXPE_QUEUE_SIZE);
   1340        1.1  hsuenaga 	mutex_enter(&sc->sc_rx_ring[q].rx_ring_mtx);
   1341        1.1  hsuenaga }
   1342        1.1  hsuenaga 
   1343        1.1  hsuenaga STATIC void
   1344        1.1  hsuenaga mvxpe_rx_unlockq(struct mvxpe_softc *sc, int q)
   1345        1.1  hsuenaga {
   1346        1.1  hsuenaga 	KASSERT(q >= 0);
   1347        1.1  hsuenaga 	KASSERT(q < MVXPE_QUEUE_SIZE);
   1348        1.1  hsuenaga 	mutex_exit(&sc->sc_rx_ring[q].rx_ring_mtx);
   1349        1.1  hsuenaga }
   1350        1.1  hsuenaga 
   1351        1.1  hsuenaga STATIC void
   1352        1.1  hsuenaga mvxpe_tx_lockq(struct mvxpe_softc *sc, int q)
   1353        1.1  hsuenaga {
   1354        1.1  hsuenaga 	KASSERT(q >= 0);
   1355        1.1  hsuenaga 	KASSERT(q < MVXPE_QUEUE_SIZE);
   1356        1.1  hsuenaga 	mutex_enter(&sc->sc_tx_ring[q].tx_ring_mtx);
   1357        1.1  hsuenaga }
   1358        1.1  hsuenaga 
   1359        1.1  hsuenaga STATIC void
   1360        1.1  hsuenaga mvxpe_tx_unlockq(struct mvxpe_softc *sc, int q)
   1361        1.1  hsuenaga {
   1362        1.1  hsuenaga 	KASSERT(q >= 0);
   1363        1.1  hsuenaga 	KASSERT(q < MVXPE_QUEUE_SIZE);
   1364        1.1  hsuenaga 	mutex_exit(&sc->sc_tx_ring[q].tx_ring_mtx);
   1365        1.1  hsuenaga }
   1366        1.1  hsuenaga 
   1367        1.1  hsuenaga /*
   1368        1.1  hsuenaga  * Interrupt Handlers
   1369        1.1  hsuenaga  */
   1370        1.1  hsuenaga STATIC void
   1371        1.1  hsuenaga mvxpe_disable_intr(struct mvxpe_softc *sc)
   1372        1.1  hsuenaga {
   1373        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_EUIM, 0);
   1374        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_EUIC, 0);
   1375        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIM, 0);
   1376        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIC, 0);
   1377        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXIM, 0);
   1378        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXIC, 0);
   1379        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMIM, 0);
   1380        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMIC, 0);
   1381        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PIE, 0);
   1382        1.1  hsuenaga }
   1383        1.1  hsuenaga 
   1384        1.1  hsuenaga STATIC void
   1385        1.1  hsuenaga mvxpe_enable_intr(struct mvxpe_softc *sc)
   1386        1.1  hsuenaga {
   1387        1.1  hsuenaga 	uint32_t reg;
   1388        1.1  hsuenaga 
   1389        1.1  hsuenaga 	/* Enable Port MISC Intr. (via RXTX_TH_Summary bit) */
   1390        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PMIM);
   1391        1.1  hsuenaga 	reg |= MVXPE_PMI_PHYSTATUSCHNG;
   1392        1.1  hsuenaga 	reg |= MVXPE_PMI_LINKCHANGE;
   1393        1.1  hsuenaga 	reg |= MVXPE_PMI_IAE;
   1394        1.1  hsuenaga 	reg |= MVXPE_PMI_RXOVERRUN;
   1395        1.1  hsuenaga 	reg |= MVXPE_PMI_RXCRCERROR;
   1396        1.1  hsuenaga 	reg |= MVXPE_PMI_RXLARGEPACKET;
   1397        1.1  hsuenaga 	reg |= MVXPE_PMI_TXUNDRN;
   1398        1.6    hikaru #if 0
   1399        1.6    hikaru 	/*
   1400        1.6    hikaru 	 * The device may raise false interrupts for SERDES even if the device
   1401        1.6    hikaru 	 * is not configured to use SERDES connection.
   1402        1.6    hikaru 	 */
   1403        1.6    hikaru 	reg |= MVXPE_PMI_PRBSERROR;
   1404        1.6    hikaru 	reg |= MVXPE_PMI_SRSE;
   1405        1.6    hikaru #else
   1406        1.6    hikaru 	reg &= ~MVXPE_PMI_PRBSERROR;
   1407        1.6    hikaru 	reg &= ~MVXPE_PMI_SRSE;
   1408        1.6    hikaru #endif
   1409        1.1  hsuenaga 	reg |= MVXPE_PMI_TREQ_MASK;
   1410        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMIM, reg);
   1411        1.1  hsuenaga 
   1412        1.1  hsuenaga 	/* Enable Summary Bit to check all interrupt cause. */
   1413        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PRXTXTIM);
   1414        1.1  hsuenaga 	reg |= MVXPE_PRXTXTI_PMISCICSUMMARY;
   1415        1.1  hsuenaga 	reg |= MVXPE_PRXTXTI_PTXERRORSUMMARY;
   1416        1.1  hsuenaga 	reg |= MVXPE_PRXTXTI_PRXTXICSUMMARY;
   1417        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg);
   1418        1.1  hsuenaga 
   1419        1.1  hsuenaga 	/* Enable All Queue Interrupt */
   1420        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PIE);
   1421        1.1  hsuenaga 	reg |= MVXPE_PIE_RXPKTINTRPTENB_MASK;
   1422        1.1  hsuenaga 	reg |= MVXPE_PIE_TXPKTINTRPTENB_MASK;
   1423        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PIE, reg);
   1424        1.1  hsuenaga }
   1425        1.1  hsuenaga 
   1426        1.1  hsuenaga STATIC int
   1427        1.1  hsuenaga mvxpe_rxtxth_intr(void *arg)
   1428        1.1  hsuenaga {
   1429        1.1  hsuenaga 	struct mvxpe_softc *sc = arg;
   1430        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1431        1.2  hsuenaga 	uint32_t ic, queues, datum = 0;
   1432        1.1  hsuenaga 
   1433        1.1  hsuenaga 	DPRINTSC(sc, 2, "got RXTX_TH_Intr\n");
   1434        1.1  hsuenaga 	MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_rxtxth);
   1435        1.1  hsuenaga 
   1436        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1437        1.2  hsuenaga 	ic = MVXPE_READ(sc, MVXPE_PRXTXTIC);
   1438        1.4    hikaru 	if (ic == 0) {
   1439        1.4    hikaru 		mvxpe_sc_unlock(sc);
   1440        1.2  hsuenaga 		return 0;
   1441        1.4    hikaru 	}
   1442        1.2  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIC, ~ic);
   1443        1.2  hsuenaga 	datum = datum ^ ic;
   1444        1.1  hsuenaga 
   1445        1.2  hsuenaga 	DPRINTIFNET(ifp, 2, "PRXTXTIC: %#x\n", ic);
   1446        1.1  hsuenaga 
   1447        1.2  hsuenaga 	/* ack maintance interrupt first */
   1448        1.2  hsuenaga 	if (ic & MVXPE_PRXTXTI_PTXERRORSUMMARY) {
   1449        1.2  hsuenaga 		DPRINTIFNET(ifp, 1, "PRXTXTIC: +PTXERRORSUMMARY\n");
   1450        1.2  hsuenaga 		MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtxth_txerr);
   1451        1.2  hsuenaga 	}
   1452        1.2  hsuenaga 	if ((ic & MVXPE_PRXTXTI_PMISCICSUMMARY)) {
   1453        1.2  hsuenaga 		DPRINTIFNET(ifp, 2, "PTXTXTIC: +PMISCICSUMMARY\n");
   1454        1.2  hsuenaga 		mvxpe_misc_intr(sc);
   1455        1.2  hsuenaga 	}
   1456        1.2  hsuenaga 	if (ic & MVXPE_PRXTXTI_PRXTXICSUMMARY) {
   1457        1.2  hsuenaga 		DPRINTIFNET(ifp, 2, "PTXTXTIC: +PRXTXICSUMMARY\n");
   1458        1.2  hsuenaga 		mvxpe_rxtx_intr(sc);
   1459        1.2  hsuenaga 	}
   1460        1.4    hikaru 	if (!(ifp->if_flags & IFF_RUNNING)) {
   1461        1.4    hikaru 		mvxpe_sc_unlock(sc);
   1462        1.2  hsuenaga 		return 1;
   1463        1.4    hikaru 	}
   1464        1.2  hsuenaga 
   1465        1.2  hsuenaga 	/* RxTxTH interrupt */
   1466        1.2  hsuenaga 	queues = MVXPE_PRXTXTI_GET_RBICTAPQ(ic);
   1467        1.2  hsuenaga 	if (queues) {
   1468        1.2  hsuenaga 		DPRINTIFNET(ifp, 2, "PRXTXTIC: +RXEOF\n");
   1469        1.2  hsuenaga 		mvxpe_rx(sc, queues);
   1470        1.2  hsuenaga 	}
   1471        1.2  hsuenaga 	queues = MVXPE_PRXTXTI_GET_TBTCQ(ic);
   1472        1.2  hsuenaga 	if (queues) {
   1473        1.2  hsuenaga 		DPRINTIFNET(ifp, 2, "PRXTXTIC: +TBTCQ\n");
   1474        1.2  hsuenaga 		mvxpe_tx_complete(sc, queues);
   1475        1.2  hsuenaga 	}
   1476        1.2  hsuenaga 	queues = MVXPE_PRXTXTI_GET_RDTAQ(ic);
   1477        1.2  hsuenaga 	if (queues) {
   1478        1.2  hsuenaga 		DPRINTIFNET(ifp, 2, "PRXTXTIC: +RDTAQ\n");
   1479        1.2  hsuenaga 		mvxpe_rx_refill(sc, queues);
   1480        1.1  hsuenaga 	}
   1481        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1482        1.1  hsuenaga 
   1483       1.16     ozaki 	if_schedule_deferred_start(ifp);
   1484        1.1  hsuenaga 
   1485        1.1  hsuenaga 	rnd_add_uint32(&sc->sc_rnd_source, datum);
   1486        1.1  hsuenaga 
   1487        1.2  hsuenaga 	return 1;
   1488        1.1  hsuenaga }
   1489        1.1  hsuenaga 
   1490        1.1  hsuenaga STATIC int
   1491        1.1  hsuenaga mvxpe_misc_intr(void *arg)
   1492        1.1  hsuenaga {
   1493        1.1  hsuenaga 	struct mvxpe_softc *sc = arg;
   1494        1.1  hsuenaga #ifdef MVXPE_DEBUG
   1495        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1496        1.1  hsuenaga #endif
   1497        1.1  hsuenaga 	uint32_t ic;
   1498        1.1  hsuenaga 	uint32_t datum = 0;
   1499        1.1  hsuenaga 	int claimed = 0;
   1500        1.1  hsuenaga 
   1501        1.1  hsuenaga 	DPRINTSC(sc, 2, "got MISC_INTR\n");
   1502        1.1  hsuenaga 	MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_misc);
   1503        1.1  hsuenaga 
   1504        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   1505        1.1  hsuenaga 
   1506        1.1  hsuenaga 	for (;;) {
   1507        1.1  hsuenaga 		ic = MVXPE_READ(sc, MVXPE_PMIC);
   1508        1.1  hsuenaga 		ic &= MVXPE_READ(sc, MVXPE_PMIM);
   1509        1.1  hsuenaga 		if (ic == 0)
   1510        1.1  hsuenaga 			break;
   1511        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PMIC, ~ic);
   1512        1.1  hsuenaga 		datum = datum ^ ic;
   1513        1.1  hsuenaga 		claimed = 1;
   1514        1.1  hsuenaga 
   1515        1.1  hsuenaga 		DPRINTIFNET(ifp, 2, "PMIC=%#x\n", ic);
   1516        1.1  hsuenaga 		if (ic & MVXPE_PMI_PHYSTATUSCHNG) {
   1517        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+PHYSTATUSCHNG\n");
   1518        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_phystatuschng);
   1519        1.1  hsuenaga 		}
   1520        1.1  hsuenaga 		if (ic & MVXPE_PMI_LINKCHANGE) {
   1521        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+LINKCHANGE\n");
   1522        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_linkchange);
   1523        1.1  hsuenaga 			mvxpe_linkupdate(sc);
   1524        1.1  hsuenaga 		}
   1525        1.1  hsuenaga 		if (ic & MVXPE_PMI_IAE) {
   1526        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+IAE\n");
   1527        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_iae);
   1528        1.1  hsuenaga 		}
   1529        1.1  hsuenaga 		if (ic & MVXPE_PMI_RXOVERRUN) {
   1530        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+RXOVERRUN\n");
   1531        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_rxoverrun);
   1532        1.1  hsuenaga 		}
   1533        1.1  hsuenaga 		if (ic & MVXPE_PMI_RXCRCERROR) {
   1534        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+RXCRCERROR\n");
   1535        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_rxcrc);
   1536        1.1  hsuenaga 		}
   1537        1.1  hsuenaga 		if (ic & MVXPE_PMI_RXLARGEPACKET) {
   1538        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+RXLARGEPACKET\n");
   1539        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_rxlargepacket);
   1540        1.1  hsuenaga 		}
   1541        1.1  hsuenaga 		if (ic & MVXPE_PMI_TXUNDRN) {
   1542        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+TXUNDRN\n");
   1543        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_txunderrun);
   1544        1.1  hsuenaga 		}
   1545        1.1  hsuenaga 		if (ic & MVXPE_PMI_PRBSERROR) {
   1546        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+PRBSERROR\n");
   1547        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_prbserr);
   1548        1.1  hsuenaga 		}
   1549        1.1  hsuenaga 		if (ic & MVXPE_PMI_TREQ_MASK) {
   1550        1.1  hsuenaga 			DPRINTIFNET(ifp, 2, "+TREQ\n");
   1551        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_txreq);
   1552        1.1  hsuenaga 		}
   1553        1.1  hsuenaga 	}
   1554        1.1  hsuenaga 	if (datum)
   1555        1.1  hsuenaga 		rnd_add_uint32(&sc->sc_rnd_source, datum);
   1556        1.1  hsuenaga 
   1557        1.1  hsuenaga 	return claimed;
   1558        1.1  hsuenaga }
   1559        1.1  hsuenaga 
   1560        1.1  hsuenaga STATIC int
   1561        1.1  hsuenaga mvxpe_rxtx_intr(void *arg)
   1562        1.1  hsuenaga {
   1563        1.1  hsuenaga 	struct mvxpe_softc *sc = arg;
   1564        1.1  hsuenaga #ifdef MVXPE_DEBUG
   1565        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1566        1.1  hsuenaga #endif
   1567        1.1  hsuenaga 	uint32_t datum = 0;
   1568        1.1  hsuenaga 	uint32_t prxtxic;
   1569        1.1  hsuenaga 	int claimed = 0;
   1570        1.1  hsuenaga 
   1571        1.1  hsuenaga 	DPRINTSC(sc, 2, "got RXTX_Intr\n");
   1572        1.1  hsuenaga 	MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_rxtx);
   1573        1.1  hsuenaga 
   1574        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   1575        1.1  hsuenaga 
   1576        1.1  hsuenaga 	for (;;) {
   1577        1.1  hsuenaga 		prxtxic = MVXPE_READ(sc, MVXPE_PRXTXIC);
   1578        1.1  hsuenaga 		prxtxic &= MVXPE_READ(sc, MVXPE_PRXTXIM);
   1579        1.1  hsuenaga 		if (prxtxic == 0)
   1580        1.1  hsuenaga 			break;
   1581        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXTXIC, ~prxtxic);
   1582        1.1  hsuenaga 		datum = datum ^ prxtxic;
   1583        1.1  hsuenaga 		claimed = 1;
   1584        1.1  hsuenaga 
   1585        1.1  hsuenaga 		DPRINTSC(sc, 2, "PRXTXIC: %#x\n", prxtxic);
   1586        1.1  hsuenaga 
   1587        1.1  hsuenaga 		if (prxtxic & MVXPE_PRXTXI_RREQ_MASK) {
   1588        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "Rx Resource Error.\n");
   1589        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_rreq);
   1590        1.1  hsuenaga 		}
   1591        1.1  hsuenaga 		if (prxtxic & MVXPE_PRXTXI_RPQ_MASK) {
   1592        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "Rx Packet in Queue.\n");
   1593        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_rpq);
   1594        1.1  hsuenaga 		}
   1595        1.1  hsuenaga 		if (prxtxic & MVXPE_PRXTXI_TBRQ_MASK) {
   1596        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "Tx Buffer Return.\n");
   1597        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_tbrq);
   1598        1.1  hsuenaga 		}
   1599        1.1  hsuenaga 		if (prxtxic & MVXPE_PRXTXI_PRXTXTHICSUMMARY) {
   1600        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "PRXTXTHIC Sumary\n");
   1601        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_rxtxth);
   1602        1.1  hsuenaga 		}
   1603        1.1  hsuenaga 		if (prxtxic & MVXPE_PRXTXI_PTXERRORSUMMARY) {
   1604        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "PTXERROR Sumary\n");
   1605        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_txerr);
   1606        1.1  hsuenaga 		}
   1607        1.1  hsuenaga 		if (prxtxic & MVXPE_PRXTXI_PMISCICSUMMARY) {
   1608        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "PMISCIC Sumary\n");
   1609        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_misc);
   1610        1.1  hsuenaga 		}
   1611        1.1  hsuenaga 	}
   1612        1.1  hsuenaga 	if (datum)
   1613        1.1  hsuenaga 		rnd_add_uint32(&sc->sc_rnd_source, datum);
   1614        1.1  hsuenaga 
   1615        1.1  hsuenaga 	return claimed;
   1616        1.1  hsuenaga }
   1617        1.1  hsuenaga 
   1618        1.1  hsuenaga STATIC void
   1619        1.1  hsuenaga mvxpe_tick(void *arg)
   1620        1.1  hsuenaga {
   1621        1.1  hsuenaga 	struct mvxpe_softc *sc = arg;
   1622        1.1  hsuenaga 	struct mii_data *mii = &sc->sc_mii;
   1623        1.1  hsuenaga 
   1624        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1625        1.1  hsuenaga 
   1626        1.1  hsuenaga 	mii_tick(mii);
   1627        1.1  hsuenaga 	mii_pollstat(&sc->sc_mii);
   1628        1.1  hsuenaga 
   1629       1.15     skrll 	/* read mib registers(clear by read) */
   1630        1.1  hsuenaga 	mvxpe_update_mib(sc);
   1631        1.1  hsuenaga 
   1632        1.1  hsuenaga 	/* read counter registers(clear by read) */
   1633        1.1  hsuenaga 	MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_pdfc,
   1634        1.1  hsuenaga 	    MVXPE_READ(sc, MVXPE_PDFC));
   1635        1.1  hsuenaga 	MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_pofc,
   1636        1.1  hsuenaga 	    MVXPE_READ(sc, MVXPE_POFC));
   1637        1.1  hsuenaga 	MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_txbadfcs,
   1638        1.1  hsuenaga 	    MVXPE_READ(sc, MVXPE_TXBADFCS));
   1639        1.1  hsuenaga 	MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_txdropped,
   1640        1.1  hsuenaga 	    MVXPE_READ(sc, MVXPE_TXDROPPED));
   1641        1.1  hsuenaga 	MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_lpic,
   1642        1.1  hsuenaga 	    MVXPE_READ(sc, MVXPE_LPIC));
   1643        1.1  hsuenaga 
   1644        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1645        1.1  hsuenaga 
   1646        1.1  hsuenaga 	callout_schedule(&sc->sc_tick_ch, hz);
   1647        1.1  hsuenaga }
   1648        1.1  hsuenaga 
   1649        1.1  hsuenaga 
   1650        1.1  hsuenaga /*
   1651        1.1  hsuenaga  * struct ifnet and mii callbacks
   1652        1.1  hsuenaga  */
   1653        1.1  hsuenaga STATIC void
   1654        1.1  hsuenaga mvxpe_start(struct ifnet *ifp)
   1655        1.1  hsuenaga {
   1656        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1657        1.1  hsuenaga 	struct mbuf *m;
   1658        1.1  hsuenaga 	int q;
   1659        1.1  hsuenaga 
   1660        1.1  hsuenaga 	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) {
   1661        1.1  hsuenaga 		DPRINTIFNET(ifp, 1, "not running\n");
   1662        1.1  hsuenaga 		return;
   1663        1.1  hsuenaga 	}
   1664        1.1  hsuenaga 
   1665        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1666        1.1  hsuenaga 	if (!MVXPE_IS_LINKUP(sc)) {
   1667        1.1  hsuenaga 		/* If Link is DOWN, can't start TX */
   1668        1.1  hsuenaga 		DPRINTIFNET(ifp, 1, "link fail\n");
   1669        1.1  hsuenaga 		for (;;) {
   1670        1.1  hsuenaga 			/*
   1671        1.1  hsuenaga 			 * discard stale packets all.
   1672        1.1  hsuenaga 			 * these may confuse DAD, ARP or timer based protocols.
   1673        1.1  hsuenaga 			 */
   1674        1.1  hsuenaga 			IFQ_DEQUEUE(&ifp->if_snd, m);
   1675        1.1  hsuenaga 			if (m == NULL)
   1676        1.1  hsuenaga 				break;
   1677        1.1  hsuenaga 			m_freem(m);
   1678        1.1  hsuenaga 		}
   1679        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   1680        1.1  hsuenaga 		return;
   1681        1.1  hsuenaga 	}
   1682        1.1  hsuenaga 	for (;;) {
   1683        1.1  hsuenaga 		/*
   1684        1.1  hsuenaga 		 * don't use IFQ_POLL().
   1685        1.1  hsuenaga 		 * there is lock problem between IFQ_POLL and IFQ_DEQUEUE
   1686        1.1  hsuenaga 		 * on SMP enabled networking stack.
   1687        1.1  hsuenaga 		 */
   1688        1.1  hsuenaga 		IFQ_DEQUEUE(&ifp->if_snd, m);
   1689        1.1  hsuenaga 		if (m == NULL)
   1690        1.1  hsuenaga 			break;
   1691        1.1  hsuenaga 
   1692        1.1  hsuenaga 		q = mvxpe_tx_queue_select(sc, m);
   1693        1.1  hsuenaga 		if (q < 0)
   1694        1.1  hsuenaga 			break;
   1695        1.1  hsuenaga 		/* mutex is held in mvxpe_tx_queue_select() */
   1696        1.1  hsuenaga 
   1697        1.1  hsuenaga 		if (mvxpe_tx_queue(sc, m, q) != 0) {
   1698        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "cannot add packet to tx ring\n");
   1699        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txerr);
   1700        1.1  hsuenaga 			mvxpe_tx_unlockq(sc, q);
   1701        1.1  hsuenaga 			break;
   1702        1.1  hsuenaga 		}
   1703        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, q);
   1704        1.2  hsuenaga 		KASSERT(sc->sc_tx_ring[q].tx_used >= 0);
   1705        1.2  hsuenaga 		KASSERT(sc->sc_tx_ring[q].tx_used <=
   1706        1.1  hsuenaga 		    sc->sc_tx_ring[q].tx_queue_len);
   1707        1.1  hsuenaga 		DPRINTIFNET(ifp, 1, "a packet is added to tx ring\n");
   1708        1.1  hsuenaga 		sc->sc_tx_pending++;
   1709       1.10    hikaru 		ifp->if_opackets++;
   1710        1.1  hsuenaga 		ifp->if_timer = 1;
   1711        1.1  hsuenaga 		sc->sc_wdogsoft = 1;
   1712  1.17.16.2  pgoyette 		bpf_mtap(ifp, m, BPF_D_OUT);
   1713        1.1  hsuenaga 	}
   1714        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1715        1.1  hsuenaga 
   1716        1.1  hsuenaga 	return;
   1717        1.1  hsuenaga }
   1718        1.1  hsuenaga 
   1719        1.1  hsuenaga STATIC int
   1720        1.1  hsuenaga mvxpe_ioctl(struct ifnet *ifp, u_long cmd, void *data)
   1721        1.1  hsuenaga {
   1722        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1723        1.1  hsuenaga 	struct ifreq *ifr = data;
   1724        1.1  hsuenaga 	int error = 0;
   1725        1.1  hsuenaga 	int s;
   1726        1.1  hsuenaga 
   1727        1.1  hsuenaga 	switch (cmd) {
   1728        1.1  hsuenaga 	case SIOCGIFMEDIA:
   1729        1.1  hsuenaga 	case SIOCSIFMEDIA:
   1730        1.1  hsuenaga 		DPRINTIFNET(ifp, 2, "mvxpe_ioctl MEDIA\n");
   1731        1.1  hsuenaga 		s = splnet(); /* XXX: is there suitable mutex? */
   1732        1.1  hsuenaga 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
   1733        1.1  hsuenaga 		splx(s);
   1734        1.1  hsuenaga 		break;
   1735        1.1  hsuenaga 	default:
   1736        1.1  hsuenaga 		DPRINTIFNET(ifp, 2, "mvxpe_ioctl ETHER\n");
   1737        1.1  hsuenaga 		error = ether_ioctl(ifp, cmd, data);
   1738        1.1  hsuenaga 		if (error == ENETRESET) {
   1739        1.1  hsuenaga 			if (ifp->if_flags & IFF_RUNNING) {
   1740        1.1  hsuenaga 				mvxpe_sc_lock(sc);
   1741        1.1  hsuenaga 				mvxpe_filter_setup(sc);
   1742        1.1  hsuenaga 				mvxpe_sc_unlock(sc);
   1743        1.1  hsuenaga 			}
   1744        1.1  hsuenaga 			error = 0;
   1745        1.1  hsuenaga 		}
   1746        1.1  hsuenaga 		break;
   1747        1.1  hsuenaga 	}
   1748        1.1  hsuenaga 
   1749        1.1  hsuenaga 	return error;
   1750        1.1  hsuenaga }
   1751        1.1  hsuenaga 
   1752        1.1  hsuenaga STATIC int
   1753        1.1  hsuenaga mvxpe_init(struct ifnet *ifp)
   1754        1.1  hsuenaga {
   1755        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1756        1.1  hsuenaga 	struct mii_data *mii = &sc->sc_mii;
   1757        1.1  hsuenaga 	uint32_t reg;
   1758        1.1  hsuenaga 	int q;
   1759        1.1  hsuenaga 
   1760        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1761        1.1  hsuenaga 
   1762        1.1  hsuenaga 	/* Start DMA Engine */
   1763        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000000);
   1764        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000000);
   1765        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PACC, MVXPE_PACC_ACCELERATIONMODE_EDM);
   1766        1.1  hsuenaga 
   1767        1.1  hsuenaga 	/* Enable port */
   1768        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PMACC0);
   1769        1.1  hsuenaga 	reg |= MVXPE_PMACC0_PORTEN;
   1770        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMACC0, reg);
   1771        1.1  hsuenaga 
   1772        1.1  hsuenaga 	/* Link up */
   1773        1.1  hsuenaga 	mvxpe_linkup(sc);
   1774        1.1  hsuenaga 
   1775        1.1  hsuenaga 	/* Enable All Queue and interrupt of each Queue */
   1776        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
   1777        1.1  hsuenaga 		mvxpe_rx_lockq(sc, q);
   1778        1.1  hsuenaga 		mvxpe_rx_queue_enable(ifp, q);
   1779        1.2  hsuenaga 		mvxpe_rx_queue_refill(sc, q);
   1780        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, q);
   1781        1.1  hsuenaga 
   1782        1.1  hsuenaga 		mvxpe_tx_lockq(sc, q);
   1783        1.1  hsuenaga 		mvxpe_tx_queue_enable(ifp, q);
   1784        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, q);
   1785        1.1  hsuenaga 	}
   1786        1.1  hsuenaga 
   1787        1.1  hsuenaga 	/* Enable interrupt */
   1788        1.1  hsuenaga 	mvxpe_enable_intr(sc);
   1789        1.1  hsuenaga 
   1790        1.1  hsuenaga 	/* Set Counter */
   1791        1.1  hsuenaga 	callout_schedule(&sc->sc_tick_ch, hz);
   1792        1.1  hsuenaga 
   1793        1.1  hsuenaga 	/* Media check */
   1794        1.1  hsuenaga 	mii_mediachg(mii);
   1795        1.1  hsuenaga 
   1796        1.1  hsuenaga 	ifp->if_flags |= IFF_RUNNING;
   1797        1.1  hsuenaga 	ifp->if_flags &= ~IFF_OACTIVE;
   1798        1.1  hsuenaga 
   1799        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1800        1.1  hsuenaga 	return 0;
   1801        1.1  hsuenaga }
   1802        1.1  hsuenaga 
   1803        1.1  hsuenaga /* ARGSUSED */
   1804        1.1  hsuenaga STATIC void
   1805        1.1  hsuenaga mvxpe_stop(struct ifnet *ifp, int disable)
   1806        1.1  hsuenaga {
   1807        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1808        1.1  hsuenaga 	uint32_t reg;
   1809        1.1  hsuenaga 	int q, cnt;
   1810        1.1  hsuenaga 
   1811        1.1  hsuenaga 	DPRINTIFNET(ifp, 1, "stop device dma and interrupts.\n");
   1812        1.1  hsuenaga 
   1813        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1814        1.1  hsuenaga 
   1815        1.1  hsuenaga 	callout_stop(&sc->sc_tick_ch);
   1816        1.1  hsuenaga 
   1817        1.1  hsuenaga 	/* Link down */
   1818        1.1  hsuenaga 	mvxpe_linkdown(sc);
   1819        1.1  hsuenaga 
   1820        1.1  hsuenaga 	/* Disable Rx interrupt */
   1821        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PIE);
   1822        1.1  hsuenaga 	reg &= ~MVXPE_PIE_RXPKTINTRPTENB_MASK;
   1823        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PIE, reg);
   1824        1.1  hsuenaga 
   1825        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PRXTXTIM);
   1826        1.1  hsuenaga 	reg &= ~MVXPE_PRXTXTI_RBICTAPQ_MASK;
   1827        1.1  hsuenaga 	reg &= ~MVXPE_PRXTXTI_RDTAQ_MASK;
   1828        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg);
   1829        1.1  hsuenaga 
   1830        1.1  hsuenaga 	/* Wait for all Rx activity to terminate. */
   1831        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_RQC) & MVXPE_RQC_EN_MASK;
   1832        1.1  hsuenaga 	reg = MVXPE_RQC_DIS(reg);
   1833        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_RQC, reg);
   1834        1.1  hsuenaga 	cnt = 0;
   1835        1.1  hsuenaga 	do {
   1836        1.1  hsuenaga 		if (cnt >= RX_DISABLE_TIMEOUT) {
   1837        1.1  hsuenaga 			aprint_error_ifnet(ifp,
   1838        1.1  hsuenaga 			    "timeout for RX stopped. rqc 0x%x\n", reg);
   1839        1.1  hsuenaga 			break;
   1840        1.1  hsuenaga 		}
   1841        1.1  hsuenaga 		cnt++;
   1842        1.1  hsuenaga 		reg = MVXPE_READ(sc, MVXPE_RQC);
   1843        1.1  hsuenaga 	} while (reg & MVXPE_RQC_EN_MASK);
   1844        1.1  hsuenaga 
   1845        1.1  hsuenaga 	/* Wait for all Tx activety to terminate. */
   1846        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PIE);
   1847        1.1  hsuenaga 	reg &= ~MVXPE_PIE_TXPKTINTRPTENB_MASK;
   1848        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PIE, reg);
   1849        1.1  hsuenaga 
   1850        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PRXTXTIM);
   1851        1.1  hsuenaga 	reg &= ~MVXPE_PRXTXTI_TBTCQ_MASK;
   1852        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg);
   1853        1.1  hsuenaga 
   1854        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_TQC) & MVXPE_TQC_EN_MASK;
   1855        1.1  hsuenaga 	reg = MVXPE_TQC_DIS(reg);
   1856        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_TQC, reg);
   1857        1.1  hsuenaga 	cnt = 0;
   1858        1.1  hsuenaga 	do {
   1859        1.1  hsuenaga 		if (cnt >= TX_DISABLE_TIMEOUT) {
   1860        1.1  hsuenaga 			aprint_error_ifnet(ifp,
   1861        1.1  hsuenaga 			    "timeout for TX stopped. tqc 0x%x\n", reg);
   1862        1.1  hsuenaga 			break;
   1863        1.1  hsuenaga 		}
   1864        1.1  hsuenaga 		cnt++;
   1865        1.1  hsuenaga 		reg = MVXPE_READ(sc, MVXPE_TQC);
   1866        1.1  hsuenaga 	} while (reg & MVXPE_TQC_EN_MASK);
   1867        1.1  hsuenaga 
   1868        1.1  hsuenaga 	/* Wait for all Tx FIFO is empty */
   1869        1.1  hsuenaga 	cnt = 0;
   1870        1.1  hsuenaga 	do {
   1871        1.1  hsuenaga 		if (cnt >= TX_FIFO_EMPTY_TIMEOUT) {
   1872        1.1  hsuenaga 			aprint_error_ifnet(ifp,
   1873        1.1  hsuenaga 			    "timeout for TX FIFO drained. ps0 0x%x\n", reg);
   1874        1.1  hsuenaga 			break;
   1875        1.1  hsuenaga 		}
   1876        1.1  hsuenaga 		cnt++;
   1877        1.1  hsuenaga 		reg = MVXPE_READ(sc, MVXPE_PS0);
   1878        1.1  hsuenaga 	} while (!(reg & MVXPE_PS0_TXFIFOEMP) && (reg & MVXPE_PS0_TXINPROG));
   1879        1.1  hsuenaga 
   1880        1.1  hsuenaga 	/* Reset the MAC Port Enable bit */
   1881        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_PMACC0);
   1882        1.1  hsuenaga 	reg &= ~MVXPE_PMACC0_PORTEN;
   1883        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PMACC0, reg);
   1884        1.1  hsuenaga 
   1885        1.1  hsuenaga 	/* Disable each of queue */
   1886        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
   1887        1.1  hsuenaga 		struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   1888        1.1  hsuenaga 
   1889        1.1  hsuenaga 		mvxpe_rx_lockq(sc, q);
   1890        1.1  hsuenaga 		mvxpe_tx_lockq(sc, q);
   1891        1.1  hsuenaga 
   1892        1.2  hsuenaga 		/* Disable Rx packet buffer refill request */
   1893        1.1  hsuenaga 		reg  = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received);
   1894        1.1  hsuenaga 		reg |= MVXPE_PRXDQTH_NODT(0);
   1895        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXITTH(q), reg);
   1896        1.1  hsuenaga 
   1897        1.1  hsuenaga 		if (disable) {
   1898        1.1  hsuenaga 			/*
   1899        1.1  hsuenaga 			 * Hold Reset state of DMA Engine
   1900        1.1  hsuenaga 			 * (must write 0x0 to restart it)
   1901        1.1  hsuenaga 			 */
   1902        1.1  hsuenaga 			MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000001);
   1903        1.1  hsuenaga 			MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000001);
   1904        1.1  hsuenaga 			mvxpe_ring_flush_queue(sc, q);
   1905        1.1  hsuenaga 		}
   1906        1.1  hsuenaga 
   1907        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, q);
   1908        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, q);
   1909        1.1  hsuenaga 	}
   1910        1.1  hsuenaga 
   1911        1.1  hsuenaga 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1912        1.1  hsuenaga 
   1913        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1914        1.1  hsuenaga }
   1915        1.1  hsuenaga 
   1916        1.1  hsuenaga STATIC void
   1917        1.1  hsuenaga mvxpe_watchdog(struct ifnet *ifp)
   1918        1.1  hsuenaga {
   1919        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1920        1.1  hsuenaga 	int q;
   1921        1.1  hsuenaga 
   1922        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1923        1.1  hsuenaga 
   1924        1.1  hsuenaga 	/*
   1925        1.1  hsuenaga 	 * Reclaim first as there is a possibility of losing Tx completion
   1926        1.1  hsuenaga 	 * interrupts.
   1927        1.1  hsuenaga 	 */
   1928        1.2  hsuenaga 	mvxpe_tx_complete(sc, 0xff);
   1929        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
   1930        1.1  hsuenaga 		struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   1931        1.1  hsuenaga 
   1932        1.1  hsuenaga 		if (tx->tx_dma != tx->tx_cpu) {
   1933        1.1  hsuenaga 			if (sc->sc_wdogsoft) {
   1934        1.1  hsuenaga 				/*
   1935        1.1  hsuenaga 				 * There is race condition between CPU and DMA
   1936        1.1  hsuenaga 				 * engine. When DMA engine encounters queue end,
   1937        1.1  hsuenaga 				 * it clears MVXPE_TQC_ENQ bit.
   1938        1.1  hsuenaga 				 * XXX: how about enhanced mode?
   1939        1.1  hsuenaga 				 */
   1940        1.1  hsuenaga 				MVXPE_WRITE(sc, MVXPE_TQC, MVXPE_TQC_ENQ(q));
   1941        1.1  hsuenaga 				ifp->if_timer = 5;
   1942        1.1  hsuenaga 				sc->sc_wdogsoft = 0;
   1943        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_wdogsoft);
   1944        1.1  hsuenaga 			} else {
   1945        1.1  hsuenaga 				aprint_error_ifnet(ifp, "watchdog timeout\n");
   1946        1.1  hsuenaga 				ifp->if_oerrors++;
   1947        1.1  hsuenaga 				mvxpe_linkreset(sc);
   1948        1.1  hsuenaga 				mvxpe_sc_unlock(sc);
   1949        1.1  hsuenaga 
   1950        1.1  hsuenaga 				/* trigger reinitialize sequence */
   1951        1.1  hsuenaga 				mvxpe_stop(ifp, 1);
   1952        1.1  hsuenaga 				mvxpe_init(ifp);
   1953        1.1  hsuenaga 
   1954        1.1  hsuenaga 				mvxpe_sc_lock(sc);
   1955        1.1  hsuenaga 			}
   1956        1.1  hsuenaga 		}
   1957        1.1  hsuenaga 	}
   1958        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1959        1.1  hsuenaga }
   1960        1.1  hsuenaga 
   1961        1.1  hsuenaga STATIC int
   1962        1.1  hsuenaga mvxpe_ifflags_cb(struct ethercom *ec)
   1963        1.1  hsuenaga {
   1964        1.1  hsuenaga 	struct ifnet *ifp = &ec->ec_if;
   1965        1.1  hsuenaga 	struct mvxpe_softc *sc = ifp->if_softc;
   1966        1.1  hsuenaga 	int change = ifp->if_flags ^ sc->sc_if_flags;
   1967        1.1  hsuenaga 
   1968        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   1969        1.1  hsuenaga 
   1970        1.1  hsuenaga 	if (change != 0)
   1971        1.1  hsuenaga 		sc->sc_if_flags = ifp->if_flags;
   1972        1.1  hsuenaga 
   1973        1.1  hsuenaga 	if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0) {
   1974        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   1975        1.1  hsuenaga 		return ENETRESET;
   1976        1.1  hsuenaga 	}
   1977        1.1  hsuenaga 
   1978        1.1  hsuenaga 	if ((change & IFF_PROMISC) != 0)
   1979        1.1  hsuenaga 		mvxpe_filter_setup(sc);
   1980        1.1  hsuenaga 
   1981        1.1  hsuenaga 	if ((change & IFF_UP) != 0)
   1982        1.1  hsuenaga 		mvxpe_linkreset(sc);
   1983        1.1  hsuenaga 
   1984        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   1985        1.1  hsuenaga 	return 0;
   1986        1.1  hsuenaga }
   1987        1.1  hsuenaga 
   1988        1.1  hsuenaga STATIC int
   1989        1.1  hsuenaga mvxpe_mediachange(struct ifnet *ifp)
   1990        1.1  hsuenaga {
   1991        1.1  hsuenaga 	return ether_mediachange(ifp);
   1992        1.1  hsuenaga }
   1993        1.1  hsuenaga 
   1994        1.1  hsuenaga STATIC void
   1995        1.1  hsuenaga mvxpe_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
   1996        1.1  hsuenaga {
   1997        1.1  hsuenaga 	ether_mediastatus(ifp, ifmr);
   1998        1.1  hsuenaga }
   1999        1.1  hsuenaga 
   2000        1.1  hsuenaga /*
   2001        1.1  hsuenaga  * Link State Notify
   2002        1.1  hsuenaga  */
   2003        1.1  hsuenaga STATIC void mvxpe_linkupdate(struct mvxpe_softc *sc)
   2004        1.1  hsuenaga {
   2005        1.1  hsuenaga 	int linkup; /* bool */
   2006        1.1  hsuenaga 
   2007        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2008        1.1  hsuenaga 
   2009        1.1  hsuenaga 	/* tell miibus */
   2010        1.1  hsuenaga 	mii_pollstat(&sc->sc_mii);
   2011        1.1  hsuenaga 
   2012        1.1  hsuenaga 	/* syslog */
   2013        1.1  hsuenaga 	linkup = MVXPE_IS_LINKUP(sc);
   2014        1.1  hsuenaga 	if (sc->sc_linkstate == linkup)
   2015        1.1  hsuenaga 		return;
   2016        1.1  hsuenaga 
   2017        1.2  hsuenaga #ifdef DEBUG
   2018        1.2  hsuenaga 	log(LOG_DEBUG,
   2019        1.2  hsuenaga 	    "%s: link %s\n", device_xname(sc->sc_dev), linkup ? "up" : "down");
   2020        1.2  hsuenaga #endif
   2021        1.1  hsuenaga 	if (linkup)
   2022        1.1  hsuenaga 		MVXPE_EVCNT_INCR(&sc->sc_ev.ev_link_up);
   2023        1.1  hsuenaga 	else
   2024        1.1  hsuenaga 		MVXPE_EVCNT_INCR(&sc->sc_ev.ev_link_down);
   2025        1.1  hsuenaga 
   2026        1.1  hsuenaga 	sc->sc_linkstate = linkup;
   2027        1.1  hsuenaga }
   2028        1.1  hsuenaga 
   2029        1.1  hsuenaga STATIC void
   2030        1.1  hsuenaga mvxpe_linkup(struct mvxpe_softc *sc)
   2031        1.1  hsuenaga {
   2032        1.1  hsuenaga 	uint32_t reg;
   2033        1.1  hsuenaga 
   2034        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2035        1.1  hsuenaga 
   2036        1.1  hsuenaga 	/* set EEE parameters */
   2037        1.1  hsuenaga 	reg = MVXPE_READ(sc, MVXPE_LPIC1);
   2038        1.1  hsuenaga 	if (sc->sc_cf.cf_lpi)
   2039        1.1  hsuenaga 		reg |= MVXPE_LPIC1_LPIRE;
   2040        1.1  hsuenaga 	else
   2041        1.1  hsuenaga 		reg &= ~MVXPE_LPIC1_LPIRE;
   2042        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_LPIC1, reg);
   2043        1.1  hsuenaga 
   2044        1.1  hsuenaga 	/* set auto-negotiation parameters */
   2045        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PANC);
   2046        1.1  hsuenaga 	if (sc->sc_cf.cf_fc) {
   2047        1.1  hsuenaga 		/* flow control negotiation */
   2048        1.1  hsuenaga 		reg |= MVXPE_PANC_PAUSEADV;
   2049        1.1  hsuenaga 		reg |= MVXPE_PANC_ANFCEN;
   2050        1.1  hsuenaga 	}
   2051        1.1  hsuenaga 	else {
   2052        1.1  hsuenaga 		reg &= ~MVXPE_PANC_PAUSEADV;
   2053        1.1  hsuenaga 		reg &= ~MVXPE_PANC_ANFCEN;
   2054        1.1  hsuenaga 	}
   2055        1.1  hsuenaga 	reg &= ~MVXPE_PANC_FORCELINKFAIL;
   2056        1.1  hsuenaga 	reg &= ~MVXPE_PANC_FORCELINKPASS;
   2057        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PANC, reg);
   2058        1.1  hsuenaga 
   2059        1.1  hsuenaga 	mii_mediachg(&sc->sc_mii);
   2060        1.1  hsuenaga }
   2061        1.1  hsuenaga 
   2062        1.1  hsuenaga STATIC void
   2063        1.1  hsuenaga mvxpe_linkdown(struct mvxpe_softc *sc)
   2064        1.1  hsuenaga {
   2065        1.1  hsuenaga 	struct mii_softc *mii;
   2066        1.1  hsuenaga 	uint32_t reg;
   2067        1.1  hsuenaga 
   2068        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2069        1.1  hsuenaga 	return;
   2070        1.1  hsuenaga 
   2071        1.1  hsuenaga 	reg  = MVXPE_READ(sc, MVXPE_PANC);
   2072        1.1  hsuenaga 	reg |= MVXPE_PANC_FORCELINKFAIL;
   2073        1.1  hsuenaga 	reg &= MVXPE_PANC_FORCELINKPASS;
   2074        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PANC, reg);
   2075        1.1  hsuenaga 
   2076        1.1  hsuenaga 	mii = LIST_FIRST(&sc->sc_mii.mii_phys);
   2077        1.1  hsuenaga 	if (mii)
   2078        1.1  hsuenaga 		mii_phy_down(mii);
   2079        1.1  hsuenaga }
   2080        1.1  hsuenaga 
   2081        1.1  hsuenaga STATIC void
   2082        1.1  hsuenaga mvxpe_linkreset(struct mvxpe_softc *sc)
   2083        1.1  hsuenaga {
   2084        1.1  hsuenaga 	struct mii_softc *mii;
   2085        1.1  hsuenaga 
   2086        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2087        1.1  hsuenaga 
   2088        1.1  hsuenaga 	/* force reset PHY first */
   2089        1.1  hsuenaga 	mii = LIST_FIRST(&sc->sc_mii.mii_phys);
   2090        1.1  hsuenaga 	if (mii)
   2091        1.1  hsuenaga 		mii_phy_reset(mii);
   2092        1.1  hsuenaga 
   2093        1.1  hsuenaga 	/* reinit MAC and PHY */
   2094        1.1  hsuenaga 	mvxpe_linkdown(sc);
   2095        1.1  hsuenaga 	if ((sc->sc_if_flags & IFF_UP) != 0)
   2096        1.1  hsuenaga 		mvxpe_linkup(sc);
   2097        1.1  hsuenaga }
   2098        1.1  hsuenaga 
   2099        1.1  hsuenaga /*
   2100        1.1  hsuenaga  * Tx Subroutines
   2101        1.1  hsuenaga  */
   2102        1.1  hsuenaga STATIC int
   2103        1.1  hsuenaga mvxpe_tx_queue_select(struct mvxpe_softc *sc, struct mbuf *m)
   2104        1.1  hsuenaga {
   2105        1.1  hsuenaga 	int q = 0;
   2106        1.1  hsuenaga 
   2107        1.1  hsuenaga 	/* XXX: get attribute from ALTQ framework? */
   2108        1.1  hsuenaga 	mvxpe_tx_lockq(sc, q);
   2109        1.1  hsuenaga 	return 0;
   2110        1.1  hsuenaga }
   2111        1.1  hsuenaga 
   2112        1.1  hsuenaga STATIC int
   2113        1.1  hsuenaga mvxpe_tx_queue(struct mvxpe_softc *sc, struct mbuf *m, int q)
   2114        1.1  hsuenaga {
   2115        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   2116        1.1  hsuenaga 	bus_dma_segment_t *txsegs;
   2117        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   2118        1.1  hsuenaga 	struct mvxpe_tx_desc *t = NULL;
   2119        1.1  hsuenaga 	uint32_t ptxsu;
   2120        1.1  hsuenaga 	int txnsegs;
   2121        1.1  hsuenaga 	int start, used;
   2122        1.1  hsuenaga 	int i;
   2123        1.1  hsuenaga 
   2124        1.2  hsuenaga 	KASSERT_TX_MTX(sc, q);
   2125        1.2  hsuenaga 	KASSERT(tx->tx_used >= 0);
   2126        1.2  hsuenaga 	KASSERT(tx->tx_used <= tx->tx_queue_len);
   2127        1.1  hsuenaga 
   2128        1.1  hsuenaga 	/* load mbuf using dmamap of 1st descriptor */
   2129        1.1  hsuenaga 	if (bus_dmamap_load_mbuf(sc->sc_dmat,
   2130        1.1  hsuenaga 	    MVXPE_TX_MAP(sc, q, tx->tx_cpu), m, BUS_DMA_NOWAIT) != 0) {
   2131        1.1  hsuenaga 		m_freem(m);
   2132        1.1  hsuenaga 		return ENOBUFS;
   2133        1.1  hsuenaga 	}
   2134        1.1  hsuenaga 	txsegs = MVXPE_TX_MAP(sc, q, tx->tx_cpu)->dm_segs;
   2135        1.1  hsuenaga 	txnsegs = MVXPE_TX_MAP(sc, q, tx->tx_cpu)->dm_nsegs;
   2136        1.2  hsuenaga 	if (txnsegs <= 0 || (txnsegs + tx->tx_used) > tx->tx_queue_len) {
   2137        1.1  hsuenaga 		/* we have no enough descriptors or mbuf is broken */
   2138        1.1  hsuenaga 		bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_MAP(sc, q, tx->tx_cpu));
   2139        1.1  hsuenaga 		m_freem(m);
   2140        1.1  hsuenaga 		return ENOBUFS;
   2141        1.1  hsuenaga 	}
   2142        1.1  hsuenaga 	DPRINTSC(sc, 2, "send packet %p descriptor %d\n", m, tx->tx_cpu);
   2143        1.1  hsuenaga 	KASSERT(MVXPE_TX_MBUF(sc, q, tx->tx_cpu) == NULL);
   2144        1.1  hsuenaga 
   2145        1.1  hsuenaga 	/* remember mbuf using 1st descriptor */
   2146        1.1  hsuenaga 	MVXPE_TX_MBUF(sc, q, tx->tx_cpu) = m;
   2147        1.1  hsuenaga 	bus_dmamap_sync(sc->sc_dmat,
   2148        1.1  hsuenaga 	    MVXPE_TX_MAP(sc, q, tx->tx_cpu), 0, m->m_pkthdr.len,
   2149       1.14  kiyohara 	    BUS_DMASYNC_PREWRITE);
   2150        1.1  hsuenaga 
   2151        1.1  hsuenaga 	/* load to tx descriptors */
   2152        1.1  hsuenaga 	start = tx->tx_cpu;
   2153        1.1  hsuenaga 	used = 0;
   2154        1.1  hsuenaga 	for (i = 0; i < txnsegs; i++) {
   2155        1.1  hsuenaga 		if (__predict_false(txsegs[i].ds_len == 0))
   2156        1.1  hsuenaga 			continue;
   2157        1.1  hsuenaga 		t = MVXPE_TX_DESC(sc, q, tx->tx_cpu);
   2158        1.1  hsuenaga 		t->command = 0;
   2159        1.1  hsuenaga 		t->l4ichk = 0;
   2160        1.1  hsuenaga 		t->flags = 0;
   2161        1.1  hsuenaga 		if (i == 0) {
   2162        1.1  hsuenaga 			/* 1st descriptor */
   2163        1.1  hsuenaga 			t->command |= MVXPE_TX_CMD_W_PACKET_OFFSET(0);
   2164        1.1  hsuenaga 			t->command |= MVXPE_TX_CMD_PADDING;
   2165        1.1  hsuenaga 			t->command |= MVXPE_TX_CMD_F;
   2166        1.1  hsuenaga 			mvxpe_tx_set_csumflag(ifp, t, m);
   2167        1.1  hsuenaga 		}
   2168        1.1  hsuenaga 		t->bufptr = txsegs[i].ds_addr;
   2169        1.1  hsuenaga 		t->bytecnt = txsegs[i].ds_len;
   2170        1.1  hsuenaga 		tx->tx_cpu = tx_counter_adv(tx->tx_cpu, 1);
   2171        1.2  hsuenaga 		tx->tx_used++;
   2172        1.1  hsuenaga 		used++;
   2173        1.1  hsuenaga 	}
   2174        1.1  hsuenaga 	/* t is last descriptor here */
   2175        1.1  hsuenaga 	KASSERT(t != NULL);
   2176        1.1  hsuenaga 	t->command |= MVXPE_TX_CMD_L;
   2177        1.1  hsuenaga 
   2178        1.1  hsuenaga 	DPRINTSC(sc, 2, "queue %d, %d descriptors used\n", q, used);
   2179        1.1  hsuenaga #ifdef MVXPE_DEBUG
   2180        1.1  hsuenaga 	if (mvxpe_debug > 2)
   2181        1.1  hsuenaga 		for (i = start; i <= tx->tx_cpu; i++) {
   2182        1.1  hsuenaga 			t = MVXPE_TX_DESC(sc, q, i);
   2183        1.1  hsuenaga 			mvxpe_dump_txdesc(t, i);
   2184        1.1  hsuenaga 		}
   2185        1.1  hsuenaga #endif
   2186        1.1  hsuenaga 	mvxpe_ring_sync_tx(sc, q, start, used,
   2187        1.1  hsuenaga 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   2188        1.1  hsuenaga 
   2189        1.1  hsuenaga 	while (used > 255) {
   2190        1.1  hsuenaga 		ptxsu = MVXPE_PTXSU_NOWD(255);
   2191        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu);
   2192        1.1  hsuenaga 		used -= 255;
   2193        1.1  hsuenaga 	}
   2194        1.1  hsuenaga 	if (used > 0) {
   2195        1.1  hsuenaga 		ptxsu = MVXPE_PTXSU_NOWD(used);
   2196        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu);
   2197        1.1  hsuenaga 	}
   2198        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_TQC, MVXPE_TQC_ENQ(q));
   2199        1.1  hsuenaga 
   2200        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2201        1.1  hsuenaga 	    "PTXDQA: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PTXDQA(q)));
   2202        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2203        1.1  hsuenaga 	    "PTXDQS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PTXDQS(q)));
   2204        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2205        1.1  hsuenaga 	    "PTXS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PTXS(q)));
   2206        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2207        1.1  hsuenaga 	    "PTXDI: queue %d, %d\n", q, MVXPE_READ(sc, MVXPE_PTXDI(q)));
   2208        1.1  hsuenaga 	DPRINTSC(sc, 2, "TQC: %#x\n", MVXPE_READ(sc, MVXPE_TQC));
   2209        1.1  hsuenaga 	DPRINTIFNET(ifp, 2,
   2210        1.2  hsuenaga 	    "Tx: tx_cpu = %d, tx_dma = %d, tx_used = %d\n",
   2211        1.2  hsuenaga 	    tx->tx_cpu, tx->tx_dma, tx->tx_used);
   2212        1.1  hsuenaga 	return 0;
   2213        1.1  hsuenaga }
   2214        1.1  hsuenaga 
   2215        1.1  hsuenaga STATIC void
   2216        1.1  hsuenaga mvxpe_tx_set_csumflag(struct ifnet *ifp,
   2217        1.1  hsuenaga     struct mvxpe_tx_desc *t, struct mbuf *m)
   2218        1.1  hsuenaga {
   2219        1.2  hsuenaga 	struct ether_header *eh;
   2220        1.1  hsuenaga 	int csum_flags;
   2221        1.1  hsuenaga 	uint32_t iphl = 0, ipoff = 0;
   2222        1.1  hsuenaga 
   2223        1.1  hsuenaga 
   2224        1.1  hsuenaga        	csum_flags = ifp->if_csum_flags_tx & m->m_pkthdr.csum_flags;
   2225        1.1  hsuenaga 
   2226        1.2  hsuenaga 	eh = mtod(m, struct ether_header *);
   2227        1.2  hsuenaga 	switch (htons(eh->ether_type)) {
   2228        1.2  hsuenaga 	case ETHERTYPE_IP:
   2229        1.2  hsuenaga 	case ETHERTYPE_IPV6:
   2230        1.2  hsuenaga 		ipoff = ETHER_HDR_LEN;
   2231        1.2  hsuenaga 		break;
   2232        1.2  hsuenaga 	case ETHERTYPE_VLAN:
   2233        1.2  hsuenaga 		ipoff = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
   2234        1.2  hsuenaga 		break;
   2235        1.2  hsuenaga 	}
   2236        1.2  hsuenaga 
   2237        1.2  hsuenaga 	if (csum_flags & (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
   2238        1.1  hsuenaga 		iphl = M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data);
   2239        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L3_IP4;
   2240        1.1  hsuenaga 	}
   2241        1.1  hsuenaga 	else if (csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
   2242  1.17.16.1  pgoyette 		iphl = M_CSUM_DATA_IPv6_IPHL(m->m_pkthdr.csum_data);
   2243        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L3_IP6;
   2244        1.1  hsuenaga 	}
   2245        1.1  hsuenaga 	else {
   2246        1.1  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NONE;
   2247        1.1  hsuenaga 		return;
   2248        1.1  hsuenaga 	}
   2249        1.1  hsuenaga 
   2250        1.2  hsuenaga 
   2251        1.1  hsuenaga 	/* L3 */
   2252        1.1  hsuenaga 	if (csum_flags & M_CSUM_IPv4) {
   2253        1.1  hsuenaga 		t->command |= MVXPE_TX_CMD_IP4_CHECKSUM;
   2254        1.1  hsuenaga 	}
   2255        1.1  hsuenaga 
   2256        1.1  hsuenaga 	/* L4 */
   2257        1.2  hsuenaga 	if ((csum_flags &
   2258        1.2  hsuenaga 	    (M_CSUM_TCPv4|M_CSUM_UDPv4|M_CSUM_TCPv6|M_CSUM_UDPv6)) == 0) {
   2259        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NONE;
   2260        1.2  hsuenaga 	}
   2261        1.2  hsuenaga 	else if (csum_flags & M_CSUM_TCPv4) {
   2262        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
   2263        1.1  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_TCP;
   2264        1.1  hsuenaga 	}
   2265        1.1  hsuenaga 	else if (csum_flags & M_CSUM_UDPv4) {
   2266        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
   2267        1.1  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_UDP;
   2268        1.1  hsuenaga 	}
   2269        1.1  hsuenaga 	else if (csum_flags & M_CSUM_TCPv6) {
   2270        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
   2271        1.1  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_TCP;
   2272        1.1  hsuenaga 	}
   2273        1.1  hsuenaga 	else if (csum_flags & M_CSUM_UDPv6) {
   2274        1.2  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG;
   2275        1.1  hsuenaga 		t->command |= MVXPE_TX_CMD_L4_UDP;
   2276        1.1  hsuenaga 	}
   2277        1.1  hsuenaga 
   2278        1.1  hsuenaga 	t->l4ichk = 0;
   2279        1.2  hsuenaga 	t->command |= MVXPE_TX_CMD_IP_HEADER_LEN(iphl >> 2);
   2280        1.2  hsuenaga 	t->command |= MVXPE_TX_CMD_L3_OFFSET(ipoff);
   2281        1.1  hsuenaga }
   2282        1.1  hsuenaga 
   2283        1.1  hsuenaga STATIC void
   2284        1.2  hsuenaga mvxpe_tx_complete(struct mvxpe_softc *sc, uint32_t queues)
   2285        1.1  hsuenaga {
   2286        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   2287        1.1  hsuenaga 	int q;
   2288        1.1  hsuenaga 
   2289        1.1  hsuenaga 	DPRINTSC(sc, 2, "tx completed.\n");
   2290        1.1  hsuenaga 
   2291        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2292        1.1  hsuenaga 
   2293        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
   2294        1.2  hsuenaga 		if (!MVXPE_IS_QUEUE_BUSY(queues, q))
   2295        1.2  hsuenaga 			continue;
   2296        1.1  hsuenaga 		mvxpe_tx_lockq(sc, q);
   2297        1.2  hsuenaga 		mvxpe_tx_queue_complete(sc, q);
   2298        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, q);
   2299        1.1  hsuenaga 	}
   2300        1.1  hsuenaga 	KASSERT(sc->sc_tx_pending >= 0);
   2301        1.1  hsuenaga 	if (sc->sc_tx_pending == 0)
   2302        1.1  hsuenaga 		ifp->if_timer = 0;
   2303        1.1  hsuenaga }
   2304        1.1  hsuenaga 
   2305        1.1  hsuenaga STATIC void
   2306        1.2  hsuenaga mvxpe_tx_queue_complete(struct mvxpe_softc *sc, int q)
   2307        1.1  hsuenaga {
   2308        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q);
   2309        1.1  hsuenaga 	struct mvxpe_tx_desc *t;
   2310       1.14  kiyohara 	struct mbuf *m;
   2311        1.1  hsuenaga 	uint32_t ptxs, ptxsu, ndesc;
   2312        1.1  hsuenaga 	int i;
   2313        1.1  hsuenaga 
   2314        1.1  hsuenaga 	KASSERT_TX_MTX(sc, q);
   2315        1.1  hsuenaga 
   2316        1.1  hsuenaga 	ptxs = MVXPE_READ(sc, MVXPE_PTXS(q));
   2317        1.1  hsuenaga 	ndesc = MVXPE_PTXS_GET_TBC(ptxs);
   2318        1.1  hsuenaga 	if (ndesc == 0)
   2319        1.1  hsuenaga 		return;
   2320        1.1  hsuenaga 
   2321        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2322        1.1  hsuenaga 	    "tx complete queue %d, %d descriptors.\n", q, ndesc);
   2323        1.1  hsuenaga 
   2324        1.1  hsuenaga 	mvxpe_ring_sync_tx(sc, q, tx->tx_dma, ndesc,
   2325        1.1  hsuenaga 	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   2326        1.1  hsuenaga 
   2327        1.1  hsuenaga 	for (i = 0; i < ndesc; i++) {
   2328        1.1  hsuenaga 		int error = 0;
   2329        1.1  hsuenaga 
   2330        1.1  hsuenaga 		t = MVXPE_TX_DESC(sc, q, tx->tx_dma);
   2331        1.1  hsuenaga 		if (t->flags & MVXPE_TX_F_ES) {
   2332        1.1  hsuenaga 			DPRINTSC(sc, 1,
   2333        1.1  hsuenaga 			    "tx error queue %d desc %d\n",
   2334        1.1  hsuenaga 			    q, tx->tx_dma);
   2335        1.1  hsuenaga 			switch (t->flags & MVXPE_TX_F_EC_MASK) {
   2336        1.1  hsuenaga 			case MVXPE_TX_F_EC_LC:
   2337        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_lc);
   2338        1.4    hikaru 				break;
   2339        1.1  hsuenaga 			case MVXPE_TX_F_EC_UR:
   2340        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_ur);
   2341        1.4    hikaru 				break;
   2342        1.1  hsuenaga 			case MVXPE_TX_F_EC_RL:
   2343        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_rl);
   2344        1.4    hikaru 				break;
   2345        1.1  hsuenaga 			default:
   2346        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_oth);
   2347        1.4    hikaru 				break;
   2348        1.1  hsuenaga 			}
   2349        1.1  hsuenaga 			error = 1;
   2350        1.1  hsuenaga 		}
   2351       1.14  kiyohara 		m = MVXPE_TX_MBUF(sc, q, tx->tx_dma);
   2352       1.14  kiyohara 		if (m != NULL) {
   2353        1.1  hsuenaga 			KASSERT((t->command & MVXPE_TX_CMD_F) != 0);
   2354       1.14  kiyohara 			MVXPE_TX_MBUF(sc, q, tx->tx_dma) = NULL;
   2355       1.14  kiyohara 			bus_dmamap_sync(sc->sc_dmat,
   2356       1.14  kiyohara 			    MVXPE_TX_MAP(sc, q, tx->tx_dma), 0, m->m_pkthdr.len,
   2357       1.14  kiyohara 			    BUS_DMASYNC_POSTWRITE);
   2358        1.1  hsuenaga 			bus_dmamap_unload(sc->sc_dmat,
   2359        1.1  hsuenaga 			    MVXPE_TX_MAP(sc, q, tx->tx_dma));
   2360       1.14  kiyohara 			m_freem(m);
   2361        1.1  hsuenaga 			sc->sc_tx_pending--;
   2362        1.1  hsuenaga 		}
   2363        1.1  hsuenaga 		else
   2364        1.1  hsuenaga 			KASSERT((t->flags & MVXPE_TX_CMD_F) == 0);
   2365        1.1  hsuenaga 		tx->tx_dma = tx_counter_adv(tx->tx_dma, 1);
   2366        1.2  hsuenaga 		tx->tx_used--;
   2367        1.1  hsuenaga 		if (error)
   2368        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txqe[q]);
   2369        1.1  hsuenaga 		else
   2370        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txq[q]);
   2371        1.1  hsuenaga 	}
   2372        1.2  hsuenaga 	KASSERT(tx->tx_used >= 0);
   2373        1.2  hsuenaga 	KASSERT(tx->tx_used <= tx->tx_queue_len);
   2374        1.1  hsuenaga 	while (ndesc > 255) {
   2375        1.1  hsuenaga 		ptxsu = MVXPE_PTXSU_NORB(255);
   2376        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu);
   2377        1.1  hsuenaga 		ndesc -= 255;
   2378        1.1  hsuenaga 	}
   2379        1.1  hsuenaga 	if (ndesc > 0) {
   2380        1.1  hsuenaga 		ptxsu = MVXPE_PTXSU_NORB(ndesc);
   2381        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu);
   2382        1.1  hsuenaga 	}
   2383        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2384        1.2  hsuenaga 	    "Tx complete q %d, tx_cpu = %d, tx_dma = %d, tx_used = %d\n",
   2385        1.2  hsuenaga 	    q, tx->tx_cpu, tx->tx_dma, tx->tx_used);
   2386        1.1  hsuenaga }
   2387        1.1  hsuenaga 
   2388        1.1  hsuenaga /*
   2389        1.1  hsuenaga  * Rx Subroutines
   2390        1.1  hsuenaga  */
   2391        1.1  hsuenaga STATIC void
   2392        1.2  hsuenaga mvxpe_rx(struct mvxpe_softc *sc, uint32_t queues)
   2393        1.1  hsuenaga {
   2394        1.1  hsuenaga 	int q, npkt;
   2395        1.1  hsuenaga 
   2396        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2397        1.1  hsuenaga 
   2398        1.2  hsuenaga 	while ( (npkt = mvxpe_rx_queue_select(sc, queues, &q))) {
   2399        1.2  hsuenaga 		/* mutex is held by rx_queue_select */
   2400        1.1  hsuenaga 		mvxpe_rx_queue(sc, q, npkt);
   2401        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, q);
   2402        1.1  hsuenaga 	}
   2403        1.1  hsuenaga }
   2404        1.1  hsuenaga 
   2405        1.1  hsuenaga STATIC void
   2406        1.1  hsuenaga mvxpe_rx_queue(struct mvxpe_softc *sc, int q, int npkt)
   2407        1.1  hsuenaga {
   2408        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   2409        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   2410        1.1  hsuenaga 	struct mvxpe_rx_desc *r;
   2411        1.2  hsuenaga 	struct mvxpbm_chunk *chunk;
   2412        1.1  hsuenaga 	struct mbuf *m;
   2413        1.1  hsuenaga 	uint32_t prxsu;
   2414        1.1  hsuenaga 	int error = 0;
   2415        1.1  hsuenaga 	int i;
   2416        1.1  hsuenaga 
   2417        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   2418        1.1  hsuenaga 
   2419        1.1  hsuenaga 	mvxpe_ring_sync_rx(sc, q, rx->rx_dma, npkt,
   2420        1.1  hsuenaga 	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   2421        1.1  hsuenaga 
   2422        1.1  hsuenaga 	for (i = 0; i < npkt; i++) {
   2423        1.1  hsuenaga 		/* get descriptor and packet */
   2424        1.1  hsuenaga 		chunk = MVXPE_RX_PKTBUF(sc, q, rx->rx_dma);
   2425        1.1  hsuenaga 		MVXPE_RX_PKTBUF(sc, q, rx->rx_dma) = NULL;
   2426        1.1  hsuenaga 		r = MVXPE_RX_DESC(sc, q, rx->rx_dma);
   2427        1.2  hsuenaga 		mvxpbm_dmamap_sync(chunk, r->bytecnt, BUS_DMASYNC_POSTREAD);
   2428        1.1  hsuenaga 
   2429        1.1  hsuenaga 		/* check errors */
   2430        1.1  hsuenaga 		if (r->status & MVXPE_RX_ES) {
   2431        1.1  hsuenaga 			switch (r->status & MVXPE_RX_EC_MASK) {
   2432        1.1  hsuenaga 			case MVXPE_RX_EC_CE:
   2433        1.1  hsuenaga 				DPRINTIFNET(ifp, 1, "CRC error\n");
   2434        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_ce);
   2435        1.1  hsuenaga 				break;
   2436        1.1  hsuenaga 			case MVXPE_RX_EC_OR:
   2437        1.1  hsuenaga 				DPRINTIFNET(ifp, 1, "Rx FIFO overrun\n");
   2438        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_or);
   2439        1.1  hsuenaga 				break;
   2440        1.1  hsuenaga 			case MVXPE_RX_EC_MF:
   2441        1.1  hsuenaga 				DPRINTIFNET(ifp, 1, "Rx too large frame\n");
   2442        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_mf);
   2443        1.1  hsuenaga 				break;
   2444        1.1  hsuenaga 			case MVXPE_RX_EC_RE:
   2445        1.1  hsuenaga 				DPRINTIFNET(ifp, 1, "Rx resource error\n");
   2446        1.1  hsuenaga 				MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_re);
   2447        1.1  hsuenaga 				break;
   2448        1.1  hsuenaga 			}
   2449        1.1  hsuenaga 			error = 1;
   2450        1.1  hsuenaga 			goto rx_done;
   2451        1.1  hsuenaga 		}
   2452        1.1  hsuenaga 		if (!(r->status & MVXPE_RX_F) || !(r->status & MVXPE_RX_L)) {
   2453        1.1  hsuenaga 			DPRINTIFNET(ifp, 1, "not support scatter buf\n");
   2454        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_scat);
   2455        1.1  hsuenaga 			error = 1;
   2456        1.1  hsuenaga 			goto rx_done;
   2457        1.1  hsuenaga 		}
   2458        1.1  hsuenaga 
   2459        1.1  hsuenaga 		if (chunk == NULL) {
   2460        1.1  hsuenaga 			device_printf(sc->sc_dev,
   2461        1.1  hsuenaga 			    "got rx interrupt, but no chunk\n");
   2462        1.1  hsuenaga 			error = 1;
   2463        1.1  hsuenaga 			goto rx_done;
   2464        1.1  hsuenaga 		}
   2465        1.1  hsuenaga 
   2466        1.1  hsuenaga 		/* extract packet buffer */
   2467        1.2  hsuenaga 		if (mvxpbm_init_mbuf_hdr(chunk) != 0) {
   2468        1.2  hsuenaga 			error = 1;
   2469        1.2  hsuenaga 			goto rx_done;
   2470        1.2  hsuenaga 		}
   2471        1.1  hsuenaga 		m = chunk->m;
   2472       1.13     ozaki 		m_set_rcvif(m, ifp);
   2473        1.1  hsuenaga 		m->m_pkthdr.len = m->m_len = r->bytecnt - ETHER_CRC_LEN;
   2474        1.1  hsuenaga 		m_adj(m, MVXPE_HWHEADER_SIZE); /* strip MH */
   2475        1.1  hsuenaga 		mvxpe_rx_set_csumflag(ifp, r, m);
   2476        1.3     ozaki 		if_percpuq_enqueue(ifp->if_percpuq, m);
   2477        1.1  hsuenaga 		chunk = NULL; /* the BM chunk goes to networking stack now */
   2478        1.1  hsuenaga rx_done:
   2479        1.1  hsuenaga 		if (chunk) {
   2480        1.1  hsuenaga 			/* rx error. just return the chunk to BM. */
   2481        1.2  hsuenaga 			mvxpbm_free_chunk(chunk);
   2482        1.1  hsuenaga 		}
   2483        1.1  hsuenaga 		if (error)
   2484        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_rxqe[q]);
   2485        1.1  hsuenaga 		else
   2486        1.1  hsuenaga 			MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_rxq[q]);
   2487        1.1  hsuenaga 		rx->rx_dma = rx_counter_adv(rx->rx_dma, 1);
   2488        1.1  hsuenaga 	}
   2489        1.1  hsuenaga 	/* DMA status update */
   2490        1.1  hsuenaga 	DPRINTSC(sc, 2, "%d packets received from queue %d\n", npkt, q);
   2491        1.1  hsuenaga 	while (npkt > 255) {
   2492        1.1  hsuenaga 		prxsu = MVXPE_PRXSU_NOOFPROCESSEDDESCRIPTORS(255);
   2493        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu);
   2494        1.1  hsuenaga 		npkt -= 255;
   2495        1.1  hsuenaga 	}
   2496        1.1  hsuenaga 	if (npkt > 0) {
   2497        1.1  hsuenaga 		prxsu = MVXPE_PRXSU_NOOFPROCESSEDDESCRIPTORS(npkt);
   2498        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu);
   2499        1.1  hsuenaga 	}
   2500        1.1  hsuenaga 
   2501        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2502        1.1  hsuenaga 	    "PRXDQA: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PRXDQA(q)));
   2503        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2504        1.1  hsuenaga 	    "PRXDQS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PRXDQS(q)));
   2505        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2506        1.1  hsuenaga 	    "PRXS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PRXS(q)));
   2507        1.1  hsuenaga 	DPRINTSC(sc, 2,
   2508        1.1  hsuenaga 	    "PRXDI: queue %d, %d\n", q, MVXPE_READ(sc, MVXPE_PRXDI(q)));
   2509        1.1  hsuenaga 	DPRINTSC(sc, 2, "RQC: %#x\n", MVXPE_READ(sc, MVXPE_RQC));
   2510        1.1  hsuenaga 	DPRINTIFNET(ifp, 2, "Rx: rx_cpu = %d, rx_dma = %d\n",
   2511        1.1  hsuenaga 	    rx->rx_cpu, rx->rx_dma);
   2512        1.1  hsuenaga }
   2513        1.1  hsuenaga 
   2514        1.1  hsuenaga STATIC int
   2515        1.2  hsuenaga mvxpe_rx_queue_select(struct mvxpe_softc *sc, uint32_t queues, int *queue)
   2516        1.1  hsuenaga {
   2517        1.1  hsuenaga 	uint32_t prxs, npkt;
   2518        1.1  hsuenaga 	int q;
   2519        1.1  hsuenaga 
   2520        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2521        1.1  hsuenaga 	KASSERT(queue != NULL);
   2522        1.1  hsuenaga 	DPRINTSC(sc, 2, "selecting rx queue\n");
   2523        1.1  hsuenaga 
   2524        1.1  hsuenaga 	for (q = MVXPE_QUEUE_SIZE - 1; q >= 0; q--) {
   2525        1.2  hsuenaga 		if (!MVXPE_IS_QUEUE_BUSY(queues, q))
   2526        1.2  hsuenaga 			continue;
   2527        1.2  hsuenaga 
   2528        1.1  hsuenaga 		prxs = MVXPE_READ(sc, MVXPE_PRXS(q));
   2529        1.1  hsuenaga 		npkt = MVXPE_PRXS_GET_ODC(prxs);
   2530        1.1  hsuenaga 		if (npkt == 0)
   2531        1.1  hsuenaga 			continue;
   2532        1.1  hsuenaga 
   2533        1.1  hsuenaga 		DPRINTSC(sc, 2,
   2534        1.1  hsuenaga 		    "queue %d selected: prxs=%#x, %u pakcet received.\n",
   2535        1.1  hsuenaga 		    q, prxs, npkt);
   2536        1.1  hsuenaga 		*queue = q;
   2537        1.1  hsuenaga 		mvxpe_rx_lockq(sc, q);
   2538        1.1  hsuenaga 		return npkt;
   2539        1.1  hsuenaga 	}
   2540        1.1  hsuenaga 
   2541        1.1  hsuenaga 	return 0;
   2542        1.1  hsuenaga }
   2543        1.1  hsuenaga 
   2544        1.1  hsuenaga STATIC void
   2545        1.2  hsuenaga mvxpe_rx_refill(struct mvxpe_softc *sc, uint32_t queues)
   2546        1.1  hsuenaga {
   2547        1.1  hsuenaga 	int q;
   2548        1.1  hsuenaga 
   2549        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2550        1.1  hsuenaga 
   2551        1.1  hsuenaga 	/* XXX: check rx bit array */
   2552        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
   2553        1.2  hsuenaga 		if (!MVXPE_IS_QUEUE_BUSY(queues, q))
   2554        1.2  hsuenaga 			continue;
   2555        1.2  hsuenaga 
   2556        1.1  hsuenaga 		mvxpe_rx_lockq(sc, q);
   2557        1.2  hsuenaga 		mvxpe_rx_queue_refill(sc, q);
   2558        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, q);
   2559        1.1  hsuenaga 	}
   2560        1.1  hsuenaga }
   2561        1.1  hsuenaga 
   2562        1.1  hsuenaga STATIC void
   2563        1.2  hsuenaga mvxpe_rx_queue_refill(struct mvxpe_softc *sc, int q)
   2564        1.1  hsuenaga {
   2565        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   2566        1.1  hsuenaga 	uint32_t prxs, prxsu, ndesc;
   2567        1.2  hsuenaga 	int idx, refill = 0;
   2568        1.1  hsuenaga 	int npkt;
   2569        1.1  hsuenaga 
   2570        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   2571        1.1  hsuenaga 
   2572        1.1  hsuenaga 	prxs = MVXPE_READ(sc, MVXPE_PRXS(q));
   2573        1.1  hsuenaga 	ndesc = MVXPE_PRXS_GET_NODC(prxs) + MVXPE_PRXS_GET_ODC(prxs);
   2574        1.2  hsuenaga 	refill = rx->rx_queue_len - ndesc;
   2575        1.2  hsuenaga 	if (refill <= 0)
   2576        1.1  hsuenaga 		return;
   2577        1.1  hsuenaga 	DPRINTPRXS(2, q);
   2578        1.2  hsuenaga 	DPRINTSC(sc, 2, "%d buffers to refill.\n", refill);
   2579        1.1  hsuenaga 
   2580        1.1  hsuenaga 	idx = rx->rx_cpu;
   2581        1.2  hsuenaga 	for (npkt = 0; npkt < refill; npkt++)
   2582        1.1  hsuenaga 		if (mvxpe_rx_queue_add(sc, q) != 0)
   2583        1.1  hsuenaga 			break;
   2584        1.2  hsuenaga 	DPRINTSC(sc, 2, "queue %d, %d buffer refilled.\n", q, npkt);
   2585        1.1  hsuenaga 	if (npkt == 0)
   2586        1.1  hsuenaga 		return;
   2587        1.1  hsuenaga 
   2588        1.1  hsuenaga 	mvxpe_ring_sync_rx(sc, q, idx, npkt,
   2589        1.1  hsuenaga 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   2590        1.1  hsuenaga 
   2591        1.1  hsuenaga 	while (npkt > 255) {
   2592        1.1  hsuenaga 		prxsu = MVXPE_PRXSU_NOOFNEWDESCRIPTORS(255);
   2593        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu);
   2594        1.1  hsuenaga 		npkt -= 255;
   2595        1.1  hsuenaga 	}
   2596        1.1  hsuenaga 	if (npkt > 0) {
   2597        1.1  hsuenaga 		prxsu = MVXPE_PRXSU_NOOFNEWDESCRIPTORS(npkt);
   2598        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu);
   2599        1.1  hsuenaga 	}
   2600        1.1  hsuenaga 	DPRINTPRXS(2, q);
   2601        1.1  hsuenaga 	return;
   2602        1.1  hsuenaga }
   2603        1.1  hsuenaga 
   2604        1.1  hsuenaga STATIC int
   2605        1.1  hsuenaga mvxpe_rx_queue_add(struct mvxpe_softc *sc, int q)
   2606        1.1  hsuenaga {
   2607        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q);
   2608        1.1  hsuenaga 	struct mvxpe_rx_desc *r;
   2609        1.2  hsuenaga 	struct mvxpbm_chunk *chunk = NULL;
   2610        1.1  hsuenaga 
   2611        1.1  hsuenaga 	KASSERT_RX_MTX(sc, q);
   2612        1.1  hsuenaga 
   2613        1.1  hsuenaga 	/* Allocate the packet buffer */
   2614        1.2  hsuenaga 	chunk = mvxpbm_alloc(sc->sc_bm);
   2615        1.1  hsuenaga 	if (chunk == NULL) {
   2616        1.1  hsuenaga 		DPRINTSC(sc, 1, "BM chunk allocation failed.\n");
   2617        1.1  hsuenaga 		return ENOBUFS;
   2618        1.1  hsuenaga 	}
   2619        1.1  hsuenaga 
   2620        1.1  hsuenaga 	/* Add the packet to descritor */
   2621        1.1  hsuenaga 	KASSERT(MVXPE_RX_PKTBUF(sc, q, rx->rx_cpu) == NULL);
   2622        1.1  hsuenaga 	MVXPE_RX_PKTBUF(sc, q, rx->rx_cpu) = chunk;
   2623        1.2  hsuenaga 	mvxpbm_dmamap_sync(chunk, BM_SYNC_ALL, BUS_DMASYNC_PREREAD);
   2624        1.1  hsuenaga 
   2625        1.1  hsuenaga 	r = MVXPE_RX_DESC(sc, q, rx->rx_cpu);
   2626        1.1  hsuenaga 	r->bufptr = chunk->buf_pa;
   2627        1.1  hsuenaga 	DPRINTSC(sc, 9, "chunk added to index %d\n", rx->rx_cpu);
   2628        1.1  hsuenaga 	rx->rx_cpu = rx_counter_adv(rx->rx_cpu, 1);
   2629        1.1  hsuenaga 	return 0;
   2630        1.1  hsuenaga }
   2631        1.1  hsuenaga 
   2632        1.1  hsuenaga STATIC void
   2633        1.1  hsuenaga mvxpe_rx_set_csumflag(struct ifnet *ifp,
   2634        1.1  hsuenaga     struct mvxpe_rx_desc *r, struct mbuf *m0)
   2635        1.1  hsuenaga {
   2636        1.1  hsuenaga 	uint32_t csum_flags = 0;
   2637        1.1  hsuenaga 
   2638        1.1  hsuenaga 	if ((r->status & (MVXPE_RX_IP_HEADER_OK|MVXPE_RX_L3_IP)) == 0)
   2639        1.1  hsuenaga 		return; /* not a IP packet */
   2640        1.1  hsuenaga 
   2641        1.1  hsuenaga 	/* L3 */
   2642        1.1  hsuenaga 	if (r->status & MVXPE_RX_L3_IP) {
   2643        1.8    hikaru 		csum_flags |= M_CSUM_IPv4 & ifp->if_csum_flags_rx;
   2644        1.8    hikaru 		if ((r->status & MVXPE_RX_IP_HEADER_OK) == 0 &&
   2645        1.9    hikaru 		    (csum_flags & M_CSUM_IPv4) != 0) {
   2646        1.1  hsuenaga 			csum_flags |= M_CSUM_IPv4_BAD;
   2647        1.1  hsuenaga 			goto finish;
   2648        1.1  hsuenaga 		}
   2649        1.1  hsuenaga 		else if (r->status & MVXPE_RX_IPV4_FRAGMENT) {
   2650        1.1  hsuenaga 			/*
   2651        1.1  hsuenaga 			 * r->l4chk has partial checksum of each framgment.
   2652        1.1  hsuenaga 			 * but there is no way to use it in NetBSD.
   2653        1.1  hsuenaga 			 */
   2654        1.1  hsuenaga 			return;
   2655        1.1  hsuenaga 		}
   2656        1.1  hsuenaga 	}
   2657        1.1  hsuenaga 
   2658        1.1  hsuenaga 	/* L4 */
   2659        1.1  hsuenaga 	switch (r->status & MVXPE_RX_L4_MASK) {
   2660        1.1  hsuenaga 	case MVXPE_RX_L4_TCP:
   2661        1.1  hsuenaga 		if (r->status & MVXPE_RX_L3_IP)
   2662        1.8    hikaru 			csum_flags |= M_CSUM_TCPv4 & ifp->if_csum_flags_rx;
   2663        1.1  hsuenaga 		else
   2664        1.8    hikaru 			csum_flags |= M_CSUM_TCPv6 & ifp->if_csum_flags_rx;
   2665        1.1  hsuenaga 		break;
   2666        1.1  hsuenaga 	case MVXPE_RX_L4_UDP:
   2667        1.1  hsuenaga 		if (r->status & MVXPE_RX_L3_IP)
   2668        1.8    hikaru 			csum_flags |= M_CSUM_UDPv4 & ifp->if_csum_flags_rx;
   2669        1.1  hsuenaga 		else
   2670        1.8    hikaru 			csum_flags |= M_CSUM_UDPv6 & ifp->if_csum_flags_rx;
   2671        1.1  hsuenaga 		break;
   2672        1.1  hsuenaga 	case MVXPE_RX_L4_OTH:
   2673        1.1  hsuenaga 	default:
   2674        1.1  hsuenaga 		break;
   2675        1.1  hsuenaga 	}
   2676        1.8    hikaru 	if ((r->status & MVXPE_RX_L4_CHECKSUM_OK) == 0 && (csum_flags &
   2677        1.9    hikaru 	    (M_CSUM_TCPv4 | M_CSUM_TCPv6 | M_CSUM_UDPv4 | M_CSUM_UDPv6)) != 0)
   2678        1.8    hikaru 		csum_flags |= M_CSUM_TCP_UDP_BAD;
   2679        1.1  hsuenaga finish:
   2680        1.8    hikaru 	m0->m_pkthdr.csum_flags = csum_flags;
   2681        1.1  hsuenaga }
   2682        1.1  hsuenaga 
   2683        1.1  hsuenaga /*
   2684        1.1  hsuenaga  * MAC address filter
   2685        1.1  hsuenaga  */
   2686        1.1  hsuenaga STATIC uint8_t
   2687        1.1  hsuenaga mvxpe_crc8(const uint8_t *data, size_t size)
   2688        1.1  hsuenaga {
   2689        1.1  hsuenaga 	int bit;
   2690        1.1  hsuenaga 	uint8_t byte;
   2691        1.1  hsuenaga 	uint8_t crc = 0;
   2692        1.1  hsuenaga 	const uint8_t poly = 0x07;
   2693        1.1  hsuenaga 
   2694        1.1  hsuenaga 	while(size--)
   2695        1.1  hsuenaga 	  for (byte = *data++, bit = NBBY-1; bit >= 0; bit--)
   2696        1.1  hsuenaga 	    crc = (crc << 1) ^ ((((crc >> 7) ^ (byte >> bit)) & 1) ? poly : 0);
   2697        1.1  hsuenaga 
   2698        1.1  hsuenaga 	return crc;
   2699        1.1  hsuenaga }
   2700        1.1  hsuenaga 
   2701        1.1  hsuenaga CTASSERT(MVXPE_NDFSMT == MVXPE_NDFOMT);
   2702        1.1  hsuenaga 
   2703        1.1  hsuenaga STATIC void
   2704        1.1  hsuenaga mvxpe_filter_setup(struct mvxpe_softc *sc)
   2705        1.1  hsuenaga {
   2706        1.1  hsuenaga 	struct ethercom *ec = &sc->sc_ethercom;
   2707        1.1  hsuenaga 	struct ifnet *ifp= &sc->sc_ethercom.ec_if;
   2708        1.1  hsuenaga 	struct ether_multi *enm;
   2709        1.1  hsuenaga 	struct ether_multistep step;
   2710        1.1  hsuenaga 	uint32_t dfut[MVXPE_NDFUT], dfsmt[MVXPE_NDFSMT], dfomt[MVXPE_NDFOMT];
   2711        1.1  hsuenaga 	uint32_t pxc;
   2712        1.1  hsuenaga 	int i;
   2713        1.1  hsuenaga 	const uint8_t special[ETHER_ADDR_LEN] = {0x01,0x00,0x5e,0x00,0x00,0x00};
   2714        1.1  hsuenaga 
   2715        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   2716        1.1  hsuenaga 
   2717        1.1  hsuenaga 	memset(dfut, 0, sizeof(dfut));
   2718        1.1  hsuenaga 	memset(dfsmt, 0, sizeof(dfsmt));
   2719        1.1  hsuenaga 	memset(dfomt, 0, sizeof(dfomt));
   2720        1.1  hsuenaga 
   2721        1.1  hsuenaga 	if (ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) {
   2722        1.1  hsuenaga 		goto allmulti;
   2723        1.1  hsuenaga 	}
   2724        1.1  hsuenaga 
   2725        1.1  hsuenaga 	ETHER_FIRST_MULTI(step, ec, enm);
   2726        1.1  hsuenaga 	while (enm != NULL) {
   2727        1.1  hsuenaga 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
   2728        1.1  hsuenaga 			/* ranges are complex and somewhat rare */
   2729        1.1  hsuenaga 			goto allmulti;
   2730        1.1  hsuenaga 		}
   2731        1.1  hsuenaga 		/* chip handles some IPv4 multicast specially */
   2732        1.1  hsuenaga 		if (memcmp(enm->enm_addrlo, special, 5) == 0) {
   2733        1.1  hsuenaga 			i = enm->enm_addrlo[5];
   2734        1.1  hsuenaga 			dfsmt[i>>2] |=
   2735       1.12    hikaru 			    MVXPE_DF(i&3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS);
   2736        1.1  hsuenaga 		} else {
   2737        1.1  hsuenaga 			i = mvxpe_crc8(enm->enm_addrlo, ETHER_ADDR_LEN);
   2738        1.1  hsuenaga 			dfomt[i>>2] |=
   2739       1.12    hikaru 			    MVXPE_DF(i&3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS);
   2740        1.1  hsuenaga 		}
   2741        1.1  hsuenaga 
   2742        1.1  hsuenaga 		ETHER_NEXT_MULTI(step, enm);
   2743        1.1  hsuenaga 	}
   2744        1.1  hsuenaga 	goto set;
   2745        1.1  hsuenaga 
   2746        1.1  hsuenaga allmulti:
   2747        1.1  hsuenaga 	if (ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) {
   2748        1.1  hsuenaga 		for (i = 0; i < MVXPE_NDFSMT; i++) {
   2749        1.1  hsuenaga 			dfsmt[i] = dfomt[i] =
   2750       1.12    hikaru 			    MVXPE_DF(0, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) |
   2751       1.12    hikaru 			    MVXPE_DF(1, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) |
   2752       1.12    hikaru 			    MVXPE_DF(2, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) |
   2753       1.12    hikaru 			    MVXPE_DF(3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS);
   2754        1.1  hsuenaga 		}
   2755        1.1  hsuenaga 	}
   2756        1.1  hsuenaga 
   2757        1.1  hsuenaga set:
   2758        1.1  hsuenaga 	pxc = MVXPE_READ(sc, MVXPE_PXC);
   2759        1.1  hsuenaga 	pxc &= ~MVXPE_PXC_UPM;
   2760        1.1  hsuenaga 	pxc |= MVXPE_PXC_RB | MVXPE_PXC_RBIP | MVXPE_PXC_RBARP;
   2761        1.1  hsuenaga 	if (ifp->if_flags & IFF_BROADCAST) {
   2762        1.1  hsuenaga 		pxc &= ~(MVXPE_PXC_RB | MVXPE_PXC_RBIP | MVXPE_PXC_RBARP);
   2763        1.1  hsuenaga 	}
   2764        1.1  hsuenaga 	if (ifp->if_flags & IFF_PROMISC) {
   2765        1.1  hsuenaga 		pxc |= MVXPE_PXC_UPM;
   2766        1.1  hsuenaga 	}
   2767        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PXC, pxc);
   2768        1.1  hsuenaga 
   2769        1.1  hsuenaga 	/* Set Destination Address Filter Unicast Table */
   2770       1.12    hikaru 	if (ifp->if_flags & IFF_PROMISC) {
   2771       1.12    hikaru 		/* pass all unicast addresses */
   2772       1.12    hikaru 		for (i = 0; i < MVXPE_NDFUT; i++) {
   2773       1.12    hikaru 			dfut[i] =
   2774       1.12    hikaru 			    MVXPE_DF(0, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) |
   2775       1.12    hikaru 			    MVXPE_DF(1, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) |
   2776       1.12    hikaru 			    MVXPE_DF(2, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) |
   2777       1.12    hikaru 			    MVXPE_DF(3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS);
   2778       1.12    hikaru 		}
   2779       1.12    hikaru 	}
   2780       1.12    hikaru 	else {
   2781       1.12    hikaru 		i = sc->sc_enaddr[5] & 0xf;             /* last nibble */
   2782       1.12    hikaru 		dfut[i>>2] = MVXPE_DF(i&3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS);
   2783       1.12    hikaru 	}
   2784        1.1  hsuenaga 	MVXPE_WRITE_REGION(sc, MVXPE_DFUT(0), dfut, MVXPE_NDFUT);
   2785        1.1  hsuenaga 
   2786        1.1  hsuenaga 	/* Set Destination Address Filter Multicast Tables */
   2787        1.1  hsuenaga 	MVXPE_WRITE_REGION(sc, MVXPE_DFSMT(0), dfsmt, MVXPE_NDFSMT);
   2788        1.1  hsuenaga 	MVXPE_WRITE_REGION(sc, MVXPE_DFOMT(0), dfomt, MVXPE_NDFOMT);
   2789        1.1  hsuenaga }
   2790        1.1  hsuenaga 
   2791        1.1  hsuenaga /*
   2792        1.1  hsuenaga  * sysctl(9)
   2793        1.1  hsuenaga  */
   2794        1.1  hsuenaga SYSCTL_SETUP(sysctl_mvxpe, "sysctl mvxpe subtree setup")
   2795        1.1  hsuenaga {
   2796        1.1  hsuenaga 	int rc;
   2797        1.1  hsuenaga 	const struct sysctlnode *node;
   2798        1.1  hsuenaga 
   2799        1.1  hsuenaga 	if ((rc = sysctl_createv(clog, 0, NULL, &node,
   2800        1.1  hsuenaga 	    0, CTLTYPE_NODE, "mvxpe",
   2801        1.1  hsuenaga 	    SYSCTL_DESCR("mvxpe interface controls"),
   2802        1.1  hsuenaga 	    NULL, 0, NULL, 0,
   2803        1.1  hsuenaga 	    CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
   2804        1.1  hsuenaga 		goto err;
   2805        1.1  hsuenaga 	}
   2806        1.1  hsuenaga 
   2807        1.1  hsuenaga 	mvxpe_root_num = node->sysctl_num;
   2808        1.1  hsuenaga 	return;
   2809        1.1  hsuenaga 
   2810        1.1  hsuenaga err:
   2811        1.1  hsuenaga 	aprint_error("%s: syctl_createv failed (rc = %d)\n", __func__, rc);
   2812        1.1  hsuenaga }
   2813        1.1  hsuenaga 
   2814        1.1  hsuenaga STATIC int
   2815        1.1  hsuenaga sysctl_read_mib(SYSCTLFN_ARGS)
   2816        1.1  hsuenaga {
   2817        1.1  hsuenaga 	struct mvxpe_sysctl_mib *arg;
   2818        1.1  hsuenaga 	struct mvxpe_softc *sc;
   2819        1.1  hsuenaga 	struct sysctlnode node;
   2820        1.1  hsuenaga 	uint64_t val;
   2821        1.1  hsuenaga 	int err;
   2822        1.1  hsuenaga 
   2823        1.1  hsuenaga 	node = *rnode;
   2824        1.1  hsuenaga 	arg = (struct mvxpe_sysctl_mib *)rnode->sysctl_data;
   2825        1.1  hsuenaga 	if (arg == NULL)
   2826        1.1  hsuenaga 		return EINVAL;
   2827        1.1  hsuenaga 
   2828        1.1  hsuenaga 	sc = arg->sc;
   2829        1.1  hsuenaga 	if (sc == NULL)
   2830        1.1  hsuenaga 		return EINVAL;
   2831        1.1  hsuenaga 	if (arg->index < 0 || arg->index > __arraycount(mvxpe_mib_list))
   2832        1.1  hsuenaga 		return EINVAL;
   2833        1.1  hsuenaga 
   2834        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   2835        1.1  hsuenaga 	val = arg->counter;
   2836        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   2837        1.1  hsuenaga 
   2838        1.1  hsuenaga 	node.sysctl_data = &val;
   2839        1.1  hsuenaga 	err = sysctl_lookup(SYSCTLFN_CALL(&node));
   2840        1.1  hsuenaga 	if (err)
   2841        1.1  hsuenaga 	       return err;
   2842        1.1  hsuenaga 	if (newp)
   2843        1.1  hsuenaga 		return EINVAL;
   2844        1.1  hsuenaga 
   2845        1.1  hsuenaga 	return 0;
   2846        1.1  hsuenaga }
   2847        1.1  hsuenaga 
   2848        1.1  hsuenaga 
   2849        1.1  hsuenaga STATIC int
   2850        1.1  hsuenaga sysctl_clear_mib(SYSCTLFN_ARGS)
   2851        1.1  hsuenaga {
   2852        1.1  hsuenaga 	struct mvxpe_softc *sc;
   2853        1.1  hsuenaga 	struct sysctlnode node;
   2854        1.1  hsuenaga 	int val;
   2855        1.1  hsuenaga 	int err;
   2856        1.1  hsuenaga 
   2857        1.1  hsuenaga 	node = *rnode;
   2858        1.1  hsuenaga 	sc = (struct mvxpe_softc *)rnode->sysctl_data;
   2859        1.1  hsuenaga 	if (sc == NULL)
   2860        1.1  hsuenaga 		return EINVAL;
   2861        1.1  hsuenaga 
   2862        1.1  hsuenaga 	val = 0;
   2863        1.1  hsuenaga 	node.sysctl_data = &val;
   2864        1.1  hsuenaga 	err = sysctl_lookup(SYSCTLFN_CALL(&node));
   2865        1.1  hsuenaga 	if (err || newp == NULL)
   2866        1.1  hsuenaga 		return err;
   2867        1.1  hsuenaga 	if (val < 0 || val > 1)
   2868        1.1  hsuenaga 		return EINVAL;
   2869        1.1  hsuenaga 	if (val == 1) {
   2870        1.1  hsuenaga 		mvxpe_sc_lock(sc);
   2871        1.1  hsuenaga 		mvxpe_clear_mib(sc);
   2872        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   2873        1.1  hsuenaga 	}
   2874        1.1  hsuenaga 
   2875        1.1  hsuenaga 	return 0;
   2876        1.1  hsuenaga }
   2877        1.1  hsuenaga 
   2878        1.1  hsuenaga STATIC int
   2879        1.1  hsuenaga sysctl_set_queue_length(SYSCTLFN_ARGS)
   2880        1.1  hsuenaga {
   2881        1.1  hsuenaga 	struct mvxpe_sysctl_queue *arg;
   2882        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = NULL;
   2883        1.1  hsuenaga 	struct mvxpe_tx_ring *tx = NULL;
   2884        1.1  hsuenaga 	struct mvxpe_softc *sc;
   2885        1.1  hsuenaga 	struct sysctlnode node;
   2886        1.1  hsuenaga 	uint32_t reg;
   2887        1.1  hsuenaga 	int val;
   2888        1.1  hsuenaga 	int err;
   2889        1.1  hsuenaga 
   2890        1.1  hsuenaga 	node = *rnode;
   2891        1.1  hsuenaga 
   2892        1.1  hsuenaga 	arg = (struct mvxpe_sysctl_queue *)rnode->sysctl_data;
   2893        1.1  hsuenaga 	if (arg == NULL)
   2894        1.1  hsuenaga 		return EINVAL;
   2895        1.1  hsuenaga 	if (arg->queue < 0 || arg->queue > MVXPE_RX_RING_CNT)
   2896        1.1  hsuenaga 		return EINVAL;
   2897        1.1  hsuenaga 	if (arg->rxtx != MVXPE_SYSCTL_RX && arg->rxtx != MVXPE_SYSCTL_TX)
   2898        1.1  hsuenaga 		return EINVAL;
   2899        1.1  hsuenaga 
   2900        1.1  hsuenaga 	sc = arg->sc;
   2901        1.1  hsuenaga 	if (sc == NULL)
   2902        1.1  hsuenaga 		return EINVAL;
   2903        1.1  hsuenaga 
   2904        1.1  hsuenaga 	/* read queue length */
   2905        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   2906        1.1  hsuenaga 	switch (arg->rxtx) {
   2907        1.1  hsuenaga 	case  MVXPE_SYSCTL_RX:
   2908        1.1  hsuenaga 		mvxpe_rx_lockq(sc, arg->queue);
   2909        1.1  hsuenaga 		rx = MVXPE_RX_RING(sc, arg->queue);
   2910        1.1  hsuenaga 		val = rx->rx_queue_len;
   2911        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, arg->queue);
   2912        1.1  hsuenaga 		break;
   2913        1.1  hsuenaga 	case  MVXPE_SYSCTL_TX:
   2914        1.1  hsuenaga 		mvxpe_tx_lockq(sc, arg->queue);
   2915        1.1  hsuenaga 		tx = MVXPE_TX_RING(sc, arg->queue);
   2916        1.1  hsuenaga 		val = tx->tx_queue_len;
   2917        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, arg->queue);
   2918        1.1  hsuenaga 		break;
   2919        1.1  hsuenaga 	}
   2920        1.1  hsuenaga 
   2921        1.1  hsuenaga 	node.sysctl_data = &val;
   2922        1.1  hsuenaga 	err = sysctl_lookup(SYSCTLFN_CALL(&node));
   2923        1.1  hsuenaga 	if (err || newp == NULL) {
   2924        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   2925        1.1  hsuenaga 		return err;
   2926        1.1  hsuenaga 	}
   2927        1.1  hsuenaga 
   2928        1.1  hsuenaga 	/* update queue length */
   2929        1.1  hsuenaga 	if (val < 8 || val > MVXPE_RX_RING_CNT) {
   2930        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   2931        1.1  hsuenaga 		return EINVAL;
   2932        1.1  hsuenaga 	}
   2933        1.1  hsuenaga 	switch (arg->rxtx) {
   2934        1.1  hsuenaga 	case  MVXPE_SYSCTL_RX:
   2935        1.1  hsuenaga 		mvxpe_rx_lockq(sc, arg->queue);
   2936        1.1  hsuenaga 		rx->rx_queue_len = val;
   2937        1.2  hsuenaga 		rx->rx_queue_th_received =
   2938        1.2  hsuenaga 		    rx->rx_queue_len / MVXPE_RXTH_RATIO;
   2939        1.2  hsuenaga 		rx->rx_queue_th_free =
   2940        1.2  hsuenaga 		    rx->rx_queue_len / MVXPE_RXTH_REFILL_RATIO;
   2941        1.1  hsuenaga 
   2942        1.1  hsuenaga 		reg  = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received);
   2943        1.1  hsuenaga 		reg |= MVXPE_PRXDQTH_NODT(rx->rx_queue_th_free);
   2944        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PRXDQTH(arg->queue), reg);
   2945        1.1  hsuenaga 
   2946        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, arg->queue);
   2947        1.1  hsuenaga 		break;
   2948        1.1  hsuenaga 	case  MVXPE_SYSCTL_TX:
   2949        1.1  hsuenaga 		mvxpe_tx_lockq(sc, arg->queue);
   2950        1.1  hsuenaga 		tx->tx_queue_len = val;
   2951        1.2  hsuenaga 		tx->tx_queue_th_free =
   2952        1.2  hsuenaga 		    tx->tx_queue_len / MVXPE_TXTH_RATIO;
   2953        1.1  hsuenaga 
   2954        1.1  hsuenaga 		reg  = MVXPE_PTXDQS_TBT(tx->tx_queue_th_free);
   2955        1.1  hsuenaga 		reg |= MVXPE_PTXDQS_DQS(MVXPE_TX_RING_CNT);
   2956        1.1  hsuenaga 		MVXPE_WRITE(sc, MVXPE_PTXDQS(arg->queue), reg);
   2957        1.1  hsuenaga 
   2958        1.1  hsuenaga 		mvxpe_tx_unlockq(sc, arg->queue);
   2959        1.1  hsuenaga 		break;
   2960        1.1  hsuenaga 	}
   2961        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   2962        1.1  hsuenaga 
   2963        1.1  hsuenaga 	return 0;
   2964        1.1  hsuenaga }
   2965        1.1  hsuenaga 
   2966        1.1  hsuenaga STATIC int
   2967        1.1  hsuenaga sysctl_set_queue_rxthtime(SYSCTLFN_ARGS)
   2968        1.1  hsuenaga {
   2969        1.1  hsuenaga 	struct mvxpe_sysctl_queue *arg;
   2970        1.1  hsuenaga 	struct mvxpe_rx_ring *rx = NULL;
   2971        1.1  hsuenaga 	struct mvxpe_softc *sc;
   2972        1.1  hsuenaga 	struct sysctlnode node;
   2973        1.1  hsuenaga 	extern uint32_t mvTclk;
   2974        1.1  hsuenaga 	uint32_t reg, time_mvtclk;
   2975        1.1  hsuenaga 	int time_us;
   2976        1.1  hsuenaga 	int err;
   2977        1.1  hsuenaga 
   2978        1.1  hsuenaga 	node = *rnode;
   2979        1.1  hsuenaga 
   2980        1.1  hsuenaga 	arg = (struct mvxpe_sysctl_queue *)rnode->sysctl_data;
   2981        1.1  hsuenaga 	if (arg == NULL)
   2982        1.1  hsuenaga 		return EINVAL;
   2983        1.1  hsuenaga 	if (arg->queue < 0 || arg->queue > MVXPE_RX_RING_CNT)
   2984        1.1  hsuenaga 		return EINVAL;
   2985        1.1  hsuenaga 	if (arg->rxtx != MVXPE_SYSCTL_RX)
   2986        1.1  hsuenaga 		return EINVAL;
   2987        1.1  hsuenaga 
   2988        1.1  hsuenaga 	sc = arg->sc;
   2989        1.1  hsuenaga 	if (sc == NULL)
   2990        1.1  hsuenaga 		return EINVAL;
   2991        1.1  hsuenaga 
   2992        1.1  hsuenaga 	/* read queue length */
   2993        1.1  hsuenaga 	mvxpe_sc_lock(sc);
   2994        1.1  hsuenaga 	mvxpe_rx_lockq(sc, arg->queue);
   2995        1.1  hsuenaga 	rx = MVXPE_RX_RING(sc, arg->queue);
   2996        1.1  hsuenaga 	time_mvtclk = rx->rx_queue_th_time;
   2997        1.1  hsuenaga 	time_us = ((uint64_t)time_mvtclk * 1000ULL * 1000ULL) / mvTclk;
   2998        1.1  hsuenaga 	node.sysctl_data = &time_us;
   2999        1.1  hsuenaga 	DPRINTSC(sc, 1, "RXITTH(%d) => %#x\n",
   3000        1.1  hsuenaga 	    arg->queue, MVXPE_READ(sc, MVXPE_PRXITTH(arg->queue)));
   3001        1.1  hsuenaga 	err = sysctl_lookup(SYSCTLFN_CALL(&node));
   3002        1.1  hsuenaga 	if (err || newp == NULL) {
   3003        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, arg->queue);
   3004        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   3005        1.1  hsuenaga 		return err;
   3006        1.1  hsuenaga 	}
   3007        1.1  hsuenaga 
   3008        1.1  hsuenaga 	/* update queue length (0[sec] - 1[sec]) */
   3009        1.1  hsuenaga 	if (time_us < 0 || time_us > (1000 * 1000)) {
   3010        1.1  hsuenaga 		mvxpe_rx_unlockq(sc, arg->queue);
   3011        1.1  hsuenaga 		mvxpe_sc_unlock(sc);
   3012        1.1  hsuenaga 		return EINVAL;
   3013        1.1  hsuenaga 	}
   3014        1.1  hsuenaga 	time_mvtclk =
   3015        1.1  hsuenaga 	    (uint64_t)mvTclk * (uint64_t)time_us / (1000ULL * 1000ULL);
   3016        1.1  hsuenaga 	rx->rx_queue_th_time = time_mvtclk;
   3017        1.1  hsuenaga 	reg = MVXPE_PRXITTH_RITT(rx->rx_queue_th_time);
   3018        1.1  hsuenaga 	MVXPE_WRITE(sc, MVXPE_PRXITTH(arg->queue), reg);
   3019        1.1  hsuenaga 	DPRINTSC(sc, 1, "RXITTH(%d) => %#x\n", arg->queue, reg);
   3020        1.1  hsuenaga 	mvxpe_rx_unlockq(sc, arg->queue);
   3021        1.1  hsuenaga 	mvxpe_sc_unlock(sc);
   3022        1.1  hsuenaga 
   3023        1.1  hsuenaga 	return 0;
   3024        1.1  hsuenaga }
   3025        1.1  hsuenaga 
   3026        1.1  hsuenaga 
   3027        1.1  hsuenaga STATIC void
   3028        1.1  hsuenaga sysctl_mvxpe_init(struct mvxpe_softc *sc)
   3029        1.1  hsuenaga {
   3030        1.1  hsuenaga 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   3031        1.1  hsuenaga 	const struct sysctlnode *node;
   3032        1.1  hsuenaga 	int mvxpe_nodenum;
   3033        1.1  hsuenaga 	int mvxpe_mibnum;
   3034        1.1  hsuenaga 	int mvxpe_rxqueuenum;
   3035        1.1  hsuenaga 	int mvxpe_txqueuenum;
   3036        1.1  hsuenaga 	int q, i;
   3037        1.1  hsuenaga 
   3038        1.1  hsuenaga 	/* hw.mvxpe.mvxpe[unit] */
   3039        1.1  hsuenaga 	if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3040        1.1  hsuenaga 	    0, CTLTYPE_NODE, ifp->if_xname,
   3041        1.1  hsuenaga 	    SYSCTL_DESCR("mvxpe per-controller controls"),
   3042        1.1  hsuenaga 	    NULL, 0, NULL, 0,
   3043        1.1  hsuenaga 	    CTL_HW, mvxpe_root_num, CTL_CREATE,
   3044        1.1  hsuenaga 	    CTL_EOL) != 0) {
   3045        1.1  hsuenaga 		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
   3046        1.1  hsuenaga 		return;
   3047        1.1  hsuenaga 	}
   3048        1.1  hsuenaga 	mvxpe_nodenum = node->sysctl_num;
   3049        1.1  hsuenaga 
   3050        1.1  hsuenaga 	/* hw.mvxpe.mvxpe[unit].mib */
   3051        1.1  hsuenaga 	if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3052        1.1  hsuenaga 	    0, CTLTYPE_NODE, "mib",
   3053        1.1  hsuenaga 	    SYSCTL_DESCR("mvxpe per-controller MIB counters"),
   3054        1.1  hsuenaga 	    NULL, 0, NULL, 0,
   3055        1.1  hsuenaga 	    CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE,
   3056        1.1  hsuenaga 	    CTL_EOL) != 0) {
   3057        1.1  hsuenaga 		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
   3058        1.1  hsuenaga 		return;
   3059        1.1  hsuenaga 	}
   3060        1.1  hsuenaga 	mvxpe_mibnum = node->sysctl_num;
   3061        1.1  hsuenaga 
   3062        1.1  hsuenaga 	/* hw.mvxpe.mvxpe[unit].rx */
   3063        1.1  hsuenaga 	if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3064        1.1  hsuenaga 	    0, CTLTYPE_NODE, "rx",
   3065        1.1  hsuenaga 	    SYSCTL_DESCR("Rx Queues"),
   3066        1.1  hsuenaga 	    NULL, 0, NULL, 0,
   3067        1.1  hsuenaga 	    CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE, CTL_EOL) != 0) {
   3068        1.1  hsuenaga 		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
   3069        1.1  hsuenaga 		return;
   3070        1.1  hsuenaga 	}
   3071        1.1  hsuenaga 	mvxpe_rxqueuenum = node->sysctl_num;
   3072        1.1  hsuenaga 
   3073        1.1  hsuenaga 	/* hw.mvxpe.mvxpe[unit].tx */
   3074        1.1  hsuenaga 	if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3075        1.1  hsuenaga 	    0, CTLTYPE_NODE, "tx",
   3076        1.1  hsuenaga 	    SYSCTL_DESCR("Tx Queues"),
   3077        1.1  hsuenaga 	    NULL, 0, NULL, 0,
   3078        1.1  hsuenaga 	    CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE, CTL_EOL) != 0) {
   3079        1.1  hsuenaga 		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
   3080        1.1  hsuenaga 		return;
   3081        1.1  hsuenaga 	}
   3082        1.1  hsuenaga 	mvxpe_txqueuenum = node->sysctl_num;
   3083        1.1  hsuenaga 
   3084        1.1  hsuenaga #ifdef MVXPE_DEBUG
   3085        1.1  hsuenaga 	/* hw.mvxpe.debug */
   3086        1.1  hsuenaga 	if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3087        1.1  hsuenaga 	    CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
   3088       1.11    hikaru 	    SYSCTL_DESCR("mvxpe device driver debug control"),
   3089        1.1  hsuenaga 	    NULL, 0, &mvxpe_debug, 0,
   3090        1.1  hsuenaga 	    CTL_HW, mvxpe_root_num, CTL_CREATE, CTL_EOL) != 0) {
   3091        1.1  hsuenaga 		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
   3092        1.1  hsuenaga 		return;
   3093        1.1  hsuenaga 	}
   3094        1.1  hsuenaga #endif
   3095        1.1  hsuenaga 	/*
   3096        1.1  hsuenaga 	 * MIB access
   3097        1.1  hsuenaga 	 */
   3098        1.1  hsuenaga 	/* hw.mvxpe.mvxpe[unit].mib.<mibs> */
   3099        1.1  hsuenaga 	for (i = 0; i < __arraycount(mvxpe_mib_list); i++) {
   3100        1.1  hsuenaga 		const char *name = mvxpe_mib_list[i].sysctl_name;
   3101        1.1  hsuenaga 		const char *desc = mvxpe_mib_list[i].desc;
   3102        1.1  hsuenaga 		struct mvxpe_sysctl_mib *mib_arg = &sc->sc_sysctl_mib[i];
   3103        1.1  hsuenaga 
   3104        1.1  hsuenaga 		mib_arg->sc = sc;
   3105        1.1  hsuenaga 		mib_arg->index = i;
   3106        1.1  hsuenaga 		if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3107        1.1  hsuenaga 		    CTLFLAG_READONLY, CTLTYPE_QUAD, name, desc,
   3108        1.1  hsuenaga 		    sysctl_read_mib, 0, (void *)mib_arg, 0,
   3109        1.1  hsuenaga 		    CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_mibnum,
   3110        1.1  hsuenaga 		    CTL_CREATE, CTL_EOL) != 0) {
   3111        1.1  hsuenaga 			aprint_normal_dev(sc->sc_dev,
   3112        1.1  hsuenaga 			    "couldn't create sysctl node\n");
   3113        1.1  hsuenaga 			break;
   3114        1.1  hsuenaga 		}
   3115        1.1  hsuenaga 	}
   3116        1.1  hsuenaga 
   3117        1.1  hsuenaga 	for (q = 0; q < MVXPE_QUEUE_SIZE; q++) {
   3118        1.1  hsuenaga 		struct mvxpe_sysctl_queue *rxarg = &sc->sc_sysctl_rx_queue[q];
   3119        1.1  hsuenaga 		struct mvxpe_sysctl_queue *txarg = &sc->sc_sysctl_tx_queue[q];
   3120        1.1  hsuenaga #define MVXPE_SYSCTL_NAME(num) "queue" # num
   3121        1.1  hsuenaga 		static const char *sysctl_queue_names[] = {
   3122        1.1  hsuenaga 			MVXPE_SYSCTL_NAME(0), MVXPE_SYSCTL_NAME(1),
   3123        1.1  hsuenaga 			MVXPE_SYSCTL_NAME(2), MVXPE_SYSCTL_NAME(3),
   3124        1.1  hsuenaga 			MVXPE_SYSCTL_NAME(4), MVXPE_SYSCTL_NAME(5),
   3125        1.1  hsuenaga 			MVXPE_SYSCTL_NAME(6), MVXPE_SYSCTL_NAME(7),
   3126        1.1  hsuenaga 		};
   3127        1.1  hsuenaga #undef MVXPE_SYSCTL_NAME
   3128        1.1  hsuenaga #ifdef SYSCTL_INCLUDE_DESCR
   3129        1.1  hsuenaga #define MVXPE_SYSCTL_DESCR(num) "configuration parameters for queue " # num
   3130        1.1  hsuenaga 		static const char *sysctl_queue_descrs[] = {
   3131       1.11    hikaru 			MVXPE_SYSCTL_DESCR(0), MVXPE_SYSCTL_DESCR(1),
   3132       1.11    hikaru 			MVXPE_SYSCTL_DESCR(2), MVXPE_SYSCTL_DESCR(3),
   3133       1.11    hikaru 			MVXPE_SYSCTL_DESCR(4), MVXPE_SYSCTL_DESCR(5),
   3134       1.11    hikaru 			MVXPE_SYSCTL_DESCR(6), MVXPE_SYSCTL_DESCR(7),
   3135        1.1  hsuenaga 		};
   3136        1.1  hsuenaga #undef MVXPE_SYSCTL_DESCR
   3137        1.1  hsuenaga #endif /* SYSCTL_INCLUDE_DESCR */
   3138        1.1  hsuenaga 		int mvxpe_curnum;
   3139        1.1  hsuenaga 
   3140        1.1  hsuenaga 		rxarg->sc = txarg->sc = sc;
   3141        1.1  hsuenaga 		rxarg->queue = txarg->queue = q;
   3142        1.1  hsuenaga 		rxarg->rxtx = MVXPE_SYSCTL_RX;
   3143        1.1  hsuenaga 		txarg->rxtx = MVXPE_SYSCTL_TX;
   3144        1.1  hsuenaga 
   3145        1.1  hsuenaga 		/* hw.mvxpe.mvxpe[unit].rx.[queue] */
   3146        1.1  hsuenaga 		if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3147        1.1  hsuenaga 		    0, CTLTYPE_NODE,
   3148        1.1  hsuenaga 		    sysctl_queue_names[q], SYSCTL_DESCR(sysctl_queue_descrs[q]),
   3149        1.1  hsuenaga 		    NULL, 0, NULL, 0,
   3150        1.1  hsuenaga 		    CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_rxqueuenum,
   3151        1.1  hsuenaga 		    CTL_CREATE, CTL_EOL) != 0) {
   3152        1.1  hsuenaga 			aprint_normal_dev(sc->sc_dev,
   3153        1.1  hsuenaga 			    "couldn't create sysctl node\n");
   3154        1.1  hsuenaga 			break;
   3155        1.1  hsuenaga 		}
   3156        1.1  hsuenaga 		mvxpe_curnum = node->sysctl_num;
   3157        1.1  hsuenaga 
   3158        1.1  hsuenaga 		/* hw.mvxpe.mvxpe[unit].rx.[queue].length */
   3159        1.1  hsuenaga 		if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3160        1.1  hsuenaga 		    CTLFLAG_READWRITE, CTLTYPE_INT, "length",
   3161        1.1  hsuenaga 		    SYSCTL_DESCR("maximum length of the queue"),
   3162        1.1  hsuenaga 		    sysctl_set_queue_length, 0, (void *)rxarg, 0,
   3163        1.1  hsuenaga 		    CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_rxqueuenum,
   3164        1.1  hsuenaga 		    mvxpe_curnum, CTL_CREATE, CTL_EOL) != 0) {
   3165        1.1  hsuenaga 			aprint_normal_dev(sc->sc_dev,
   3166        1.1  hsuenaga 			    "couldn't create sysctl node\n");
   3167        1.1  hsuenaga 			break;
   3168        1.1  hsuenaga 		}
   3169        1.1  hsuenaga 
   3170        1.1  hsuenaga 		/* hw.mvxpe.mvxpe[unit].rx.[queue].threshold_timer_us */
   3171        1.1  hsuenaga 		if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3172        1.1  hsuenaga 		    CTLFLAG_READWRITE, CTLTYPE_INT, "threshold_timer_us",
   3173        1.1  hsuenaga 		    SYSCTL_DESCR("interrupt coalescing threshold timer [us]"),
   3174        1.1  hsuenaga 		    sysctl_set_queue_rxthtime, 0, (void *)rxarg, 0,
   3175        1.1  hsuenaga 		    CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_rxqueuenum,
   3176        1.1  hsuenaga 		    mvxpe_curnum, CTL_CREATE, CTL_EOL) != 0) {
   3177        1.1  hsuenaga 			aprint_normal_dev(sc->sc_dev,
   3178        1.1  hsuenaga 			    "couldn't create sysctl node\n");
   3179        1.1  hsuenaga 			break;
   3180        1.1  hsuenaga 		}
   3181        1.1  hsuenaga 
   3182        1.1  hsuenaga 		/* hw.mvxpe.mvxpe[unit].tx.[queue] */
   3183        1.1  hsuenaga 		if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3184        1.1  hsuenaga 		    0, CTLTYPE_NODE,
   3185        1.1  hsuenaga 		    sysctl_queue_names[q], SYSCTL_DESCR(sysctl_queue_descs[q]),
   3186        1.1  hsuenaga 		    NULL, 0, NULL, 0,
   3187        1.1  hsuenaga 		    CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_txqueuenum,
   3188        1.1  hsuenaga 		    CTL_CREATE, CTL_EOL) != 0) {
   3189        1.1  hsuenaga 			aprint_normal_dev(sc->sc_dev,
   3190        1.1  hsuenaga 			    "couldn't create sysctl node\n");
   3191        1.1  hsuenaga 			break;
   3192        1.1  hsuenaga 		}
   3193        1.1  hsuenaga 		mvxpe_curnum = node->sysctl_num;
   3194        1.1  hsuenaga 
   3195        1.1  hsuenaga 		/* hw.mvxpe.mvxpe[unit].tx.length[queue] */
   3196        1.1  hsuenaga 		if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3197        1.1  hsuenaga 		    CTLFLAG_READWRITE, CTLTYPE_INT, "length",
   3198        1.1  hsuenaga 		    SYSCTL_DESCR("maximum length of the queue"),
   3199        1.1  hsuenaga 		    sysctl_set_queue_length, 0, (void *)txarg, 0,
   3200        1.1  hsuenaga 		    CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_txqueuenum,
   3201        1.1  hsuenaga 		    mvxpe_curnum, CTL_CREATE, CTL_EOL) != 0) {
   3202        1.1  hsuenaga 			aprint_normal_dev(sc->sc_dev,
   3203        1.1  hsuenaga 			    "couldn't create sysctl node\n");
   3204        1.1  hsuenaga 			break;
   3205        1.1  hsuenaga 		}
   3206        1.1  hsuenaga 	}
   3207        1.1  hsuenaga 
   3208        1.1  hsuenaga 	/* hw.mvxpe.mvxpe[unit].clear_mib */
   3209        1.1  hsuenaga 	if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node,
   3210        1.1  hsuenaga 	    CTLFLAG_READWRITE, CTLTYPE_INT, "clear_mib",
   3211       1.11    hikaru 	    SYSCTL_DESCR("mvxpe device driver debug control"),
   3212        1.1  hsuenaga 	    sysctl_clear_mib, 0, (void *)sc, 0,
   3213        1.1  hsuenaga 	    CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE,
   3214        1.1  hsuenaga 	    CTL_EOL) != 0) {
   3215        1.1  hsuenaga 		aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n");
   3216        1.1  hsuenaga 		return;
   3217        1.1  hsuenaga 	}
   3218        1.1  hsuenaga 
   3219        1.1  hsuenaga }
   3220        1.1  hsuenaga 
   3221        1.1  hsuenaga /*
   3222        1.1  hsuenaga  * MIB
   3223        1.1  hsuenaga  */
   3224        1.1  hsuenaga STATIC void
   3225        1.1  hsuenaga mvxpe_clear_mib(struct mvxpe_softc *sc)
   3226        1.1  hsuenaga {
   3227        1.1  hsuenaga 	int i;
   3228        1.1  hsuenaga 
   3229        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   3230        1.1  hsuenaga 
   3231        1.1  hsuenaga 	for (i = 0; i < __arraycount(mvxpe_mib_list); i++) {
   3232        1.1  hsuenaga 		if (mvxpe_mib_list[i].reg64)
   3233        1.1  hsuenaga 			MVXPE_READ_MIB(sc, (mvxpe_mib_list[i].regnum + 4));
   3234        1.1  hsuenaga 		MVXPE_READ_MIB(sc, mvxpe_mib_list[i].regnum);
   3235        1.1  hsuenaga 		sc->sc_sysctl_mib[i].counter = 0;
   3236        1.1  hsuenaga 	}
   3237        1.1  hsuenaga }
   3238        1.1  hsuenaga 
   3239        1.1  hsuenaga STATIC void
   3240        1.1  hsuenaga mvxpe_update_mib(struct mvxpe_softc *sc)
   3241        1.1  hsuenaga {
   3242       1.10    hikaru 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   3243        1.1  hsuenaga 	int i;
   3244        1.1  hsuenaga 
   3245        1.1  hsuenaga 	KASSERT_SC_MTX(sc);
   3246        1.1  hsuenaga 
   3247        1.1  hsuenaga 	for (i = 0; i < __arraycount(mvxpe_mib_list); i++) {
   3248        1.1  hsuenaga 		uint32_t val_hi;
   3249        1.1  hsuenaga 		uint32_t val_lo;
   3250       1.10    hikaru 		uint64_t val;
   3251        1.1  hsuenaga 
   3252        1.1  hsuenaga 		if (mvxpe_mib_list[i].reg64) {
   3253        1.1  hsuenaga 			/* XXX: implement bus_space_read_8() */
   3254        1.1  hsuenaga 			val_lo = MVXPE_READ_MIB(sc,
   3255        1.1  hsuenaga 			    (mvxpe_mib_list[i].regnum + 4));
   3256        1.1  hsuenaga 			val_hi = MVXPE_READ_MIB(sc, mvxpe_mib_list[i].regnum);
   3257        1.1  hsuenaga 		}
   3258        1.1  hsuenaga 		else {
   3259        1.1  hsuenaga 			val_lo = MVXPE_READ_MIB(sc, mvxpe_mib_list[i].regnum);
   3260        1.1  hsuenaga 			val_hi = 0;
   3261        1.1  hsuenaga 		}
   3262        1.1  hsuenaga 
   3263        1.1  hsuenaga 		if ((val_lo | val_hi) == 0)
   3264        1.1  hsuenaga 			continue;
   3265        1.1  hsuenaga 
   3266       1.10    hikaru 		val = ((uint64_t)val_hi << 32) | (uint64_t)val_lo;
   3267       1.10    hikaru 		sc->sc_sysctl_mib[i].counter += val;
   3268       1.10    hikaru 
   3269       1.10    hikaru 		switch (mvxpe_mib_list[i].ext) {
   3270       1.10    hikaru 		case MVXPE_MIBEXT_IF_OERRORS:
   3271       1.10    hikaru 			ifp->if_oerrors += val;
   3272       1.10    hikaru 			break;
   3273       1.10    hikaru 		case MVXPE_MIBEXT_IF_IERRORS:
   3274       1.10    hikaru 			ifp->if_ierrors += val;
   3275       1.10    hikaru 			break;
   3276       1.10    hikaru 		case MVXPE_MIBEXT_IF_COLLISIONS:
   3277       1.10    hikaru 			ifp->if_collisions += val;
   3278       1.10    hikaru 			break;
   3279       1.10    hikaru 		default:
   3280       1.10    hikaru 			break;
   3281       1.10    hikaru 		}
   3282       1.10    hikaru 
   3283        1.1  hsuenaga 	}
   3284        1.1  hsuenaga }
   3285        1.1  hsuenaga 
   3286        1.1  hsuenaga /*
   3287        1.1  hsuenaga  * for Debug
   3288        1.1  hsuenaga  */
   3289        1.1  hsuenaga STATIC void
   3290        1.1  hsuenaga mvxpe_dump_txdesc(struct mvxpe_tx_desc *desc, int idx)
   3291        1.1  hsuenaga {
   3292        1.1  hsuenaga #define DESC_PRINT(X)					\
   3293        1.1  hsuenaga 	if (X)						\
   3294        1.1  hsuenaga 		printf("txdesc[%d]." #X "=%#x\n", idx, X);
   3295        1.1  hsuenaga 
   3296        1.1  hsuenaga        DESC_PRINT(desc->command);
   3297        1.1  hsuenaga        DESC_PRINT(desc->l4ichk);
   3298        1.1  hsuenaga        DESC_PRINT(desc->bytecnt);
   3299        1.1  hsuenaga        DESC_PRINT(desc->bufptr);
   3300        1.1  hsuenaga        DESC_PRINT(desc->flags);
   3301        1.1  hsuenaga #undef DESC_PRINT
   3302        1.1  hsuenaga }
   3303        1.1  hsuenaga 
   3304        1.1  hsuenaga STATIC void
   3305        1.1  hsuenaga mvxpe_dump_rxdesc(struct mvxpe_rx_desc *desc, int idx)
   3306        1.1  hsuenaga {
   3307        1.1  hsuenaga #define DESC_PRINT(X)					\
   3308        1.1  hsuenaga 	if (X)						\
   3309        1.1  hsuenaga 		printf("rxdesc[%d]." #X "=%#x\n", idx, X);
   3310        1.1  hsuenaga 
   3311        1.1  hsuenaga        DESC_PRINT(desc->status);
   3312        1.1  hsuenaga        DESC_PRINT(desc->bytecnt);
   3313        1.1  hsuenaga        DESC_PRINT(desc->bufptr);
   3314        1.1  hsuenaga        DESC_PRINT(desc->l4chk);
   3315        1.1  hsuenaga #undef DESC_PRINT
   3316        1.1  hsuenaga }
   3317