Home | History | Annotate | Download | only in bge
      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 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include "bge_impl.h"
     28 
     29 #define	BGE_DBG		BGE_DBG_STATS	/* debug flag for this code	*/
     30 
     31 /*
     32  * Local datatype for defining tables of (Offset, Name) pairs
     33  */
     34 typedef struct {
     35 	offset_t	index;
     36 	char		*name;
     37 } bge_ksindex_t;
     38 
     39 
     40 /*
     41  * Table of Hardware-defined Statistics Block Offsets and Names
     42  */
     43 #define	KS_NAME(s)			{ KS_ ## s, #s }
     44 
     45 static const bge_ksindex_t bge_statistics[] = {
     46 	KS_NAME(ifHCInOctets),
     47 	KS_NAME(etherStatsFragments),
     48 	KS_NAME(ifHCInUcastPkts),
     49 	KS_NAME(ifHCInMulticastPkts),
     50 	KS_NAME(ifHCInBroadcastPkts),
     51 	KS_NAME(dot3StatsFCSErrors),
     52 	KS_NAME(dot3StatsAlignmentErrors),
     53 	KS_NAME(xonPauseFramesReceived),
     54 	KS_NAME(xoffPauseFramesReceived),
     55 	KS_NAME(macControlFramesReceived),
     56 	KS_NAME(xoffStateEntered),
     57 	KS_NAME(dot3StatsFrameTooLongs),
     58 	KS_NAME(etherStatsJabbers),
     59 	KS_NAME(etherStatsUndersizePkts),
     60 	KS_NAME(inRangeLengthError),
     61 	KS_NAME(outRangeLengthError),
     62 	KS_NAME(etherStatsPkts64Octets),
     63 	KS_NAME(etherStatsPkts65to127Octets),
     64 	KS_NAME(etherStatsPkts128to255Octets),
     65 	KS_NAME(etherStatsPkts256to511Octets),
     66 	KS_NAME(etherStatsPkts512to1023Octets),
     67 	KS_NAME(etherStatsPkts1024to1518Octets),
     68 	KS_NAME(etherStatsPkts1519to2047Octets),
     69 	KS_NAME(etherStatsPkts2048to4095Octets),
     70 	KS_NAME(etherStatsPkts4096to8191Octets),
     71 	KS_NAME(etherStatsPkts8192to9022Octets),
     72 
     73 	KS_NAME(ifHCOutOctets),
     74 	KS_NAME(etherStatsCollisions),
     75 	KS_NAME(outXonSent),
     76 	KS_NAME(outXoffSent),
     77 	KS_NAME(flowControlDone),
     78 	KS_NAME(dot3StatsInternalMacTransmitErrors),
     79 	KS_NAME(dot3StatsSingleCollisionFrames),
     80 	KS_NAME(dot3StatsMultipleCollisionFrames),
     81 	KS_NAME(dot3StatsDeferredTransmissions),
     82 	KS_NAME(dot3StatsExcessiveCollisions),
     83 	KS_NAME(dot3StatsLateCollisions),
     84 	KS_NAME(dot3Collided2Times),
     85 	KS_NAME(dot3Collided3Times),
     86 	KS_NAME(dot3Collided4Times),
     87 	KS_NAME(dot3Collided5Times),
     88 	KS_NAME(dot3Collided6Times),
     89 	KS_NAME(dot3Collided7Times),
     90 	KS_NAME(dot3Collided8Times),
     91 	KS_NAME(dot3Collided9Times),
     92 	KS_NAME(dot3Collided10Times),
     93 	KS_NAME(dot3Collided11Times),
     94 	KS_NAME(dot3Collided12Times),
     95 	KS_NAME(dot3Collided13Times),
     96 	KS_NAME(dot3Collided14Times),
     97 	KS_NAME(dot3Collided15Times),
     98 	KS_NAME(ifHCOutUcastPkts),
     99 	KS_NAME(ifHCOutMulticastPkts),
    100 	KS_NAME(ifHCOutBroadcastPkts),
    101 	KS_NAME(dot3StatsCarrierSenseErrors),
    102 	KS_NAME(ifOutDiscards),
    103 	KS_NAME(ifOutErrors),
    104 
    105 	KS_NAME(COSIfHCInPkts_1),
    106 	KS_NAME(COSIfHCInPkts_2),
    107 	KS_NAME(COSIfHCInPkts_3),
    108 	KS_NAME(COSIfHCInPkts_4),
    109 	KS_NAME(COSIfHCInPkts_5),
    110 	KS_NAME(COSIfHCInPkts_6),
    111 	KS_NAME(COSIfHCInPkts_7),
    112 	KS_NAME(COSIfHCInPkts_8),
    113 	KS_NAME(COSIfHCInPkts_9),
    114 	KS_NAME(COSIfHCInPkts_10),
    115 	KS_NAME(COSIfHCInPkts_11),
    116 	KS_NAME(COSIfHCInPkts_12),
    117 	KS_NAME(COSIfHCInPkts_13),
    118 	KS_NAME(COSIfHCInPkts_14),
    119 	KS_NAME(COSIfHCInPkts_15),
    120 	KS_NAME(COSIfHCInPkts_16),
    121 	KS_NAME(COSFramesDroppedDueToFilters),
    122 	KS_NAME(nicDmaWriteQueueFull),
    123 	KS_NAME(nicDmaWriteHighPriQueueFull),
    124 	KS_NAME(nicNoMoreRxBDs),
    125 	KS_NAME(ifInDiscards),
    126 	KS_NAME(ifInErrors),
    127 	KS_NAME(nicRecvThresholdHit),
    128 
    129 	KS_NAME(COSIfHCOutPkts_1),
    130 	KS_NAME(COSIfHCOutPkts_2),
    131 	KS_NAME(COSIfHCOutPkts_3),
    132 	KS_NAME(COSIfHCOutPkts_4),
    133 	KS_NAME(COSIfHCOutPkts_5),
    134 	KS_NAME(COSIfHCOutPkts_6),
    135 	KS_NAME(COSIfHCOutPkts_7),
    136 	KS_NAME(COSIfHCOutPkts_8),
    137 	KS_NAME(COSIfHCOutPkts_9),
    138 	KS_NAME(COSIfHCOutPkts_10),
    139 	KS_NAME(COSIfHCOutPkts_11),
    140 	KS_NAME(COSIfHCOutPkts_12),
    141 	KS_NAME(COSIfHCOutPkts_13),
    142 	KS_NAME(COSIfHCOutPkts_14),
    143 	KS_NAME(COSIfHCOutPkts_15),
    144 	KS_NAME(COSIfHCOutPkts_16),
    145 	KS_NAME(nicDmaReadQueueFull),
    146 	KS_NAME(nicDmaReadHighPriQueueFull),
    147 	KS_NAME(nicSendDataCompQueueFull),
    148 	KS_NAME(nicRingSetSendProdIndex),
    149 	KS_NAME(nicRingStatusUpdate),
    150 	KS_NAME(nicInterrupts),
    151 	KS_NAME(nicAvoidedInterrupts),
    152 	KS_NAME(nicSendThresholdHit),
    153 
    154 	{ KS_STATS_SIZE, NULL }
    155 };
    156 
    157 static const bge_ksindex_t bge_stat_val[] = {
    158 	KS_NAME(ifHCOutOctets),
    159 	KS_NAME(etherStatsCollisions),
    160 	KS_NAME(outXonSent),
    161 	KS_NAME(outXoffSent),
    162 	KS_NAME(dot3StatsInternalMacTransmitErrors),
    163 	KS_NAME(dot3StatsSingleCollisionFrames),
    164 	KS_NAME(dot3StatsMultipleCollisionFrames),
    165 	KS_NAME(dot3StatsDeferredTransmissions),
    166 	KS_NAME(dot3StatsExcessiveCollisions),
    167 	KS_NAME(dot3StatsLateCollisions),
    168 	KS_NAME(ifHCOutUcastPkts),
    169 	KS_NAME(ifHCOutMulticastPkts),
    170 	KS_NAME(ifHCOutBroadcastPkts),
    171 	KS_NAME(ifHCInOctets),
    172 	KS_NAME(etherStatsFragments),
    173 	KS_NAME(ifHCInUcastPkts),
    174 	KS_NAME(ifHCInMulticastPkts),
    175 	KS_NAME(ifHCInBroadcastPkts),
    176 	KS_NAME(dot3StatsFCSErrors),
    177 	KS_NAME(dot3StatsAlignmentErrors),
    178 	KS_NAME(xonPauseFramesReceived),
    179 	KS_NAME(xoffPauseFramesReceived),
    180 	KS_NAME(macControlFramesReceived),
    181 	KS_NAME(xoffStateEntered),
    182 	KS_NAME(dot3StatsFrameTooLongs),
    183 	KS_NAME(etherStatsJabbers),
    184 	KS_NAME(etherStatsUndersizePkts),
    185 
    186 	{ KS_STAT_REG_SIZE, NULL }
    187 };
    188 
    189 static int
    190 bge_statistics_update(kstat_t *ksp, int flag)
    191 {
    192 	bge_t *bgep;
    193 	bge_statistics_t *bstp;
    194 	bge_statistics_reg_t *pstats;
    195 	kstat_named_t *knp;
    196 	const bge_ksindex_t *ksip;
    197 
    198 	if (flag != KSTAT_READ)
    199 		return (EACCES);
    200 
    201 	bgep = ksp->ks_private;
    202 	if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    203 		bstp = DMA_VPTR(bgep->statistics);
    204 
    205 	knp = ksp->ks_data;
    206 
    207 	/*
    208 	 * Transfer the statistics values from the copy that the
    209 	 * chip updates via DMA to the named-kstat structure.
    210 	 *
    211 	 * As above, we don't bother to sync or stop updates to the
    212 	 * statistics, 'cos it doesn't really matter if they're a few
    213 	 * microseconds out of date or less than 100% consistent ...
    214 	 */
    215 	if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    216 		for (ksip = bge_statistics; ksip->name != NULL; ++knp, ++ksip)
    217 			knp->value.ui64 = bstp->a[ksip->index];
    218 	else {
    219 		pstats = bgep->pstats;
    220 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCOutOctets);
    221 		(knp++)->value.ui64 = (uint64_t)(pstats->etherStatsCollisions);
    222 		(knp++)->value.ui64 = (uint64_t)(pstats->outXonSent);
    223 		(knp++)->value.ui64 = (uint64_t)(pstats->outXoffSent);
    224 		(knp++)->value.ui64 =
    225 		    (uint64_t)(pstats->dot3StatsInternalMacTransmitErrors);
    226 		(knp++)->value.ui64 =
    227 		    (uint64_t)(pstats->dot3StatsSingleCollisionFrames);
    228 		(knp++)->value.ui64 =
    229 		    (uint64_t)(pstats->dot3StatsMultipleCollisionFrames);
    230 		(knp++)->value.ui64 =
    231 		    (uint64_t)(pstats->dot3StatsDeferredTransmissions);
    232 		(knp++)->value.ui64 =
    233 		    (uint64_t)(pstats->dot3StatsExcessiveCollisions);
    234 		(knp++)->value.ui64 =
    235 		    (uint64_t)(pstats->dot3StatsLateCollisions);
    236 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCOutUcastPkts);
    237 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCOutMulticastPkts);
    238 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCOutBroadcastPkts);
    239 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCInOctets);
    240 		(knp++)->value.ui64 = (uint64_t)(pstats->etherStatsFragments);
    241 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCInUcastPkts);
    242 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCInMulticastPkts);
    243 		(knp++)->value.ui64 = (uint64_t)(pstats->ifHCInBroadcastPkts);
    244 		(knp++)->value.ui64 = (uint64_t)(pstats->dot3StatsFCSErrors);
    245 		(knp++)->value.ui64 =
    246 		    (uint64_t)(pstats->dot3StatsAlignmentErrors);
    247 		(knp++)->value.ui64 =
    248 		    (uint64_t)(pstats->xonPauseFramesReceived);
    249 		(knp++)->value.ui64 =
    250 		    (uint64_t)(pstats->xoffPauseFramesReceived);
    251 		(knp++)->value.ui64 =
    252 		    (uint64_t)(pstats->macControlFramesReceived);
    253 		(knp++)->value.ui64 = (uint64_t)(pstats->xoffStateEntered);
    254 		(knp++)->value.ui64 =
    255 		    (uint64_t)(pstats->dot3StatsFrameTooLongs);
    256 		(knp++)->value.ui64 = (uint64_t)(pstats->etherStatsJabbers);
    257 		(knp++)->value.ui64 =
    258 		    (uint64_t)(pstats->etherStatsUndersizePkts);
    259 	}
    260 
    261 	return (0);
    262 }
    263 
    264 static const bge_ksindex_t bge_chipid[] = {
    265 	{ 0,				"asic_rev"		},
    266 	{ 1,				"businfo"		},
    267 	{ 2,				"command"		},
    268 
    269 	{ 3,				"vendor_id"		},
    270 	{ 4,				"device_id"		},
    271 	{ 5,				"subsystem_vendor_id"	},
    272 	{ 6,				"subsystem_device_id"	},
    273 	{ 7,				"revision_id"		},
    274 	{ 8,				"cache_line_size"	},
    275 	{ 9,				"latency_timer"		},
    276 
    277 	{ 10,				"flags"			},
    278 	{ 11,				"chip_type"		},
    279 	{ 12,				"mbuf_base"		},
    280 	{ 13,				"mbuf_count"		},
    281 	{ 14,				"hw_mac_addr"		},
    282 
    283 	{ 15,				"&bus_type"		},
    284 	{ 16,				"&bus_speed"		},
    285 	{ 17,				"&bus_size"		},
    286 	{ 18,				"&supported"		},
    287 	{ 19,				"&interface"		},
    288 
    289 	{ -1,				NULL 			}
    290 };
    291 
    292 static void
    293 bge_set_char_kstat(kstat_named_t *knp, const char *s)
    294 {
    295 	(void) strncpy(knp->value.c, s, sizeof (knp->value.c));
    296 }
    297 
    298 static int
    299 bge_chipid_update(kstat_t *ksp, int flag)
    300 {
    301 	bge_t *bgep;
    302 	kstat_named_t *knp;
    303 	uint64_t tmp;
    304 
    305 	if (flag != KSTAT_READ)
    306 		return (EACCES);
    307 
    308 	bgep = ksp->ks_private;
    309 	knp = ksp->ks_data;
    310 
    311 	(knp++)->value.ui64 = bgep->chipid.asic_rev;
    312 	(knp++)->value.ui64 = bgep->chipid.businfo;
    313 	(knp++)->value.ui64 = bgep->chipid.command;
    314 
    315 	(knp++)->value.ui64 = bgep->chipid.vendor;
    316 	(knp++)->value.ui64 = bgep->chipid.device;
    317 	(knp++)->value.ui64 = bgep->chipid.subven;
    318 	(knp++)->value.ui64 = bgep->chipid.subdev;
    319 	(knp++)->value.ui64 = bgep->chipid.revision;
    320 	(knp++)->value.ui64 = bgep->chipid.clsize;
    321 	(knp++)->value.ui64 = bgep->chipid.latency;
    322 
    323 	(knp++)->value.ui64 = bgep->chipid.flags;
    324 	(knp++)->value.ui64 = bgep->chipid.chip_label;
    325 	(knp++)->value.ui64 = bgep->chipid.mbuf_base;
    326 	(knp++)->value.ui64 = bgep->chipid.mbuf_length;
    327 	(knp++)->value.ui64 = bgep->chipid.hw_mac_addr;
    328 
    329 	/*
    330 	 * Now we interpret some of the above into readable strings
    331 	 */
    332 	tmp = bgep->chipid.businfo;
    333 	bge_set_char_kstat(knp++,
    334 	    tmp & PCISTATE_BUS_IS_PCI ? "PCI" : "PCI-X");
    335 	bge_set_char_kstat(knp++,
    336 	    tmp & PCISTATE_BUS_IS_FAST ? "fast" : "normal");
    337 	bge_set_char_kstat(knp++,
    338 	    tmp & PCISTATE_BUS_IS_32_BIT ? "32 bit" : "64 bit");
    339 
    340 	tmp = bgep->chipid.flags;
    341 	bge_set_char_kstat(knp++,
    342 	    tmp & CHIP_FLAG_SUPPORTED ? "yes" : "no");
    343 	bge_set_char_kstat(knp++,
    344 	    tmp & CHIP_FLAG_SERDES ? "serdes" : "copper");
    345 
    346 	return (0);
    347 }
    348 
    349 static const bge_ksindex_t bge_driverinfo[] = {
    350 	{ 0,				"rx_buff_addr"		},
    351 	{ 1,				"tx_buff_addr"		},
    352 	{ 2,				"rx_desc_addr"		},
    353 	{ 3,				"tx_desc_addr"		},
    354 
    355 	{ 4,				"tx_desc_free"		},
    356 	{ 5,				"tx_array"		},
    357 	{ 6,				"tc_next"		},
    358 	{ 7,				"tx_next"		},
    359 	{ 8,				"txfill_next"		},
    360 	{ 9,				"txpkt_next"		},
    361 	{ 10,				"tx_bufs"		},
    362 	{ 11,				"tx_flow"		},
    363 	{ 12,				"tx_resched_needed"	},
    364 	{ 13,				"tx_resched"		},
    365 	{ 14,				"tx_nobuf"		},
    366 	{ 15,				"tx_nobd"		},
    367 	{ 16,				"tx_block"		},
    368 	{ 17,				"tx_alloc_fail"		},
    369 
    370 	{ 18,				"watchdog"		},
    371 	{ 19,				"chip_resets"		},
    372 	{ 20,				"dma_misses"		},
    373 	{ 21,				"update_misses"		},
    374 
    375 	{ 22,				"misc_host_config"	},
    376 	{ 23,				"dma_rw_control"	},
    377 	{ 24,				"pci_bus_info"		},
    378 
    379 	{ 25,				"buff_mgr_status"	},
    380 	{ 26,				"rcv_init_status"	},
    381 
    382 	{ -1,				NULL 			}
    383 };
    384 
    385 static int
    386 bge_driverinfo_update(kstat_t *ksp, int flag)
    387 {
    388 	bge_t *bgep;
    389 	kstat_named_t *knp;
    390 	ddi_acc_handle_t handle;
    391 
    392 	if (flag != KSTAT_READ)
    393 		return (EACCES);
    394 
    395 	bgep = ksp->ks_private;
    396 	if (bgep->bge_chip_state == BGE_CHIP_FAULT)
    397 		return (EIO);
    398 
    399 	knp = ksp->ks_data;
    400 
    401 	(knp++)->value.ui64 = bgep->rx_buff[0].cookie.dmac_laddress;
    402 	(knp++)->value.ui64 = bgep->tx_buff[0].cookie.dmac_laddress;
    403 	(knp++)->value.ui64 = bgep->rx_desc[0].cookie.dmac_laddress;
    404 	(knp++)->value.ui64 = bgep->tx_desc.cookie.dmac_laddress;
    405 
    406 	(knp++)->value.ui64 = bgep->send[0].tx_free;
    407 	(knp++)->value.ui64 = bgep->send[0].tx_array;
    408 	(knp++)->value.ui64 = bgep->send[0].tc_next;
    409 	(knp++)->value.ui64 = bgep->send[0].tx_next;
    410 	(knp++)->value.ui64 = bgep->send[0].txfill_next;
    411 	(knp++)->value.ui64 = bgep->send[0].txpkt_next;
    412 	(knp++)->value.ui64 = bgep->send[0].txbuf_pop_queue->count +
    413 	    bgep->send[0].txbuf_push_queue->count;
    414 	(knp++)->value.ui64 = bgep->send[0].tx_flow;
    415 	(knp++)->value.ui64 = bgep->tx_resched_needed;
    416 	(knp++)->value.ui64 = bgep->tx_resched;
    417 	(knp++)->value.ui64 = bgep->send[0].tx_nobuf;
    418 	(knp++)->value.ui64 = bgep->send[0].tx_nobd;
    419 	(knp++)->value.ui64 = bgep->send[0].tx_block;
    420 	(knp++)->value.ui64 = bgep->send[0].tx_alloc_fail;
    421 
    422 	(knp++)->value.ui64 = bgep->watchdog;
    423 	(knp++)->value.ui64 = bgep->chip_resets;
    424 	(knp++)->value.ui64 = bgep->missed_dmas;
    425 	(knp++)->value.ui64 = bgep->missed_updates;
    426 
    427 	/*
    428 	 * Hold the mutex while accessing the chip registers
    429 	 * just in case the factotum is trying to reset it!
    430 	 */
    431 	handle = bgep->cfg_handle;
    432 	mutex_enter(bgep->genlock);
    433 	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_MHCR);
    434 	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_PDRWCR);
    435 	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_PCISTATE);
    436 	if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) {
    437 		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
    438 		mutex_exit(bgep->genlock);
    439 		return (EIO);
    440 	}
    441 
    442 	(knp++)->value.ui64 = bge_reg_get32(bgep, BUFFER_MANAGER_STATUS_REG);
    443 	(knp++)->value.ui64 = bge_reg_get32(bgep, RCV_INITIATOR_STATUS_REG);
    444 	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
    445 		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
    446 		mutex_exit(bgep->genlock);
    447 		return (EIO);
    448 	}
    449 	mutex_exit(bgep->genlock);
    450 
    451 	return (0);
    452 }
    453 
    454 static const bge_ksindex_t bge_serdes[] = {
    455 	{ 0,				"serdes_status"		},
    456 	{ 1,				"serdes_advert"		},
    457 	{ 2,				"serdes_lpadv"		},
    458 
    459 	{ -1,				NULL }
    460 };
    461 
    462 static int
    463 bge_serdes_update(kstat_t *ksp, int flag)
    464 {
    465 	bge_t *bgep;
    466 	kstat_named_t *knp;
    467 
    468 	if (flag != KSTAT_READ)
    469 		return (EACCES);
    470 
    471 	bgep = ksp->ks_private;
    472 	knp = ksp->ks_data;
    473 
    474 	(knp++)->value.ui64 = bgep->serdes_status;
    475 	(knp++)->value.ui64 = bgep->serdes_advert;
    476 	(knp++)->value.ui64 = bgep->serdes_lpadv;
    477 
    478 	return (0);
    479 }
    480 
    481 static const bge_ksindex_t bge_phydata[] = {
    482 	{ MII_CONTROL,			"mii_control"		},
    483 	{ MII_STATUS,			"mii_status"		},
    484 	{ MII_PHYIDH,			"phy_identifier"	},
    485 	{ MII_AN_ADVERT,		"an_advert"		},
    486 	{ MII_AN_LPABLE,		"an_lp_ability"		},
    487 	{ MII_AN_EXPANSION,		"an_expansion"		},
    488 	{ MII_AN_NXTPGLP,		"an_lp_nextpage"	},
    489 	{ MII_MSCONTROL,		"gbit_control"		},
    490 	{ MII_MSSTATUS,			"gbit_status"		},
    491 	{ MII_EXTSTATUS,		"ieee_ext_status"	},
    492 	{ MII_EXT_CONTROL,		"phy_ext_control"	},
    493 	{ MII_EXT_STATUS,		"phy_ext_status"	},
    494 	{ MII_RCV_ERR_COUNT,		"receive_error_count"	},
    495 	{ MII_FALSE_CARR_COUNT,		"false_carrier_count"	},
    496 	{ MII_RCV_NOT_OK_COUNT,		"receiver_not_ok_count"	},
    497 	{ MII_AUX_CONTROL,		"aux_control"		},
    498 	{ MII_AUX_STATUS,		"aux_status"		},
    499 	{ MII_INTR_STATUS,		"intr_status"		},
    500 	{ MII_INTR_MASK,		"intr_mask"		},
    501 	{ MII_HCD_STATUS,		"hcd_status"		},
    502 
    503 	{ -1,				NULL }
    504 };
    505 
    506 static int
    507 bge_phydata_update(kstat_t *ksp, int flag)
    508 {
    509 	bge_t *bgep;
    510 	kstat_named_t *knp;
    511 	const bge_ksindex_t *ksip;
    512 
    513 	if (flag != KSTAT_READ)
    514 		return (EACCES);
    515 
    516 	bgep = ksp->ks_private;
    517 	if (bgep->bge_chip_state == BGE_CHIP_FAULT)
    518 		return (EIO);
    519 
    520 	knp = ksp->ks_data;
    521 
    522 	/*
    523 	 * Read the PHY registers & update the kstats ...
    524 	 *
    525 	 * We need to hold the mutex while performing MII reads, but
    526 	 * we don't want to hold it across the entire sequence of reads.
    527 	 * So we grab and release it on each iteration, 'cos it doesn't
    528 	 * really matter if the kstats are less than 100% consistent ...
    529 	 */
    530 	for (ksip = bge_phydata; ksip->name != NULL; ++knp, ++ksip) {
    531 		mutex_enter(bgep->genlock);
    532 		switch (ksip->index) {
    533 		case MII_STATUS:
    534 			knp->value.ui64 = bgep->phy_gen_status;
    535 			break;
    536 
    537 		case MII_PHYIDH:
    538 			knp->value.ui64 = bge_mii_get16(bgep, MII_PHYIDH);
    539 			knp->value.ui64 <<= 16;
    540 			knp->value.ui64 |= bge_mii_get16(bgep, MII_PHYIDL);
    541 			break;
    542 
    543 		default:
    544 			knp->value.ui64 = bge_mii_get16(bgep, ksip->index);
    545 			break;
    546 		}
    547 		if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
    548 			ddi_fm_service_impact(bgep->devinfo,
    549 			    DDI_SERVICE_DEGRADED);
    550 			mutex_exit(bgep->genlock);
    551 			return (EIO);
    552 		}
    553 		mutex_exit(bgep->genlock);
    554 	}
    555 
    556 	return (0);
    557 }
    558 
    559 static kstat_t *
    560 bge_setup_named_kstat(bge_t *bgep, int instance, char *name,
    561 	const bge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
    562 {
    563 	kstat_t *ksp;
    564 	kstat_named_t *knp;
    565 	char *np;
    566 	int type;
    567 
    568 	size /= sizeof (bge_ksindex_t);
    569 	ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net",
    570 	    KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
    571 	if (ksp == NULL)
    572 		return (NULL);
    573 
    574 	ksp->ks_private = bgep;
    575 	ksp->ks_update = update;
    576 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
    577 		switch (*np) {
    578 		default:
    579 			type = KSTAT_DATA_UINT64;
    580 			break;
    581 		case '%':
    582 			np += 1;
    583 			type = KSTAT_DATA_UINT32;
    584 			break;
    585 		case '$':
    586 			np += 1;
    587 			type = KSTAT_DATA_STRING;
    588 			break;
    589 		case '&':
    590 			np += 1;
    591 			type = KSTAT_DATA_CHAR;
    592 			break;
    593 		}
    594 		kstat_named_init(knp, np, type);
    595 	}
    596 	kstat_install(ksp);
    597 
    598 	return (ksp);
    599 }
    600 
    601 void
    602 bge_init_kstats(bge_t *bgep, int instance)
    603 {
    604 	kstat_t *ksp;
    605 
    606 	BGE_TRACE(("bge_init_kstats($%p, %d)", (void *)bgep, instance));
    607 
    608 	if (bgep->chipid.statistic_type == BGE_STAT_BLK) {
    609 		DMA_ZERO(bgep->statistics);
    610 		bgep->bge_kstats[BGE_KSTAT_RAW] = ksp =
    611 		    kstat_create(BGE_DRIVER_NAME, instance,
    612 		    "raw_statistics", "net", KSTAT_TYPE_RAW,
    613 		    sizeof (bge_statistics_t), KSTAT_FLAG_VIRTUAL);
    614 		if (ksp != NULL) {
    615 			ksp->ks_data = DMA_VPTR(bgep->statistics);
    616 			kstat_install(ksp);
    617 		}
    618 
    619 		bgep->bge_kstats[BGE_KSTAT_STATS] = bge_setup_named_kstat(bgep,
    620 		    instance, "statistics", bge_statistics,
    621 		    sizeof (bge_statistics), bge_statistics_update);
    622 	} else {
    623 		bgep->bge_kstats[BGE_KSTAT_STATS] = bge_setup_named_kstat(bgep,
    624 		    instance, "statistics", bge_stat_val,
    625 		    sizeof (bge_stat_val), bge_statistics_update);
    626 	}
    627 
    628 	bgep->bge_kstats[BGE_KSTAT_CHIPID] = bge_setup_named_kstat(bgep,
    629 	    instance, "chipid", bge_chipid,
    630 	    sizeof (bge_chipid), bge_chipid_update);
    631 
    632 	bgep->bge_kstats[BGE_KSTAT_DRIVER] = bge_setup_named_kstat(bgep,
    633 	    instance, "driverinfo", bge_driverinfo,
    634 	    sizeof (bge_driverinfo), bge_driverinfo_update);
    635 
    636 	if (bgep->chipid.flags & CHIP_FLAG_SERDES)
    637 		bgep->bge_kstats[BGE_KSTAT_PHYS] = bge_setup_named_kstat(bgep,
    638 		    instance, "serdes", bge_serdes,
    639 		    sizeof (bge_serdes), bge_serdes_update);
    640 	else
    641 		bgep->bge_kstats[BGE_KSTAT_PHYS] = bge_setup_named_kstat(bgep,
    642 		    instance, "phydata", bge_phydata,
    643 		    sizeof (bge_phydata), bge_phydata_update);
    644 
    645 }
    646 
    647 void
    648 bge_fini_kstats(bge_t *bgep)
    649 {
    650 	int i;
    651 
    652 	BGE_TRACE(("bge_fini_kstats($%p)", (void *)bgep));
    653 
    654 	for (i = BGE_KSTAT_COUNT; --i >= 0; )
    655 		if (bgep->bge_kstats[i] != NULL)
    656 			kstat_delete(bgep->bge_kstats[i]);
    657 }
    658 
    659 int
    660 bge_m_stat(void *arg, uint_t stat, uint64_t *val)
    661 {
    662 	bge_t *bgep = arg;
    663 	bge_statistics_t *bstp;
    664 	bge_statistics_reg_t *pstats;
    665 
    666 	if (bgep->bge_chip_state == BGE_CHIP_FAULT) {
    667 		return (EINVAL);
    668 	}
    669 
    670 	if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    671 		bstp = DMA_VPTR(bgep->statistics);
    672 	else {
    673 		pstats = bgep->pstats;
    674 		pstats->ifHCOutOctets +=
    675 		    bge_reg_get32(bgep, STAT_IFHCOUT_OCTETS_REG);
    676 		pstats->etherStatsCollisions +=
    677 		    bge_reg_get32(bgep, STAT_ETHER_COLLIS_REG);
    678 		pstats->outXonSent +=
    679 		    bge_reg_get32(bgep, STAT_OUTXON_SENT_REG);
    680 		pstats->outXoffSent +=
    681 		    bge_reg_get32(bgep, STAT_OUTXOFF_SENT_REG);
    682 		pstats->dot3StatsInternalMacTransmitErrors +=
    683 		    bge_reg_get32(bgep, STAT_DOT3_INTMACTX_ERR_REG);
    684 		pstats->dot3StatsSingleCollisionFrames +=
    685 		    bge_reg_get32(bgep, STAT_DOT3_SCOLLI_FRAME_REG);
    686 		pstats->dot3StatsMultipleCollisionFrames +=
    687 		    bge_reg_get32(bgep, STAT_DOT3_MCOLLI_FRAME_REG);
    688 		pstats->dot3StatsDeferredTransmissions +=
    689 		    bge_reg_get32(bgep, STAT_DOT3_DEFERED_TX_REG);
    690 		pstats->dot3StatsExcessiveCollisions +=
    691 		    bge_reg_get32(bgep, STAT_DOT3_EXCE_COLLI_REG);
    692 		pstats->dot3StatsLateCollisions +=
    693 		    bge_reg_get32(bgep, STAT_DOT3_LATE_COLLI_REG);
    694 		pstats->ifHCOutUcastPkts +=
    695 		    bge_reg_get32(bgep, STAT_IFHCOUT_UPKGS_REG);
    696 		pstats->ifHCOutMulticastPkts +=
    697 		    bge_reg_get32(bgep, STAT_IFHCOUT_MPKGS_REG);
    698 		pstats->ifHCOutBroadcastPkts +=
    699 		    bge_reg_get32(bgep, STAT_IFHCOUT_BPKGS_REG);
    700 		pstats->ifHCInOctets +=
    701 		    bge_reg_get32(bgep, STAT_IFHCIN_OCTETS_REG);
    702 		pstats->etherStatsFragments +=
    703 		    bge_reg_get32(bgep, STAT_ETHER_FRAGMENT_REG);
    704 		pstats->ifHCInUcastPkts +=
    705 		    bge_reg_get32(bgep, STAT_IFHCIN_UPKGS_REG);
    706 		pstats->ifHCInMulticastPkts +=
    707 		    bge_reg_get32(bgep, STAT_IFHCIN_MPKGS_REG);
    708 		pstats->ifHCInBroadcastPkts +=
    709 		    bge_reg_get32(bgep, STAT_IFHCIN_BPKGS_REG);
    710 		pstats->dot3StatsFCSErrors +=
    711 		    bge_reg_get32(bgep, STAT_DOT3_FCS_ERR_REG);
    712 		pstats->dot3StatsAlignmentErrors +=
    713 		    bge_reg_get32(bgep, STAT_DOT3_ALIGN_ERR_REG);
    714 		pstats->xonPauseFramesReceived +=
    715 		    bge_reg_get32(bgep, STAT_XON_PAUSE_RX_REG);
    716 		pstats->xoffPauseFramesReceived +=
    717 		    bge_reg_get32(bgep, STAT_XOFF_PAUSE_RX_REG);
    718 		pstats->macControlFramesReceived +=
    719 		    bge_reg_get32(bgep, STAT_MAC_CTRL_RX_REG);
    720 		pstats->xoffStateEntered +=
    721 		    bge_reg_get32(bgep, STAT_XOFF_STATE_ENTER_REG);
    722 		pstats->dot3StatsFrameTooLongs +=
    723 		    bge_reg_get32(bgep, STAT_DOT3_FRAME_TOOLONG_REG);
    724 		pstats->etherStatsJabbers +=
    725 		    bge_reg_get32(bgep, STAT_ETHER_JABBERS_REG);
    726 		pstats->etherStatsUndersizePkts +=
    727 		    bge_reg_get32(bgep, STAT_ETHER_UNDERSIZE_REG);
    728 		mutex_enter(bgep->genlock);
    729 		if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
    730 			ddi_fm_service_impact(bgep->devinfo,
    731 			    DDI_SERVICE_UNAFFECTED);
    732 		}
    733 		mutex_exit(bgep->genlock);
    734 	}
    735 
    736 	switch (stat) {
    737 	case MAC_STAT_IFSPEED:
    738 		*val = bgep->param_link_speed * 1000000ull;
    739 		break;
    740 
    741 	case MAC_STAT_MULTIRCV:
    742 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    743 			*val = bstp->s.ifHCInMulticastPkts;
    744 		else
    745 			*val = pstats->ifHCInMulticastPkts;
    746 		break;
    747 
    748 	case MAC_STAT_BRDCSTRCV:
    749 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    750 			*val = bstp->s.ifHCInBroadcastPkts;
    751 		else
    752 			*val = pstats->ifHCInBroadcastPkts;
    753 		break;
    754 
    755 	case MAC_STAT_MULTIXMT:
    756 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    757 			*val = bstp->s.ifHCOutMulticastPkts;
    758 		else
    759 			*val = pstats->ifHCOutMulticastPkts;
    760 		break;
    761 
    762 	case MAC_STAT_BRDCSTXMT:
    763 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    764 			*val = bstp->s.ifHCOutBroadcastPkts;
    765 		else
    766 			*val = pstats->ifHCOutBroadcastPkts;
    767 		break;
    768 
    769 	case MAC_STAT_NORCVBUF:
    770 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    771 			*val = bstp->s.ifInDiscards;
    772 		else
    773 			*val = 0;
    774 		break;
    775 
    776 	case MAC_STAT_IERRORS:
    777 		if (bgep->chipid.statistic_type == BGE_STAT_BLK) {
    778 			*val = bstp->s.dot3StatsFCSErrors +
    779 			    bstp->s.dot3StatsAlignmentErrors +
    780 			    bstp->s.dot3StatsFrameTooLongs +
    781 			    bstp->s.etherStatsUndersizePkts +
    782 			    bstp->s.etherStatsJabbers;
    783 		} else {
    784 			*val = pstats->dot3StatsFCSErrors +
    785 			    pstats->dot3StatsAlignmentErrors +
    786 			    pstats->dot3StatsFrameTooLongs +
    787 			    pstats->etherStatsUndersizePkts +
    788 			    pstats->etherStatsJabbers;
    789 		}
    790 		break;
    791 
    792 	case MAC_STAT_NOXMTBUF:
    793 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    794 			*val = bstp->s.ifOutDiscards;
    795 		else
    796 			*val = 0;
    797 		break;
    798 
    799 	case MAC_STAT_OERRORS:
    800 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    801 			*val = bstp->s.ifOutDiscards;
    802 		else
    803 			*val = 0;
    804 		break;
    805 
    806 	case MAC_STAT_COLLISIONS:
    807 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    808 			*val = bstp->s.etherStatsCollisions;
    809 		else
    810 			*val = pstats->etherStatsCollisions;
    811 		break;
    812 
    813 	case MAC_STAT_RBYTES:
    814 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    815 			*val = bstp->s.ifHCInOctets;
    816 		else
    817 			*val = pstats->ifHCInOctets;
    818 		break;
    819 
    820 	case MAC_STAT_IPACKETS:
    821 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    822 			*val = bstp->s.ifHCInUcastPkts +
    823 			    bstp->s.ifHCInMulticastPkts +
    824 			    bstp->s.ifHCInBroadcastPkts;
    825 		else
    826 			*val = pstats->ifHCInUcastPkts +
    827 			    pstats->ifHCInMulticastPkts +
    828 			    pstats->ifHCInBroadcastPkts;
    829 		break;
    830 
    831 	case MAC_STAT_OBYTES:
    832 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    833 			*val = bstp->s.ifHCOutOctets;
    834 		else
    835 			*val = pstats->ifHCOutOctets;
    836 		break;
    837 
    838 	case MAC_STAT_OPACKETS:
    839 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    840 			*val = bstp->s.ifHCOutUcastPkts +
    841 			    bstp->s.ifHCOutMulticastPkts +
    842 			    bstp->s.ifHCOutBroadcastPkts;
    843 		else
    844 			*val = pstats->ifHCOutUcastPkts +
    845 			    pstats->ifHCOutMulticastPkts +
    846 			    pstats->ifHCOutBroadcastPkts;
    847 		break;
    848 
    849 	case ETHER_STAT_ALIGN_ERRORS:
    850 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    851 			*val = bstp->s.dot3StatsAlignmentErrors;
    852 		else
    853 			*val = pstats->dot3StatsAlignmentErrors;
    854 		break;
    855 
    856 	case ETHER_STAT_FCS_ERRORS:
    857 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    858 			*val = bstp->s.dot3StatsFCSErrors;
    859 		else
    860 			*val = pstats->dot3StatsFCSErrors;
    861 		break;
    862 
    863 	case ETHER_STAT_FIRST_COLLISIONS:
    864 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    865 			*val = bstp->s.dot3StatsSingleCollisionFrames;
    866 		else
    867 			*val = pstats->dot3StatsSingleCollisionFrames;
    868 		break;
    869 
    870 	case ETHER_STAT_MULTI_COLLISIONS:
    871 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    872 			*val = bstp->s.dot3StatsMultipleCollisionFrames;
    873 		else
    874 			*val = pstats->dot3StatsMultipleCollisionFrames;
    875 		break;
    876 
    877 	case ETHER_STAT_DEFER_XMTS:
    878 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    879 			*val = bstp->s.dot3StatsDeferredTransmissions;
    880 		else
    881 			*val = pstats->dot3StatsDeferredTransmissions;
    882 		break;
    883 
    884 	case ETHER_STAT_TX_LATE_COLLISIONS:
    885 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    886 			*val = bstp->s.dot3StatsLateCollisions;
    887 		else
    888 			*val = pstats->dot3StatsLateCollisions;
    889 		break;
    890 
    891 	case ETHER_STAT_EX_COLLISIONS:
    892 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    893 			*val = bstp->s.dot3StatsExcessiveCollisions;
    894 		else
    895 			*val = pstats->dot3StatsExcessiveCollisions;
    896 		break;
    897 
    898 	case ETHER_STAT_MACXMT_ERRORS:
    899 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    900 			*val = bstp->s.dot3StatsInternalMacTransmitErrors;
    901 		else
    902 			*val = bgep->pstats->dot3StatsInternalMacTransmitErrors;
    903 		break;
    904 
    905 	case ETHER_STAT_CARRIER_ERRORS:
    906 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    907 			*val = bstp->s.dot3StatsCarrierSenseErrors;
    908 		else
    909 			*val = 0;
    910 		break;
    911 
    912 	case ETHER_STAT_TOOLONG_ERRORS:
    913 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    914 			*val = bstp->s.dot3StatsFrameTooLongs;
    915 		else
    916 			*val = pstats->dot3StatsFrameTooLongs;
    917 		break;
    918 
    919 	case ETHER_STAT_TOOSHORT_ERRORS:
    920 		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
    921 			*val = bstp->s.etherStatsUndersizePkts;
    922 		else
    923 			*val = pstats->etherStatsUndersizePkts;
    924 		break;
    925 
    926 	case ETHER_STAT_XCVR_ADDR:
    927 		*val = bgep->phy_mii_addr;
    928 		break;
    929 
    930 	case ETHER_STAT_XCVR_ID:
    931 		mutex_enter(bgep->genlock);
    932 		*val = bge_mii_get16(bgep, MII_PHYIDH);
    933 		*val <<= 16;
    934 		*val |= bge_mii_get16(bgep, MII_PHYIDL);
    935 		if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
    936 			ddi_fm_service_impact(bgep->devinfo,
    937 			    DDI_SERVICE_UNAFFECTED);
    938 		}
    939 		mutex_exit(bgep->genlock);
    940 		break;
    941 
    942 	case ETHER_STAT_XCVR_INUSE:
    943 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
    944 			*val = XCVR_1000X;
    945 		else
    946 			*val = XCVR_1000T;
    947 		break;
    948 
    949 	case ETHER_STAT_CAP_1000FDX:
    950 		*val = 1;
    951 		break;
    952 
    953 	case ETHER_STAT_CAP_1000HDX:
    954 		*val = 1;
    955 		break;
    956 
    957 	case ETHER_STAT_CAP_100FDX:
    958 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
    959 			*val = 0;
    960 		else
    961 			*val = 1;
    962 		break;
    963 
    964 	case ETHER_STAT_CAP_100HDX:
    965 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
    966 			*val = 0;
    967 		else
    968 			*val = 1;
    969 		break;
    970 
    971 	case ETHER_STAT_CAP_10FDX:
    972 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
    973 			*val = 0;
    974 		else
    975 			*val = 1;
    976 		break;
    977 
    978 	case ETHER_STAT_CAP_10HDX:
    979 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
    980 			*val = 0;
    981 		else
    982 			*val = 1;
    983 		break;
    984 
    985 	case ETHER_STAT_CAP_ASMPAUSE:
    986 		*val = 1;
    987 		break;
    988 
    989 	case ETHER_STAT_CAP_PAUSE:
    990 		*val = 1;
    991 		break;
    992 
    993 	case ETHER_STAT_CAP_AUTONEG:
    994 		*val = 1;
    995 		break;
    996 
    997 	case ETHER_STAT_CAP_REMFAULT:
    998 		*val = 1;
    999 		break;
   1000 
   1001 	case ETHER_STAT_ADV_CAP_1000FDX:
   1002 		*val = bgep->param_adv_1000fdx;
   1003 		break;
   1004 
   1005 	case ETHER_STAT_ADV_CAP_1000HDX:
   1006 		*val = bgep->param_adv_1000hdx;
   1007 		break;
   1008 
   1009 	case ETHER_STAT_ADV_CAP_100FDX:
   1010 		*val = bgep->param_adv_100fdx;
   1011 		break;
   1012 
   1013 	case ETHER_STAT_ADV_CAP_100HDX:
   1014 		*val = bgep->param_adv_100hdx;
   1015 		break;
   1016 
   1017 	case ETHER_STAT_ADV_CAP_10FDX:
   1018 		*val = bgep->param_adv_10fdx;
   1019 		break;
   1020 
   1021 	case ETHER_STAT_ADV_CAP_10HDX:
   1022 		*val = bgep->param_adv_10hdx;
   1023 		break;
   1024 
   1025 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
   1026 		*val = bgep->param_adv_asym_pause;
   1027 		break;
   1028 
   1029 	case ETHER_STAT_ADV_CAP_PAUSE:
   1030 		*val = bgep->param_adv_pause;
   1031 		break;
   1032 
   1033 	case ETHER_STAT_ADV_CAP_AUTONEG:
   1034 		*val = bgep->param_adv_autoneg;
   1035 		break;
   1036 
   1037 	case ETHER_STAT_ADV_REMFAULT:
   1038 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
   1039 			*val = 0;
   1040 		else {
   1041 			mutex_enter(bgep->genlock);
   1042 			*val = bge_mii_get16(bgep, MII_AN_ADVERT) &
   1043 			    MII_AN_ADVERT_REMFAULT ? 1 : 0;
   1044 			if (bge_check_acc_handle(bgep, bgep->io_handle) !=
   1045 			    DDI_FM_OK) {
   1046 				ddi_fm_service_impact(bgep->devinfo,
   1047 				    DDI_SERVICE_UNAFFECTED);
   1048 			}
   1049 			mutex_exit(bgep->genlock);
   1050 		}
   1051 		break;
   1052 
   1053 	case ETHER_STAT_LP_CAP_1000FDX:
   1054 		*val = bgep->param_lp_1000fdx;
   1055 		break;
   1056 
   1057 	case ETHER_STAT_LP_CAP_1000HDX:
   1058 		*val = bgep->param_lp_1000hdx;
   1059 		break;
   1060 
   1061 	case ETHER_STAT_LP_CAP_100FDX:
   1062 		*val = bgep->param_lp_100fdx;
   1063 		break;
   1064 
   1065 	case ETHER_STAT_LP_CAP_100HDX:
   1066 		*val = bgep->param_lp_100hdx;
   1067 		break;
   1068 
   1069 	case ETHER_STAT_LP_CAP_10FDX:
   1070 		*val = bgep->param_lp_10fdx;
   1071 		break;
   1072 
   1073 	case ETHER_STAT_LP_CAP_10HDX:
   1074 		*val = bgep->param_lp_10hdx;
   1075 		break;
   1076 
   1077 	case ETHER_STAT_LP_CAP_ASMPAUSE:
   1078 		*val = bgep->param_lp_asym_pause;
   1079 		break;
   1080 
   1081 	case ETHER_STAT_LP_CAP_PAUSE:
   1082 		*val = bgep->param_lp_pause;
   1083 		break;
   1084 
   1085 	case ETHER_STAT_LP_CAP_AUTONEG:
   1086 		*val = bgep->param_lp_autoneg;
   1087 		break;
   1088 
   1089 	case ETHER_STAT_LP_REMFAULT:
   1090 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
   1091 			*val = 0;
   1092 		else {
   1093 			mutex_enter(bgep->genlock);
   1094 			*val = bge_mii_get16(bgep, MII_AN_LPABLE) &
   1095 			    MII_AN_ADVERT_REMFAULT ? 1 : 0;
   1096 			if (bge_check_acc_handle(bgep, bgep->io_handle) !=
   1097 			    DDI_FM_OK) {
   1098 				ddi_fm_service_impact(bgep->devinfo,
   1099 				    DDI_SERVICE_UNAFFECTED);
   1100 			}
   1101 			mutex_exit(bgep->genlock);
   1102 		}
   1103 		break;
   1104 
   1105 	case ETHER_STAT_LINK_ASMPAUSE:
   1106 		*val = bgep->param_adv_asym_pause &&
   1107 		    bgep->param_lp_asym_pause &&
   1108 		    bgep->param_adv_pause != bgep->param_lp_pause;
   1109 		break;
   1110 
   1111 	case ETHER_STAT_LINK_PAUSE:
   1112 		*val = bgep->param_link_rx_pause;
   1113 		break;
   1114 
   1115 	case ETHER_STAT_LINK_AUTONEG:
   1116 		*val = bgep->param_link_autoneg;
   1117 		break;
   1118 
   1119 	case ETHER_STAT_LINK_DUPLEX:
   1120 		*val = bgep->param_link_duplex;
   1121 		break;
   1122 
   1123 	default:
   1124 		return (ENOTSUP);
   1125 	}
   1126 
   1127 	return (0);
   1128 }
   1129