1744Sgs150176 /*
2744Sgs150176 * CDDL HEADER START
3744Sgs150176 *
4744Sgs150176 * The contents of this file are subject to the terms of the
52311Sseb * Common Development and Distribution License (the "License").
62311Sseb * You may not use this file except in compliance with the License.
7744Sgs150176 *
8744Sgs150176 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9744Sgs150176 * or http://www.opensolaris.org/os/licensing.
10744Sgs150176 * See the License for the specific language governing permissions
11744Sgs150176 * and limitations under the License.
12744Sgs150176 *
13744Sgs150176 * When distributing Covered Code, include this CDDL HEADER in each
14744Sgs150176 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15744Sgs150176 * If applicable, add the following below this CDDL HEADER, with the
16744Sgs150176 * fields enclosed by brackets "[]" replaced with your own identifying
17744Sgs150176 * information: Portions Copyright [yyyy] [name of copyright owner]
18744Sgs150176 *
19744Sgs150176 * CDDL HEADER END
20744Sgs150176 */
21744Sgs150176 /*
22*4403Sgd78059 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23744Sgs150176 * Use is subject to license terms.
24744Sgs150176 */
25744Sgs150176
26744Sgs150176 #pragma ident "%Z%%M% %I% %E% SMI"
27744Sgs150176
28744Sgs150176 #include "rge.h"
29744Sgs150176
30744Sgs150176 #define RGE_DBG RGE_DBG_STATS /* debug flag for this code */
31744Sgs150176
32744Sgs150176 /*
33744Sgs150176 * Local datatype for defining tables of (Offset, Name) pairs
34744Sgs150176 */
35744Sgs150176 typedef struct {
36744Sgs150176 offset_t index;
37744Sgs150176 char *name;
38744Sgs150176 } rge_ksindex_t;
39744Sgs150176
40744Sgs150176 static const rge_ksindex_t rge_driverinfo[] = {
41744Sgs150176 { 0, "rx_ring_addr" },
42744Sgs150176 { 1, "rx_next" },
43744Sgs150176 { 2, "rx_free" },
44744Sgs150176 { 3, "rx_bcopy" },
45744Sgs150176 { 4, "tx_ring_addr" },
46744Sgs150176 { 5, "tx_next" },
47744Sgs150176 { 6, "tx_free" },
48744Sgs150176 { 7, "tx_flow" },
49744Sgs150176 { 8, "resched_needed" },
50744Sgs150176 { 9, "watchdog" },
51744Sgs150176 { 10, "rx_config" },
52744Sgs150176 { 11, "tx_config" },
53744Sgs150176 { 12, "mac_ver" },
54744Sgs150176 { 13, "phy_ver" },
55744Sgs150176 { 14, "chip_reset" },
56744Sgs150176 { 15, "phy_reset" },
57*4403Sgd78059 { 16, "loop_mode" },
58744Sgs150176 { -1, NULL }
59744Sgs150176 };
60744Sgs150176
61744Sgs150176 static int
rge_driverinfo_update(kstat_t * ksp,int flag)62744Sgs150176 rge_driverinfo_update(kstat_t *ksp, int flag)
63744Sgs150176 {
64744Sgs150176 rge_t *rgep;
65744Sgs150176 kstat_named_t *knp;
66744Sgs150176
67744Sgs150176 if (flag != KSTAT_READ)
68744Sgs150176 return (EACCES);
69744Sgs150176
70744Sgs150176 rgep = ksp->ks_private;
71744Sgs150176 knp = ksp->ks_data;
72744Sgs150176
73744Sgs150176 (knp++)->value.ui64 = rgep->dma_area_rxdesc.cookie.dmac_laddress;
74744Sgs150176 (knp++)->value.ui64 = rgep->rx_next;
75744Sgs150176 (knp++)->value.ui64 = rgep->rx_free;
76744Sgs150176 (knp++)->value.ui64 = rgep->rx_bcopy;
77744Sgs150176 (knp++)->value.ui64 = rgep->dma_area_txdesc.cookie.dmac_laddress;
78744Sgs150176 (knp++)->value.ui64 = rgep->tx_next;
79744Sgs150176 (knp++)->value.ui64 = rgep->tx_free;
80744Sgs150176 (knp++)->value.ui64 = rgep->tx_flow;
81744Sgs150176 (knp++)->value.ui64 = rgep->resched_needed;
82744Sgs150176 (knp++)->value.ui64 = rgep->watchdog;
83744Sgs150176 (knp++)->value.ui64 = rgep->chipid.rxconfig;
84744Sgs150176 (knp++)->value.ui64 = rgep->chipid.txconfig;
85744Sgs150176 (knp++)->value.ui64 = rgep->chipid.mac_ver;
86744Sgs150176 (knp++)->value.ui64 = rgep->chipid.phy_ver;
87744Sgs150176 (knp++)->value.ui64 = rgep->stats.chip_reset;
88744Sgs150176 (knp++)->value.ui64 = rgep->stats.phy_reset;
89*4403Sgd78059 (knp++)->value.ui64 = rgep->param_loop_mode;
90744Sgs150176
91744Sgs150176 return (0);
92744Sgs150176 }
93744Sgs150176
94744Sgs150176 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))95744Sgs150176 rge_setup_named_kstat(rge_t *rgep, int instance, char *name,
96744Sgs150176 const rge_ksindex_t *ksip, size_t size, int (*update)(kstat_t *, int))
97744Sgs150176 {
98744Sgs150176 kstat_t *ksp;
99744Sgs150176 kstat_named_t *knp;
100744Sgs150176 char *np;
101744Sgs150176 int type;
102744Sgs150176
103744Sgs150176 size /= sizeof (rge_ksindex_t);
104744Sgs150176 ksp = kstat_create(RGE_DRIVER_NAME, instance, name, "net",
105744Sgs150176 KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
106744Sgs150176 if (ksp == NULL)
107744Sgs150176 return (NULL);
108744Sgs150176
109744Sgs150176 ksp->ks_private = rgep;
110744Sgs150176 ksp->ks_update = update;
111744Sgs150176 for (knp = ksp->ks_data; (np = ksip->name) != NULL; ++knp, ++ksip) {
112744Sgs150176 switch (*np) {
113744Sgs150176 default:
114744Sgs150176 type = KSTAT_DATA_UINT64;
115744Sgs150176 break;
116744Sgs150176 case '%':
117744Sgs150176 np += 1;
118744Sgs150176 type = KSTAT_DATA_UINT32;
119744Sgs150176 break;
120744Sgs150176 case '$':
121744Sgs150176 np += 1;
122744Sgs150176 type = KSTAT_DATA_STRING;
123744Sgs150176 break;
124744Sgs150176 case '&':
125744Sgs150176 np += 1;
126744Sgs150176 type = KSTAT_DATA_CHAR;
127744Sgs150176 break;
128744Sgs150176 }
129744Sgs150176 kstat_named_init(knp, np, type);
130744Sgs150176 }
131744Sgs150176 kstat_install(ksp);
132744Sgs150176
133744Sgs150176 return (ksp);
134744Sgs150176 }
135744Sgs150176
136744Sgs150176 void
rge_init_kstats(rge_t * rgep,int instance)137744Sgs150176 rge_init_kstats(rge_t *rgep, int instance)
138744Sgs150176 {
139744Sgs150176 rgep->rge_kstats[RGE_KSTAT_DRIVER] = rge_setup_named_kstat(rgep,
140744Sgs150176 instance, "driverinfo", rge_driverinfo,
141744Sgs150176 sizeof (rge_driverinfo), rge_driverinfo_update);
142744Sgs150176 }
143744Sgs150176
144744Sgs150176 void
rge_fini_kstats(rge_t * rgep)145744Sgs150176 rge_fini_kstats(rge_t *rgep)
146744Sgs150176 {
147744Sgs150176 int i;
148744Sgs150176
149744Sgs150176 for (i = RGE_KSTAT_COUNT; --i >= 0; )
150744Sgs150176 if (rgep->rge_kstats[i] != NULL) {
151744Sgs150176 kstat_delete(rgep->rge_kstats[i]);
152744Sgs150176 }
153744Sgs150176 }
154744Sgs150176
1552311Sseb int
rge_m_stat(void * arg,uint_t stat,uint64_t * val)1562311Sseb rge_m_stat(void *arg, uint_t stat, uint64_t *val)
157744Sgs150176 {
158744Sgs150176 rge_t *rgep = arg;
159744Sgs150176 rge_hw_stats_t *bstp;
160744Sgs150176
161744Sgs150176 mutex_enter(rgep->genlock);
162744Sgs150176 rge_hw_stats_dump(rgep);
163744Sgs150176 mutex_exit(rgep->genlock);
164744Sgs150176 bstp = rgep->hw_stats;
165744Sgs150176
166744Sgs150176 switch (stat) {
167744Sgs150176 case MAC_STAT_IFSPEED:
1682311Sseb *val = rgep->param_link_speed * 1000000ull;
169744Sgs150176 break;
170744Sgs150176
171744Sgs150176 case MAC_STAT_MULTIRCV:
1722311Sseb *val = RGE_BSWAP_32(bstp->multi_rcv);
173744Sgs150176 break;
174744Sgs150176
175744Sgs150176 case MAC_STAT_BRDCSTRCV:
1762311Sseb *val = RGE_BSWAP_64(bstp->brdcst_rcv);
177744Sgs150176 break;
178744Sgs150176
179744Sgs150176 case MAC_STAT_NORCVBUF:
1802311Sseb *val = RGE_BSWAP_16(bstp->in_discards);
181744Sgs150176 break;
182744Sgs150176
183744Sgs150176 case MAC_STAT_IERRORS:
1842311Sseb *val = RGE_BSWAP_32(bstp->rcv_err);
185744Sgs150176 break;
186744Sgs150176
187744Sgs150176 case MAC_STAT_OERRORS:
1882311Sseb *val = RGE_BSWAP_64(bstp->xmt_err);
189744Sgs150176 break;
190744Sgs150176
191744Sgs150176 case MAC_STAT_COLLISIONS:
1922311Sseb *val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
193744Sgs150176 break;
194744Sgs150176
195744Sgs150176 case MAC_STAT_RBYTES:
1962311Sseb *val = rgep->stats.rbytes;
197744Sgs150176 break;
198744Sgs150176
199744Sgs150176 case MAC_STAT_IPACKETS:
2002311Sseb *val = RGE_BSWAP_64(bstp->rcv_ok);
201744Sgs150176 break;
202744Sgs150176
203744Sgs150176 case MAC_STAT_OBYTES:
2042311Sseb *val = rgep->stats.obytes;
205744Sgs150176 break;
206744Sgs150176
207744Sgs150176 case MAC_STAT_OPACKETS:
2082311Sseb *val = RGE_BSWAP_64(bstp->xmt_ok);
209744Sgs150176 break;
210744Sgs150176
2112311Sseb case ETHER_STAT_ALIGN_ERRORS:
2122311Sseb *val = RGE_BSWAP_16(bstp->frame_err);
213744Sgs150176 break;
214744Sgs150176
2152311Sseb case ETHER_STAT_FIRST_COLLISIONS:
2162311Sseb *val = RGE_BSWAP_32(bstp->xmt_1col);
217744Sgs150176 break;
218744Sgs150176
2192311Sseb case ETHER_STAT_MULTI_COLLISIONS:
2202311Sseb *val = RGE_BSWAP_32(bstp->xmt_mcol);
221744Sgs150176 break;
222744Sgs150176
2232311Sseb case ETHER_STAT_DEFER_XMTS:
2242311Sseb *val = rgep->stats.defer;
225744Sgs150176 break;
226744Sgs150176
2272311Sseb case ETHER_STAT_XCVR_ADDR:
2282311Sseb *val = rgep->phy_mii_addr;
229744Sgs150176 break;
230744Sgs150176
2312311Sseb case ETHER_STAT_XCVR_ID:
232744Sgs150176 mutex_enter(rgep->genlock);
2332311Sseb *val = rge_mii_get16(rgep, MII_PHYIDH);
2342311Sseb *val <<= 16;
2352311Sseb *val |= rge_mii_get16(rgep, MII_PHYIDL);
236744Sgs150176 mutex_exit(rgep->genlock);
237744Sgs150176 break;
238744Sgs150176
2392311Sseb case ETHER_STAT_XCVR_INUSE:
2402311Sseb *val = XCVR_1000T;
241744Sgs150176 break;
242744Sgs150176
2432311Sseb case ETHER_STAT_CAP_1000FDX:
2442311Sseb *val = 1;
245744Sgs150176 break;
246744Sgs150176
2472311Sseb case ETHER_STAT_CAP_1000HDX:
2482311Sseb *val = 0;
249744Sgs150176 break;
250744Sgs150176
2512311Sseb case ETHER_STAT_CAP_100FDX:
2522311Sseb *val = 1;
253744Sgs150176 break;
254744Sgs150176
2552311Sseb case ETHER_STAT_CAP_100HDX:
2562311Sseb *val = 1;
257744Sgs150176 break;
258744Sgs150176
2592311Sseb case ETHER_STAT_CAP_10FDX:
2602311Sseb *val = 1;
261744Sgs150176 break;
262744Sgs150176
2632311Sseb case ETHER_STAT_CAP_10HDX:
2642311Sseb *val = 1;
265744Sgs150176 break;
266744Sgs150176
2672311Sseb case ETHER_STAT_CAP_ASMPAUSE:
2682311Sseb *val = 1;
269744Sgs150176 break;
270744Sgs150176
2712311Sseb case ETHER_STAT_CAP_PAUSE:
2722311Sseb *val = 1;
273744Sgs150176 break;
274744Sgs150176
2752311Sseb case ETHER_STAT_CAP_AUTONEG:
2762311Sseb *val = 1;
277744Sgs150176 break;
278744Sgs150176
2792311Sseb case ETHER_STAT_ADV_CAP_1000FDX:
2802311Sseb *val = rgep->param_adv_1000fdx;
281744Sgs150176 break;
282744Sgs150176
2832311Sseb case ETHER_STAT_ADV_CAP_1000HDX:
2842311Sseb *val = rgep->param_adv_1000hdx;
285744Sgs150176 break;
286744Sgs150176
2872311Sseb case ETHER_STAT_ADV_CAP_100FDX:
2882311Sseb *val = rgep->param_adv_100fdx;
289744Sgs150176 break;
290744Sgs150176
2912311Sseb case ETHER_STAT_ADV_CAP_100HDX:
2922311Sseb *val = rgep->param_adv_100hdx;
293744Sgs150176 break;
294744Sgs150176
2952311Sseb case ETHER_STAT_ADV_CAP_10FDX:
2962311Sseb *val = rgep->param_adv_10fdx;
297744Sgs150176 break;
298744Sgs150176
2992311Sseb case ETHER_STAT_ADV_CAP_10HDX:
3002311Sseb *val = rgep->param_adv_10hdx;
301744Sgs150176 break;
302744Sgs150176
3032311Sseb case ETHER_STAT_ADV_CAP_ASMPAUSE:
3042311Sseb *val = rgep->param_adv_asym_pause;
305744Sgs150176 break;
306744Sgs150176
3072311Sseb case ETHER_STAT_ADV_CAP_PAUSE:
3082311Sseb *val = rgep->param_adv_pause;
309744Sgs150176 break;
310744Sgs150176
3112311Sseb case ETHER_STAT_ADV_CAP_AUTONEG:
3122311Sseb *val = rgep->param_adv_autoneg;
3132311Sseb break;
3142311Sseb
3152311Sseb case ETHER_STAT_LINK_DUPLEX:
3162311Sseb *val = rgep->param_link_duplex;
3172311Sseb break;
3182311Sseb
319744Sgs150176 default:
3202311Sseb return (ENOTSUP);
321744Sgs150176 }
322744Sgs150176
3232311Sseb return (0);
324744Sgs150176 }
325