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