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