xref: /illumos-gate/usr/src/uts/common/io/bge/bge_kstats.c (revision 56f33205c9ed776c3c909e07d52e94610a675740)
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