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