1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate * All rights reserved.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/async.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/pci/pci_obj.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> /* lddphys() */
36*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
37*7c478bd9Sstevel@tonic-gate
38*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
39*7c478bd9Sstevel@tonic-gate
40*7c478bd9Sstevel@tonic-gate static kstat_t *pci_create_picN_kstat(char *, int, int, int,
41*7c478bd9Sstevel@tonic-gate pci_kev_mask_t *);
42*7c478bd9Sstevel@tonic-gate
43*7c478bd9Sstevel@tonic-gate void
pci_kstat_create(pci_t * pci_p)44*7c478bd9Sstevel@tonic-gate pci_kstat_create(pci_t *pci_p)
45*7c478bd9Sstevel@tonic-gate {
46*7c478bd9Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p;
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gate if (cmn_p->pci_common_attachcnt == 0)
49*7c478bd9Sstevel@tonic-gate pci_add_upstream_kstat(pci_p);
50*7c478bd9Sstevel@tonic-gate
51*7c478bd9Sstevel@tonic-gate pci_add_pci_kstat(pci_p);
52*7c478bd9Sstevel@tonic-gate }
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gate void
pci_kstat_destroy(pci_t * pci_p)55*7c478bd9Sstevel@tonic-gate pci_kstat_destroy(pci_t *pci_p)
56*7c478bd9Sstevel@tonic-gate {
57*7c478bd9Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p;
58*7c478bd9Sstevel@tonic-gate
59*7c478bd9Sstevel@tonic-gate pci_rem_pci_kstat(pci_p);
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gate if (cmn_p->pci_common_attachcnt == 0)
62*7c478bd9Sstevel@tonic-gate pci_rem_upstream_kstat(pci_p);
63*7c478bd9Sstevel@tonic-gate }
64*7c478bd9Sstevel@tonic-gate
65*7c478bd9Sstevel@tonic-gate void
pci_create_name_kstat(char * name,pci_ksinfo_t * pp,pci_kev_mask_t * ev)66*7c478bd9Sstevel@tonic-gate pci_create_name_kstat(char *name, pci_ksinfo_t *pp, pci_kev_mask_t *ev)
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate int i;
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) {
71*7c478bd9Sstevel@tonic-gate pp->pic_name_ksp[i] = pci_create_picN_kstat(name,
72*7c478bd9Sstevel@tonic-gate i, pp->pic_shift[i], pp->pic_no_evs, ev);
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate if (pp->pic_name_ksp[i] == NULL) {
75*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "pci: unable to create name kstat");
76*7c478bd9Sstevel@tonic-gate }
77*7c478bd9Sstevel@tonic-gate }
78*7c478bd9Sstevel@tonic-gate }
79*7c478bd9Sstevel@tonic-gate
80*7c478bd9Sstevel@tonic-gate void
pci_delete_name_kstat(pci_ksinfo_t * pp)81*7c478bd9Sstevel@tonic-gate pci_delete_name_kstat(pci_ksinfo_t *pp)
82*7c478bd9Sstevel@tonic-gate {
83*7c478bd9Sstevel@tonic-gate int i;
84*7c478bd9Sstevel@tonic-gate
85*7c478bd9Sstevel@tonic-gate if (pp != NULL) {
86*7c478bd9Sstevel@tonic-gate for (i = 0; i < NUM_OF_PICS; i++) {
87*7c478bd9Sstevel@tonic-gate if (pp->pic_name_ksp[i] != NULL)
88*7c478bd9Sstevel@tonic-gate kstat_delete(pp->pic_name_ksp[i]);
89*7c478bd9Sstevel@tonic-gate }
90*7c478bd9Sstevel@tonic-gate }
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate
93*7c478bd9Sstevel@tonic-gate /*
94*7c478bd9Sstevel@tonic-gate * Create the picN kstat. Returns a pointer to the
95*7c478bd9Sstevel@tonic-gate * kstat which the driver must store to allow it
96*7c478bd9Sstevel@tonic-gate * to be deleted when necessary.
97*7c478bd9Sstevel@tonic-gate */
98*7c478bd9Sstevel@tonic-gate static kstat_t *
pci_create_picN_kstat(char * mod_name,int pic,int pic_shift,int num_ev,pci_kev_mask_t * ev_array)99*7c478bd9Sstevel@tonic-gate pci_create_picN_kstat(char *mod_name, int pic, int pic_shift,
100*7c478bd9Sstevel@tonic-gate int num_ev, pci_kev_mask_t *ev_array)
101*7c478bd9Sstevel@tonic-gate {
102*7c478bd9Sstevel@tonic-gate struct kstat_named *pic_named_data;
103*7c478bd9Sstevel@tonic-gate int inst = 0;
104*7c478bd9Sstevel@tonic-gate int event;
105*7c478bd9Sstevel@tonic-gate char pic_name[30];
106*7c478bd9Sstevel@tonic-gate kstat_t *picN_ksp = NULL;
107*7c478bd9Sstevel@tonic-gate
108*7c478bd9Sstevel@tonic-gate (void) sprintf(pic_name, "pic%d", pic);
109*7c478bd9Sstevel@tonic-gate if ((picN_ksp = kstat_create(mod_name, inst, pic_name,
110*7c478bd9Sstevel@tonic-gate "bus", KSTAT_TYPE_NAMED, num_ev, NULL)) == NULL) {
111*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s %s : kstat create failed",
112*7c478bd9Sstevel@tonic-gate mod_name, pic_name);
113*7c478bd9Sstevel@tonic-gate
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate * It is up to the calling function to delete any kstats
116*7c478bd9Sstevel@tonic-gate * that may have been created already. We just
117*7c478bd9Sstevel@tonic-gate * return NULL to indicate an error has occured.
118*7c478bd9Sstevel@tonic-gate */
119*7c478bd9Sstevel@tonic-gate return (NULL);
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate pic_named_data = (struct kstat_named *)
123*7c478bd9Sstevel@tonic-gate picN_ksp->ks_data;
124*7c478bd9Sstevel@tonic-gate
125*7c478bd9Sstevel@tonic-gate /*
126*7c478bd9Sstevel@tonic-gate * Write event names and their associated pcr masks. The
127*7c478bd9Sstevel@tonic-gate * last entry in the array (clear_pic) is added seperately
128*7c478bd9Sstevel@tonic-gate * below as the pic value must be inverted.
129*7c478bd9Sstevel@tonic-gate */
130*7c478bd9Sstevel@tonic-gate for (event = 0; event < num_ev - 1; event++) {
131*7c478bd9Sstevel@tonic-gate pic_named_data[event].value.ui64 =
132*7c478bd9Sstevel@tonic-gate (ev_array[event].pcr_mask << pic_shift);
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate kstat_named_init(&pic_named_data[event],
135*7c478bd9Sstevel@tonic-gate ev_array[event].event_name,
136*7c478bd9Sstevel@tonic-gate KSTAT_DATA_UINT64);
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate
139*7c478bd9Sstevel@tonic-gate /*
140*7c478bd9Sstevel@tonic-gate * add the clear_pic entry.
141*7c478bd9Sstevel@tonic-gate */
142*7c478bd9Sstevel@tonic-gate pic_named_data[event].value.ui64 =
143*7c478bd9Sstevel@tonic-gate (uint64_t)~(ev_array[event].pcr_mask << pic_shift);
144*7c478bd9Sstevel@tonic-gate
145*7c478bd9Sstevel@tonic-gate kstat_named_init(&pic_named_data[event],
146*7c478bd9Sstevel@tonic-gate ev_array[event].event_name,
147*7c478bd9Sstevel@tonic-gate KSTAT_DATA_UINT64);
148*7c478bd9Sstevel@tonic-gate
149*7c478bd9Sstevel@tonic-gate kstat_install(picN_ksp);
150*7c478bd9Sstevel@tonic-gate
151*7c478bd9Sstevel@tonic-gate return (picN_ksp);
152*7c478bd9Sstevel@tonic-gate }
153*7c478bd9Sstevel@tonic-gate
154*7c478bd9Sstevel@tonic-gate /*
155*7c478bd9Sstevel@tonic-gate * Create the "counters" kstat.
156*7c478bd9Sstevel@tonic-gate */
pci_create_cntr_kstat(pci_t * pci_p,char * name,int num_pics,int (* update)(kstat_t *,int),void * cntr_addr_p)157*7c478bd9Sstevel@tonic-gate kstat_t *pci_create_cntr_kstat(pci_t *pci_p, char *name,
158*7c478bd9Sstevel@tonic-gate int num_pics, int (*update)(kstat_t *, int),
159*7c478bd9Sstevel@tonic-gate void *cntr_addr_p)
160*7c478bd9Sstevel@tonic-gate {
161*7c478bd9Sstevel@tonic-gate struct kstat *counters_ksp;
162*7c478bd9Sstevel@tonic-gate struct kstat_named *counters_named_data;
163*7c478bd9Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip;
164*7c478bd9Sstevel@tonic-gate char *drv_name = (char *)ddi_driver_name(dip);
165*7c478bd9Sstevel@tonic-gate int drv_instance = ddi_get_instance(dip);
166*7c478bd9Sstevel@tonic-gate char pic_str[10];
167*7c478bd9Sstevel@tonic-gate int i;
168*7c478bd9Sstevel@tonic-gate
169*7c478bd9Sstevel@tonic-gate /*
170*7c478bd9Sstevel@tonic-gate * Size of kstat is num_pics + 1 as it
171*7c478bd9Sstevel@tonic-gate * also contains the %pcr
172*7c478bd9Sstevel@tonic-gate */
173*7c478bd9Sstevel@tonic-gate if ((counters_ksp = kstat_create(name, drv_instance,
174*7c478bd9Sstevel@tonic-gate "counters", "bus", KSTAT_TYPE_NAMED,
175*7c478bd9Sstevel@tonic-gate num_pics + 1,
176*7c478bd9Sstevel@tonic-gate KSTAT_FLAG_WRITABLE)) == NULL) {
177*7c478bd9Sstevel@tonic-gate
178*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d counters kstat_create failed",
179*7c478bd9Sstevel@tonic-gate drv_name, drv_instance);
180*7c478bd9Sstevel@tonic-gate return (NULL);
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate counters_named_data =
184*7c478bd9Sstevel@tonic-gate (struct kstat_named *)(counters_ksp->ks_data);
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate /* initialize the named kstats */
187*7c478bd9Sstevel@tonic-gate kstat_named_init(&counters_named_data[0],
188*7c478bd9Sstevel@tonic-gate "pcr", KSTAT_DATA_UINT64);
189*7c478bd9Sstevel@tonic-gate
190*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_pics; i++) {
191*7c478bd9Sstevel@tonic-gate (void) sprintf(pic_str, "pic%d", i);
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate kstat_named_init(&counters_named_data[i+1],
194*7c478bd9Sstevel@tonic-gate pic_str, KSTAT_DATA_UINT64);
195*7c478bd9Sstevel@tonic-gate }
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate * Store the register offset's in the kstat's
199*7c478bd9Sstevel@tonic-gate * private field so that they are available
200*7c478bd9Sstevel@tonic-gate * to the update function.
201*7c478bd9Sstevel@tonic-gate */
202*7c478bd9Sstevel@tonic-gate counters_ksp->ks_private = (void *)cntr_addr_p;
203*7c478bd9Sstevel@tonic-gate counters_ksp->ks_update = update;
204*7c478bd9Sstevel@tonic-gate
205*7c478bd9Sstevel@tonic-gate kstat_install(counters_ksp);
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gate return (counters_ksp);
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate
210*7c478bd9Sstevel@tonic-gate /*
211*7c478bd9Sstevel@tonic-gate * kstat update function. Handles reads/writes
212*7c478bd9Sstevel@tonic-gate * from/to kstat.
213*7c478bd9Sstevel@tonic-gate */
214*7c478bd9Sstevel@tonic-gate int
pci_cntr_kstat_update(kstat_t * ksp,int rw)215*7c478bd9Sstevel@tonic-gate pci_cntr_kstat_update(kstat_t *ksp, int rw)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate struct kstat_named *data_p;
218*7c478bd9Sstevel@tonic-gate pci_cntr_addr_t *cntr_addr_p = ksp->ks_private;
219*7c478bd9Sstevel@tonic-gate uint64_t pic;
220*7c478bd9Sstevel@tonic-gate
221*7c478bd9Sstevel@tonic-gate data_p = (struct kstat_named *)ksp->ks_data;
222*7c478bd9Sstevel@tonic-gate
223*7c478bd9Sstevel@tonic-gate if (rw == KSTAT_WRITE) {
224*7c478bd9Sstevel@tonic-gate *cntr_addr_p->pcr_addr = data_p[0].value.ui64;
225*7c478bd9Sstevel@tonic-gate return (0);
226*7c478bd9Sstevel@tonic-gate } else {
227*7c478bd9Sstevel@tonic-gate pic = *cntr_addr_p->pic_addr;
228*7c478bd9Sstevel@tonic-gate data_p[0].value.ui64 = *cntr_addr_p->pcr_addr;
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate /* pic0 : lo 32 bits */
231*7c478bd9Sstevel@tonic-gate data_p[1].value.ui64 = (pic <<32) >> 32;
232*7c478bd9Sstevel@tonic-gate /* pic1 : hi 32 bits */
233*7c478bd9Sstevel@tonic-gate data_p[2].value.ui64 = pic >> 32;
234*7c478bd9Sstevel@tonic-gate }
235*7c478bd9Sstevel@tonic-gate return (0);
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate
238*7c478bd9Sstevel@tonic-gate /*
239*7c478bd9Sstevel@tonic-gate * kstat update function using physical addresses.
240*7c478bd9Sstevel@tonic-gate */
241*7c478bd9Sstevel@tonic-gate int
pci_cntr_kstat_pa_update(kstat_t * ksp,int rw)242*7c478bd9Sstevel@tonic-gate pci_cntr_kstat_pa_update(kstat_t *ksp, int rw)
243*7c478bd9Sstevel@tonic-gate {
244*7c478bd9Sstevel@tonic-gate struct kstat_named *data_p;
245*7c478bd9Sstevel@tonic-gate pci_cntr_pa_t *cntr_pa_p = (pci_cntr_pa_t *)ksp->ks_private;
246*7c478bd9Sstevel@tonic-gate uint64_t pic;
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gate data_p = (struct kstat_named *)ksp->ks_data;
249*7c478bd9Sstevel@tonic-gate
250*7c478bd9Sstevel@tonic-gate if (rw == KSTAT_WRITE) {
251*7c478bd9Sstevel@tonic-gate stdphysio(cntr_pa_p->pcr_pa, data_p[0].value.ui64);
252*7c478bd9Sstevel@tonic-gate return (0);
253*7c478bd9Sstevel@tonic-gate } else {
254*7c478bd9Sstevel@tonic-gate pic = lddphysio(cntr_pa_p->pic_pa);
255*7c478bd9Sstevel@tonic-gate data_p[0].value.ui64 = lddphysio(cntr_pa_p->pcr_pa);
256*7c478bd9Sstevel@tonic-gate
257*7c478bd9Sstevel@tonic-gate /* pic0 : lo 32 bits */
258*7c478bd9Sstevel@tonic-gate data_p[1].value.ui64 = (pic << 32) >> 32;
259*7c478bd9Sstevel@tonic-gate /* pic1 : hi 32 bits */
260*7c478bd9Sstevel@tonic-gate data_p[2].value.ui64 = pic >> 32;
261*7c478bd9Sstevel@tonic-gate }
262*7c478bd9Sstevel@tonic-gate return (0);
263*7c478bd9Sstevel@tonic-gate }
264*7c478bd9Sstevel@tonic-gate
265*7c478bd9Sstevel@tonic-gate
266*7c478bd9Sstevel@tonic-gate /*
267*7c478bd9Sstevel@tonic-gate * Matched with pci_add_upstream_kstat()
268*7c478bd9Sstevel@tonic-gate */
269*7c478bd9Sstevel@tonic-gate void
pci_rem_upstream_kstat(pci_t * pci_p)270*7c478bd9Sstevel@tonic-gate pci_rem_upstream_kstat(pci_t *pci_p)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p;
273*7c478bd9Sstevel@tonic-gate
274*7c478bd9Sstevel@tonic-gate if (cmn_p->pci_common_uksp != NULL)
275*7c478bd9Sstevel@tonic-gate kstat_delete(cmn_p->pci_common_uksp);
276*7c478bd9Sstevel@tonic-gate cmn_p->pci_common_uksp = NULL;
277*7c478bd9Sstevel@tonic-gate }
278