1c7fd2ed0Sgs150176 /*
2c7fd2ed0Sgs150176 * CDDL HEADER START
3c7fd2ed0Sgs150176 *
4c7fd2ed0Sgs150176 * The contents of this file are subject to the terms of the
5ba2e4443Sseb * Common Development and Distribution License (the "License").
6ba2e4443Sseb * You may not use this file except in compliance with the License.
7c7fd2ed0Sgs150176 *
8c7fd2ed0Sgs150176 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c7fd2ed0Sgs150176 * or http://www.opensolaris.org/os/licensing.
10c7fd2ed0Sgs150176 * See the License for the specific language governing permissions
11c7fd2ed0Sgs150176 * and limitations under the License.
12c7fd2ed0Sgs150176 *
13c7fd2ed0Sgs150176 * When distributing Covered Code, include this CDDL HEADER in each
14c7fd2ed0Sgs150176 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c7fd2ed0Sgs150176 * If applicable, add the following below this CDDL HEADER, with the
16c7fd2ed0Sgs150176 * fields enclosed by brackets "[]" replaced with your own identifying
17c7fd2ed0Sgs150176 * information: Portions Copyright [yyyy] [name of copyright owner]
18c7fd2ed0Sgs150176 *
19c7fd2ed0Sgs150176 * CDDL HEADER END
20c7fd2ed0Sgs150176 */
21c7fd2ed0Sgs150176 /*
22*0d2a8e5eSgd78059 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23c7fd2ed0Sgs150176 * Use is subject to license terms.
24c7fd2ed0Sgs150176 */
25c7fd2ed0Sgs150176
26c7fd2ed0Sgs150176 #pragma ident "%Z%%M% %I% %E% SMI"
27c7fd2ed0Sgs150176
28c7fd2ed0Sgs150176 #include "rge.h"
29c7fd2ed0Sgs150176
30c7fd2ed0Sgs150176 #define RGE_DBG RGE_DBG_STATS /* debug flag for this code */
31c7fd2ed0Sgs150176
32c7fd2ed0Sgs150176 /*
33c7fd2ed0Sgs150176 * Local datatype for defining tables of (Offset, Name) pairs
34c7fd2ed0Sgs150176 */
35c7fd2ed0Sgs150176 typedef struct {
36c7fd2ed0Sgs150176 offset_t index;
37c7fd2ed0Sgs150176 char *name;
38c7fd2ed0Sgs150176 } rge_ksindex_t;
39c7fd2ed0Sgs150176
40c7fd2ed0Sgs150176 static const rge_ksindex_t rge_driverinfo[] = {
41c7fd2ed0Sgs150176 { 0, "rx_ring_addr" },
42c7fd2ed0Sgs150176 { 1, "rx_next" },
43c7fd2ed0Sgs150176 { 2, "rx_free" },
44c7fd2ed0Sgs150176 { 3, "rx_bcopy" },
45c7fd2ed0Sgs150176 { 4, "tx_ring_addr" },
46c7fd2ed0Sgs150176 { 5, "tx_next" },
47c7fd2ed0Sgs150176 { 6, "tx_free" },
48c7fd2ed0Sgs150176 { 7, "tx_flow" },
49c7fd2ed0Sgs150176 { 8, "resched_needed" },
50c7fd2ed0Sgs150176 { 9, "watchdog" },
51c7fd2ed0Sgs150176 { 10, "rx_config" },
52c7fd2ed0Sgs150176 { 11, "tx_config" },
53c7fd2ed0Sgs150176 { 12, "mac_ver" },
54c7fd2ed0Sgs150176 { 13, "phy_ver" },
55c7fd2ed0Sgs150176 { 14, "chip_reset" },
56c7fd2ed0Sgs150176 { 15, "phy_reset" },
57*0d2a8e5eSgd78059 { 16, "loop_mode" },
58c7fd2ed0Sgs150176 { -1, NULL }
59c7fd2ed0Sgs150176 };
60c7fd2ed0Sgs150176
61c7fd2ed0Sgs150176 static int
rge_driverinfo_update(kstat_t * ksp,int flag)62c7fd2ed0Sgs150176 rge_driverinfo_update(kstat_t *ksp, int flag)
63c7fd2ed0Sgs150176 {
64c7fd2ed0Sgs150176 rge_t *rgep;
65c7fd2ed0Sgs150176 kstat_named_t *knp;
66c7fd2ed0Sgs150176
67c7fd2ed0Sgs150176 if (flag != KSTAT_READ)
68c7fd2ed0Sgs150176 return (EACCES);
69c7fd2ed0Sgs150176
70c7fd2ed0Sgs150176 rgep = ksp->ks_private;
71c7fd2ed0Sgs150176 knp = ksp->ks_data;
72c7fd2ed0Sgs150176
73c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->dma_area_rxdesc.cookie.dmac_laddress;
74c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->rx_next;
75c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->rx_free;
76c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->rx_bcopy;
77c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->dma_area_txdesc.cookie.dmac_laddress;
78c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->tx_next;
79c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->tx_free;
80c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->tx_flow;
81c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->resched_needed;
82c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->watchdog;
83c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->chipid.rxconfig;
84c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->chipid.txconfig;
85c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->chipid.mac_ver;
86c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->chipid.phy_ver;
87c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->stats.chip_reset;
88c7fd2ed0Sgs150176 (knp++)->value.ui64 = rgep->stats.phy_reset;
89*0d2a8e5eSgd78059 (knp++)->value.ui64 = rgep->param_loop_mode;
90c7fd2ed0Sgs150176
91c7fd2ed0Sgs150176 return (0);
92c7fd2ed0Sgs150176 }
93c7fd2ed0Sgs150176
94c7fd2ed0Sgs150176 static kstat_t *
rge_setup_named_kstat(rge_t * rgep,int instance,char * name,const rge_ksindex_t * ksip,size_t size,int (* update)(kstat_t *,int))95c7fd2ed0Sgs150176 rge_setup_named_kstat(rge_t *rgep, int instance, char *name,
96c7fd2ed0Sgs150176 const rge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
97c7fd2ed0Sgs150176 {
98c7fd2ed0Sgs150176 kstat_t *ksp;
99c7fd2ed0Sgs150176 kstat_named_t *knp;
100c7fd2ed0Sgs150176 char *np;
101c7fd2ed0Sgs150176 int type;
102c7fd2ed0Sgs150176
103c7fd2ed0Sgs150176 size /= sizeof (rge_ksindex_t);
104c7fd2ed0Sgs150176 ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
105c7fd2ed0Sgs150176 KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
106c7fd2ed0Sgs150176 if (ksp == NULL)
107c7fd2ed0Sgs150176 return (NULL);
108c7fd2ed0Sgs150176
109c7fd2ed0Sgs150176 ksp->ks_private = rgep;
110c7fd2ed0Sgs150176 ksp->ks_update = update;
111c7fd2ed0Sgs150176 for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
112c7fd2ed0Sgs150176 switch (*np) {
113c7fd2ed0Sgs150176 default:
114c7fd2ed0Sgs150176 type = KSTAT_DATA_UINT64;
115c7fd2ed0Sgs150176 break;
116c7fd2ed0Sgs150176 case '%':
117c7fd2ed0Sgs150176 np += 1;
118c7fd2ed0Sgs150176 type = KSTAT_DATA_UINT32;
119c7fd2ed0Sgs150176 break;
120c7fd2ed0Sgs150176 case '$':
121c7fd2ed0Sgs150176 np += 1;
122c7fd2ed0Sgs150176 type = KSTAT_DATA_STRING;
123c7fd2ed0Sgs150176 break;
124c7fd2ed0Sgs150176 case '&':
125c7fd2ed0Sgs150176 np += 1;
126c7fd2ed0Sgs150176 type = KSTAT_DATA_CHAR;
127c7fd2ed0Sgs150176 break;
128c7fd2ed0Sgs150176 }
129c7fd2ed0Sgs150176 kstat_named_init(knp, np, type);
130c7fd2ed0Sgs150176 }
131c7fd2ed0Sgs150176 kstat_install(ksp);
132c7fd2ed0Sgs150176
133c7fd2ed0Sgs150176 return (ksp);
134c7fd2ed0Sgs150176 }
135c7fd2ed0Sgs150176
136c7fd2ed0Sgs150176 void
rge_init_kstats(rge_t * rgep,int instance)137c7fd2ed0Sgs150176 rge_init_kstats(rge_t *rgep, int instance)
138c7fd2ed0Sgs150176 {
139c7fd2ed0Sgs150176 rgep->rge_kstats[RGE_KSTAT_DRIVER] = rge_setup_named_kstat(rgep,
140c7fd2ed0Sgs150176 instance, "driverinfo", rge_driverinfo,
141c7fd2ed0Sgs150176 sizeof (rge_driverinfo), rge_driverinfo_update);
142c7fd2ed0Sgs150176 }
143c7fd2ed0Sgs150176
144c7fd2ed0Sgs150176 void
rge_fini_kstats(rge_t * rgep)145c7fd2ed0Sgs150176 rge_fini_kstats(rge_t *rgep)
146c7fd2ed0Sgs150176 {
147c7fd2ed0Sgs150176 int i;
148c7fd2ed0Sgs150176
149c7fd2ed0Sgs150176 for (i = RGE_KSTAT_COUNT; --i >= 0; )
150c7fd2ed0Sgs150176 if (rgep->rge_kstats[i] != NULL) {
151c7fd2ed0Sgs150176 kstat_delete(rgep->rge_kstats[i]);
152c7fd2ed0Sgs150176 }
153c7fd2ed0Sgs150176 }
154c7fd2ed0Sgs150176
155ba2e4443Sseb int
rge_m_stat(void * arg,uint_t stat,uint64_t * val)156ba2e4443Sseb rge_m_stat(void *arg, uint_t stat, uint64_t *val)
157c7fd2ed0Sgs150176 {
158c7fd2ed0Sgs150176 rge_t *rgep = arg;
159c7fd2ed0Sgs150176 rge_hw_stats_t *bstp;
160c7fd2ed0Sgs150176
161c7fd2ed0Sgs150176 mutex_enter(rgep->genlock);
162c7fd2ed0Sgs150176 rge_hw_stats_dump(rgep);
163c7fd2ed0Sgs150176 mutex_exit(rgep->genlock);
164c7fd2ed0Sgs150176 bstp = rgep->hw_stats;
165c7fd2ed0Sgs150176
166c7fd2ed0Sgs150176 switch (stat) {
167c7fd2ed0Sgs150176 case MAC_STAT_IFSPEED:
168ba2e4443Sseb *val = rgep->param_link_speed * 1000000ull;
169c7fd2ed0Sgs150176 break;
170c7fd2ed0Sgs150176
171c7fd2ed0Sgs150176 case MAC_STAT_MULTIRCV:
172ba2e4443Sseb *val = RGE_BSWAP_32(bstp->multi_rcv);
173c7fd2ed0Sgs150176 break;
174c7fd2ed0Sgs150176
175c7fd2ed0Sgs150176 case MAC_STAT_BRDCSTRCV:
176ba2e4443Sseb *val = RGE_BSWAP_64(bstp->brdcst_rcv);
177c7fd2ed0Sgs150176 break;
178c7fd2ed0Sgs150176
179c7fd2ed0Sgs150176 case MAC_STAT_NORCVBUF:
180ba2e4443Sseb *val = RGE_BSWAP_16(bstp->in_discards);
181c7fd2ed0Sgs150176 break;
182c7fd2ed0Sgs150176
183c7fd2ed0Sgs150176 case MAC_STAT_IERRORS:
184ba2e4443Sseb *val = RGE_BSWAP_32(bstp->rcv_err);
185c7fd2ed0Sgs150176 break;
186c7fd2ed0Sgs150176
187c7fd2ed0Sgs150176 case MAC_STAT_OERRORS:
188ba2e4443Sseb *val = RGE_BSWAP_64(bstp->xmt_err);
189c7fd2ed0Sgs150176 break;
190c7fd2ed0Sgs150176
191c7fd2ed0Sgs150176 case MAC_STAT_COLLISIONS:
192ba2e4443Sseb *val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
193c7fd2ed0Sgs150176 break;
194c7fd2ed0Sgs150176
195c7fd2ed0Sgs150176 case MAC_STAT_RBYTES:
196ba2e4443Sseb *val = rgep->stats.rbytes;
197c7fd2ed0Sgs150176 break;
198c7fd2ed0Sgs150176
199c7fd2ed0Sgs150176 case MAC_STAT_IPACKETS:
200ba2e4443Sseb *val = RGE_BSWAP_64(bstp->rcv_ok);
201c7fd2ed0Sgs150176 break;
202c7fd2ed0Sgs150176
203c7fd2ed0Sgs150176 case MAC_STAT_OBYTES:
204ba2e4443Sseb *val = rgep->stats.obytes;
205c7fd2ed0Sgs150176 break;
206c7fd2ed0Sgs150176
207c7fd2ed0Sgs150176 case MAC_STAT_OPACKETS:
208ba2e4443Sseb *val = RGE_BSWAP_64(bstp->xmt_ok);
209c7fd2ed0Sgs150176 break;
210c7fd2ed0Sgs150176
211ba2e4443Sseb case ETHER_STAT_ALIGN_ERRORS:
212ba2e4443Sseb *val = RGE_BSWAP_16(bstp->frame_err);
213c7fd2ed0Sgs150176 break;
214c7fd2ed0Sgs150176
215ba2e4443Sseb case ETHER_STAT_FIRST_COLLISIONS:
216ba2e4443Sseb *val = RGE_BSWAP_32(bstp->xmt_1col);
217c7fd2ed0Sgs150176 break;
218c7fd2ed0Sgs150176
219ba2e4443Sseb case ETHER_STAT_MULTI_COLLISIONS:
220ba2e4443Sseb *val = RGE_BSWAP_32(bstp->xmt_mcol);
221c7fd2ed0Sgs150176 break;
222c7fd2ed0Sgs150176
223ba2e4443Sseb case ETHER_STAT_DEFER_XMTS:
224ba2e4443Sseb *val = rgep->stats.defer;
225c7fd2ed0Sgs150176 break;
226c7fd2ed0Sgs150176
227ba2e4443Sseb case ETHER_STAT_XCVR_ADDR:
228ba2e4443Sseb *val = rgep->phy_mii_addr;
229c7fd2ed0Sgs150176 break;
230c7fd2ed0Sgs150176
231ba2e4443Sseb case ETHER_STAT_XCVR_ID:
232c7fd2ed0Sgs150176 mutex_enter(rgep->genlock);
233ba2e4443Sseb *val = rge_mii_get16(rgep, MII_PHYIDH);
234ba2e4443Sseb *val <<= 16;
235ba2e4443Sseb *val |= rge_mii_get16(rgep, MII_PHYIDL);
236c7fd2ed0Sgs150176 mutex_exit(rgep->genlock);
237c7fd2ed0Sgs150176 break;
238c7fd2ed0Sgs150176
239ba2e4443Sseb case ETHER_STAT_XCVR_INUSE:
240ba2e4443Sseb *val = XCVR_1000T;
241c7fd2ed0Sgs150176 break;
242c7fd2ed0Sgs150176
243ba2e4443Sseb case ETHER_STAT_CAP_1000FDX:
244ba2e4443Sseb *val = 1;
245c7fd2ed0Sgs150176 break;
246c7fd2ed0Sgs150176
247ba2e4443Sseb case ETHER_STAT_CAP_1000HDX:
248ba2e4443Sseb *val = 0;
249c7fd2ed0Sgs150176 break;
250c7fd2ed0Sgs150176
251ba2e4443Sseb case ETHER_STAT_CAP_100FDX:
252ba2e4443Sseb *val = 1;
253c7fd2ed0Sgs150176 break;
254c7fd2ed0Sgs150176
255ba2e4443Sseb case ETHER_STAT_CAP_100HDX:
256ba2e4443Sseb *val = 1;
257c7fd2ed0Sgs150176 break;
258c7fd2ed0Sgs150176
259ba2e4443Sseb case ETHER_STAT_CAP_10FDX:
260ba2e4443Sseb *val = 1;
261c7fd2ed0Sgs150176 break;
262c7fd2ed0Sgs150176
263ba2e4443Sseb case ETHER_STAT_CAP_10HDX:
264ba2e4443Sseb *val = 1;
265c7fd2ed0Sgs150176 break;
266c7fd2ed0Sgs150176
267ba2e4443Sseb case ETHER_STAT_CAP_ASMPAUSE:
268ba2e4443Sseb *val = 1;
269c7fd2ed0Sgs150176 break;
270c7fd2ed0Sgs150176
271ba2e4443Sseb case ETHER_STAT_CAP_PAUSE:
272ba2e4443Sseb *val = 1;
273c7fd2ed0Sgs150176 break;
274c7fd2ed0Sgs150176
275ba2e4443Sseb case ETHER_STAT_CAP_AUTONEG:
276ba2e4443Sseb *val = 1;
277c7fd2ed0Sgs150176 break;
278c7fd2ed0Sgs150176
279ba2e4443Sseb case ETHER_STAT_ADV_CAP_1000FDX:
280ba2e4443Sseb *val = rgep->param_adv_1000fdx;
281c7fd2ed0Sgs150176 break;
282c7fd2ed0Sgs150176
283ba2e4443Sseb case ETHER_STAT_ADV_CAP_1000HDX:
284ba2e4443Sseb *val = rgep->param_adv_1000hdx;
285c7fd2ed0Sgs150176 break;
286c7fd2ed0Sgs150176
287ba2e4443Sseb case ETHER_STAT_ADV_CAP_100FDX:
288ba2e4443Sseb *val = rgep->param_adv_100fdx;
289c7fd2ed0Sgs150176 break;
290c7fd2ed0Sgs150176
291ba2e4443Sseb case ETHER_STAT_ADV_CAP_100HDX:
292ba2e4443Sseb *val = rgep->param_adv_100hdx;
293c7fd2ed0Sgs150176 break;
294c7fd2ed0Sgs150176
295ba2e4443Sseb case ETHER_STAT_ADV_CAP_10FDX:
296ba2e4443Sseb *val = rgep->param_adv_10fdx;
297c7fd2ed0Sgs150176 break;
298c7fd2ed0Sgs150176
299ba2e4443Sseb case ETHER_STAT_ADV_CAP_10HDX:
300ba2e4443Sseb *val = rgep->param_adv_10hdx;
301c7fd2ed0Sgs150176 break;
302c7fd2ed0Sgs150176
303ba2e4443Sseb case ETHER_STAT_ADV_CAP_ASMPAUSE:
304ba2e4443Sseb *val = rgep->param_adv_asym_pause;
305c7fd2ed0Sgs150176 break;
306c7fd2ed0Sgs150176
307ba2e4443Sseb case ETHER_STAT_ADV_CAP_PAUSE:
308ba2e4443Sseb *val = rgep->param_adv_pause;
309c7fd2ed0Sgs150176 break;
310c7fd2ed0Sgs150176
311ba2e4443Sseb case ETHER_STAT_ADV_CAP_AUTONEG:
312ba2e4443Sseb *val = rgep->param_adv_autoneg;
313c7fd2ed0Sgs150176 break;
314c7fd2ed0Sgs150176
315ba2e4443Sseb case ETHER_STAT_LINK_DUPLEX:
316ba2e4443Sseb *val = rgep->param_link_duplex;
317c7fd2ed0Sgs150176 break;
318c7fd2ed0Sgs150176
319c7fd2ed0Sgs150176 default:
320ba2e4443Sseb return (ENOTSUP);
321c7fd2ed0Sgs150176 }
322c7fd2ed0Sgs150176
323ba2e4443Sseb return (0);
324c7fd2ed0Sgs150176 }
325