Home | History | Annotate | Download | only in rge
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include "rge.h"
     29 
     30 #define	RGE_DBG		RGE_DBG_STATS	/* debug flag for this code	*/
     31 
     32 /*
     33  * Local datatype for defining tables of (Offset, Name) pairs
     34  */
     35 typedef struct {
     36 	offset_t	index;
     37 	char		*name;
     38 } rge_ksindex_t;
     39 
     40 static const rge_ksindex_t rge_driverinfo[] = {
     41 	{ 0,		"rx_ring_addr"		},
     42 	{ 1,		"rx_next"		},
     43 	{ 2,		"rx_free"		},
     44 	{ 3,		"rx_bcopy"		},
     45 	{ 4,		"tx_ring_addr"		},
     46 	{ 5,		"tx_next"		},
     47 	{ 6,		"tx_free"		},
     48 	{ 7,		"tx_flow"		},
     49 	{ 8,		"resched_needed"	},
     50 	{ 9,		"watchdog"		},
     51 	{ 10,		"rx_config"		},
     52 	{ 11,		"tx_config"		},
     53 	{ 12,		"mac_ver"		},
     54 	{ 13,		"phy_ver"		},
     55 	{ 14,		"chip_reset"		},
     56 	{ 15,		"phy_reset"		},
     57 	{ 16,		"loop_mode"		},
     58 	{ -1,		NULL 			}
     59 };
     60 
     61 static int
     62 rge_driverinfo_update(kstat_t *ksp, int flag)
     63 {
     64 	rge_t *rgep;
     65 	kstat_named_t *knp;
     66 
     67 	if (flag != KSTAT_READ)
     68 		return (EACCES);
     69 
     70 	rgep = ksp->ks_private;
     71 	knp = ksp->ks_data;
     72 
     73 	(knp++)->value.ui64 = rgep->dma_area_rxdesc.cookie.dmac_laddress;
     74 	(knp++)->value.ui64 = rgep->rx_next;
     75 	(knp++)->value.ui64 = rgep->rx_free;
     76 	(knp++)->value.ui64 = rgep->rx_bcopy;
     77 	(knp++)->value.ui64 = rgep->dma_area_txdesc.cookie.dmac_laddress;
     78 	(knp++)->value.ui64 = rgep->tx_next;
     79 	(knp++)->value.ui64 = rgep->tx_free;
     80 	(knp++)->value.ui64 = rgep->tx_flow;
     81 	(knp++)->value.ui64 = rgep->resched_needed;
     82 	(knp++)->value.ui64 = rgep->watchdog;
     83 	(knp++)->value.ui64 = rgep->chipid.rxconfig;
     84 	(knp++)->value.ui64 = rgep->chipid.txconfig;
     85 	(knp++)->value.ui64 = rgep->chipid.mac_ver;
     86 	(knp++)->value.ui64 = rgep->chipid.phy_ver;
     87 	(knp++)->value.ui64 = rgep->stats.chip_reset;
     88 	(knp++)->value.ui64 = rgep->stats.phy_reset;
     89 	(knp++)->value.ui64 = rgep->param_loop_mode;
     90 
     91 	return (0);
     92 }
     93 
     94 static kstat_t *
     95 rge_setup_named_kstat(rge_t *rgep, int instance, char *name,
     96 	const rge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
     97 {
     98 	kstat_t *ksp;
     99 	kstat_named_t *knp;
    100 	char *np;
    101 	int type;
    102 
    103 	size /= sizeof (rge_ksindex_t);
    104 	ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
    105 		KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
    106 	if (ksp == NULL)
    107 		return (NULL);
    108 
    109 	ksp->ks_private = rgep;
    110 	ksp->ks_update = update;
    111 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
    112 		switch (*np) {
    113 		default:
    114 			type = KSTAT_DATA_UINT64;
    115 			break;
    116 		case '%':
    117 			np += 1;
    118 			type = KSTAT_DATA_UINT32;
    119 			break;
    120 		case '$':
    121 			np += 1;
    122 			type = KSTAT_DATA_STRING;
    123 			break;
    124 		case '&':
    125 			np += 1;
    126 			type = KSTAT_DATA_CHAR;
    127 			break;
    128 		}
    129 		kstat_named_init(knp, np, type);
    130 	}
    131 	kstat_install(ksp);
    132 
    133 	return (ksp);
    134 }
    135 
    136 void
    137 rge_init_kstats(rge_t *rgep, int instance)
    138 {
    139 	rgep->rge_kstats[RGE_KSTAT_DRIVER] = rge_setup_named_kstat(rgep,
    140 		instance, "driverinfo", rge_driverinfo,
    141 		sizeof (rge_driverinfo), rge_driverinfo_update);
    142 }
    143 
    144 void
    145 rge_fini_kstats(rge_t *rgep)
    146 {
    147 	int i;
    148 
    149 	for (i = RGE_KSTAT_COUNT; --i >= 0; )
    150 		if (rgep->rge_kstats[i] != NULL) {
    151 			kstat_delete(rgep->rge_kstats[i]);
    152 		}
    153 }
    154 
    155 int
    156 rge_m_stat(void *arg, uint_t stat, uint64_t *val)
    157 {
    158 	rge_t *rgep = arg;
    159 	rge_hw_stats_t *bstp;
    160 
    161 	mutex_enter(rgep->genlock);
    162 	rge_hw_stats_dump(rgep);
    163 	mutex_exit(rgep->genlock);
    164 	bstp = rgep->hw_stats;
    165 
    166 	switch (stat) {
    167 	case MAC_STAT_IFSPEED:
    168 		*val = rgep->param_link_speed * 1000000ull;
    169 		break;
    170 
    171 	case MAC_STAT_MULTIRCV:
    172 		*val = RGE_BSWAP_32(bstp->multi_rcv);
    173 		break;
    174 
    175 	case MAC_STAT_BRDCSTRCV:
    176 		*val = RGE_BSWAP_64(bstp->brdcst_rcv);
    177 		break;
    178 
    179 	case MAC_STAT_NORCVBUF:
    180 		*val = RGE_BSWAP_16(bstp->in_discards);
    181 		break;
    182 
    183 	case MAC_STAT_IERRORS:
    184 		*val = RGE_BSWAP_32(bstp->rcv_err);
    185 		break;
    186 
    187 	case MAC_STAT_OERRORS:
    188 		*val = RGE_BSWAP_64(bstp->xmt_err);
    189 		break;
    190 
    191 	case MAC_STAT_COLLISIONS:
    192 		*val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
    193 		break;
    194 
    195 	case MAC_STAT_RBYTES:
    196 		*val = rgep->stats.rbytes;
    197 		break;
    198 
    199 	case MAC_STAT_IPACKETS:
    200 		*val = RGE_BSWAP_64(bstp->rcv_ok);
    201 		break;
    202 
    203 	case MAC_STAT_OBYTES:
    204 		*val = rgep->stats.obytes;
    205 		break;
    206 
    207 	case MAC_STAT_OPACKETS:
    208 		*val = RGE_BSWAP_64(bstp->xmt_ok);
    209 		break;
    210 
    211 	case ETHER_STAT_ALIGN_ERRORS:
    212 		*val = RGE_BSWAP_16(bstp->frame_err);
    213 		break;
    214 
    215 	case ETHER_STAT_FIRST_COLLISIONS:
    216 		*val = RGE_BSWAP_32(bstp->xmt_1col);
    217 		break;
    218 
    219 	case ETHER_STAT_MULTI_COLLISIONS:
    220 		*val = RGE_BSWAP_32(bstp->xmt_mcol);
    221 		break;
    222 
    223 	case ETHER_STAT_DEFER_XMTS:
    224 		*val = rgep->stats.defer;
    225 		break;
    226 
    227 	case ETHER_STAT_XCVR_ADDR:
    228 		*val = rgep->phy_mii_addr;
    229 		break;
    230 
    231 	case ETHER_STAT_XCVR_ID:
    232 		mutex_enter(rgep->genlock);
    233 		*val = rge_mii_get16(rgep, MII_PHYIDH);
    234 		*val <<= 16;
    235 		*val |= rge_mii_get16(rgep, MII_PHYIDL);
    236 		mutex_exit(rgep->genlock);
    237 		break;
    238 
    239 	case ETHER_STAT_XCVR_INUSE:
    240 		*val = XCVR_1000T;
    241 		break;
    242 
    243 	case ETHER_STAT_CAP_1000FDX:
    244 		*val = 1;
    245 		break;
    246 
    247 	case ETHER_STAT_CAP_1000HDX:
    248 		*val = 0;
    249 		break;
    250 
    251 	case ETHER_STAT_CAP_100FDX:
    252 		*val = 1;
    253 		break;
    254 
    255 	case ETHER_STAT_CAP_100HDX:
    256 		*val = 1;
    257 		break;
    258 
    259 	case ETHER_STAT_CAP_10FDX:
    260 		*val = 1;
    261 		break;
    262 
    263 	case ETHER_STAT_CAP_10HDX:
    264 		*val = 1;
    265 		break;
    266 
    267 	case ETHER_STAT_CAP_ASMPAUSE:
    268 		*val = 1;
    269 		break;
    270 
    271 	case ETHER_STAT_CAP_PAUSE:
    272 		*val = 1;
    273 		break;
    274 
    275 	case ETHER_STAT_CAP_AUTONEG:
    276 		*val = 1;
    277 		break;
    278 
    279 	case ETHER_STAT_ADV_CAP_1000FDX:
    280 		*val = rgep->param_adv_1000fdx;
    281 		break;
    282 
    283 	case ETHER_STAT_ADV_CAP_1000HDX:
    284 		*val = rgep->param_adv_1000hdx;
    285 		break;
    286 
    287 	case ETHER_STAT_ADV_CAP_100FDX:
    288 		*val = rgep->param_adv_100fdx;
    289 		break;
    290 
    291 	case ETHER_STAT_ADV_CAP_100HDX:
    292 		*val = rgep->param_adv_100hdx;
    293 		break;
    294 
    295 	case ETHER_STAT_ADV_CAP_10FDX:
    296 		*val = rgep->param_adv_10fdx;
    297 		break;
    298 
    299 	case ETHER_STAT_ADV_CAP_10HDX:
    300 		*val = rgep->param_adv_10hdx;
    301 		break;
    302 
    303 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
    304 		*val = rgep->param_adv_asym_pause;
    305 		break;
    306 
    307 	case ETHER_STAT_ADV_CAP_PAUSE:
    308 		*val = rgep->param_adv_pause;
    309 		break;
    310 
    311 	case ETHER_STAT_ADV_CAP_AUTONEG:
    312 		*val = rgep->param_adv_autoneg;
    313 		break;
    314 
    315 	case ETHER_STAT_LINK_DUPLEX:
    316 		*val = rgep->param_link_duplex;
    317 		break;
    318 
    319 	default:
    320 		return (ENOTSUP);
    321 	}
    322 
    323 	return (0);
    324 }
    325