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