1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 #include <sys/kstat.h>
9 #include <sys/ddi.h>
10 #include <sys/sunddi.h>
11 #include <sys/sunldi.h>
12 #include <sys/agpgart.h>
13 #include <sys/agp/agpdefs.h>
14 #include <sys/agp/agpgart_impl.h>
15
16 /*
17 * The values of type agp_arc_type_t are used as indices into arc_name
18 * So if agp_arc_type_t's values are changed in the future, the content
19 * of arc_name must be changed accordingly.
20 */
21 static const char *arc_name[] = {
22 "IGD_810",
23 "IGD_830",
24 "INTEL_AGP",
25 "AMD64_AGP",
26 "AMD64_NONAGP",
27 "UNKNOWN"
28 };
29
30 static char *agpkstat_name[] = {
31 "&arc_type",
32 "master_dev_id",
33 "master_dev_version",
34 "master_dev_status",
35 "$prealloc_size",
36 "target_dev_id",
37 "target_dev_version",
38 "target_dev_status",
39 "$aper_base",
40 "$aper_size",
41 "&agp_enabled",
42 "agp_mode_set",
43 "$aper_used",
44 NULL
45 };
46
47 static void
agp_set_char_kstat(kstat_named_t * knp,const char * s)48 agp_set_char_kstat(kstat_named_t *knp, const char *s)
49 {
50 (void) strlcpy(knp->value.c, s, sizeof (knp->value.c));
51 }
52
53 static int
agp_kstat_update(kstat_t * ksp,int flag)54 agp_kstat_update(kstat_t *ksp, int flag)
55 {
56 agpgart_softstate_t *sc;
57 kstat_named_t *knp;
58 int tmp;
59
60 if (flag != KSTAT_READ)
61 return (EACCES);
62
63 sc = ksp->ks_private;
64 knp = ksp->ks_data;
65
66 agp_set_char_kstat(knp++, arc_name[sc->asoft_devreg.agprd_arctype]);
67 (knp++)->value.ui32 = sc->asoft_info.agpki_mdevid;
68 (knp++)->value.ui32 = (sc->asoft_info.agpki_mver.agpv_major<<16) |
69 sc->asoft_info.agpki_mver.agpv_minor;
70 (knp++)->value.ui32 = sc->asoft_info.agpki_mstatus;
71 (knp++)->value.ui64 = (sc->asoft_info.agpki_presize << 10) & UI32_MASK;
72 (knp++)->value.ui32 = sc->asoft_info.agpki_tdevid;
73 (knp++)->value.ui32 = (sc->asoft_info.agpki_tver.agpv_major<<16) |
74 sc->asoft_info.agpki_tver.agpv_minor;
75 (knp++)->value.ui32 = sc->asoft_info.agpki_tstatus;
76 (knp++)->value.ui64 = sc->asoft_info.agpki_aperbase;
77 (knp++)->value.ui64 =
78 (sc->asoft_info.agpki_apersize << 20) & UI32_MASK;
79
80 tmp = sc->asoft_agpen;
81 agp_set_char_kstat(knp++, (tmp > 0) ? "yes" : "no");
82
83 (knp++)->value.ui32 = sc->asoft_mode;
84 (knp++)->value.ui64 = (sc->asoft_pgused << 12) & UI32_MASK;
85
86 return (0);
87 }
88
89 int
agp_init_kstats(agpgart_softstate_t * sc)90 agp_init_kstats(agpgart_softstate_t *sc)
91 {
92 int instance;
93 kstat_t *ksp;
94 kstat_named_t *knp;
95 char *np;
96 int type;
97 char **aknp;
98
99 instance = ddi_get_instance(sc->asoft_dip);
100 aknp = agpkstat_name;
101 ksp = kstat_create(AGPGART_DEVNODE, instance, "agpinfo", "agp",
102 KSTAT_TYPE_NAMED, sizeof (agpkstat_name)/sizeof (char *) - 1,
103 KSTAT_FLAG_PERSISTENT);
104 if (ksp == NULL)
105 return (NULL);
106
107 ksp->ks_private = sc;
108 ksp->ks_update = agp_kstat_update;
109 for (knp = ksp->ks_data; (np = (*aknp)) != NULL; knp++, aknp++) {
110 switch (*np) {
111 case '$':
112 np += 1;
113 type = KSTAT_DATA_UINT64;
114 break;
115 case '&':
116 np += 1;
117 type = KSTAT_DATA_CHAR;
118 break;
119 default:
120 type = KSTAT_DATA_UINT32;
121 break;
122
123 }
124 kstat_named_init(knp, np, type);
125 }
126 kstat_install(ksp);
127
128 sc->asoft_ksp = ksp;
129
130 return (0);
131 }
132
133 void
agp_fini_kstats(agpgart_softstate_t * sc)134 agp_fini_kstats(agpgart_softstate_t *sc)
135 {
136 ASSERT(sc->asoft_ksp);
137 kstat_delete(sc->asoft_ksp);
138 }
139