This source file includes following definitions.
- acpitz_match
- acpitz_attach
- acpitz_setcpu
- acpitz_setfan
- acpitz_refresh
- acpitz_getreading
- acpitz_notify
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <sys/param.h>
20 #include <sys/proc.h>
21 #include <sys/signalvar.h>
22 #include <sys/systm.h>
23 #include <sys/device.h>
24 #include <sys/malloc.h>
25
26 #include <machine/bus.h>
27
28 #include <dev/acpi/acpireg.h>
29 #include <dev/acpi/acpivar.h>
30 #include <dev/acpi/acpidev.h>
31 #include <dev/acpi/amltypes.h>
32 #include <dev/acpi/dsdt.h>
33
34 #include <sys/sensors.h>
35
36 #define ACPITZ_MAX_AC 10
37
38 struct acpitz_softc {
39 struct device sc_dev;
40
41 struct acpi_softc *sc_acpi;
42 struct aml_node *sc_devnode;
43
44 int sc_tmp;
45 int sc_crt;
46 int sc_hot;
47 int sc_ac[ACPITZ_MAX_AC];
48 int sc_ac_stat[ACPITZ_MAX_AC];
49 int sc_pse;
50 int sc_psv;
51 int sc_tc1;
52 int sc_tc2;
53 int sc_lasttmp;
54 struct ksensor sc_sens;
55 struct ksensordev sc_sensdev;
56 };
57
58 int acpitz_match(struct device *, void *, void *);
59 void acpitz_attach(struct device *, struct device *, void *);
60
61 struct cfattach acpitz_ca = {
62 sizeof(struct acpitz_softc), acpitz_match, acpitz_attach
63 };
64
65 struct cfdriver acpitz_cd = {
66 NULL, "acpitz", DV_DULL
67 };
68
69 void acpitz_monitor(struct acpitz_softc *);
70 void acpitz_refresh(void *);
71 int acpitz_notify(struct aml_node *, int, void *);
72 int acpitz_getreading(struct acpitz_softc *, char *);
73 int acpitz_setfan(struct acpitz_softc *, int, char *);
74 int acpitz_setcpu(struct acpitz_softc *, int);
75
76 int
77 acpitz_match(struct device *parent, void *match, void *aux)
78 {
79 struct acpi_attach_args *aa = aux;
80 struct cfdata *cf = match;
81
82
83 if (aa->aaa_name == NULL ||
84 strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
85 aa->aaa_table != NULL)
86 return (0);
87
88 if (aa->aaa_node->value->type != AML_OBJTYPE_THERMZONE)
89 return (0);
90
91 return (1);
92 }
93
94 void
95 acpitz_attach(struct device *parent, struct device *self, void *aux)
96 {
97 struct acpitz_softc *sc = (struct acpitz_softc *)self;
98 struct acpi_attach_args *aa = aux;
99 int i;
100 char name[8];
101
102 sc->sc_acpi = (struct acpi_softc *)parent;
103 sc->sc_devnode = aa->aaa_node->child;
104
105 sc->sc_lasttmp = -1;
106 if ((sc->sc_tmp = acpitz_getreading(sc, "_TMP")) == -1) {
107 printf(", failed to read _TMP\n");
108 return;
109 }
110
111 if ((sc->sc_crt = acpitz_getreading(sc, "_CRT")) == -1) {
112 printf(", no critical temperature defined!\n");
113 sc->sc_crt = 0;
114 } else
115 printf(", critical temperature: %d degC\n",
116 (sc->sc_crt - 2732) / 10);
117
118 for (i = 0; i < ACPITZ_MAX_AC; i++) {
119 snprintf(name, sizeof name, "_AC%d", i);
120 sc->sc_ac[i] = acpitz_getreading(sc, name);
121 sc->sc_ac_stat[0] = -1;
122 }
123
124 sc->sc_hot = acpitz_getreading(sc, "_HOT");
125 sc->sc_tc1 = acpitz_getreading(sc, "_TC1");
126 sc->sc_tc2 = acpitz_getreading(sc, "_TC2");
127 sc->sc_psv = acpitz_getreading(sc, "_PSV");
128
129 strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
130 sizeof(sc->sc_sensdev.xname));
131 strlcpy(sc->sc_sens.desc, "zone temperature",
132 sizeof(sc->sc_sens.desc));
133 sc->sc_sens.type = SENSOR_TEMP;
134 sensor_attach(&sc->sc_sensdev, &sc->sc_sens);
135 sensordev_install(&sc->sc_sensdev);
136 sc->sc_sens.value = 0;
137
138 aml_register_notify(sc->sc_devnode->parent, NULL,
139 acpitz_notify, sc, ACPIDEV_POLL);
140 }
141
142 int
143 acpitz_setcpu(struct acpitz_softc *sc, int trend)
144 {
145 struct aml_value res0, *ref;
146 int x;
147
148 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSL", 0, NULL, &res0)) {
149 printf("%s: _PSL failed\n", DEVNAME(sc));
150 goto out;
151 }
152 if (res0.type != AML_OBJTYPE_PACKAGE) {
153 printf("%s: not a package\n", DEVNAME(sc));
154 goto out;
155 }
156 for (x = 0; x < res0.length; x++) {
157 if (res0.v_package[x]->type != AML_OBJTYPE_OBJREF) {
158 printf("%s: _PSL[%d] not a object ref\n", DEVNAME(sc), x);
159 continue;
160 }
161 ref = res0.v_package[x]->v_objref.ref;
162 if (ref->type != AML_OBJTYPE_PROCESSOR)
163 printf("%s: _PSL[%d] not a CPU\n", DEVNAME(sc), x);
164 }
165 out:
166 aml_freevalue(&res0);
167 return (0);
168 }
169
170 int
171 acpitz_setfan(struct acpitz_softc *sc, int i, char *method)
172 {
173 struct aml_value res0, res1, res2, *ref;
174 char name[8];
175 int rv = 1, x, y;
176
177 dnprintf(20, "%s: acpitz_setfan(%d, %s)\n", DEVNAME(sc), i, method);
178
179 snprintf(name, sizeof name, "_AL%d", i);
180 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res0)) {
181 dnprintf(20, "%s: %s failed\n", DEVNAME(sc), name);
182 goto out;
183 }
184
185 if (res0.type != AML_OBJTYPE_PACKAGE) {
186 printf("%s: %s not a package\n", DEVNAME(sc), name);
187 goto out;
188 }
189
190 for (x = 0; x < res0.length; x++) {
191 if (res0.v_package[x]->type != AML_OBJTYPE_OBJREF) {
192 printf("%s: %s[%d] not a object ref\n", DEVNAME(sc),
193 name, x);
194 continue;
195 }
196 ref = res0.v_package[x]->v_objref.ref;
197 if (aml_evalname(sc->sc_acpi, ref->node, "_PR0",0 , NULL,
198 &res1)) {
199 printf("%s: %s[%d] _PR0 failed\n", DEVNAME(sc),
200 name, x);
201 aml_freevalue(&res1);
202 continue;
203 }
204 if (res1.type != AML_OBJTYPE_PACKAGE) {
205 printf("%s: %s[%d] _PR0 not a package\n", DEVNAME(sc),
206 name, x);
207 aml_freevalue(&res1);
208 continue;
209 }
210 for (y = 0; y < res1.length; y++) {
211 if (res1.v_package[y]->type != AML_OBJTYPE_OBJREF) {
212 printf("%s: %s[%d.%d] _PR0 not a package\n",
213 DEVNAME(sc), name, x, y);
214 continue;
215 }
216 ref = res1.v_package[y]->v_objref.ref;
217 if (aml_evalname(sc->sc_acpi, ref->node, method, 0,
218 NULL, NULL))
219 printf("%s: %s[%d.%d] %s fails\n",
220 DEVNAME(sc), name, x, y, method);
221
222
223 if (aml_evalname(sc->sc_acpi, ref->node, "_STA", 0,
224 NULL, &res2))
225 printf("%s: %s[%d.%d] _STA fails\n",
226 DEVNAME(sc), name, x, y);
227 else {
228 sc->sc_ac_stat[i] = aml_val2int(&res2);
229 aml_freevalue(&res2);
230 }
231 }
232 aml_freevalue(&res1);
233 }
234 rv = 0;
235 out:
236 aml_freevalue(&res0);
237 return (rv);
238 }
239
240 void
241 acpitz_refresh(void *arg)
242 {
243 struct acpitz_softc *sc = arg;
244 int i, trend;
245 extern int acpi_s5;
246
247 dnprintf(30, "%s: %s: refresh\n", DEVNAME(sc),
248 sc->sc_devnode->parent->name);
249
250 if (-1 == (sc->sc_tmp = acpitz_getreading(sc, "_TMP"))) {
251 dnprintf(30, "%s: %s: failed to read temp!\n", DEVNAME(sc),
252 sc->sc_devnode->parent->name);
253 sc->sc_tmp = 0;
254 }
255
256 if (sc->sc_crt != -1 && sc->sc_crt <= sc->sc_tmp) {
257
258 printf("%s: Critical temperature, shutting down!\n",
259 DEVNAME(sc));
260 acpi_s5 = 1;
261 psignal(initproc, SIGUSR1);
262 }
263 if (sc->sc_hot != -1 && sc->sc_hot <= sc->sc_tmp)
264 printf("%s: _HOT temperature\n", DEVNAME(sc));
265
266 if (sc->sc_lasttmp != -1 && sc->sc_tc1 != -1 && sc->sc_tc2 != -1 &&
267 sc->sc_psv != -1) {
268 if (sc->sc_psv <= sc->sc_tmp) {
269 sc->sc_pse = 1;
270 trend = sc->sc_tc1 * (sc->sc_tmp - sc->sc_lasttmp) +
271 sc->sc_tc2 * (sc->sc_tmp - sc->sc_psv);
272
273 } else if (sc->sc_pse)
274 sc->sc_pse = 0;
275 }
276 sc->sc_lasttmp = sc->sc_tmp;
277
278 for (i = 0; i < ACPITZ_MAX_AC; i++) {
279 if (sc->sc_ac[i] != -1 && sc->sc_ac[i] <= sc->sc_tmp) {
280
281 if (sc->sc_ac_stat[i] <= 0)
282 acpitz_setfan(sc, i, "_ON_");
283 } else if (sc->sc_ac[i] != -1) {
284
285 if (sc->sc_ac_stat[i] > 0)
286 acpitz_setfan(sc, i, "_OFF");
287 }
288 }
289 sc->sc_sens.value = sc->sc_tmp * 100000;
290 }
291
292 int
293 acpitz_getreading(struct acpitz_softc *sc, char *name)
294 {
295 struct aml_value res;
296 int rv = -1;
297
298 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, name, 0, NULL, &res)) {
299 dnprintf(10, "%s: no %s\n", DEVNAME(sc), name);
300 goto out;
301 }
302 rv = aml_val2int(&res);
303 out:
304 aml_freevalue(&res);
305 return (rv);
306 }
307
308 int
309 acpitz_notify(struct aml_node *node, int notify_type, void *arg)
310 {
311 struct acpitz_softc *sc = arg;
312 u_int64_t crt;
313
314 dnprintf(10, "%s notify: %.2x %s\n", DEVNAME(sc), notify_type,
315 sc->sc_devnode->parent->name);
316
317 switch (notify_type) {
318 case 0x81:
319 sc->sc_psv = acpitz_getreading(sc, "_PSV");
320 crt = sc->sc_crt;
321 sc->sc_crt = acpitz_getreading(sc, "_CRT");
322 if (crt != sc->sc_crt)
323 printf("%s: critical temperature: %u degC",
324 DEVNAME(sc), (sc->sc_crt - 2732) / 10);
325 break;
326 default:
327 break;
328 }
329 acpitz_refresh(sc);
330 return (0);
331 }