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