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