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