| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: acpi_tz.c,v 1.68 2010/04/24 06:31:44 jruoho Exp $ */ | | 1 | /* $NetBSD: acpi_tz.c,v 1.69 2010/04/24 19:11:48 jruoho Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2003 Jared D. McNeill <jmcneill@invisible.ca> | | 4 | * Copyright (c) 2003 Jared D. McNeill <jmcneill@invisible.ca> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. The name of the author may not be used to endorse or promote products | | 12 | * 2. The name of the author may not be used to endorse or promote products |
13 | * derived from this software without specific prior written permission. | | 13 | * derived from this software without specific prior written permission. |
14 | * | | 14 | * |
| @@ -20,142 +20,124 @@ | | | @@ -20,142 +20,124 @@ |
20 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 20 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
22 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 22 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 | * SUCH DAMAGE. | | 25 | * SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | /* | | 28 | /* |
29 | * ACPI Thermal Zone driver | | 29 | * ACPI Thermal Zone driver |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.68 2010/04/24 06:31:44 jruoho Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.69 2010/04/24 19:11:48 jruoho Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/device.h> | | 36 | #include <sys/device.h> |
37 | #include <sys/callout.h> | | 37 | #include <sys/callout.h> |
38 | #include <sys/kernel.h> | | 38 | #include <sys/kernel.h> |
39 | #include <sys/systm.h> | | 39 | #include <sys/systm.h> |
40 | | | 40 | |
41 | #include <dev/acpi/acpireg.h> | | 41 | #include <dev/acpi/acpireg.h> |
42 | #include <dev/acpi/acpivar.h> | | 42 | #include <dev/acpi/acpivar.h> |
43 | #include <dev/acpi/acpi_power.h> | | 43 | #include <dev/acpi/acpi_power.h> |
44 | | | 44 | |
45 | #define _COMPONENT ACPI_TZ_COMPONENT | | 45 | #define _COMPONENT ACPI_TZ_COMPONENT |
46 | ACPI_MODULE_NAME ("acpi_tz") | | 46 | ACPI_MODULE_NAME ("acpi_tz") |
47 | | | 47 | |
48 | /* flags */ | | 48 | #define ATZ_F_CRITICAL 0x01 /* zone critical */ |
49 | #define ATZ_F_VERBOSE 0x01 /* show events to console */ | | 49 | #define ATZ_F_HOT 0x02 /* zone hot */ |
50 | #define ATZ_F_CRITICAL 0x02 /* zone critical */ | | 50 | #define ATZ_F_PASSIVE 0x04 /* zone passive cooling */ |
51 | #define ATZ_F_HOT 0x04 /* zone hot */ | | 51 | #define ATZ_F_PASSIVEONLY 0x08 /* zone is passive cooling only */ |
52 | #define ATZ_F_PASSIVE 0x08 /* zone passive cooling */ | | | |
53 | #define ATZ_F_PASSIVEONLY 0x10 /* zone is passive cooling only */ | | | |
54 | | | | |
55 | /* no active cooling level */ | | | |
56 | #define ATZ_ACTIVE_NONE -1 | | | |
57 | | | | |
58 | /* constants */ | | | |
59 | #define ATZ_TZP_RATE 300 /* default if no _TZP CM present (30 secs) */ | | | |
60 | #define ATZ_NLEVELS 10 /* number of cooling levels, from ACPI spec */ | | | |
61 | #define ATZ_ZEROC 2732 /* 0C, measured in 0.1 Kelvin */ | | | |
62 | #define ATZ_TMP_INVALID 0xffffffff /* invalid temperature */ | | | |
63 | #define ATZ_ZONE_EXPIRE 9000 /* zone info refetch interval (15min) */ | | | |
64 | | | 52 | |
65 | /* sensor indexes */ | | 53 | #define ATZ_ACTIVE_NONE -1 |
66 | #define ATZ_SENSOR_TEMP 0 /* thermal zone temperature */ | | | |
67 | | | 54 | |
68 | /* | | 55 | /* |
69 | * ACPI Temperature Zone information. Note all temperatures are reported | | 56 | * The constants are as follows: |
70 | * in 0.1 Kelvin, and that the ACPI specification assumes that | | 57 | * |
71 | * K = C + 273.2 rather than the nominal 273.15 used by envsys(4). | | 58 | * ATZ_TZP_RATE default polling interval (30 seconds) if no _TZP |
72 | * So define an appropriate conversion. | | 59 | * ATZ_NLEVELS number of cooling levels for _ACx and _ALx |
| | | 60 | * ATZ_ZEROC 0 C, measured in 0.1 Kelvin |
| | | 61 | * ATZ_TMP_INVALID temporarily invalid temperature |
| | | 62 | * ATZ_ZONE_EXPIRE zone info refetch interval (15 minutes) |
73 | */ | | 63 | */ |
| | | 64 | #define ATZ_TZP_RATE 300 |
| | | 65 | #define ATZ_NLEVELS 10 |
| | | 66 | #define ATZ_ZEROC 2732 |
| | | 67 | #define ATZ_TMP_INVALID 0xffffffff |
| | | 68 | #define ATZ_ZONE_EXPIRE 9000 |
74 | | | 69 | |
| | | 70 | /* |
| | | 71 | * All temperatures are reported in 0.1 Kelvin. |
| | | 72 | * The ACPI specification assumes that K = C + 273.2 |
| | | 73 | * rather than the nominal 273.15 used by envsys(4). |
| | | 74 | */ |
75 | #define ATZ2UKELVIN(t) ((t) * 100000 - 50000) | | 75 | #define ATZ2UKELVIN(t) ((t) * 100000 - 50000) |
76 | | | 76 | |
77 | struct acpitz_zone { | | 77 | struct acpitz_zone { |
78 | /* Active cooling temperature threshold */ | | 78 | char *name; |
79 | uint32_t ac[ATZ_NLEVELS]; | | 79 | ACPI_BUFFER al[ATZ_NLEVELS]; |
80 | /* Package of references to all active cooling devices for a level */ | | 80 | uint32_t ac[ATZ_NLEVELS]; |
81 | ACPI_BUFFER al[ATZ_NLEVELS]; | | 81 | uint32_t crt; |
82 | /* Critical temperature threshold for system shutdown */ | | 82 | uint32_t hot; |
83 | uint32_t crt; | | 83 | uint32_t rtv; |
84 | /* Critical temperature threshold for S4 sleep */ | | 84 | uint32_t psv; |
85 | uint32_t hot; | | 85 | uint32_t tc1; |
86 | /* Package of references to processor objects for passive cooling */ | | 86 | uint32_t tc2; |
87 | ACPI_BUFFER psl; | | 87 | uint32_t tmp; |
88 | /* Conveys if temperatures are absolute or relative values. */ | | 88 | uint32_t prevtmp; |
89 | uint32_t rtv; | | 89 | uint32_t tzp; |
90 | /* Passive cooling temperature threshold */ | | 90 | uint32_t fanmin; |
91 | uint32_t psv; | | 91 | uint32_t fanmax; |
92 | /* Thermal constants for use in passive cooling formulas */ | | 92 | uint32_t fancurrent; |
93 | uint32_t tc1, tc2; | | | |
94 | /* Current temperature of the thermal zone */ | | | |
95 | uint32_t prevtmp, tmp; | | | |
96 | /* Thermal sampling period for passive cooling, in tenths of seconds */ | | | |
97 | uint32_t tsp; | | | |
98 | /* Package of references to devices in this TZ (optional) */ | | | |
99 | ACPI_BUFFER tzd; | | | |
100 | /* Recommended TZ polling frequency, in tenths of seconds */ | | | |
101 | uint32_t tzp; | | | |
102 | /* Thermal zone name */ | | | |
103 | char *name; | | | |
104 | /* FAN min, max, current rpms */ | | | |
105 | uint32_t fanmin, fanmax, fancurrent; | | | |
106 | }; | | 93 | }; |
107 | | | 94 | |
108 | struct acpitz_softc { | | 95 | struct acpitz_softc { |
109 | struct acpi_devnode *sc_devnode; | | 96 | struct acpi_devnode *sc_node; |
110 | struct acpitz_zone sc_zone; | | 97 | struct sysmon_envsys *sc_sme; |
111 | struct callout sc_callout; | | 98 | struct acpitz_zone sc_zone; |
112 | struct sysmon_envsys *sc_sme; | | 99 | struct callout sc_callout; |
113 | envsys_data_t sc_temp_sensor; | | 100 | envsys_data_t sc_temp_sensor; |
114 | envsys_data_t sc_fan_sensor; | | 101 | envsys_data_t sc_fan_sensor; |
115 | int sc_active; /* active cooling level */ | | 102 | int sc_active; |
116 | int sc_flags; | | 103 | int sc_flags; |
117 | int sc_rate; /* tz poll rate */ | | 104 | int sc_zone_expire; |
118 | int sc_zone_expire; | | 105 | bool sc_first; |
119 | | | 106 | bool sc_have_fan; |
120 | int sc_first; | | | |
121 | int sc_have_fan; /* FAN sensor is optional */ | | | |
122 | }; | | 107 | }; |
123 | | | 108 | |
124 | static int acpitz_match(device_t, cfdata_t, void *); | | 109 | static int acpitz_match(device_t, cfdata_t, void *); |
125 | static void acpitz_attach(device_t, device_t, void *); | | 110 | static void acpitz_attach(device_t, device_t, void *); |
126 | static int acpitz_detach(device_t, int); | | 111 | static int acpitz_detach(device_t, int); |
127 | | | 112 | static void acpitz_get_status(void *); |
128 | static void acpitz_get_status(void *); | | 113 | static void acpitz_get_zone(void *, int); |
129 | static void acpitz_get_zone(void *, int); | | 114 | static void acpitz_get_zone_quiet(void *); |
130 | static void acpitz_get_zone_quiet(void *); | | 115 | static char *acpitz_celcius_string(int); |
131 | static char *acpitz_celcius_string(int); | | 116 | static void acpitz_power_off(struct acpitz_softc *); |
132 | static void acpitz_print_status(device_t); | | 117 | static void acpitz_power_zone(struct acpitz_softc *, int, int); |
133 | static void acpitz_power_off(struct acpitz_softc *); | | 118 | static void acpitz_sane_temp(uint32_t *tmp); |
134 | static void acpitz_power_zone(struct acpitz_softc *, int, int); | | 119 | static ACPI_STATUS acpitz_switch_cooler(ACPI_OBJECT *, void *); |
135 | static void acpitz_sane_temp(uint32_t *tmp); | | 120 | static void acpitz_notify_handler(ACPI_HANDLE, uint32_t, void *); |
136 | static ACPI_STATUS | | 121 | static int acpitz_get_integer(device_t, const char *, uint32_t *); |
137 | acpitz_switch_cooler(ACPI_OBJECT *, void *); | | 122 | static void acpitz_tick(void *); |
138 | static void acpitz_notify_handler(ACPI_HANDLE, uint32_t, void *); | | 123 | static void acpitz_init_envsys(device_t); |
139 | static int acpitz_get_integer(device_t, const char *, uint32_t *); | | 124 | static void acpitz_get_limits(struct sysmon_envsys *, |
140 | static void acpitz_tick(void *); | | 125 | envsys_data_t *, |
141 | static void acpitz_init_envsys(device_t); | | 126 | sysmon_envsys_lim_t *, uint32_t *); |
142 | static void acpitz_get_limits(struct sysmon_envsys *, envsys_data_t *, | | 127 | static int acpitz_get_fanspeed(device_t, uint32_t *, |
143 | sysmon_envsys_lim_t *, uint32_t *); | | 128 | uint32_t *, uint32_t *); |
144 | static int acpitz_get_fanspeed(device_t, uint32_t *, | | | |
145 | uint32_t *, uint32_t *); | | | |
146 | #ifdef notyet | | 129 | #ifdef notyet |
147 | static ACPI_STATUS | | 130 | static ACPI_STATUS acpitz_set_fanspeed(device_t, uint32_t); |
148 | acpitz_set_fanspeed(device_t, uint32_t); | | | |
149 | #endif | | 131 | #endif |
150 | | | 132 | |
151 | CFATTACH_DECL_NEW(acpitz, sizeof(struct acpitz_softc), | | 133 | CFATTACH_DECL_NEW(acpitz, sizeof(struct acpitz_softc), |
152 | acpitz_match, acpitz_attach, acpitz_detach, NULL); | | 134 | acpitz_match, acpitz_attach, acpitz_detach, NULL); |
153 | | | 135 | |
154 | /* | | 136 | /* |
155 | * acpitz_match: autoconf(9) match routine | | 137 | * acpitz_match: autoconf(9) match routine |
156 | */ | | 138 | */ |
157 | static int | | 139 | static int |
158 | acpitz_match(device_t parent, cfdata_t match, void *aux) | | 140 | acpitz_match(device_t parent, cfdata_t match, void *aux) |
159 | { | | 141 | { |
160 | struct acpi_attach_args *aa = aux; | | 142 | struct acpi_attach_args *aa = aux; |
161 | | | 143 | |
| @@ -163,92 +145,95 @@ acpitz_match(device_t parent, cfdata_t m | | | @@ -163,92 +145,95 @@ acpitz_match(device_t parent, cfdata_t m |
163 | return 0; | | 145 | return 0; |
164 | | | 146 | |
165 | return 1; | | 147 | return 1; |
166 | } | | 148 | } |
167 | | | 149 | |
168 | /* | | 150 | /* |
169 | * acpitz_attach: autoconf(9) attach routine | | 151 | * acpitz_attach: autoconf(9) attach routine |
170 | */ | | 152 | */ |
171 | static void | | 153 | static void |
172 | acpitz_attach(device_t parent, device_t self, void *aux) | | 154 | acpitz_attach(device_t parent, device_t self, void *aux) |
173 | { | | 155 | { |
174 | struct acpitz_softc *sc = device_private(self); | | 156 | struct acpitz_softc *sc = device_private(self); |
175 | struct acpi_attach_args *aa = aux; | | 157 | struct acpi_attach_args *aa = aux; |
| | | 158 | ACPI_INTEGER val; |
176 | ACPI_STATUS rv; | | 159 | ACPI_STATUS rv; |
177 | ACPI_INTEGER v; | | | |
178 | | | | |
179 | #if 0 | | | |
180 | sc->sc_flags = ATZ_F_VERBOSE; | | | |
181 | #endif | | | |
182 | sc->sc_devnode = aa->aa_node; | | | |
183 | | | 160 | |
184 | aprint_naive("\n"); | | 161 | aprint_naive("\n"); |
185 | aprint_normal(": ACPI Thermal Zone\n"); | | 162 | aprint_normal(": ACPI Thermal Zone\n"); |
186 | | | 163 | |
187 | rv = acpi_eval_integer(sc->sc_devnode->ad_handle, "_TZP", &v); | | 164 | sc->sc_first = true; |
188 | if (ACPI_FAILURE(rv)) | | 165 | sc->sc_have_fan = false; |
189 | sc->sc_zone.tzp = ATZ_TZP_RATE; | | 166 | sc->sc_node = aa->aa_node; |
190 | else | | 167 | sc->sc_zone.tzp = ATZ_TZP_RATE; |
191 | sc->sc_zone.tzp = v; | | 168 | |
| | | 169 | /* |
| | | 170 | * The _TZP (ACPI 4.0, p. 430) defines the recommended |
| | | 171 | * polling interval (in tenths of seconds). A value zero |
| | | 172 | * means that polling "should not be necessary". |
| | | 173 | */ |
| | | 174 | rv = acpi_eval_integer(sc->sc_node->ad_handle, "_TZP", &val); |
| | | 175 | |
| | | 176 | if (ACPI_SUCCESS(rv) && val != 0) |
| | | 177 | sc->sc_zone.tzp = val; |
192 | | | 178 | |
193 | aprint_debug_dev(self, "sample rate %d.%ds\n", | | 179 | aprint_debug_dev(self, "sample rate %d.%ds\n", |
194 | sc->sc_zone.tzp / 10, sc->sc_zone.tzp % 10); | | 180 | sc->sc_zone.tzp / 10, sc->sc_zone.tzp % 10); |
195 | | | 181 | |
196 | /* XXX a value of 0 means "polling is not necessary" */ | | | |
197 | if (sc->sc_zone.tzp == 0) | | | |
198 | sc->sc_zone.tzp = ATZ_TZP_RATE; | | | |
199 | | | | |
200 | sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp; | | 182 | sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp; |
201 | sc->sc_first = 1; | | | |
202 | sc->sc_have_fan = 0; | | | |
203 | if (acpitz_get_fanspeed(self, | | | |
204 | &sc->sc_zone.fanmin, &sc->sc_zone.fanmax, &sc->sc_zone.fancurrent) | | | |
205 | == 0) | | | |
206 | sc->sc_have_fan = 1; | | | |
207 | | | 183 | |
208 | rv = acpi_eval_string(sc->sc_devnode->ad_handle, | | 184 | /* |
| | | 185 | * XXX: The fan controls seen here are available on |
| | | 186 | * some HP laptops. Arguably these should not |
| | | 187 | * appear in a generic device driver like this. |
| | | 188 | */ |
| | | 189 | if (acpitz_get_fanspeed(self, &sc->sc_zone.fanmin, |
| | | 190 | &sc->sc_zone.fanmax, &sc->sc_zone.fancurrent) == 0) |
| | | 191 | sc->sc_have_fan = true; |
| | | 192 | |
| | | 193 | rv = acpi_eval_string(sc->sc_node->ad_handle, |
209 | "REGN", &sc->sc_zone.name); | | 194 | "REGN", &sc->sc_zone.name); |
210 | | | 195 | |
211 | if (ACPI_FAILURE(rv)) | | 196 | if (ACPI_FAILURE(rv)) |
212 | sc->sc_zone.name = __UNCONST("temperature"); | | 197 | sc->sc_zone.name = __UNCONST("temperature"); |
213 | | | 198 | |
214 | acpitz_get_zone(self, 1); | | 199 | acpitz_get_zone(self, 1); |
215 | acpitz_get_status(self); | | 200 | acpitz_get_status(self); |
216 | | | 201 | |
217 | (void)pmf_device_register(self, NULL, NULL); | | 202 | (void)pmf_device_register(self, NULL, NULL); |
218 | (void)acpi_register_notify(sc->sc_devnode, acpitz_notify_handler); | | 203 | (void)acpi_register_notify(sc->sc_node, acpitz_notify_handler); |
219 | | | 204 | |
220 | callout_init(&sc->sc_callout, CALLOUT_MPSAFE); | | 205 | callout_init(&sc->sc_callout, CALLOUT_MPSAFE); |
221 | callout_setfunc(&sc->sc_callout, acpitz_tick, self); | | 206 | callout_setfunc(&sc->sc_callout, acpitz_tick, self); |
222 | | | 207 | |
223 | acpitz_init_envsys(self); | | 208 | acpitz_init_envsys(self); |
224 | | | 209 | |
225 | callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); | | 210 | callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); |
226 | } | | 211 | } |
227 | | | 212 | |
228 | static int | | 213 | static int |
229 | acpitz_detach(device_t self, int flags) | | 214 | acpitz_detach(device_t self, int flags) |
230 | { | | 215 | { |
231 | struct acpitz_softc *sc = device_private(self); | | 216 | struct acpitz_softc *sc = device_private(self); |
232 | ACPI_HANDLE hdl; | | 217 | ACPI_HANDLE hdl; |
233 | ACPI_BUFFER al; | | 218 | ACPI_BUFFER al; |
234 | ACPI_STATUS rv; | | 219 | ACPI_STATUS rv; |
235 | int i; | | 220 | int i; |
236 | | | 221 | |
237 | callout_halt(&sc->sc_callout, NULL); | | 222 | callout_halt(&sc->sc_callout, NULL); |
238 | callout_destroy(&sc->sc_callout); | | 223 | callout_destroy(&sc->sc_callout); |
239 | | | 224 | |
240 | pmf_device_deregister(self); | | 225 | pmf_device_deregister(self); |
241 | acpi_deregister_notify(sc->sc_devnode); | | 226 | acpi_deregister_notify(sc->sc_node); |
242 | | | 227 | |
243 | /* | | 228 | /* |
244 | * Although the device itself should not contain any power | | 229 | * Although the device itself should not contain any power |
245 | * resources, we have possibly used the resources of active | | 230 | * resources, we have possibly used the resources of active |
246 | * cooling devices. To unregister these, first fetch a fresh | | 231 | * cooling devices. To unregister these, first fetch a fresh |
247 | * active cooling zone, and then detach the resources from | | 232 | * active cooling zone, and then detach the resources from |
248 | * the reference handles contained in the cooling zone. | | 233 | * the reference handles contained in the cooling zone. |
249 | */ | | 234 | */ |
250 | acpitz_get_zone(self, 0); | | 235 | acpitz_get_zone(self, 0); |
251 | | | 236 | |
252 | for (i = 0; i < ATZ_NLEVELS; i++) { | | 237 | for (i = 0; i < ATZ_NLEVELS; i++) { |
253 | | | 238 | |
254 | if (sc->sc_zone.al[i].Pointer == NULL) | | 239 | if (sc->sc_zone.al[i].Pointer == NULL) |
| @@ -271,490 +256,495 @@ acpitz_detach(device_t self, int flags) | | | @@ -271,490 +256,495 @@ acpitz_detach(device_t self, int flags) |
271 | | | 256 | |
272 | static void | | 257 | static void |
273 | acpitz_get_zone_quiet(void *opaque) | | 258 | acpitz_get_zone_quiet(void *opaque) |
274 | { | | 259 | { |
275 | acpitz_get_zone(opaque, 0); | | 260 | acpitz_get_zone(opaque, 0); |
276 | } | | 261 | } |
277 | | | 262 | |
278 | static void | | 263 | static void |
279 | acpitz_get_status(void *opaque) | | 264 | acpitz_get_status(void *opaque) |
280 | { | | 265 | { |
281 | device_t dv = opaque; | | 266 | device_t dv = opaque; |
282 | struct acpitz_softc *sc = device_private(dv); | | 267 | struct acpitz_softc *sc = device_private(dv); |
283 | uint32_t tmp, active, fmin, fmax, fcurrent; | | 268 | uint32_t tmp, active, fmin, fmax, fcurrent; |
284 | int i, flags; | | 269 | int changed, flags, i; |
285 | | | 270 | |
286 | sc->sc_zone_expire--; | | 271 | sc->sc_zone_expire--; |
| | | 272 | |
287 | if (sc->sc_zone_expire <= 0) { | | 273 | if (sc->sc_zone_expire <= 0) { |
288 | sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp; | | 274 | sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp; |
289 | if (sc->sc_flags & ATZ_F_VERBOSE) | | 275 | |
290 | printf("%s: force refetch zone\n", device_xname(dv)); | | 276 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| | | 277 | "%s: zone refetch forced\n", device_xname(dv))); |
| | | 278 | |
291 | acpitz_get_zone(dv, 0); | | 279 | acpitz_get_zone(dv, 0); |
292 | } | | 280 | } |
293 | | | 281 | |
294 | if (acpitz_get_integer(dv, "_TMP", &tmp) != 0) | | 282 | if (acpitz_get_integer(dv, "_TMP", &tmp) != 0) |
295 | return; | | 283 | return; |
296 | | | 284 | |
297 | sc->sc_zone.prevtmp = sc->sc_zone.tmp; | | 285 | sc->sc_zone.prevtmp = sc->sc_zone.tmp; |
298 | sc->sc_zone.tmp = tmp; | | 286 | sc->sc_zone.tmp = tmp; |
299 | if (sc->sc_first) | | 287 | |
300 | sc->sc_zone.prevtmp = tmp; | | 288 | if (sc->sc_first != false) |
301 | /* XXX sanity check for tmp here? */ | | 289 | sc->sc_zone.prevtmp = tmp; /* XXX: Sanity check? */ |
302 | | | 290 | |
303 | if (acpitz_get_fanspeed(dv, &fmin, &fmax, &fcurrent) == 0) { | | 291 | if (acpitz_get_fanspeed(dv, &fmin, &fmax, &fcurrent) == 0) { |
| | | 292 | |
304 | if (fcurrent != ATZ_TMP_INVALID) | | 293 | if (fcurrent != ATZ_TMP_INVALID) |
305 | sc->sc_zone.fancurrent = fcurrent; | | 294 | sc->sc_zone.fancurrent = fcurrent; |
306 | } | | 295 | } |
307 | | | 296 | |
308 | /* | | | |
309 | * The temperature unit for envsys(4) is microKelvin, so convert to | | | |
310 | * that from ACPI's microKelvin. Also, the ACPI specification assumes | | | |
311 | * that K = C + 273.2 rather than the nominal 273.15 used by envsys(4), | | | |
312 | * so we correct for that too. | | | |
313 | */ | | | |
314 | sc->sc_temp_sensor.value_cur = ATZ2UKELVIN(sc->sc_zone.tmp); | | | |
315 | sc->sc_temp_sensor.state = ENVSYS_SVALID; | | 297 | sc->sc_temp_sensor.state = ENVSYS_SVALID; |
| | | 298 | sc->sc_temp_sensor.value_cur = ATZ2UKELVIN(sc->sc_zone.tmp); |
316 | | | 299 | |
317 | sc->sc_fan_sensor.value_cur = sc->sc_zone.fancurrent; | | | |
318 | sc->sc_fan_sensor.state = ENVSYS_SVALID; | | 300 | sc->sc_fan_sensor.state = ENVSYS_SVALID; |
| | | 301 | sc->sc_fan_sensor.value_cur = sc->sc_zone.fancurrent; |
319 | | | 302 | |
320 | if (sc->sc_flags & ATZ_F_VERBOSE) | | 303 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: zone temperature is %s C\n", |
321 | acpitz_print_status(dv); | | 304 | device_xname(dv), acpitz_celcius_string(sc->sc_zone.tmp))); |
322 | | | 305 | |
323 | if (sc->sc_flags & ATZ_F_PASSIVEONLY) { | | 306 | /* |
324 | /* Passive Cooling: XXX not yet */ | | 307 | * XXX: Passive cooling is not yet supported. |
| | | 308 | */ |
| | | 309 | if ((sc->sc_flags & ATZ_F_PASSIVEONLY) != 0) |
| | | 310 | return; |
325 | | | 311 | |
326 | } else { | | 312 | /* |
327 | /* Active Cooling */ | | 313 | * As noted in ACPI 4.0 (p. 420), the temperature |
| | | 314 | * thresholds are conveyed in the optional _ACx |
| | | 315 | * object (x = 0 ... 9). The smaller the x, the |
| | | 316 | * greater the cooling level. We prefer to keep |
| | | 317 | * the highest cooling mode when in "active". |
| | | 318 | */ |
| | | 319 | active = ATZ_ACTIVE_NONE; |
328 | | | 320 | |
329 | /* temperature threshold: _AC0 > ... > _AC9 */ | | 321 | for (i = ATZ_NLEVELS - 1; i >= 0; i--) { |
330 | active = ATZ_ACTIVE_NONE; | | 322 | |
331 | for (i = ATZ_NLEVELS - 1; i >= 0; i--) { | | 323 | if (sc->sc_zone.ac[i] == ATZ_TMP_INVALID) |
332 | if (sc->sc_zone.ac[i] == ATZ_TMP_INVALID) | | 324 | continue; |
333 | continue; | | 325 | |
334 | | | 326 | if (sc->sc_zone.ac[i] <= tmp) |
335 | /* we want to keep highest cooling mode in 'active' */ | | 327 | active = i; |
336 | if (sc->sc_zone.ac[i] <= tmp) | | 328 | } |
337 | active = i; | | 329 | |
338 | } | | 330 | flags = sc->sc_flags & ~(ATZ_F_CRITICAL | ATZ_F_HOT | ATZ_F_PASSIVE); |
339 | | | 331 | |
340 | flags = sc->sc_flags & | | 332 | if (sc->sc_zone.psv != ATZ_TMP_INVALID && tmp >= sc->sc_zone.psv) |
341 | ~(ATZ_F_CRITICAL|ATZ_F_HOT|ATZ_F_PASSIVE); | | 333 | flags |= ATZ_F_PASSIVE; |
342 | if (sc->sc_zone.psv != ATZ_TMP_INVALID && | | 334 | |
343 | tmp >= sc->sc_zone.psv) | | 335 | if (sc->sc_zone.hot != ATZ_TMP_INVALID && tmp >= sc->sc_zone.hot) |
344 | flags |= ATZ_F_PASSIVE; | | 336 | flags |= ATZ_F_HOT; |
345 | if (sc->sc_zone.hot != ATZ_TMP_INVALID && | | | |
346 | tmp >= sc->sc_zone.hot) | | | |
347 | flags |= ATZ_F_HOT; | | | |
348 | if (sc->sc_zone.crt != ATZ_TMP_INVALID && | | | |
349 | tmp >= sc->sc_zone.crt) | | | |
350 | flags |= ATZ_F_CRITICAL; | | | |
351 | | | | |
352 | if (flags != sc->sc_flags) { | | | |
353 | int changed = (sc->sc_flags ^ flags) & flags; | | | |
354 | sc->sc_flags = flags; | | | |
355 | if (changed & ATZ_F_CRITICAL) { | | | |
356 | sc->sc_temp_sensor.state = ENVSYS_SCRITOVER; | | | |
357 | aprint_debug_dev(dv, | | | |
358 | "zone went critical at temp %sC\n", | | | |
359 | acpitz_celcius_string(tmp)); | | | |
360 | } else if (changed & ATZ_F_HOT) { | | | |
361 | sc->sc_temp_sensor.state = ENVSYS_SCRITOVER; | | | |
362 | aprint_debug_dev(dv, | | | |
363 | "zone went hot at temp %sC\n", | | | |
364 | acpitz_celcius_string(tmp)); | | | |
365 | } | | | |
366 | } | | | |
367 | | | 337 | |
368 | /* power on fans */ | | 338 | if (sc->sc_zone.crt != ATZ_TMP_INVALID && tmp >= sc->sc_zone.crt) |
369 | if (sc->sc_active != active) { | | 339 | flags |= ATZ_F_CRITICAL; |
370 | if (sc->sc_active != ATZ_ACTIVE_NONE) | | | |
371 | acpitz_power_zone(sc, sc->sc_active, 0); | | | |
372 | | | 340 | |
373 | if (active != ATZ_ACTIVE_NONE) { | | 341 | if (flags != sc->sc_flags) { |
374 | if (sc->sc_flags & ATZ_F_VERBOSE) | | | |
375 | printf("%s: active cooling level %u\n", | | | |
376 | device_xname(dv), active); | | | |
377 | acpitz_power_zone(sc, active, 1); | | | |
378 | } else if (sc->sc_flags & ATZ_F_VERBOSE) | | | |
379 | printf("%s: no active cooling level\n", | | | |
380 | device_xname(dv)); | | | |
381 | | | 342 | |
382 | sc->sc_active = active; | | 343 | changed = (sc->sc_flags ^ flags) & flags; |
| | | 344 | sc->sc_flags = flags; |
| | | 345 | |
| | | 346 | if ((changed & ATZ_F_CRITICAL) != 0) { |
| | | 347 | sc->sc_temp_sensor.state = ENVSYS_SCRITOVER; |
| | | 348 | |
| | | 349 | aprint_debug_dev(dv, "zone went critical, %s C\n", |
| | | 350 | acpitz_celcius_string(tmp)); |
| | | 351 | |
| | | 352 | } else if ((changed & ATZ_F_HOT) != 0) { |
| | | 353 | sc->sc_temp_sensor.state = ENVSYS_SCRITOVER; |
| | | 354 | |
| | | 355 | aprint_debug_dev(dv, "zone went hot, %s C\n", |
| | | 356 | acpitz_celcius_string(tmp)); |
383 | } | | 357 | } |
384 | } | | 358 | } |
385 | | | 359 | |
386 | return; | | 360 | /* Power on the fans. */ |
| | | 361 | if (sc->sc_active != active) { |
| | | 362 | |
| | | 363 | if (sc->sc_active != ATZ_ACTIVE_NONE) |
| | | 364 | acpitz_power_zone(sc, sc->sc_active, 0); |
| | | 365 | |
| | | 366 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: active cooling " |
| | | 367 | "level %u\n", device_xname(dv), active)); |
| | | 368 | |
| | | 369 | if (active != ATZ_ACTIVE_NONE) |
| | | 370 | acpitz_power_zone(sc, active, 1); |
| | | 371 | |
| | | 372 | sc->sc_active = active; |
| | | 373 | } |
387 | } | | 374 | } |
388 | | | 375 | |
389 | static char * | | 376 | static char * |
390 | acpitz_celcius_string(int dk) | | 377 | acpitz_celcius_string(int dk) |
391 | { | | 378 | { |
392 | static char buf[10]; | | 379 | static char buf[10]; |
393 | int dc; | | 380 | int dc; |
394 | | | 381 | |
395 | dc = abs(dk - ATZ_ZEROC); | | 382 | dc = abs(dk - ATZ_ZEROC); |
396 | snprintf(buf, sizeof(buf), "%s%d.%d", (dk >= ATZ_ZEROC)?"":"-", | | | |
397 | dc / 10, dc % 10); | | | |
398 | | | | |
399 | return buf; | | | |
400 | } | | | |
401 | | | | |
402 | static void | | | |
403 | acpitz_print_status(device_t dv) | | | |
404 | { | | | |
405 | struct acpitz_softc *sc = device_private(dv); | | | |
406 | | | 383 | |
407 | printf("%s: zone temperature is now %sC\n", device_xname(dv), | | 384 | (void)snprintf(buf, sizeof(buf), "%s%d.%d", |
408 | acpitz_celcius_string(sc->sc_zone.tmp)); | | 385 | (dk >= ATZ_ZEROC) ? "" : "-", dc / 10, dc % 10); |
409 | if (sc->sc_have_fan) { | | | |
410 | printf("%s: fan rpm %u\n", device_xname(dv), | | | |
411 | sc->sc_zone.fancurrent); | | | |
412 | } | | | |
413 | | | 386 | |
414 | return; | | 387 | return buf; |
415 | } | | 388 | } |
416 | | | 389 | |
417 | static ACPI_STATUS | | 390 | static ACPI_STATUS |
418 | acpitz_switch_cooler(ACPI_OBJECT *obj, void *arg) | | 391 | acpitz_switch_cooler(ACPI_OBJECT *obj, void *arg) |
419 | { | | 392 | { |
420 | int flag, pwr_state; | | 393 | int flag, pwr_state; |
421 | ACPI_HANDLE cooler; | | 394 | ACPI_HANDLE cooler; |
422 | ACPI_STATUS rv; | | 395 | ACPI_STATUS rv; |
423 | | | 396 | |
424 | /* | | 397 | /* |
425 | * The _ALx object is a package in which the elements | | 398 | * The _ALx object is a package in which the elements |
426 | * are reference handles to an active cooling device | | 399 | * are reference handles to an active cooling device |
427 | * (typically PNP0C0B, ACPI fan device). Try to turn | | 400 | * (typically PNP0C0B, ACPI fan device). Try to turn |
428 | * on (or off) the power resources behind these handles | | 401 | * on (or off) the power resources behind these handles |
429 | * to start (or terminate) the active cooling. | | 402 | * to start (or terminate) the active cooling. |
430 | */ | | 403 | */ |
431 | flag = *(int *)arg; | | 404 | flag = *(int *)arg; |
432 | pwr_state = (flag != 0) ? ACPI_STATE_D0 : ACPI_STATE_D3; | | 405 | pwr_state = (flag != 0) ? ACPI_STATE_D0 : ACPI_STATE_D3; |
433 | | | 406 | |
434 | rv = acpi_eval_reference_handle(obj, &cooler); | | 407 | rv = acpi_eval_reference_handle(obj, &cooler); |
435 | | | 408 | |
436 | if (ACPI_FAILURE(rv)) { | | 409 | if (ACPI_FAILURE(rv)) |
437 | aprint_error("%s: failed to get reference handle\n", __func__); | | | |
438 | return rv; | | 410 | return rv; |
439 | } | | | |
440 | | | 411 | |
441 | (void)acpi_power_set_from_handle(cooler, pwr_state); | | 412 | (void)acpi_power_set_from_handle(cooler, pwr_state); |
442 | | | 413 | |
443 | return AE_OK; | | 414 | return AE_OK; |
444 | } | | 415 | } |
445 | | | 416 | |
446 | /* | | 417 | /* |
447 | * acpitz_power_zone: | | 418 | * acpitz_power_zone: |
448 | * power on or off the i:th part of the zone zone | | 419 | * |
| | | 420 | * Power on or off the i:th part of the zone zone. |
449 | */ | | 421 | */ |
450 | static void | | 422 | static void |
451 | acpitz_power_zone(struct acpitz_softc *sc, int i, int on) | | 423 | acpitz_power_zone(struct acpitz_softc *sc, int i, int on) |
452 | { | | 424 | { |
| | | 425 | |
453 | KASSERT(i >= 0 && i < ATZ_NLEVELS); | | 426 | KASSERT(i >= 0 && i < ATZ_NLEVELS); |
454 | | | 427 | |
455 | acpi_foreach_package_object(sc->sc_zone.al[i].Pointer, | | 428 | (void)acpi_foreach_package_object(sc->sc_zone.al[i].Pointer, |
456 | acpitz_switch_cooler, &on); | | 429 | acpitz_switch_cooler, &on); |
457 | } | | 430 | } |
458 | | | 431 | |
459 | | | 432 | |
460 | /* | | 433 | /* |
461 | * acpitz_power_off: | | 434 | * acpitz_power_off: |
462 | * power off parts of the zone | | 435 | * |
| | | 436 | * Power off parts of the zone. |
463 | */ | | 437 | */ |
464 | static void | | 438 | static void |
465 | acpitz_power_off(struct acpitz_softc *sc) | | 439 | acpitz_power_off(struct acpitz_softc *sc) |
466 | { | | 440 | { |
467 | int i; | | 441 | int i; |
468 | | | 442 | |
469 | for (i = 0 ; i < ATZ_NLEVELS; i++) { | | 443 | for (i = 0 ; i < ATZ_NLEVELS; i++) { |
| | | 444 | |
470 | if (sc->sc_zone.al[i].Pointer == NULL) | | 445 | if (sc->sc_zone.al[i].Pointer == NULL) |
471 | continue; | | 446 | continue; |
| | | 447 | |
472 | acpitz_power_zone(sc, i, 0); | | 448 | acpitz_power_zone(sc, i, 0); |
473 | } | | 449 | } |
| | | 450 | |
474 | sc->sc_active = ATZ_ACTIVE_NONE; | | 451 | sc->sc_active = ATZ_ACTIVE_NONE; |
475 | sc->sc_flags &= ~(ATZ_F_CRITICAL|ATZ_F_HOT|ATZ_F_PASSIVE); | | 452 | sc->sc_flags &= ~(ATZ_F_CRITICAL | ATZ_F_HOT | ATZ_F_PASSIVE); |
476 | } | | 453 | } |
477 | | | 454 | |
478 | static void | | 455 | static void |
479 | acpitz_get_zone(void *opaque, int verbose) | | 456 | acpitz_get_zone(void *opaque, int verbose) |
480 | { | | 457 | { |
481 | device_t dv = opaque; | | 458 | device_t dv = opaque; |
482 | struct acpitz_softc *sc = device_private(dv); | | 459 | struct acpitz_softc *sc = device_private(dv); |
| | | 460 | int comma, i, valid_levels; |
| | | 461 | ACPI_OBJECT *obj; |
483 | ACPI_STATUS rv; | | 462 | ACPI_STATUS rv; |
484 | char buf[8]; | | 463 | char buf[5]; |
485 | int i, valid_levels; | | | |
486 | | | 464 | |
487 | if (!sc->sc_first) { | | 465 | if (sc->sc_first != true) { |
488 | acpitz_power_off(sc); | | 466 | acpitz_power_off(sc); |
489 | | | 467 | |
490 | for (i = 0; i < ATZ_NLEVELS; i++) { | | 468 | for (i = 0; i < ATZ_NLEVELS; i++) { |
| | | 469 | |
491 | if (sc->sc_zone.al[i].Pointer != NULL) | | 470 | if (sc->sc_zone.al[i].Pointer != NULL) |
492 | ACPI_FREE(sc->sc_zone.al[i].Pointer); | | 471 | ACPI_FREE(sc->sc_zone.al[i].Pointer); |
| | | 472 | |
493 | sc->sc_zone.al[i].Pointer = NULL; | | 473 | sc->sc_zone.al[i].Pointer = NULL; |
494 | } | | 474 | } |
495 | } | | 475 | } |
496 | | | 476 | |
497 | valid_levels = 0; | | 477 | valid_levels = 0; |
498 | | | 478 | |
499 | for (i = 0; i < ATZ_NLEVELS; i++) { | | 479 | for (i = 0; i < ATZ_NLEVELS; i++) { |
500 | ACPI_OBJECT *obj; | | | |
501 | | | 480 | |
502 | snprintf(buf, sizeof(buf), "_AC%d", i); | | 481 | (void)snprintf(buf, sizeof(buf), "_AC%d", i); |
| | | 482 | |
503 | if (acpitz_get_integer(dv, buf, &sc->sc_zone.ac[i])) | | 483 | if (acpitz_get_integer(dv, buf, &sc->sc_zone.ac[i])) |
504 | continue; | | 484 | continue; |
505 | | | 485 | |
506 | snprintf(buf, sizeof(buf), "_AL%d", i); | | 486 | (void)snprintf(buf, sizeof(buf), "_AL%d", i); |
507 | rv = acpi_eval_struct(sc->sc_devnode->ad_handle, buf, | | 487 | |
| | | 488 | rv = acpi_eval_struct(sc->sc_node->ad_handle, buf, |
508 | &sc->sc_zone.al[i]); | | 489 | &sc->sc_zone.al[i]); |
| | | 490 | |
509 | if (ACPI_FAILURE(rv)) { | | 491 | if (ACPI_FAILURE(rv)) { |
510 | sc->sc_zone.al[i].Pointer = NULL; | | 492 | sc->sc_zone.al[i].Pointer = NULL; |
511 | continue; | | 493 | continue; |
512 | } | | 494 | } |
513 | | | 495 | |
514 | obj = sc->sc_zone.al[i].Pointer; | | 496 | obj = sc->sc_zone.al[i].Pointer; |
515 | if (obj != NULL) { | | 497 | |
516 | if (obj->Type != ACPI_TYPE_PACKAGE) { | | 498 | if (obj->Type != ACPI_TYPE_PACKAGE) { |
517 | aprint_error("%d not package\n", i); | | 499 | sc->sc_zone.al[i].Pointer = NULL; |
518 | ACPI_FREE(obj); | | 500 | ACPI_FREE(obj); |
519 | sc->sc_zone.al[i].Pointer = NULL; | | 501 | continue; |
520 | continue; | | | |
521 | } | | | |
522 | } | | 502 | } |
523 | | | 503 | |
524 | if (sc->sc_first) | | 504 | if (sc->sc_first != false) |
525 | aprint_normal(" active cooling level %d: %sC", i, | | 505 | aprint_normal(" active cooling level %d: %sC", i, |
526 | acpitz_celcius_string(sc->sc_zone.ac[i])); | | 506 | acpitz_celcius_string(sc->sc_zone.ac[i])); |
527 | | | 507 | |
528 | valid_levels++; | | 508 | valid_levels++; |
529 | } | | 509 | } |
530 | | | 510 | |
531 | acpitz_get_integer(dv, "_TMP", &sc->sc_zone.tmp); | | 511 | /* |
532 | acpitz_get_integer(dv, "_CRT", &sc->sc_zone.crt); | | 512 | * A brief summary (ACPI 4.0, section 11.4): |
533 | acpitz_get_integer(dv, "_HOT", &sc->sc_zone.hot); | | 513 | * |
534 | acpitz_get_integer(dv, "_PSV", &sc->sc_zone.psv); | | 514 | * _TMP : current temperature (in tenths of degrees) |
535 | acpitz_get_integer(dv, "_TC1", &sc->sc_zone.tc1); | | 515 | * _CRT : critical trip-point at which to shutdown |
536 | acpitz_get_integer(dv, "_TC2", &sc->sc_zone.tc2); | | 516 | * _HOT : critical trip-point at which to go to S4 |
537 | | | 517 | * _PSV : passive cooling policy threshold |
538 | #if 0 | | 518 | * _TC1 : thermal constant for passive cooling |
539 | sc->sc_zone.psl.Length = ACPI_ALLOCATE_LOCAL_BUFFER; | | 519 | * _TC2 : thermal constant for passive cooling |
540 | sc->sc_zone.psl.Pointer = NULL; | | 520 | */ |
541 | AcpiEvaluateObject(sc->sc_devnode->ad_handle, | | 521 | (void)acpitz_get_integer(dv, "_TMP", &sc->sc_zone.tmp); |
542 | "_PSL", NULL, &sc->sc_zone.psl); | | 522 | (void)acpitz_get_integer(dv, "_CRT", &sc->sc_zone.crt); |
543 | #endif | | 523 | (void)acpitz_get_integer(dv, "_HOT", &sc->sc_zone.hot); |
| | | 524 | (void)acpitz_get_integer(dv, "_PSV", &sc->sc_zone.psv); |
| | | 525 | (void)acpitz_get_integer(dv, "_TC1", &sc->sc_zone.tc1); |
| | | 526 | (void)acpitz_get_integer(dv, "_TC2", &sc->sc_zone.tc2); |
544 | | | 527 | |
545 | /* ACPI spec: If _RTV is not present or present and zero, | | 528 | /* |
546 | * values are absolute. */ | | 529 | * If _RTV is not present or present and zero, |
| | | 530 | * values are absolute (see ACPI 4.0, 425). |
| | | 531 | */ |
547 | acpitz_get_integer(dv, "_RTV", &sc->sc_zone.rtv); | | 532 | acpitz_get_integer(dv, "_RTV", &sc->sc_zone.rtv); |
| | | 533 | |
548 | if (sc->sc_zone.rtv == ATZ_TMP_INVALID) | | 534 | if (sc->sc_zone.rtv == ATZ_TMP_INVALID) |
549 | sc->sc_zone.rtv = 0; | | 535 | sc->sc_zone.rtv = 0; |
550 | | | 536 | |
551 | | | | |
552 | acpitz_sane_temp(&sc->sc_zone.tmp); | | 537 | acpitz_sane_temp(&sc->sc_zone.tmp); |
553 | acpitz_sane_temp(&sc->sc_zone.crt); | | 538 | acpitz_sane_temp(&sc->sc_zone.crt); |
554 | acpitz_sane_temp(&sc->sc_zone.hot); | | 539 | acpitz_sane_temp(&sc->sc_zone.hot); |
555 | acpitz_sane_temp(&sc->sc_zone.psv); | | 540 | acpitz_sane_temp(&sc->sc_zone.psv); |
556 | | | 541 | |
557 | if (verbose != 0) { | | 542 | if (verbose != 0) { |
558 | int comma = 0; | | 543 | comma = 0; |
559 | | | 544 | |
560 | aprint_verbose_dev(dv, ""); | | 545 | aprint_verbose_dev(dv, ""); |
561 | | | 546 | |
562 | if (sc->sc_zone.crt != ATZ_TMP_INVALID) { | | 547 | if (sc->sc_zone.crt != ATZ_TMP_INVALID) { |
563 | aprint_verbose("critical %s C", | | 548 | aprint_verbose("critical %s C", |
564 | acpitz_celcius_string(sc->sc_zone.crt)); | | 549 | acpitz_celcius_string(sc->sc_zone.crt)); |
565 | comma = 1; | | 550 | comma = 1; |
566 | } | | 551 | } |
567 | | | 552 | |
568 | if (sc->sc_zone.hot != ATZ_TMP_INVALID) { | | 553 | if (sc->sc_zone.hot != ATZ_TMP_INVALID) { |
569 | aprint_verbose("%shot %s C", comma ? ", " : "", | | 554 | aprint_verbose("%shot %s C", comma ? ", " : "", |
570 | acpitz_celcius_string(sc->sc_zone.hot)); | | 555 | acpitz_celcius_string(sc->sc_zone.hot)); |
571 | comma = 1; | | 556 | comma = 1; |
572 | } | | 557 | } |
573 | | | 558 | |
574 | if (sc->sc_zone.psv != ATZ_TMP_INVALID) { | | 559 | if (sc->sc_zone.psv != ATZ_TMP_INVALID) { |
575 | aprint_normal("%spassive %s C", comma ? ", " : "", | | 560 | aprint_normal("%spassive %s C", comma ? ", " : "", |
576 | acpitz_celcius_string(sc->sc_zone.psv)); | | 561 | acpitz_celcius_string(sc->sc_zone.psv)); |
577 | comma = 1; | | 562 | comma = 1; |
578 | } | | 563 | } |
579 | | | 564 | |
580 | if (valid_levels == 0) { | | 565 | if (valid_levels == 0) { |
581 | sc->sc_flags |= ATZ_F_PASSIVEONLY; | | 566 | sc->sc_flags |= ATZ_F_PASSIVEONLY; |
582 | | | 567 | |
583 | if (sc->sc_first) | | 568 | if (sc->sc_first != false) |
584 | aprint_verbose("%spassive cooling", comma ? | | 569 | aprint_verbose("%spassive cooling", comma ? |
585 | ", " : ""); | | 570 | ", " : ""); |
586 | } | | 571 | } |
587 | | | 572 | |
588 | aprint_verbose("\n"); | | 573 | aprint_verbose("\n"); |
589 | } | | 574 | } |
590 | | | 575 | |
591 | for (i = 0; i < ATZ_NLEVELS; i++) | | 576 | for (i = 0; i < ATZ_NLEVELS; i++) |
592 | acpitz_sane_temp(&sc->sc_zone.ac[i]); | | 577 | acpitz_sane_temp(&sc->sc_zone.ac[i]); |
593 | | | 578 | |
594 | acpitz_power_off(sc); | | 579 | acpitz_power_off(sc); |
595 | sc->sc_first = 0; | | 580 | sc->sc_first = false; |
596 | } | | 581 | } |
597 | | | 582 | |
598 | static void | | 583 | static void |
599 | acpitz_notify_handler(ACPI_HANDLE hdl, uint32_t notify, void *opaque) | | 584 | acpitz_notify_handler(ACPI_HANDLE hdl, uint32_t notify, void *opaque) |
600 | { | | 585 | { |
601 | device_t dv = opaque; | | | |
602 | ACPI_OSD_EXEC_CALLBACK func = NULL; | | 586 | ACPI_OSD_EXEC_CALLBACK func = NULL; |
603 | const char *name; | | 587 | device_t dv = opaque; |
604 | ACPI_STATUS rv; | | | |
605 | | | 588 | |
606 | switch (notify) { | | 589 | switch (notify) { |
| | | 590 | |
607 | case ACPI_NOTIFY_ThermalZoneStatusChanged: | | 591 | case ACPI_NOTIFY_ThermalZoneStatusChanged: |
608 | func = acpitz_get_status; | | 592 | func = acpitz_get_status; |
609 | name = "status check"; | | | |
610 | break; | | 593 | break; |
| | | 594 | |
611 | case ACPI_NOTIFY_ThermalZoneTripPointsChanged: | | 595 | case ACPI_NOTIFY_ThermalZoneTripPointsChanged: |
612 | case ACPI_NOTIFY_DeviceListsChanged: | | 596 | case ACPI_NOTIFY_DeviceListsChanged: |
613 | func = acpitz_get_zone_quiet; | | 597 | func = acpitz_get_zone_quiet; |
614 | name = "get zone"; | | | |
615 | break; | | 598 | break; |
| | | 599 | |
616 | default: | | 600 | default: |
617 | aprint_debug_dev(dv, | | 601 | aprint_debug_dev(dv, "unknown notify 0x%02X\n", notify); |
618 | "received unhandled notify message 0x%x\n", notify); | | | |
619 | return; | | 602 | return; |
620 | } | | 603 | } |
621 | | | 604 | |
622 | KASSERT(func != NULL); | | 605 | (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, dv); |
623 | | | | |
624 | rv = AcpiOsExecute(OSL_NOTIFY_HANDLER, func, dv); | | | |
625 | if (ACPI_FAILURE(rv)) | | | |
626 | aprint_debug_dev(dv, "unable to queue %s\n", name); | | | |
627 | } | | 606 | } |
628 | | | 607 | |
629 | static void | | 608 | static void |
630 | acpitz_sane_temp(uint32_t *tmp) | | 609 | acpitz_sane_temp(uint32_t *tmp) |
631 | { | | 610 | { |
632 | /* Sane temperatures are beteen 0 and 150 C */ | | 611 | /* Sane temperatures are beteen 0 and 150 C. */ |
633 | if (*tmp < ATZ_ZEROC || *tmp > ATZ_ZEROC + 1500) | | 612 | if (*tmp < ATZ_ZEROC || *tmp > ATZ_ZEROC + 1500) |
634 | *tmp = ATZ_TMP_INVALID; | | 613 | *tmp = ATZ_TMP_INVALID; |
635 | } | | 614 | } |
636 | | | 615 | |
637 | static int | | 616 | static int |
638 | acpitz_get_integer(device_t dv, const char *cm, uint32_t *val) | | 617 | acpitz_get_integer(device_t dv, const char *cm, uint32_t *val) |
639 | { | | 618 | { |
640 | struct acpitz_softc *sc = device_private(dv); | | 619 | struct acpitz_softc *sc = device_private(dv); |
641 | ACPI_STATUS rv; | | | |
642 | ACPI_INTEGER tmp; | | 620 | ACPI_INTEGER tmp; |
| | | 621 | ACPI_STATUS rv; |
643 | | | 622 | |
644 | rv = acpi_eval_integer(sc->sc_devnode->ad_handle, cm, &tmp); | | 623 | rv = acpi_eval_integer(sc->sc_node->ad_handle, cm, &tmp); |
645 | | | 624 | |
646 | if (ACPI_FAILURE(rv)) { | | 625 | if (ACPI_FAILURE(rv)) { |
647 | *val = ATZ_TMP_INVALID; | | 626 | *val = ATZ_TMP_INVALID; |
648 | | | 627 | |
649 | if (rv != AE_NOT_FOUND) | | 628 | ACPI_DEBUG_PRINT((ACPI_DB_DEBUG_OBJECT, |
650 | aprint_debug_dev(dv, "failed to evaluate %s: %s\n", | | 629 | "%s: failed to evaluate %s: %s\n", |
651 | cm, AcpiFormatException(rv)); | | 630 | device_xname(dv), cm, AcpiFormatException(rv))); |
652 | | | 631 | |
653 | return 1; | | 632 | return 1; |
654 | } | | 633 | } |
655 | | | 634 | |
656 | *val = tmp; | | 635 | *val = tmp; |
657 | | | 636 | |
658 | return 0; | | 637 | return 0; |
659 | } | | 638 | } |
660 | | | 639 | |
661 | static int | | 640 | static int |
662 | acpitz_get_fanspeed(device_t dv, | | 641 | acpitz_get_fanspeed(device_t dv, |
663 | uint32_t *fanmin, uint32_t *fanmax, uint32_t *fancurrent) | | 642 | uint32_t *fanmin, uint32_t *fanmax, uint32_t *fancurrent) |
664 | { | | 643 | { |
665 | struct acpitz_softc *sc = device_private(dv); | | 644 | struct acpitz_softc *sc = device_private(dv); |
666 | ACPI_STATUS rv; | | | |
667 | ACPI_HANDLE handle; | | | |
668 | ACPI_INTEGER fmin, fmax, fcurr; | | 645 | ACPI_INTEGER fmin, fmax, fcurr; |
| | | 646 | ACPI_HANDLE handle; |
| | | 647 | ACPI_STATUS rv; |
669 | int rc = 0; | | 648 | int rc = 0; |
670 | | | 649 | |
671 | handle = sc->sc_devnode->ad_handle; | | 650 | handle = sc->sc_node->ad_handle; |
| | | 651 | |
672 | rv = acpi_eval_integer(handle, "FMIN", &fmin); | | 652 | rv = acpi_eval_integer(handle, "FMIN", &fmin); |
| | | 653 | |
673 | if (ACPI_FAILURE(rv)) { | | 654 | if (ACPI_FAILURE(rv)) { |
674 | fmin = ATZ_TMP_INVALID; | | 655 | fmin = ATZ_TMP_INVALID; |
675 | rc = 1; | | 656 | rc = 1; |
676 | } | | 657 | } |
| | | 658 | |
677 | rv = acpi_eval_integer(handle, "FMAX", &fmax); | | 659 | rv = acpi_eval_integer(handle, "FMAX", &fmax); |
| | | 660 | |
678 | if (ACPI_FAILURE(rv)) { | | 661 | if (ACPI_FAILURE(rv)) { |
679 | fmax = ATZ_TMP_INVALID; | | 662 | fmax = ATZ_TMP_INVALID; |
680 | rc = 1; | | 663 | rc = 1; |
681 | } | | 664 | } |
682 | rv = acpi_eval_integer(handle, "FRSP", &fcurr); | | 665 | rv = acpi_eval_integer(handle, "FRSP", &fcurr); |
| | | 666 | |
683 | if (ACPI_FAILURE(rv)) { | | 667 | if (ACPI_FAILURE(rv)) { |
684 | fcurr = ATZ_TMP_INVALID; | | 668 | fcurr = ATZ_TMP_INVALID; |
685 | rc = 1; | | 669 | rc = 1; |
686 | } | | 670 | } |
687 | | | 671 | |
688 | if (fanmin) | | 672 | if (fanmin != NULL) |
689 | *fanmin = fmin; | | 673 | *fanmin = fmin; |
690 | if (fanmax) | | 674 | |
| | | 675 | if (fanmax != NULL) |
691 | *fanmax = fmax; | | 676 | *fanmax = fmax; |
692 | if (fancurrent) | | 677 | |
| | | 678 | if (fancurrent != NULL) |
693 | *fancurrent = fcurr; | | 679 | *fancurrent = fcurr; |
| | | 680 | |
694 | return rc; | | 681 | return rc; |
695 | } | | 682 | } |
696 | | | 683 | |
697 | #ifdef notyet | | 684 | #ifdef notyet |
698 | static ACPI_STATUS | | 685 | static ACPI_STATUS |
699 | acpitz_set_fanspeed(device_t dv, uint32_t fanspeed) | | 686 | acpitz_set_fanspeed(device_t dv, uint32_t fanspeed) |
700 | { | | 687 | { |
701 | struct acpitz_softc *sc = device_private(dv); | | 688 | struct acpitz_softc *sc = device_private(dv); |
702 | ACPI_STATUS rv; | | | |
703 | ACPI_HANDLE handle; | | 689 | ACPI_HANDLE handle; |
704 | handle = sc->sc_devnode->ad_handle; | | 690 | ACPI_STATUS rv; |
| | | 691 | |
| | | 692 | handle = sc->sc_node->ad_handle; |
705 | | | 693 | |
706 | rv = acpi_eval_set_integer(handle, "FSSP", fanspeed); | | 694 | rv = acpi_eval_set_integer(handle, "FSSP", fanspeed); |
| | | 695 | |
707 | if (ACPI_FAILURE(rv)) | | 696 | if (ACPI_FAILURE(rv)) |
708 | aprint_debug_dev(dv, "failed to set fanspeed to %u rpm: %s\n", | | 697 | aprint_debug_dev(dv, "failed to set fan speed to %u RPM: %s\n", |
709 | fanspeed, AcpiFormatException(rv)); | | 698 | fanspeed, AcpiFormatException(rv)); |
| | | 699 | |
710 | return rv; | | 700 | return rv; |
711 | } | | 701 | } |
712 | #endif | | 702 | #endif |
713 | | | 703 | |
714 | static void | | 704 | static void |
715 | acpitz_tick(void *opaque) | | 705 | acpitz_tick(void *opaque) |
716 | { | | 706 | { |
717 | device_t dv = opaque; | | 707 | device_t dv = opaque; |
718 | struct acpitz_softc *sc = device_private(dv); | | 708 | struct acpitz_softc *sc = device_private(dv); |
719 | | | 709 | |
720 | AcpiOsExecute(OSL_NOTIFY_HANDLER, acpitz_get_status, dv); | | 710 | (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpitz_get_status, dv); |
721 | | | 711 | |
722 | callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); | | 712 | callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); |
723 | } | | 713 | } |
724 | | | 714 | |
725 | static void | | 715 | static void |
726 | acpitz_init_envsys(device_t dv) | | 716 | acpitz_init_envsys(device_t dv) |
727 | { | | 717 | { |
728 | const int flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP; | | 718 | const int flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP; |
729 | struct acpitz_softc *sc = device_private(dv); | | 719 | struct acpitz_softc *sc = device_private(dv); |
730 | | | 720 | |
731 | sc->sc_sme = sysmon_envsys_create(); | | 721 | sc->sc_sme = sysmon_envsys_create(); |
732 | | | 722 | |
733 | sc->sc_sme->sme_cookie = sc; | | 723 | sc->sc_sme->sme_cookie = sc; |
734 | sc->sc_sme->sme_name = device_xname(dv); | | 724 | sc->sc_sme->sme_name = device_xname(dv); |
735 | sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; | | 725 | sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; |
736 | sc->sc_sme->sme_get_limits = acpitz_get_limits; | | 726 | sc->sc_sme->sme_get_limits = acpitz_get_limits; |
737 | | | 727 | |
738 | sc->sc_temp_sensor.flags = flags; | | 728 | sc->sc_temp_sensor.flags = flags; |
739 | sc->sc_temp_sensor.units = ENVSYS_STEMP; | | 729 | sc->sc_temp_sensor.units = ENVSYS_STEMP; |
740 | | | 730 | |
741 | (void)strlcpy(sc->sc_temp_sensor.desc, | | 731 | (void)strlcpy(sc->sc_temp_sensor.desc, |
742 | sc->sc_zone.name, sizeof(sc->sc_temp_sensor.desc)); | | 732 | sc->sc_zone.name, sizeof(sc->sc_temp_sensor.desc)); |
743 | | | 733 | |
744 | if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_sensor)) | | 734 | if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_sensor)) |
745 | goto out; | | 735 | goto out; |
746 | | | 736 | |
747 | if (sc->sc_have_fan != 0) { | | 737 | if (sc->sc_have_fan != false) { |
748 | | | 738 | |
749 | sc->sc_fan_sensor.flags = flags; | | 739 | sc->sc_fan_sensor.flags = flags; |
750 | sc->sc_fan_sensor.units = ENVSYS_SFANRPM; | | 740 | sc->sc_fan_sensor.units = ENVSYS_SFANRPM; |
751 | | | 741 | |
752 | (void)strlcpy(sc->sc_fan_sensor.desc, | | 742 | (void)strlcpy(sc->sc_fan_sensor.desc, |
753 | "FAN", sizeof(sc->sc_fan_sensor.desc)); | | 743 | "FAN", sizeof(sc->sc_fan_sensor.desc)); |
754 | | | 744 | |
755 | /* Ignore error because fan sensor is optional. */ | | 745 | /* Ignore error because fan sensor is optional. */ |
756 | (void)sysmon_envsys_sensor_attach(sc->sc_sme, | | 746 | (void)sysmon_envsys_sensor_attach(sc->sc_sme, |
757 | &sc->sc_fan_sensor); | | 747 | &sc->sc_fan_sensor); |
758 | } | | 748 | } |
759 | | | 749 | |
760 | if (sysmon_envsys_register(sc->sc_sme) == 0) | | 750 | if (sysmon_envsys_register(sc->sc_sme) == 0) |