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