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