1 1.91 andvar /* $NetBSD: acpi_tz.c,v 1.91 2022/05/22 11:27:35 andvar Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /* 4 1.1 jmcneill * Copyright (c) 2003 Jared D. McNeill <jmcneill (at) invisible.ca> 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. The name of the author may not be used to endorse or promote products 13 1.1 jmcneill * derived from this software without specific prior written permission. 14 1.1 jmcneill * 15 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 1.1 jmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 1.1 jmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 1.1 jmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 1.1 jmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 jmcneill * SUCH DAMAGE. 26 1.1 jmcneill */ 27 1.1 jmcneill 28 1.1 jmcneill /* 29 1.1 jmcneill * ACPI Thermal Zone driver 30 1.1 jmcneill */ 31 1.1 jmcneill 32 1.1 jmcneill #include <sys/cdefs.h> 33 1.91 andvar __KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.91 2022/05/22 11:27:35 andvar Exp $"); 34 1.1 jmcneill 35 1.1 jmcneill #include <sys/param.h> 36 1.1 jmcneill #include <sys/device.h> 37 1.1 jmcneill #include <sys/callout.h> 38 1.61 jruoho #include <sys/kernel.h> 39 1.75 jruoho #include <sys/module.h> 40 1.61 jruoho #include <sys/systm.h> 41 1.83 jmcneill #include <sys/kmem.h> 42 1.90 mrg #include <sys/cpu.h> 43 1.1 jmcneill 44 1.1 jmcneill #include <dev/acpi/acpireg.h> 45 1.1 jmcneill #include <dev/acpi/acpivar.h> 46 1.67 jruoho #include <dev/acpi/acpi_power.h> 47 1.1 jmcneill 48 1.69 jruoho #define _COMPONENT ACPI_TZ_COMPONENT 49 1.69 jruoho ACPI_MODULE_NAME ("acpi_tz") 50 1.47 mlelstv 51 1.71 jruoho #define ACPI_NOTIFY_TZ_ZONE 0x80 52 1.71 jruoho #define ACPI_NOTIFY_TZ_TRIP 0x81 53 1.71 jruoho #define ACPI_NOTIFY_TZ_DEVLIST 0x82 54 1.71 jruoho 55 1.69 jruoho #define ATZ_F_CRITICAL 0x01 /* zone critical */ 56 1.69 jruoho #define ATZ_F_HOT 0x02 /* zone hot */ 57 1.69 jruoho #define ATZ_F_PASSIVE 0x04 /* zone passive cooling */ 58 1.69 jruoho #define ATZ_F_PASSIVEONLY 0x08 /* zone is passive cooling only */ 59 1.1 jmcneill 60 1.69 jruoho #define ATZ_ACTIVE_NONE -1 61 1.1 jmcneill 62 1.1 jmcneill /* 63 1.69 jruoho * The constants are as follows: 64 1.69 jruoho * 65 1.69 jruoho * ATZ_TZP_RATE default polling interval (30 seconds) if no _TZP 66 1.69 jruoho * ATZ_NLEVELS number of cooling levels for _ACx and _ALx 67 1.69 jruoho * ATZ_ZEROC 0 C, measured in 0.1 Kelvin 68 1.69 jruoho * ATZ_TMP_INVALID temporarily invalid temperature 69 1.69 jruoho * ATZ_ZONE_EXPIRE zone info refetch interval (15 minutes) 70 1.1 jmcneill */ 71 1.69 jruoho #define ATZ_TZP_RATE 300 72 1.69 jruoho #define ATZ_NLEVELS 10 73 1.69 jruoho #define ATZ_ZEROC 2732 74 1.69 jruoho #define ATZ_TMP_INVALID 0xffffffff 75 1.69 jruoho #define ATZ_ZONE_EXPIRE 9000 76 1.45 pgoyette 77 1.69 jruoho /* 78 1.69 jruoho * All temperatures are reported in 0.1 Kelvin. 79 1.69 jruoho * The ACPI specification assumes that K = C + 273.2 80 1.69 jruoho * rather than the nominal 273.15 used by envsys(4). 81 1.69 jruoho */ 82 1.45 pgoyette #define ATZ2UKELVIN(t) ((t) * 100000 - 50000) 83 1.45 pgoyette 84 1.1 jmcneill struct acpitz_zone { 85 1.69 jruoho ACPI_BUFFER al[ATZ_NLEVELS]; 86 1.69 jruoho uint32_t ac[ATZ_NLEVELS]; 87 1.69 jruoho uint32_t crt; 88 1.69 jruoho uint32_t hot; 89 1.69 jruoho uint32_t rtv; 90 1.69 jruoho uint32_t psv; 91 1.69 jruoho uint32_t tc1; 92 1.69 jruoho uint32_t tc2; 93 1.69 jruoho uint32_t tmp; 94 1.69 jruoho uint32_t prevtmp; 95 1.69 jruoho uint32_t tzp; 96 1.69 jruoho uint32_t fanmin; 97 1.69 jruoho uint32_t fanmax; 98 1.69 jruoho uint32_t fancurrent; 99 1.1 jmcneill }; 100 1.1 jmcneill 101 1.1 jmcneill struct acpitz_softc { 102 1.69 jruoho struct acpi_devnode *sc_node; 103 1.69 jruoho struct sysmon_envsys *sc_sme; 104 1.69 jruoho struct acpitz_zone sc_zone; 105 1.69 jruoho struct callout sc_callout; 106 1.69 jruoho envsys_data_t sc_temp_sensor; 107 1.69 jruoho envsys_data_t sc_fan_sensor; 108 1.69 jruoho int sc_active; 109 1.69 jruoho int sc_flags; 110 1.69 jruoho int sc_zone_expire; 111 1.69 jruoho bool sc_first; 112 1.69 jruoho bool sc_have_fan; 113 1.83 jmcneill struct cpu_info **sc_psl; 114 1.83 jmcneill size_t sc_psl_size; 115 1.1 jmcneill }; 116 1.1 jmcneill 117 1.69 jruoho static int acpitz_match(device_t, cfdata_t, void *); 118 1.69 jruoho static void acpitz_attach(device_t, device_t, void *); 119 1.69 jruoho static int acpitz_detach(device_t, int); 120 1.69 jruoho static void acpitz_get_status(void *); 121 1.69 jruoho static void acpitz_get_zone(void *, int); 122 1.69 jruoho static void acpitz_get_zone_quiet(void *); 123 1.69 jruoho static char *acpitz_celcius_string(int); 124 1.69 jruoho static void acpitz_power_off(struct acpitz_softc *); 125 1.69 jruoho static void acpitz_power_zone(struct acpitz_softc *, int, int); 126 1.69 jruoho static void acpitz_sane_temp(uint32_t *tmp); 127 1.69 jruoho static ACPI_STATUS acpitz_switch_cooler(ACPI_OBJECT *, void *); 128 1.69 jruoho static void acpitz_notify_handler(ACPI_HANDLE, uint32_t, void *); 129 1.69 jruoho static int acpitz_get_integer(device_t, const char *, uint32_t *); 130 1.69 jruoho static void acpitz_tick(void *); 131 1.69 jruoho static void acpitz_init_envsys(device_t); 132 1.69 jruoho static void acpitz_get_limits(struct sysmon_envsys *, 133 1.69 jruoho envsys_data_t *, 134 1.69 jruoho sysmon_envsys_lim_t *, uint32_t *); 135 1.69 jruoho static int acpitz_get_fanspeed(device_t, uint32_t *, 136 1.69 jruoho uint32_t *, uint32_t *); 137 1.49 cegger #ifdef notyet 138 1.69 jruoho static ACPI_STATUS acpitz_set_fanspeed(device_t, uint32_t); 139 1.49 cegger #endif 140 1.78 jmcneill static void acpitz_print_processor_list(device_t); 141 1.1 jmcneill 142 1.68 jruoho CFATTACH_DECL_NEW(acpitz, sizeof(struct acpitz_softc), 143 1.68 jruoho acpitz_match, acpitz_attach, acpitz_detach, NULL); 144 1.1 jmcneill 145 1.1 jmcneill /* 146 1.1 jmcneill * acpitz_match: autoconf(9) match routine 147 1.1 jmcneill */ 148 1.11 kochi static int 149 1.33 xtraeme acpitz_match(device_t parent, cfdata_t match, void *aux) 150 1.1 jmcneill { 151 1.1 jmcneill struct acpi_attach_args *aa = aux; 152 1.1 jmcneill 153 1.1 jmcneill if (aa->aa_node->ad_type != ACPI_TYPE_THERMAL) 154 1.1 jmcneill return 0; 155 1.1 jmcneill 156 1.1 jmcneill return 1; 157 1.1 jmcneill } 158 1.1 jmcneill 159 1.1 jmcneill /* 160 1.1 jmcneill * acpitz_attach: autoconf(9) attach routine 161 1.1 jmcneill */ 162 1.11 kochi static void 163 1.33 xtraeme acpitz_attach(device_t parent, device_t self, void *aux) 164 1.1 jmcneill { 165 1.33 xtraeme struct acpitz_softc *sc = device_private(self); 166 1.1 jmcneill struct acpi_attach_args *aa = aux; 167 1.69 jruoho ACPI_INTEGER val; 168 1.1 jmcneill ACPI_STATUS rv; 169 1.1 jmcneill 170 1.69 jruoho sc->sc_first = true; 171 1.69 jruoho sc->sc_have_fan = false; 172 1.69 jruoho sc->sc_node = aa->aa_node; 173 1.69 jruoho sc->sc_zone.tzp = ATZ_TZP_RATE; 174 1.69 jruoho 175 1.78 jmcneill aprint_naive("\n"); 176 1.78 jmcneill acpitz_print_processor_list(self); 177 1.78 jmcneill aprint_normal("\n"); 178 1.78 jmcneill 179 1.69 jruoho /* 180 1.69 jruoho * The _TZP (ACPI 4.0, p. 430) defines the recommended 181 1.69 jruoho * polling interval (in tenths of seconds). A value zero 182 1.69 jruoho * means that polling "should not be necessary". 183 1.69 jruoho */ 184 1.69 jruoho rv = acpi_eval_integer(sc->sc_node->ad_handle, "_TZP", &val); 185 1.69 jruoho 186 1.69 jruoho if (ACPI_SUCCESS(rv) && val != 0) 187 1.69 jruoho sc->sc_zone.tzp = val; 188 1.31 jmcneill 189 1.76 jruoho aprint_debug_dev(self, "polling interval %d.%d seconds\n", 190 1.31 jmcneill sc->sc_zone.tzp / 10, sc->sc_zone.tzp % 10); 191 1.3 mycroft 192 1.69 jruoho sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp; 193 1.10 kochi 194 1.69 jruoho /* 195 1.69 jruoho * XXX: The fan controls seen here are available on 196 1.69 jruoho * some HP laptops. Arguably these should not 197 1.69 jruoho * appear in a generic device driver like this. 198 1.69 jruoho */ 199 1.69 jruoho if (acpitz_get_fanspeed(self, &sc->sc_zone.fanmin, 200 1.69 jruoho &sc->sc_zone.fanmax, &sc->sc_zone.fancurrent) == 0) 201 1.69 jruoho sc->sc_have_fan = true; 202 1.13 kochi 203 1.33 xtraeme acpitz_get_zone(self, 1); 204 1.33 xtraeme acpitz_get_status(self); 205 1.1 jmcneill 206 1.68 jruoho (void)pmf_device_register(self, NULL, NULL); 207 1.77 jruoho (void)acpi_power_register(sc->sc_node->ad_handle); 208 1.69 jruoho (void)acpi_register_notify(sc->sc_node, acpitz_notify_handler); 209 1.1 jmcneill 210 1.33 xtraeme callout_init(&sc->sc_callout, CALLOUT_MPSAFE); 211 1.33 xtraeme callout_setfunc(&sc->sc_callout, acpitz_tick, self); 212 1.1 jmcneill 213 1.33 xtraeme acpitz_init_envsys(self); 214 1.25 joerg 215 1.68 jruoho callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); 216 1.68 jruoho } 217 1.68 jruoho 218 1.68 jruoho static int 219 1.68 jruoho acpitz_detach(device_t self, int flags) 220 1.68 jruoho { 221 1.68 jruoho struct acpitz_softc *sc = device_private(self); 222 1.68 jruoho ACPI_HANDLE hdl; 223 1.68 jruoho ACPI_BUFFER al; 224 1.68 jruoho ACPI_STATUS rv; 225 1.68 jruoho int i; 226 1.68 jruoho 227 1.68 jruoho callout_halt(&sc->sc_callout, NULL); 228 1.68 jruoho callout_destroy(&sc->sc_callout); 229 1.68 jruoho 230 1.68 jruoho pmf_device_deregister(self); 231 1.69 jruoho acpi_deregister_notify(sc->sc_node); 232 1.68 jruoho 233 1.68 jruoho /* 234 1.68 jruoho * Although the device itself should not contain any power 235 1.68 jruoho * resources, we have possibly used the resources of active 236 1.68 jruoho * cooling devices. To unregister these, first fetch a fresh 237 1.68 jruoho * active cooling zone, and then detach the resources from 238 1.68 jruoho * the reference handles contained in the cooling zone. 239 1.68 jruoho */ 240 1.68 jruoho acpitz_get_zone(self, 0); 241 1.68 jruoho 242 1.68 jruoho for (i = 0; i < ATZ_NLEVELS; i++) { 243 1.68 jruoho 244 1.68 jruoho if (sc->sc_zone.al[i].Pointer == NULL) 245 1.68 jruoho continue; 246 1.68 jruoho 247 1.68 jruoho al = sc->sc_zone.al[i]; 248 1.68 jruoho rv = acpi_eval_reference_handle(al.Pointer, &hdl); 249 1.68 jruoho 250 1.68 jruoho if (ACPI_SUCCESS(rv)) 251 1.74 jruoho acpi_power_deregister(hdl); 252 1.68 jruoho 253 1.68 jruoho ACPI_FREE(sc->sc_zone.al[i].Pointer); 254 1.68 jruoho } 255 1.32 jmcneill 256 1.83 jmcneill if (sc->sc_psl) 257 1.83 jmcneill kmem_free(sc->sc_psl, sc->sc_psl_size); 258 1.83 jmcneill 259 1.68 jruoho if (sc->sc_sme != NULL) 260 1.68 jruoho sysmon_envsys_unregister(sc->sc_sme); 261 1.68 jruoho 262 1.68 jruoho return 0; 263 1.1 jmcneill } 264 1.1 jmcneill 265 1.11 kochi static void 266 1.14 martin acpitz_get_zone_quiet(void *opaque) 267 1.14 martin { 268 1.14 martin acpitz_get_zone(opaque, 0); 269 1.14 martin } 270 1.14 martin 271 1.14 martin static void 272 1.1 jmcneill acpitz_get_status(void *opaque) 273 1.1 jmcneill { 274 1.33 xtraeme device_t dv = opaque; 275 1.33 xtraeme struct acpitz_softc *sc = device_private(dv); 276 1.76 jruoho uint32_t tmp, fmin, fmax, fcurrent; 277 1.76 jruoho int active, changed, flags, i; 278 1.13 kochi 279 1.13 kochi sc->sc_zone_expire--; 280 1.69 jruoho 281 1.13 kochi if (sc->sc_zone_expire <= 0) { 282 1.13 kochi sc->sc_zone_expire = ATZ_ZONE_EXPIRE / sc->sc_zone.tzp; 283 1.69 jruoho 284 1.69 jruoho ACPI_DEBUG_PRINT((ACPI_DB_INFO, 285 1.69 jruoho "%s: zone refetch forced\n", device_xname(dv))); 286 1.69 jruoho 287 1.34 xtraeme acpitz_get_zone(dv, 0); 288 1.13 kochi } 289 1.3 mycroft 290 1.63 jruoho if (acpitz_get_integer(dv, "_TMP", &tmp) != 0) 291 1.3 mycroft return; 292 1.49 cegger 293 1.49 cegger sc->sc_zone.prevtmp = sc->sc_zone.tmp; 294 1.13 kochi sc->sc_zone.tmp = tmp; 295 1.69 jruoho 296 1.69 jruoho if (sc->sc_first != false) 297 1.69 jruoho sc->sc_zone.prevtmp = tmp; /* XXX: Sanity check? */ 298 1.1 jmcneill 299 1.87 pgoyette if (acpitz_get_fanspeed(dv, &fmin, &fmax, &fcurrent) == 0) { 300 1.85 tls 301 1.87 pgoyette if (fcurrent != ATZ_TMP_INVALID) 302 1.49 cegger sc->sc_zone.fancurrent = fcurrent; 303 1.49 cegger } 304 1.49 cegger 305 1.69 jruoho sc->sc_temp_sensor.state = ENVSYS_SVALID; 306 1.69 jruoho sc->sc_temp_sensor.value_cur = ATZ2UKELVIN(sc->sc_zone.tmp); 307 1.69 jruoho 308 1.69 jruoho sc->sc_fan_sensor.state = ENVSYS_SVALID; 309 1.69 jruoho sc->sc_fan_sensor.value_cur = sc->sc_zone.fancurrent; 310 1.69 jruoho 311 1.69 jruoho ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: zone temperature is %s C\n", 312 1.69 jruoho device_xname(dv), acpitz_celcius_string(sc->sc_zone.tmp))); 313 1.69 jruoho 314 1.7 soren /* 315 1.69 jruoho * XXX: Passive cooling is not yet supported. 316 1.7 soren */ 317 1.69 jruoho if ((sc->sc_flags & ATZ_F_PASSIVEONLY) != 0) 318 1.69 jruoho return; 319 1.69 jruoho 320 1.69 jruoho /* 321 1.69 jruoho * As noted in ACPI 4.0 (p. 420), the temperature 322 1.69 jruoho * thresholds are conveyed in the optional _ACx 323 1.69 jruoho * object (x = 0 ... 9). The smaller the x, the 324 1.69 jruoho * greater the cooling level. We prefer to keep 325 1.69 jruoho * the highest cooling mode when in "active". 326 1.69 jruoho */ 327 1.69 jruoho active = ATZ_ACTIVE_NONE; 328 1.69 jruoho 329 1.69 jruoho for (i = ATZ_NLEVELS - 1; i >= 0; i--) { 330 1.69 jruoho 331 1.69 jruoho if (sc->sc_zone.ac[i] == ATZ_TMP_INVALID) 332 1.69 jruoho continue; 333 1.69 jruoho 334 1.69 jruoho if (sc->sc_zone.ac[i] <= tmp) 335 1.69 jruoho active = i; 336 1.69 jruoho } 337 1.69 jruoho 338 1.69 jruoho flags = sc->sc_flags & ~(ATZ_F_CRITICAL | ATZ_F_HOT | ATZ_F_PASSIVE); 339 1.69 jruoho 340 1.69 jruoho if (sc->sc_zone.psv != ATZ_TMP_INVALID && tmp >= sc->sc_zone.psv) 341 1.69 jruoho flags |= ATZ_F_PASSIVE; 342 1.49 cegger 343 1.69 jruoho if (sc->sc_zone.hot != ATZ_TMP_INVALID && tmp >= sc->sc_zone.hot) 344 1.69 jruoho flags |= ATZ_F_HOT; 345 1.1 jmcneill 346 1.69 jruoho if (sc->sc_zone.crt != ATZ_TMP_INVALID && tmp >= sc->sc_zone.crt) 347 1.69 jruoho flags |= ATZ_F_CRITICAL; 348 1.1 jmcneill 349 1.69 jruoho if (flags != sc->sc_flags) { 350 1.13 kochi 351 1.69 jruoho changed = (sc->sc_flags ^ flags) & flags; 352 1.69 jruoho sc->sc_flags = flags; 353 1.13 kochi 354 1.69 jruoho if ((changed & ATZ_F_CRITICAL) != 0) { 355 1.69 jruoho sc->sc_temp_sensor.state = ENVSYS_SCRITOVER; 356 1.13 kochi 357 1.69 jruoho aprint_debug_dev(dv, "zone went critical, %s C\n", 358 1.69 jruoho acpitz_celcius_string(tmp)); 359 1.13 kochi 360 1.69 jruoho } else if ((changed & ATZ_F_HOT) != 0) { 361 1.69 jruoho sc->sc_temp_sensor.state = ENVSYS_SCRITOVER; 362 1.13 kochi 363 1.69 jruoho aprint_debug_dev(dv, "zone went hot, %s C\n", 364 1.69 jruoho acpitz_celcius_string(tmp)); 365 1.13 kochi } 366 1.13 kochi } 367 1.13 kochi 368 1.69 jruoho /* Power on the fans. */ 369 1.69 jruoho if (sc->sc_active != active) { 370 1.69 jruoho 371 1.69 jruoho if (sc->sc_active != ATZ_ACTIVE_NONE) 372 1.69 jruoho acpitz_power_zone(sc, sc->sc_active, 0); 373 1.69 jruoho 374 1.69 jruoho ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: active cooling " 375 1.76 jruoho "level %d\n", device_xname(dv), active)); 376 1.69 jruoho 377 1.69 jruoho if (active != ATZ_ACTIVE_NONE) 378 1.69 jruoho acpitz_power_zone(sc, active, 1); 379 1.69 jruoho 380 1.69 jruoho sc->sc_active = active; 381 1.69 jruoho } 382 1.1 jmcneill } 383 1.1 jmcneill 384 1.13 kochi static char * 385 1.13 kochi acpitz_celcius_string(int dk) 386 1.13 kochi { 387 1.13 kochi static char buf[10]; 388 1.59 pgoyette int dc; 389 1.13 kochi 390 1.59 pgoyette dc = abs(dk - ATZ_ZEROC); 391 1.69 jruoho 392 1.69 jruoho (void)snprintf(buf, sizeof(buf), "%s%d.%d", 393 1.69 jruoho (dk >= ATZ_ZEROC) ? "" : "-", dc / 10, dc % 10); 394 1.13 kochi 395 1.13 kochi return buf; 396 1.13 kochi } 397 1.13 kochi 398 1.13 kochi static ACPI_STATUS 399 1.13 kochi acpitz_switch_cooler(ACPI_OBJECT *obj, void *arg) 400 1.13 kochi { 401 1.68 jruoho int flag, pwr_state; 402 1.13 kochi ACPI_HANDLE cooler; 403 1.13 kochi ACPI_STATUS rv; 404 1.13 kochi 405 1.68 jruoho /* 406 1.68 jruoho * The _ALx object is a package in which the elements 407 1.68 jruoho * are reference handles to an active cooling device 408 1.68 jruoho * (typically PNP0C0B, ACPI fan device). Try to turn 409 1.68 jruoho * on (or off) the power resources behind these handles 410 1.68 jruoho * to start (or terminate) the active cooling. 411 1.68 jruoho */ 412 1.13 kochi flag = *(int *)arg; 413 1.68 jruoho pwr_state = (flag != 0) ? ACPI_STATE_D0 : ACPI_STATE_D3; 414 1.13 kochi 415 1.56 jruoho rv = acpi_eval_reference_handle(obj, &cooler); 416 1.67 jruoho 417 1.69 jruoho if (ACPI_FAILURE(rv)) 418 1.56 jruoho return rv; 419 1.13 kochi 420 1.74 jruoho (void)acpi_power_set(cooler, pwr_state); 421 1.13 kochi 422 1.13 kochi return AE_OK; 423 1.13 kochi } 424 1.13 kochi 425 1.13 kochi /* 426 1.13 kochi * acpitz_power_zone: 427 1.69 jruoho * 428 1.69 jruoho * Power on or off the i:th part of the zone zone. 429 1.13 kochi */ 430 1.13 kochi static void 431 1.13 kochi acpitz_power_zone(struct acpitz_softc *sc, int i, int on) 432 1.13 kochi { 433 1.69 jruoho 434 1.13 kochi KASSERT(i >= 0 && i < ATZ_NLEVELS); 435 1.13 kochi 436 1.69 jruoho (void)acpi_foreach_package_object(sc->sc_zone.al[i].Pointer, 437 1.13 kochi acpitz_switch_cooler, &on); 438 1.13 kochi } 439 1.13 kochi 440 1.13 kochi 441 1.13 kochi /* 442 1.13 kochi * acpitz_power_off: 443 1.69 jruoho * 444 1.69 jruoho * Power off parts of the zone. 445 1.13 kochi */ 446 1.13 kochi static void 447 1.13 kochi acpitz_power_off(struct acpitz_softc *sc) 448 1.13 kochi { 449 1.13 kochi int i; 450 1.13 kochi 451 1.13 kochi for (i = 0 ; i < ATZ_NLEVELS; i++) { 452 1.69 jruoho 453 1.13 kochi if (sc->sc_zone.al[i].Pointer == NULL) 454 1.13 kochi continue; 455 1.69 jruoho 456 1.13 kochi acpitz_power_zone(sc, i, 0); 457 1.13 kochi } 458 1.69 jruoho 459 1.13 kochi sc->sc_active = ATZ_ACTIVE_NONE; 460 1.69 jruoho sc->sc_flags &= ~(ATZ_F_CRITICAL | ATZ_F_HOT | ATZ_F_PASSIVE); 461 1.13 kochi } 462 1.13 kochi 463 1.13 kochi static void 464 1.14 martin acpitz_get_zone(void *opaque, int verbose) 465 1.13 kochi { 466 1.33 xtraeme device_t dv = opaque; 467 1.33 xtraeme struct acpitz_softc *sc = device_private(dv); 468 1.69 jruoho int comma, i, valid_levels; 469 1.69 jruoho ACPI_OBJECT *obj; 470 1.13 kochi ACPI_STATUS rv; 471 1.69 jruoho char buf[5]; 472 1.13 kochi 473 1.69 jruoho if (sc->sc_first != true) { 474 1.13 kochi acpitz_power_off(sc); 475 1.13 kochi 476 1.13 kochi for (i = 0; i < ATZ_NLEVELS; i++) { 477 1.69 jruoho 478 1.13 kochi if (sc->sc_zone.al[i].Pointer != NULL) 479 1.47 mlelstv ACPI_FREE(sc->sc_zone.al[i].Pointer); 480 1.69 jruoho 481 1.13 kochi sc->sc_zone.al[i].Pointer = NULL; 482 1.13 kochi } 483 1.63 jruoho } 484 1.13 kochi 485 1.13 kochi valid_levels = 0; 486 1.13 kochi 487 1.13 kochi for (i = 0; i < ATZ_NLEVELS; i++) { 488 1.13 kochi 489 1.69 jruoho (void)snprintf(buf, sizeof(buf), "_AC%d", i); 490 1.69 jruoho 491 1.33 xtraeme if (acpitz_get_integer(dv, buf, &sc->sc_zone.ac[i])) 492 1.13 kochi continue; 493 1.13 kochi 494 1.69 jruoho (void)snprintf(buf, sizeof(buf), "_AL%d", i); 495 1.69 jruoho 496 1.69 jruoho rv = acpi_eval_struct(sc->sc_node->ad_handle, buf, 497 1.13 kochi &sc->sc_zone.al[i]); 498 1.69 jruoho 499 1.13 kochi if (ACPI_FAILURE(rv)) { 500 1.13 kochi sc->sc_zone.al[i].Pointer = NULL; 501 1.13 kochi continue; 502 1.13 kochi } 503 1.13 kochi 504 1.13 kochi obj = sc->sc_zone.al[i].Pointer; 505 1.69 jruoho 506 1.86 christos if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count == 0) { 507 1.69 jruoho sc->sc_zone.al[i].Pointer = NULL; 508 1.69 jruoho ACPI_FREE(obj); 509 1.69 jruoho continue; 510 1.13 kochi } 511 1.13 kochi 512 1.69 jruoho if (sc->sc_first != false) 513 1.72 plunky aprint_normal_dev(dv, "active cooling level %d: %sC\n", 514 1.72 plunky i, acpitz_celcius_string(sc->sc_zone.ac[i])); 515 1.13 kochi 516 1.13 kochi valid_levels++; 517 1.13 kochi } 518 1.13 kochi 519 1.69 jruoho /* 520 1.69 jruoho * A brief summary (ACPI 4.0, section 11.4): 521 1.69 jruoho * 522 1.69 jruoho * _TMP : current temperature (in tenths of degrees) 523 1.69 jruoho * _CRT : critical trip-point at which to shutdown 524 1.69 jruoho * _HOT : critical trip-point at which to go to S4 525 1.69 jruoho * _PSV : passive cooling policy threshold 526 1.69 jruoho * _TC1 : thermal constant for passive cooling 527 1.69 jruoho * _TC2 : thermal constant for passive cooling 528 1.69 jruoho */ 529 1.69 jruoho (void)acpitz_get_integer(dv, "_TMP", &sc->sc_zone.tmp); 530 1.69 jruoho (void)acpitz_get_integer(dv, "_CRT", &sc->sc_zone.crt); 531 1.69 jruoho (void)acpitz_get_integer(dv, "_HOT", &sc->sc_zone.hot); 532 1.69 jruoho (void)acpitz_get_integer(dv, "_PSV", &sc->sc_zone.psv); 533 1.69 jruoho (void)acpitz_get_integer(dv, "_TC1", &sc->sc_zone.tc1); 534 1.69 jruoho (void)acpitz_get_integer(dv, "_TC2", &sc->sc_zone.tc2); 535 1.13 kochi 536 1.69 jruoho /* 537 1.69 jruoho * If _RTV is not present or present and zero, 538 1.69 jruoho * values are absolute (see ACPI 4.0, 425). 539 1.69 jruoho */ 540 1.48 cegger acpitz_get_integer(dv, "_RTV", &sc->sc_zone.rtv); 541 1.69 jruoho 542 1.48 cegger if (sc->sc_zone.rtv == ATZ_TMP_INVALID) 543 1.48 cegger sc->sc_zone.rtv = 0; 544 1.48 cegger 545 1.13 kochi acpitz_sane_temp(&sc->sc_zone.tmp); 546 1.13 kochi acpitz_sane_temp(&sc->sc_zone.crt); 547 1.13 kochi acpitz_sane_temp(&sc->sc_zone.hot); 548 1.13 kochi acpitz_sane_temp(&sc->sc_zone.psv); 549 1.13 kochi 550 1.63 jruoho if (verbose != 0) { 551 1.69 jruoho comma = 0; 552 1.66 christos 553 1.76 jruoho aprint_verbose_dev(dv, "levels: "); 554 1.63 jruoho 555 1.66 christos if (sc->sc_zone.crt != ATZ_TMP_INVALID) { 556 1.63 jruoho aprint_verbose("critical %s C", 557 1.14 martin acpitz_celcius_string(sc->sc_zone.crt)); 558 1.66 christos comma = 1; 559 1.66 christos } 560 1.63 jruoho 561 1.66 christos if (sc->sc_zone.hot != ATZ_TMP_INVALID) { 562 1.66 christos aprint_verbose("%shot %s C", comma ? ", " : "", 563 1.14 martin acpitz_celcius_string(sc->sc_zone.hot)); 564 1.66 christos comma = 1; 565 1.66 christos } 566 1.63 jruoho 567 1.66 christos if (sc->sc_zone.psv != ATZ_TMP_INVALID) { 568 1.73 plunky aprint_verbose("%spassive %s C", comma ? ", " : "", 569 1.59 pgoyette acpitz_celcius_string(sc->sc_zone.psv)); 570 1.66 christos comma = 1; 571 1.66 christos } 572 1.29 jmcneill 573 1.66 christos if (valid_levels == 0) { 574 1.66 christos sc->sc_flags |= ATZ_F_PASSIVEONLY; 575 1.63 jruoho 576 1.69 jruoho if (sc->sc_first != false) 577 1.66 christos aprint_verbose("%spassive cooling", comma ? 578 1.66 christos ", " : ""); 579 1.66 christos } 580 1.63 jruoho 581 1.63 jruoho aprint_verbose("\n"); 582 1.66 christos } 583 1.13 kochi 584 1.13 kochi for (i = 0; i < ATZ_NLEVELS; i++) 585 1.13 kochi acpitz_sane_temp(&sc->sc_zone.ac[i]); 586 1.13 kochi 587 1.13 kochi acpitz_power_off(sc); 588 1.69 jruoho sc->sc_first = false; 589 1.13 kochi } 590 1.13 kochi 591 1.11 kochi static void 592 1.64 jruoho acpitz_notify_handler(ACPI_HANDLE hdl, uint32_t notify, void *opaque) 593 1.1 jmcneill { 594 1.69 jruoho ACPI_OSD_EXEC_CALLBACK func = NULL; 595 1.33 xtraeme device_t dv = opaque; 596 1.1 jmcneill 597 1.1 jmcneill switch (notify) { 598 1.69 jruoho 599 1.71 jruoho case ACPI_NOTIFY_TZ_ZONE: 600 1.13 kochi func = acpitz_get_status; 601 1.13 kochi break; 602 1.69 jruoho 603 1.71 jruoho case ACPI_NOTIFY_TZ_TRIP: 604 1.71 jruoho case ACPI_NOTIFY_TZ_DEVLIST: 605 1.14 martin func = acpitz_get_zone_quiet; 606 1.1 jmcneill break; 607 1.69 jruoho 608 1.1 jmcneill default: 609 1.69 jruoho aprint_debug_dev(dv, "unknown notify 0x%02X\n", notify); 610 1.13 kochi return; 611 1.1 jmcneill } 612 1.1 jmcneill 613 1.69 jruoho (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, dv); 614 1.1 jmcneill } 615 1.1 jmcneill 616 1.1 jmcneill static void 617 1.64 jruoho acpitz_sane_temp(uint32_t *tmp) 618 1.13 kochi { 619 1.91 andvar /* Sane temperatures are between 0 and 150 C. */ 620 1.13 kochi if (*tmp < ATZ_ZEROC || *tmp > ATZ_ZEROC + 1500) 621 1.13 kochi *tmp = ATZ_TMP_INVALID; 622 1.13 kochi } 623 1.13 kochi 624 1.13 kochi static int 625 1.64 jruoho acpitz_get_integer(device_t dv, const char *cm, uint32_t *val) 626 1.13 kochi { 627 1.33 xtraeme struct acpitz_softc *sc = device_private(dv); 628 1.69 jruoho ACPI_INTEGER tmp; 629 1.13 kochi ACPI_STATUS rv; 630 1.13 kochi 631 1.69 jruoho rv = acpi_eval_integer(sc->sc_node->ad_handle, cm, &tmp); 632 1.63 jruoho 633 1.13 kochi if (ACPI_FAILURE(rv)) { 634 1.13 kochi *val = ATZ_TMP_INVALID; 635 1.63 jruoho 636 1.69 jruoho ACPI_DEBUG_PRINT((ACPI_DB_DEBUG_OBJECT, 637 1.69 jruoho "%s: failed to evaluate %s: %s\n", 638 1.69 jruoho device_xname(dv), cm, AcpiFormatException(rv))); 639 1.63 jruoho 640 1.13 kochi return 1; 641 1.13 kochi } 642 1.13 kochi 643 1.13 kochi *val = tmp; 644 1.13 kochi 645 1.13 kochi return 0; 646 1.13 kochi } 647 1.13 kochi 648 1.49 cegger static int 649 1.49 cegger acpitz_get_fanspeed(device_t dv, 650 1.64 jruoho uint32_t *fanmin, uint32_t *fanmax, uint32_t *fancurrent) 651 1.49 cegger { 652 1.49 cegger struct acpitz_softc *sc = device_private(dv); 653 1.69 jruoho ACPI_INTEGER fmin, fmax, fcurr; 654 1.69 jruoho ACPI_HANDLE handle; 655 1.49 cegger ACPI_STATUS rv; 656 1.49 cegger int rc = 0; 657 1.49 cegger 658 1.69 jruoho handle = sc->sc_node->ad_handle; 659 1.69 jruoho 660 1.49 cegger rv = acpi_eval_integer(handle, "FMIN", &fmin); 661 1.69 jruoho 662 1.49 cegger if (ACPI_FAILURE(rv)) { 663 1.49 cegger fmin = ATZ_TMP_INVALID; 664 1.49 cegger rc = 1; 665 1.49 cegger } 666 1.69 jruoho 667 1.49 cegger rv = acpi_eval_integer(handle, "FMAX", &fmax); 668 1.69 jruoho 669 1.49 cegger if (ACPI_FAILURE(rv)) { 670 1.49 cegger fmax = ATZ_TMP_INVALID; 671 1.49 cegger rc = 1; 672 1.49 cegger } 673 1.49 cegger rv = acpi_eval_integer(handle, "FRSP", &fcurr); 674 1.69 jruoho 675 1.49 cegger if (ACPI_FAILURE(rv)) { 676 1.49 cegger fcurr = ATZ_TMP_INVALID; 677 1.49 cegger rc = 1; 678 1.49 cegger } 679 1.49 cegger 680 1.69 jruoho if (fanmin != NULL) 681 1.49 cegger *fanmin = fmin; 682 1.69 jruoho 683 1.69 jruoho if (fanmax != NULL) 684 1.49 cegger *fanmax = fmax; 685 1.69 jruoho 686 1.69 jruoho if (fancurrent != NULL) 687 1.49 cegger *fancurrent = fcurr; 688 1.69 jruoho 689 1.49 cegger return rc; 690 1.49 cegger } 691 1.49 cegger 692 1.49 cegger #ifdef notyet 693 1.49 cegger static ACPI_STATUS 694 1.64 jruoho acpitz_set_fanspeed(device_t dv, uint32_t fanspeed) 695 1.49 cegger { 696 1.49 cegger struct acpitz_softc *sc = device_private(dv); 697 1.69 jruoho ACPI_HANDLE handle; 698 1.49 cegger ACPI_STATUS rv; 699 1.69 jruoho 700 1.69 jruoho handle = sc->sc_node->ad_handle; 701 1.49 cegger 702 1.49 cegger rv = acpi_eval_set_integer(handle, "FSSP", fanspeed); 703 1.69 jruoho 704 1.49 cegger if (ACPI_FAILURE(rv)) 705 1.69 jruoho aprint_debug_dev(dv, "failed to set fan speed to %u RPM: %s\n", 706 1.69 jruoho fanspeed, AcpiFormatException(rv)); 707 1.69 jruoho 708 1.49 cegger return rv; 709 1.49 cegger } 710 1.49 cegger #endif 711 1.49 cegger 712 1.13 kochi static void 713 1.78 jmcneill acpitz_print_processor_list(device_t dv) 714 1.78 jmcneill { 715 1.78 jmcneill struct acpitz_softc *sc = device_private(dv); 716 1.78 jmcneill ACPI_HANDLE handle = sc->sc_node->ad_handle; 717 1.81 jruoho ACPI_OBJECT *obj, *pref; 718 1.78 jmcneill ACPI_HANDLE prhandle; 719 1.81 jruoho ACPI_BUFFER buf; 720 1.78 jmcneill ACPI_STATUS rv; 721 1.78 jmcneill struct cpu_info *ci; 722 1.78 jmcneill unsigned int i, cnt; 723 1.78 jmcneill 724 1.78 jmcneill rv = acpi_eval_struct(handle, "_PSL", &buf); 725 1.81 jruoho 726 1.78 jmcneill if (ACPI_FAILURE(rv) || buf.Pointer == NULL) 727 1.78 jmcneill return; 728 1.81 jruoho 729 1.78 jmcneill obj = buf.Pointer; 730 1.81 jruoho 731 1.78 jmcneill if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count == 0) 732 1.78 jmcneill goto done; 733 1.78 jmcneill 734 1.83 jmcneill sc->sc_psl_size = sizeof(ci) * (obj->Package.Count + 1); 735 1.83 jmcneill sc->sc_psl = kmem_zalloc(sc->sc_psl_size, KM_SLEEP); 736 1.81 jruoho for (cnt = i = 0; i < obj->Package.Count; i++) { 737 1.81 jruoho 738 1.78 jmcneill pref = &obj->Package.Elements[i]; 739 1.78 jmcneill rv = acpi_eval_reference_handle(pref, &prhandle); 740 1.81 jruoho 741 1.78 jmcneill if (ACPI_FAILURE(rv)) 742 1.78 jmcneill continue; 743 1.81 jruoho 744 1.81 jruoho ci = acpi_match_cpu_handle(prhandle); 745 1.81 jruoho 746 1.81 jruoho if (ci == NULL) 747 1.78 jmcneill continue; 748 1.81 jruoho 749 1.81 jruoho if (cnt == 0) 750 1.81 jruoho aprint_normal(":"); 751 1.81 jruoho 752 1.90 mrg aprint_normal(" %s", cpu_name(ci)); 753 1.83 jmcneill 754 1.89 chs sc->sc_psl[cnt] = ci; 755 1.81 jruoho ++cnt; 756 1.78 jmcneill } 757 1.78 jmcneill 758 1.78 jmcneill done: 759 1.78 jmcneill ACPI_FREE(buf.Pointer); 760 1.78 jmcneill } 761 1.78 jmcneill 762 1.78 jmcneill static void 763 1.1 jmcneill acpitz_tick(void *opaque) 764 1.1 jmcneill { 765 1.33 xtraeme device_t dv = opaque; 766 1.33 xtraeme struct acpitz_softc *sc = device_private(dv); 767 1.1 jmcneill 768 1.69 jruoho (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpitz_get_status, dv); 769 1.1 jmcneill 770 1.25 joerg callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10); 771 1.1 jmcneill } 772 1.1 jmcneill 773 1.1 jmcneill static void 774 1.33 xtraeme acpitz_init_envsys(device_t dv) 775 1.1 jmcneill { 776 1.87 pgoyette const int flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP | 777 1.87 pgoyette ENVSYS_FHAS_ENTROPY; 778 1.33 xtraeme struct acpitz_softc *sc = device_private(dv); 779 1.83 jmcneill unsigned int i; 780 1.33 xtraeme 781 1.27 xtraeme sc->sc_sme = sysmon_envsys_create(); 782 1.68 jruoho 783 1.42 pgoyette sc->sc_sme->sme_cookie = sc; 784 1.42 pgoyette sc->sc_sme->sme_name = device_xname(dv); 785 1.42 pgoyette sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; 786 1.68 jruoho sc->sc_sme->sme_get_limits = acpitz_get_limits; 787 1.49 cegger 788 1.68 jruoho sc->sc_temp_sensor.flags = flags; 789 1.49 cegger sc->sc_temp_sensor.units = ENVSYS_STEMP; 790 1.82 pgoyette sc->sc_temp_sensor.state = ENVSYS_SINVALID; 791 1.68 jruoho 792 1.83 jmcneill memset(sc->sc_temp_sensor.desc, 0, sizeof(sc->sc_temp_sensor.desc)); 793 1.83 jmcneill if (sc->sc_psl) { 794 1.83 jmcneill for (i = 0; sc->sc_psl[i] != NULL; i++) { 795 1.83 jmcneill if (i > 0) 796 1.83 jmcneill strlcat(sc->sc_temp_sensor.desc, "/", 797 1.83 jmcneill sizeof(sc->sc_temp_sensor.desc)); 798 1.83 jmcneill strlcat(sc->sc_temp_sensor.desc, 799 1.83 jmcneill device_xname(sc->sc_psl[i]->ci_dev), 800 1.83 jmcneill sizeof(sc->sc_temp_sensor.desc)); 801 1.83 jmcneill } 802 1.83 jmcneill strlcat(sc->sc_temp_sensor.desc, " ", 803 1.83 jmcneill sizeof(sc->sc_temp_sensor.desc)); 804 1.83 jmcneill } 805 1.83 jmcneill strlcat(sc->sc_temp_sensor.desc, "temperature", 806 1.70 jruoho sizeof(sc->sc_temp_sensor.desc)); 807 1.68 jruoho 808 1.49 cegger if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_sensor)) 809 1.42 pgoyette goto out; 810 1.42 pgoyette 811 1.69 jruoho if (sc->sc_have_fan != false) { 812 1.68 jruoho 813 1.68 jruoho sc->sc_fan_sensor.flags = flags; 814 1.49 cegger sc->sc_fan_sensor.units = ENVSYS_SFANRPM; 815 1.82 pgoyette sc->sc_fan_sensor.state = ENVSYS_SINVALID; 816 1.68 jruoho 817 1.68 jruoho (void)strlcpy(sc->sc_fan_sensor.desc, 818 1.49 cegger "FAN", sizeof(sc->sc_fan_sensor.desc)); 819 1.68 jruoho 820 1.68 jruoho /* Ignore error because fan sensor is optional. */ 821 1.68 jruoho (void)sysmon_envsys_sensor_attach(sc->sc_sme, 822 1.68 jruoho &sc->sc_fan_sensor); 823 1.49 cegger } 824 1.49 cegger 825 1.42 pgoyette if (sysmon_envsys_register(sc->sc_sme) == 0) 826 1.27 xtraeme return; 827 1.49 cegger 828 1.42 pgoyette out: 829 1.42 pgoyette aprint_error_dev(dv, "unable to register with sysmon\n"); 830 1.68 jruoho 831 1.42 pgoyette sysmon_envsys_destroy(sc->sc_sme); 832 1.68 jruoho sc->sc_sme = NULL; 833 1.42 pgoyette } 834 1.42 pgoyette 835 1.42 pgoyette static void 836 1.42 pgoyette acpitz_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 837 1.58 pgoyette sysmon_envsys_lim_t *limits, uint32_t *props) 838 1.42 pgoyette { 839 1.42 pgoyette struct acpitz_softc *sc = sme->sme_cookie; 840 1.1 jmcneill 841 1.49 cegger switch (edata->units) { 842 1.49 cegger case ENVSYS_STEMP: 843 1.58 pgoyette *props = 0; 844 1.49 cegger if (sc->sc_zone.hot != ATZ_TMP_INVALID) { 845 1.58 pgoyette *props |= PROP_CRITMAX; 846 1.49 cegger limits->sel_critmax = ATZ2UKELVIN(sc->sc_zone.hot); 847 1.49 cegger } else if (sc->sc_zone.crt != ATZ_TMP_INVALID) { 848 1.58 pgoyette *props |= PROP_CRITMAX; 849 1.49 cegger limits->sel_critmax = ATZ2UKELVIN(sc->sc_zone.crt); 850 1.49 cegger } 851 1.49 cegger break; 852 1.49 cegger 853 1.49 cegger case ENVSYS_SFANRPM: 854 1.58 pgoyette *props = 0; 855 1.49 cegger if (sc->sc_zone.fanmin != ATZ_TMP_INVALID) { 856 1.58 pgoyette *props |= PROP_WARNMIN; 857 1.49 cegger limits->sel_warnmin = sc->sc_zone.fanmin; 858 1.49 cegger } 859 1.49 cegger if (sc->sc_zone.fanmax != ATZ_TMP_INVALID) { 860 1.58 pgoyette *props |= PROP_WARNMAX; 861 1.49 cegger limits->sel_warnmax = sc->sc_zone.fanmax; 862 1.42 pgoyette } 863 1.49 cegger break; 864 1.49 cegger } 865 1.1 jmcneill } 866 1.75 jruoho 867 1.88 pgoyette MODULE(MODULE_CLASS_DRIVER, acpitz, "sysmon_envsys"); 868 1.75 jruoho 869 1.79 jruoho #ifdef _MODULE 870 1.75 jruoho #include "ioconf.c" 871 1.79 jruoho #endif 872 1.75 jruoho 873 1.75 jruoho static int 874 1.79 jruoho acpitz_modcmd(modcmd_t cmd, void *aux) 875 1.75 jruoho { 876 1.79 jruoho int rv = 0; 877 1.75 jruoho 878 1.75 jruoho switch (cmd) { 879 1.75 jruoho 880 1.75 jruoho case MODULE_CMD_INIT: 881 1.79 jruoho 882 1.79 jruoho #ifdef _MODULE 883 1.79 jruoho rv = config_init_component(cfdriver_ioconf_acpitz, 884 1.75 jruoho cfattach_ioconf_acpitz, cfdata_ioconf_acpitz); 885 1.79 jruoho #endif 886 1.79 jruoho break; 887 1.75 jruoho 888 1.75 jruoho case MODULE_CMD_FINI: 889 1.79 jruoho 890 1.79 jruoho #ifdef _MODULE 891 1.79 jruoho rv = config_fini_component(cfdriver_ioconf_acpitz, 892 1.75 jruoho cfattach_ioconf_acpitz, cfdata_ioconf_acpitz); 893 1.79 jruoho #endif 894 1.79 jruoho break; 895 1.75 jruoho 896 1.75 jruoho default: 897 1.79 jruoho rv = ENOTTY; 898 1.75 jruoho } 899 1.79 jruoho 900 1.79 jruoho return rv; 901 1.75 jruoho } 902