xref: /illumos-gate/usr/src/uts/common/io/bge/bge_kstats.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 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_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 int
175 bge_statistics_update(kstat_t *ksp, int flag)
176 {
177 	bge_t *bgep;
178 	bge_statistics_t *bstp;
179 	kstat_named_t *knp;
180 	const bge_ksindex_t *ksip;
181 
182 	if (flag != KSTAT_READ)
183 		return (EACCES);
184 
185 	bgep = ksp->ks_private;
186 	bstp = DMA_VPTR(bgep->statistics);
187 	knp = ksp->ks_data;
188 
189 	/*
190 	 * Transfer the statistics values from the copy that the
191 	 * chip updates via DMA to the named-kstat structure.
192 	 *
193 	 * As above, we don't bother to sync or stop updates to the
194 	 * statistics, 'cos it doesn't really matter if they're a few
195 	 * microsends out of date or less than 100% consistent ...
196 	 */
197 	for (ksip = bge_statistics; ksip->name != NULL; ++knp, ++ksip)
198 		knp->value.ui64 = bstp->a[ksip->index];
199 
200 	return (0);
201 }
202 
203 static int
204 bge_params_update(kstat_t *ksp, int flag)
205 {
206 	bge_t *bgep;
207 	kstat_named_t *knp;
208 	int i;
209 
210 	if (flag != KSTAT_READ)
211 		return (EACCES);
212 
213 	bgep = ksp->ks_private;
214 	for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
215 		knp->value.ui64 = bgep->nd_params[i].ndp_val;
216 
217 	return (0);
218 }
219 
220 static const bge_ksindex_t bge_chipid[] = {
221 	{ 0,				"asic_rev"		},
222 	{ 1,				"businfo"		},
223 	{ 2,				"command"		},
224 
225 	{ 3,				"vendor_id"		},
226 	{ 4,				"device_id"		},
227 	{ 5,				"subsystem_vendor_id"	},
228 	{ 6,				"subsystem_device_id"	},
229 	{ 7,				"revision_id"		},
230 	{ 8,				"cache_line_size"	},
231 	{ 9,				"latency_timer"		},
232 
233 	{ 10,				"flags"			},
234 	{ 11,				"chip_type"		},
235 	{ 12,				"mbuf_base"		},
236 	{ 13,				"mbuf_count"		},
237 	{ 14,				"hw_mac_addr"		},
238 
239 	{ 15,				"&bus_type"		},
240 	{ 16,				"&bus_speed"		},
241 	{ 17,				"&bus_size"		},
242 	{ 18,				"&supported"		},
243 	{ 19,				"&interface"		},
244 
245 	{ -1,				NULL 			}
246 };
247 
248 static void
249 bge_set_char_kstat(kstat_named_t *knp, const char *s)
250 {
251 	(void) strncpy(knp->value.c, s, sizeof (knp->value.c));
252 }
253 
254 static int
255 bge_chipid_update(kstat_t *ksp, int flag)
256 {
257 	bge_t *bgep;
258 	kstat_named_t *knp;
259 	uint64_t tmp;
260 
261 	if (flag != KSTAT_READ)
262 		return (EACCES);
263 
264 	bgep = ksp->ks_private;
265 	knp = ksp->ks_data;
266 
267 	(knp++)->value.ui64 = bgep->chipid.asic_rev;
268 	(knp++)->value.ui64 = bgep->chipid.businfo;
269 	(knp++)->value.ui64 = bgep->chipid.command;
270 
271 	(knp++)->value.ui64 = bgep->chipid.vendor;
272 	(knp++)->value.ui64 = bgep->chipid.device;
273 	(knp++)->value.ui64 = bgep->chipid.subven;
274 	(knp++)->value.ui64 = bgep->chipid.subdev;
275 	(knp++)->value.ui64 = bgep->chipid.revision;
276 	(knp++)->value.ui64 = bgep->chipid.clsize;
277 	(knp++)->value.ui64 = bgep->chipid.latency;
278 
279 	(knp++)->value.ui64 = bgep->chipid.flags;
280 	(knp++)->value.ui64 = bgep->chipid.chip_label;
281 	(knp++)->value.ui64 = bgep->chipid.mbuf_base;
282 	(knp++)->value.ui64 = bgep->chipid.mbuf_length;
283 	(knp++)->value.ui64 = bgep->chipid.hw_mac_addr;
284 
285 	/*
286 	 * Now we interpret some of the above into readable strings
287 	 */
288 	tmp = bgep->chipid.businfo;
289 	bge_set_char_kstat(knp++,
290 		tmp & PCISTATE_BUS_IS_PCI ? "PCI" : "PCI-X");
291 	bge_set_char_kstat(knp++,
292 		tmp & PCISTATE_BUS_IS_FAST ? "fast" : "normal");
293 	bge_set_char_kstat(knp++,
294 		tmp & PCISTATE_BUS_IS_32_BIT ? "32 bit" : "64 bit");
295 
296 	tmp = bgep->chipid.flags;
297 	bge_set_char_kstat(knp++,
298 		tmp & CHIP_FLAG_SUPPORTED ? "yes" : "no");
299 	bge_set_char_kstat(knp++,
300 		tmp & CHIP_FLAG_SERDES ? "serdes" : "copper");
301 
302 	return (0);
303 }
304 
305 static const bge_ksindex_t bge_driverinfo[] = {
306 	{ 0,				"rx_buff_addr"		},
307 	{ 1,				"tx_buff_addr"		},
308 	{ 2,				"rx_desc_addr"		},
309 	{ 3,				"tx_desc_addr"		},
310 
311 	{ 4,				"tx_desc_free"		},
312 	{ 5,				"resched_needed"	},
313 	{ 6,				"watchdog"		},
314 	{ 7,				"chip_resets"		},
315 	{ 8,				"dma_misses"		},
316 
317 	{ 9,				"misc_host_config"	},
318 	{ 10,				"dma_rw_control"	},
319 	{ 11,				"pci_bus_info"		},
320 
321 	{ 12,				"buff_mgr_status"	},
322 	{ 13,				"rcv_init_status"	},
323 
324 	{ -1,				NULL 			}
325 };
326 
327 static int
328 bge_driverinfo_update(kstat_t *ksp, int flag)
329 {
330 	bge_t *bgep;
331 	kstat_named_t *knp;
332 	ddi_acc_handle_t handle;
333 
334 	if (flag != KSTAT_READ)
335 		return (EACCES);
336 
337 	bgep = ksp->ks_private;
338 	knp = ksp->ks_data;
339 
340 	(knp++)->value.ui64 = bgep->rx_buff[0].cookie.dmac_laddress;
341 	(knp++)->value.ui64 = bgep->tx_buff[0].cookie.dmac_laddress;
342 	(knp++)->value.ui64 = bgep->rx_desc[0].cookie.dmac_laddress;
343 	(knp++)->value.ui64 = bgep->tx_desc.cookie.dmac_laddress;
344 
345 	(knp++)->value.ui64 = bgep->send[0].tx_free;
346 	(knp++)->value.ui64 = bgep->resched_needed;
347 	(knp++)->value.ui64 = bgep->watchdog;
348 	(knp++)->value.ui64 = bgep->chip_resets;
349 	(knp++)->value.ui64 = bgep->missed_dmas;
350 
351 	/*
352 	 * Hold the mutex while accessing the chip registers
353 	 * just in case the factotum is trying to reset it!
354 	 */
355 	handle = bgep->cfg_handle;
356 	mutex_enter(bgep->genlock);
357 	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_MHCR);
358 	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_PDRWCR);
359 	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_PCISTATE);
360 
361 	(knp++)->value.ui64 = bge_reg_get32(bgep, BUFFER_MANAGER_STATUS_REG);
362 	(knp++)->value.ui64 = bge_reg_get32(bgep, RCV_INITIATOR_STATUS_REG);
363 	mutex_exit(bgep->genlock);
364 
365 	return (0);
366 }
367 
368 static const bge_ksindex_t bge_mii_kstats[] = {
369 	{ 0,				"%xcvr_addr"		},
370 	{ 1,				"%xcvr_id"			},
371 	{ 2,				"%xcvr_inuse"		},
372 
373 	{ 3,				"%cap_1000fdx"		},
374 	{ 4,				"%cap_1000hdx"		},
375 	{ 5,				"%cap_100fdx"		},
376 	{ 6,				"%cap_100hdx"		},
377 	{ 7,				"%cap_10fdx"		},
378 	{ 8,				"%cap_10hdx"		},
379 	{ 9,				"%cap_asmpause"		},
380 	{ 10,				"%cap_pause"		},
381 	{ 11,				"%cap_rem_fault"	},
382 	{ 12,				"%cap_autoneg"		},
383 
384 	{ 13,				"%adv_cap_1000fdx"	},
385 	{ 14,				"%adv_cap_1000hdx"	},
386 	{ 15,				"%adv_cap_100fdx"	},
387 	{ 16,				"%adv_cap_100hdx"	},
388 	{ 17,				"%adv_cap_10fdx"	},
389 	{ 18,				"%adv_cap_10hdx"	},
390 	{ 19,				"%adv_cap_asmpause"	},
391 	{ 20,				"%adv_cap_pause"	},
392 	{ 21,				"%adv_rem_fault"	},
393 	{ 22,				"%adv_cap_autoneg"	},
394 
395 	{ 23,				"%lp_cap_1000fdx"	},
396 	{ 24,				"%lp_cap_1000hdx"	},
397 	{ 25,				"%lp_cap_100fdx"	},
398 	{ 26,				"%lp_cap_100hdx"	},
399 	{ 27,				"%lp_cap_10fdx"		},
400 	{ 28,				"%lp_cap_10hdx"		},
401 	{ 29,				"%lp_cap_asmpause"	},
402 	{ 30,				"%lp_cap_pause"		},
403 	{ 31,				"%lp_rem_fault"		},
404 	{ 32,				"%lp_cap_autoneg"	},
405 
406 	{ 33,				"%link_asmpause"	},
407 	{ 34,				"%link_pause"		},
408 	{ 35,				"%link_duplex"		},
409 	{ 36,				"%link_up"			},
410 
411 	{ -1,				NULL 				}
412 };
413 
414 /*
415  * Derive and publish the standard "mii" kstats.
416  *
417  * The information required is somewhat scattered: some is already held
418  * in driver softstate, some is available in the MII registers, and some
419  * has to be computed from combinations of both ...
420  */
421 static int
422 bge_mii_update(kstat_t *ksp, int flag)
423 {
424 	bge_t *bgep;
425 	kstat_named_t *knp;
426 	uint16_t anlpar;
427 	uint16_t anar;
428 	uint32_t xcvr_id;
429 	uint32_t xcvr_inuse;
430 	boolean_t asym_pause;
431 
432 	if (flag != KSTAT_READ)
433 		return (EACCES);
434 
435 	bgep = ksp->ks_private;
436 	knp = ksp->ks_data;
437 
438 	/*
439 	 * Read all the relevant PHY registers
440 	 */
441 	mutex_enter(bgep->genlock);
442 	anlpar = bge_mii_get16(bgep, MII_AN_LPABLE);
443 	anar = bge_mii_get16(bgep, MII_AN_ADVERT);
444 
445 	/*
446 	 * Derive PHY characterisation parameters
447 	 */
448 	xcvr_id = bge_mii_get16(bgep, MII_PHYIDH);
449 	xcvr_id <<= 16;
450 	xcvr_id |= bge_mii_get16(bgep, MII_PHYIDL);
451 	mutex_exit(bgep->genlock);
452 
453 	switch (bgep->param_link_speed) {
454 	case 1000:
455 		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
456 			xcvr_inuse = XCVR_TYPE_1000BASE_X;
457 		else
458 			xcvr_inuse = XCVR_TYPE_1000BASE_T;
459 		break;
460 
461 	case 100:
462 		xcvr_inuse = XCVR_TYPE_100BASE_X;
463 		break;
464 
465 	case 10:
466 		xcvr_inuse = XCVR_TYPE_10BASE_T;
467 		break;
468 
469 	default:
470 		xcvr_inuse = XCVR_TYPE_UNDEFINED;
471 		break;
472 	}
473 
474 	/*
475 	 * Other miscellaneous transformations ...
476 	 */
477 	asym_pause = bgep->param_link_rx_pause != bgep->param_link_tx_pause;
478 
479 	/*
480 	 * All required values are now available; assign them to the
481 	 * actual kstats, in the sequence defined by the table above.
482 	 */
483 	(knp++)->value.ui32 = bgep->phy_mii_addr;
484 	(knp++)->value.ui32 = xcvr_id;
485 	(knp++)->value.ui32 = xcvr_inuse;
486 
487 	/*
488 	 * Our capabilities
489 	 */
490 	(knp++)->value.ui32 = bgep->nd_params[PARAM_1000FDX_CAP].ndp_val;
491 	(knp++)->value.ui32 = bgep->nd_params[PARAM_1000HDX_CAP].ndp_val;
492 	(knp++)->value.ui32 = bgep->nd_params[PARAM_100FDX_CAP].ndp_val;
493 	(knp++)->value.ui32 = bgep->nd_params[PARAM_100HDX_CAP].ndp_val;
494 	(knp++)->value.ui32 = bgep->nd_params[PARAM_10FDX_CAP].ndp_val;
495 	(knp++)->value.ui32 = bgep->nd_params[PARAM_10HDX_CAP].ndp_val;
496 	(knp++)->value.ui32 = bgep->nd_params[PARAM_ASYM_PAUSE_CAP].ndp_val;
497 	(knp++)->value.ui32 = bgep->nd_params[PARAM_PAUSE_CAP].ndp_val;
498 	(knp++)->value.ui32 = B_TRUE;
499 	(knp++)->value.ui32 = bgep->nd_params[PARAM_AUTONEG_CAP].ndp_val;
500 
501 	/*
502 	 * Our *advertised* capabilities
503 	 */
504 	(knp++)->value.ui32 = bgep->param_adv_1000fdx;
505 	(knp++)->value.ui32 = bgep->param_adv_1000hdx;
506 	(knp++)->value.ui32 = bgep->param_adv_100fdx;
507 	(knp++)->value.ui32 = bgep->param_adv_100hdx;
508 	(knp++)->value.ui32 = bgep->param_adv_10fdx;
509 	(knp++)->value.ui32 = bgep->param_adv_10hdx;
510 	(knp++)->value.ui32 = bgep->param_adv_asym_pause;
511 	(knp++)->value.ui32 = bgep->param_adv_pause;
512 	(knp++)->value.ui32 = (anar & MII_AN_ADVERT_REMFAULT) ? 1 : 0;
513 	(knp++)->value.ui32 = bgep->param_adv_autoneg;
514 
515 	/*
516 	 * Link Partner's advertised capabilities
517 	 */
518 	(knp++)->value.ui32 = bgep->param_lp_1000fdx;
519 	(knp++)->value.ui32 = bgep->param_lp_1000hdx;
520 	(knp++)->value.ui32 = bgep->param_lp_100fdx;
521 	(knp++)->value.ui32 = bgep->param_lp_100hdx;
522 	(knp++)->value.ui32 = bgep->param_lp_10fdx;
523 	(knp++)->value.ui32 = bgep->param_lp_10hdx;
524 	(knp++)->value.ui32 = bgep->param_lp_asym_pause;
525 	(knp++)->value.ui32 = bgep->param_lp_pause;
526 	(knp++)->value.ui32 = (anlpar & MII_AN_ADVERT_REMFAULT) ? 1 : 0;
527 	(knp++)->value.ui32 = bgep->param_lp_autoneg;
528 
529 	/*
530 	 * Current operating modes
531 	 */
532 	(knp++)->value.ui32 = asym_pause;
533 	(knp++)->value.ui32 = bgep->param_link_rx_pause;
534 	(knp++)->value.ui32 = bgep->param_link_duplex;
535 	(knp++)->value.ui32 = bgep->param_link_up;
536 
537 	return (0);
538 }
539 
540 static const bge_ksindex_t bge_serdes[] = {
541 	{ 0,				"serdes_status"		},
542 	{ 1,				"serdes_advert"		},
543 	{ 2,				"serdes_lpadv"		},
544 
545 	{ -1,				NULL }
546 };
547 
548 static int
549 bge_serdes_update(kstat_t *ksp, int flag)
550 {
551 	bge_t *bgep;
552 	kstat_named_t *knp;
553 
554 	if (flag != KSTAT_READ)
555 		return (EACCES);
556 
557 	bgep = ksp->ks_private;
558 	knp = ksp->ks_data;
559 
560 	(knp++)->value.ui64 = bgep->serdes_status;
561 	(knp++)->value.ui64 = bgep->serdes_advert;
562 	(knp++)->value.ui64 = bgep->serdes_lpadv;
563 
564 	return (0);
565 }
566 
567 static const bge_ksindex_t bge_phydata[] = {
568 	{ MII_CONTROL,			"mii_control"		},
569 	{ MII_STATUS,			"mii_status"		},
570 	{ MII_PHYIDH,			"phy_identifier"	},
571 	{ MII_AN_ADVERT,		"an_advert"		},
572 	{ MII_AN_LPABLE,		"an_lp_ability"		},
573 	{ MII_AN_EXPANSION,		"an_expansion"		},
574 	{ MII_AN_LPNXTPG,		"an_lp_nextpage"	},
575 	{ MII_1000BASE_T_CONTROL,	"gbit_control"		},
576 	{ MII_1000BASE_T_STATUS,	"gbit_status"		},
577 	{ MII_IEEE_EXT_STATUS,		"ieee_ext_status"	},
578 	{ MII_EXT_CONTROL,		"phy_ext_control"	},
579 	{ MII_EXT_STATUS,		"phy_ext_status"	},
580 	{ MII_RCV_ERR_COUNT,		"receive_error_count"	},
581 	{ MII_FALSE_CARR_COUNT,		"false_carrier_count"	},
582 	{ MII_RCV_NOT_OK_COUNT,		"receiver_not_ok_count"	},
583 	{ MII_AUX_CONTROL,		"aux_control"		},
584 	{ MII_AUX_STATUS,		"aux_status"		},
585 	{ MII_INTR_STATUS,		"intr_status"		},
586 	{ MII_INTR_MASK,		"intr_mask"		},
587 	{ MII_HCD_STATUS,		"hcd_status"		},
588 
589 	{ -1,				NULL }
590 };
591 
592 static int
593 bge_phydata_update(kstat_t *ksp, int flag)
594 {
595 	bge_t *bgep;
596 	kstat_named_t *knp;
597 	const bge_ksindex_t *ksip;
598 
599 	if (flag != KSTAT_READ)
600 		return (EACCES);
601 
602 	bgep = ksp->ks_private;
603 	knp = ksp->ks_data;
604 
605 	/*
606 	 * Read the PHY registers & update the kstats ...
607 	 *
608 	 * We need to hold the mutex while performing MII reads, but
609 	 * we don't want to hold it across the entire sequence of reads.
610 	 * So we grab and release it on each iteration, 'cos it doesn't
611 	 * really matter if the kstats are less than 100% consistent ...
612 	 */
613 	for (ksip = bge_phydata; ksip->name != NULL; ++knp, ++ksip) {
614 		mutex_enter(bgep->genlock);
615 		switch (ksip->index) {
616 		case MII_STATUS:
617 			knp->value.ui64 = bgep->phy_gen_status;
618 			break;
619 
620 		case MII_PHYIDH:
621 			knp->value.ui64 = bge_mii_get16(bgep, MII_PHYIDH);
622 			knp->value.ui64 <<= 16;
623 			knp->value.ui64 |= bge_mii_get16(bgep, MII_PHYIDL);
624 			break;
625 
626 		default:
627 			knp->value.ui64 = bge_mii_get16(bgep, ksip->index);
628 			break;
629 		}
630 		mutex_exit(bgep->genlock);
631 	}
632 
633 	return (0);
634 }
635 
636 static kstat_t *
637 bge_setup_named_kstat(bge_t *bgep, int instance, char *name,
638 	const bge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
639 {
640 	kstat_t *ksp;
641 	kstat_named_t *knp;
642 	char *np;
643 	int type;
644 
645 	size /= sizeof (bge_ksindex_t);
646 	ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net",
647 		KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
648 	if (ksp == NULL)
649 		return (NULL);
650 
651 	ksp->ks_private = bgep;
652 	ksp->ks_update = update;
653 	for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
654 		switch (*np) {
655 		default:
656 			type = KSTAT_DATA_UINT64;
657 			break;
658 		case '%':
659 			np += 1;
660 			type = KSTAT_DATA_UINT32;
661 			break;
662 		case '$':
663 			np += 1;
664 			type = KSTAT_DATA_STRING;
665 			break;
666 		case '&':
667 			np += 1;
668 			type = KSTAT_DATA_CHAR;
669 			break;
670 		}
671 		kstat_named_init(knp, np, type);
672 	}
673 	kstat_install(ksp);
674 
675 	return (ksp);
676 }
677 
678 /*
679  * Create kstats corresponding to NDD parameters
680  */
681 static kstat_t *
682 bge_setup_params_kstat(bge_t *bgep, int instance, char *name,
683 	int (*update)(kstat_t *, int))
684 {
685 	kstat_t *ksp;
686 	kstat_named_t *knp;
687 	int i;
688 
689 	ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net",
690 		KSTAT_TYPE_NAMED, PARAM_COUNT, KSTAT_FLAG_PERSISTENT);
691 	if (ksp != NULL) {
692 		ksp->ks_private = bgep;
693 		ksp->ks_update = update;
694 		for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
695 			kstat_named_init(knp, bgep->nd_params[i].ndp_name+1,
696 				KSTAT_DATA_UINT64);
697 		kstat_install(ksp);
698 	}
699 
700 	return (ksp);
701 }
702 
703 void
704 bge_init_kstats(bge_t *bgep, int instance)
705 {
706 	kstat_t *ksp;
707 
708 	BGE_TRACE(("bge_init_kstats($%p, %d)", (void *)bgep, instance));
709 
710 	DMA_ZERO(bgep->statistics);
711 	bgep->bge_kstats[BGE_KSTAT_RAW] = ksp = kstat_create(BGE_DRIVER_NAME,
712 		instance, "raw_statistics", "net", KSTAT_TYPE_RAW,
713 		sizeof (bge_statistics_t), KSTAT_FLAG_VIRTUAL);
714 	if (ksp != NULL) {
715 		ksp->ks_data = DMA_VPTR(bgep->statistics);
716 		kstat_install(ksp);
717 	}
718 
719 	bgep->bge_kstats[BGE_KSTAT_STATS] = bge_setup_named_kstat(bgep,
720 		instance, "statistics", bge_statistics,
721 		sizeof (bge_statistics), bge_statistics_update);
722 
723 	bgep->bge_kstats[BGE_KSTAT_CHIPID] = bge_setup_named_kstat(bgep,
724 		instance, "chipid", bge_chipid,
725 		sizeof (bge_chipid), bge_chipid_update);
726 
727 	bgep->bge_kstats[BGE_KSTAT_DRIVER] = bge_setup_named_kstat(bgep,
728 		instance, "driverinfo", bge_driverinfo,
729 		sizeof (bge_driverinfo), bge_driverinfo_update);
730 
731 	bgep->bge_kstats[BGE_KSTAT_MII] = bge_setup_named_kstat(bgep,
732 		instance, "mii", bge_mii_kstats,
733 		sizeof (bge_mii_kstats), bge_mii_update);
734 
735 	if (bgep->chipid.flags & CHIP_FLAG_SERDES)
736 		bgep->bge_kstats[BGE_KSTAT_PHYS] = bge_setup_named_kstat(bgep,
737 			instance, "serdes", bge_serdes,
738 			sizeof (bge_serdes), bge_serdes_update);
739 	else
740 		bgep->bge_kstats[BGE_KSTAT_PHYS] = bge_setup_named_kstat(bgep,
741 			instance, "phydata", bge_phydata,
742 			sizeof (bge_phydata), bge_phydata_update);
743 
744 	bgep->bge_kstats[BGE_KSTAT_PARAMS] = bge_setup_params_kstat(bgep,
745 		instance, "parameters", bge_params_update);
746 }
747 
748 void
749 bge_fini_kstats(bge_t *bgep)
750 {
751 	int i;
752 
753 	BGE_TRACE(("bge_fini_kstats($%p)", (void *)bgep));
754 
755 	for (i = BGE_KSTAT_COUNT; --i >= 0; )
756 		if (bgep->bge_kstats[i] != NULL)
757 			kstat_delete(bgep->bge_kstats[i]);
758 }
759 
760 uint64_t
761 bge_m_stat(void *arg, enum mac_stat stat)
762 {
763 	bge_t *bgep = arg;
764 	bge_statistics_t *bstp = DMA_VPTR(bgep->statistics);
765 	uint64_t val;
766 
767 	switch (stat) {
768 	case MAC_STAT_IFSPEED:
769 		val = bgep->param_link_speed * 1000000ull;
770 		break;
771 
772 	case MAC_STAT_MULTIRCV:
773 		val = bstp->s.ifHCInMulticastPkts;
774 		break;
775 
776 	case MAC_STAT_BRDCSTRCV:
777 		val = bstp->s.ifHCInBroadcastPkts;
778 		break;
779 
780 	case MAC_STAT_MULTIXMT:
781 		val = bstp->s.ifHCOutMulticastPkts;
782 		break;
783 
784 	case MAC_STAT_BRDCSTXMT:
785 		val = bstp->s.ifHCOutBroadcastPkts;
786 		break;
787 
788 	case MAC_STAT_NORCVBUF:
789 		val = bstp->s.ifInDiscards;
790 		break;
791 
792 	case MAC_STAT_IERRORS:
793 		val = bstp->s.ifInErrors;
794 		break;
795 
796 	case MAC_STAT_NOXMTBUF:
797 		val = bstp->s.ifOutDiscards;
798 		break;
799 
800 	case MAC_STAT_OERRORS:
801 		val = bstp->s.ifOutErrors;
802 		break;
803 
804 	case MAC_STAT_COLLISIONS:
805 		val = bstp->s.etherStatsCollisions;
806 		break;
807 
808 	case MAC_STAT_RBYTES:
809 		val = bstp->s.ifHCInOctets;
810 		break;
811 
812 	case MAC_STAT_IPACKETS:
813 		val = bstp->s.ifHCInUcastPkts +
814 		    bstp->s.ifHCInMulticastPkts +
815 		    bstp->s.ifHCInBroadcastPkts;
816 		break;
817 
818 	case MAC_STAT_OBYTES:
819 		val = bstp->s.ifHCOutOctets;
820 		break;
821 
822 	case MAC_STAT_OPACKETS:
823 		val = bstp->s.ifHCOutUcastPkts +
824 		    bstp->s.ifHCOutMulticastPkts +
825 		    bstp->s.ifHCOutBroadcastPkts;
826 		break;
827 
828 	case MAC_STAT_ALIGN_ERRORS:
829 		val = bstp->s.dot3StatsAlignmentErrors;
830 		break;
831 
832 	case MAC_STAT_FCS_ERRORS:
833 		val = bstp->s.dot3StatsFCSErrors;
834 		break;
835 
836 	case MAC_STAT_FIRST_COLLISIONS:
837 		val = bstp->s.dot3StatsSingleCollisionFrames;
838 		break;
839 
840 	case MAC_STAT_MULTI_COLLISIONS:
841 		val = bstp->s.dot3StatsMultipleCollisionFrames;
842 		break;
843 
844 	case MAC_STAT_DEFER_XMTS:
845 		val = bstp->s.dot3StatsDeferredTransmissions;
846 		break;
847 
848 	case MAC_STAT_TX_LATE_COLLISIONS:
849 		val = bstp->s.dot3StatsLateCollisions;
850 		break;
851 
852 	case MAC_STAT_EX_COLLISIONS:
853 		val = bstp->s.dot3StatsExcessiveCollisions;
854 		break;
855 
856 	case MAC_STAT_MACXMT_ERRORS:
857 		val = bstp->s.dot3StatsInternalMacTransmitErrors;
858 		break;
859 
860 	case MAC_STAT_CARRIER_ERRORS:
861 		val = bstp->s.dot3StatsCarrierSenseErrors;
862 		break;
863 
864 	case MAC_STAT_TOOLONG_ERRORS:
865 		val = bstp->s.dot3StatsFrameTooLongs;
866 		break;
867 
868 	case MAC_STAT_XCVR_ADDR:
869 		val = bgep->phy_mii_addr;
870 		break;
871 
872 	case MAC_STAT_XCVR_ID:
873 		mutex_enter(bgep->genlock);
874 		val = bge_mii_get16(bgep, MII_PHYIDH);
875 		val <<= 16;
876 		val |= bge_mii_get16(bgep, MII_PHYIDL);
877 		mutex_exit(bgep->genlock);
878 		break;
879 
880 	case MAC_STAT_XCVR_INUSE:
881 		val = XCVR_1000T;
882 		break;
883 
884 	case MAC_STAT_CAP_1000FDX:
885 		val = 1;
886 		break;
887 
888 	case MAC_STAT_CAP_1000HDX:
889 		val = 1;
890 		break;
891 
892 	case MAC_STAT_CAP_100FDX:
893 		val = 1;
894 		break;
895 
896 	case MAC_STAT_CAP_100HDX:
897 		val = 1;
898 		break;
899 
900 	case MAC_STAT_CAP_10FDX:
901 		val = 1;
902 		break;
903 
904 	case MAC_STAT_CAP_10HDX:
905 		val = 1;
906 		break;
907 
908 	case MAC_STAT_CAP_ASMPAUSE:
909 		val = 1;
910 		break;
911 
912 	case MAC_STAT_CAP_PAUSE:
913 		val = 1;
914 		break;
915 
916 	case MAC_STAT_CAP_AUTONEG:
917 		val = 1;
918 		break;
919 
920 	case MAC_STAT_ADV_CAP_1000FDX:
921 		val = bgep->param_adv_1000fdx;
922 		break;
923 
924 	case MAC_STAT_ADV_CAP_1000HDX:
925 		val = bgep->param_adv_1000hdx;
926 		break;
927 
928 	case MAC_STAT_ADV_CAP_100FDX:
929 		val = bgep->param_adv_100fdx;
930 		break;
931 
932 	case MAC_STAT_ADV_CAP_100HDX:
933 		val = bgep->param_adv_100hdx;
934 		break;
935 
936 	case MAC_STAT_ADV_CAP_10FDX:
937 		val = bgep->param_adv_10fdx;
938 		break;
939 
940 	case MAC_STAT_ADV_CAP_10HDX:
941 		val = bgep->param_adv_10hdx;
942 		break;
943 
944 	case MAC_STAT_ADV_CAP_ASMPAUSE:
945 		val = bgep->param_adv_asym_pause;
946 		break;
947 
948 	case MAC_STAT_ADV_CAP_PAUSE:
949 		val = bgep->param_adv_pause;
950 		break;
951 
952 	case MAC_STAT_ADV_CAP_AUTONEG:
953 		val = bgep->param_adv_autoneg;
954 		break;
955 
956 	case MAC_STAT_LP_CAP_1000FDX:
957 		val = bgep->param_lp_1000fdx;
958 		break;
959 
960 	case MAC_STAT_LP_CAP_1000HDX:
961 		val = bgep->param_lp_1000hdx;
962 		break;
963 
964 	case MAC_STAT_LP_CAP_100FDX:
965 		val = bgep->param_lp_100fdx;
966 		break;
967 
968 	case MAC_STAT_LP_CAP_100HDX:
969 		val = bgep->param_lp_100hdx;
970 		break;
971 
972 	case MAC_STAT_LP_CAP_10FDX:
973 		val = bgep->param_lp_10fdx;
974 		break;
975 
976 	case MAC_STAT_LP_CAP_10HDX:
977 		val = bgep->param_lp_10hdx;
978 		break;
979 
980 	case MAC_STAT_LP_CAP_ASMPAUSE:
981 		val = bgep->param_lp_asym_pause;
982 		break;
983 
984 	case MAC_STAT_LP_CAP_PAUSE:
985 		val = bgep->param_lp_pause;
986 		break;
987 
988 	case MAC_STAT_LP_CAP_AUTONEG:
989 		val = bgep->param_lp_autoneg;
990 		break;
991 
992 	case MAC_STAT_LINK_ASMPAUSE:
993 		val = bgep->param_adv_asym_pause &&
994 		    bgep->param_lp_asym_pause &&
995 		    bgep->param_adv_pause != bgep->param_lp_pause;
996 		break;
997 
998 	case MAC_STAT_LINK_PAUSE:
999 		val = bgep->param_link_rx_pause;
1000 		break;
1001 
1002 	case MAC_STAT_LINK_AUTONEG:
1003 		val = bgep->param_link_autoneg;
1004 		break;
1005 
1006 	case MAC_STAT_LINK_DUPLEX:
1007 		val = bgep->param_link_duplex;
1008 		break;
1009 
1010 #ifdef	DEBUG
1011 	default:
1012 		/*
1013 		 * Shouldn't reach here...
1014 		 */
1015 		cmn_err(CE_PANIC,
1016 		    "bge_m_stat: unrecognized parameter value = %d",
1017 		    stat);
1018 #endif
1019 	}
1020 
1021 	return (val);
1022 }
1023