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