1 1.9 thorpej /* $NetBSD: acpi_pmtr.c,v 1.9 2021/01/29 15:49:55 thorpej Exp $ */ 2 1.1 jruoho 3 1.1 jruoho /*- 4 1.1 jruoho * Copyright (c) 2011 Jukka Ruohonen <jruohonen (at) iki.fi> 5 1.1 jruoho * All rights reserved. 6 1.1 jruoho * 7 1.1 jruoho * Redistribution and use in source and binary forms, with or without 8 1.1 jruoho * modification, are permitted provided that the following conditions 9 1.1 jruoho * are met: 10 1.1 jruoho * 11 1.1 jruoho * 1. Redistributions of source code must retain the above copyright 12 1.1 jruoho * notice, this list of conditions and the following disclaimer. 13 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 jruoho * notice, this list of conditions and the following disclaimer in the 15 1.1 jruoho * documentation and/or other materials provided with the distribution. 16 1.1 jruoho * 17 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 1.1 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 1.1 jruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 1.1 jruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 1.1 jruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 1.1 jruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 1.1 jruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 1.1 jruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 1.1 jruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 1.1 jruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 1.1 jruoho * SUCH DAMAGE. 28 1.1 jruoho */ 29 1.1 jruoho #include <sys/cdefs.h> 30 1.9 thorpej __KERNEL_RCSID(0, "$NetBSD: acpi_pmtr.c,v 1.9 2021/01/29 15:49:55 thorpej Exp $"); 31 1.1 jruoho 32 1.1 jruoho #include <sys/param.h> 33 1.1 jruoho #include <sys/module.h> 34 1.4 jruoho #include <sys/mutex.h> 35 1.1 jruoho 36 1.1 jruoho #include <dev/acpi/acpireg.h> 37 1.1 jruoho #include <dev/acpi/acpivar.h> 38 1.1 jruoho 39 1.1 jruoho #include <dev/sysmon/sysmonvar.h> 40 1.1 jruoho 41 1.1 jruoho #define _COMPONENT ACPI_RESOURCE_COMPONENT 42 1.1 jruoho ACPI_MODULE_NAME ("acpi_pmtr") 43 1.1 jruoho 44 1.1 jruoho #define ACPIPMTR_CAP_FLAGS 0 45 1.1 jruoho #define ACPIPMTR_CAP_UNIT 1 46 1.1 jruoho #define ACPIPMTR_CAP_TYPE 2 47 1.1 jruoho #define ACPIPMTR_CAP_ACCURACY 3 48 1.1 jruoho #define ACPIPMTR_CAP_SAMPLING 4 49 1.1 jruoho #define ACPIPMTR_CAP_IVAL_MIN 5 50 1.1 jruoho #define ACPIPMTR_CAP_IVAL_MAX 6 51 1.1 jruoho #define ACPIPMTR_CAP_HYSTERESIS 7 52 1.1 jruoho #define ACPIPMTR_CAP_HWLIMIT 8 53 1.1 jruoho #define ACPIPMTR_CAP_HWLIMIT_MIN 9 54 1.1 jruoho #define ACPIPMTR_CAP_HWLIMIT_MAX 10 55 1.1 jruoho #define ACPIPMTR_CAP_COUNT 11 56 1.1 jruoho /* ACPIPMTR_CAP_MODEL 11 */ 57 1.1 jruoho /* ACPIPMTR_CAP_SERIAL 12 */ 58 1.1 jruoho /* ACPIPMTR_CAP_OEM 13 */ 59 1.1 jruoho 60 1.1 jruoho #define ACPIPMTR_FLAGS_MEASURE __BIT(0) 61 1.1 jruoho #define ACPIPMTR_FLAGS_TRIP __BIT(1) 62 1.1 jruoho #define ACPIPMTR_FLAGS_HWLIMIT __BIT(2) 63 1.1 jruoho #define ACPIPMTR_FLAGS_NOTIFY __BIT(3) 64 1.1 jruoho #define ACPIPMTR_FLAGS_DISCHARGE __BIT(8) 65 1.1 jruoho 66 1.1 jruoho #define ACPIPMTR_POWER_INPUT 0x00 67 1.1 jruoho #define ACPIPMTR_POWER_OUTPUT 0x01 68 1.1 jruoho 69 1.1 jruoho #define ACPIPMTR_NOTIFY_CAP 0x80 70 1.1 jruoho #define ACPIPMTR_NOTIFY_TRIP 0x81 71 1.1 jruoho #define ACPIPMTR_NOTIFY_HWLIMIT1 0x82 72 1.1 jruoho #define ACPIPMTR_NOTIFY_HWLIMIT2 0x83 73 1.1 jruoho #define ACPIPMTR_NOTIFY_INTERVAL 0x84 74 1.1 jruoho 75 1.1 jruoho struct acpipmtr_softc { 76 1.1 jruoho device_t sc_dev; 77 1.1 jruoho struct acpi_devnode *sc_node; 78 1.1 jruoho struct sysmon_envsys *sc_sme; 79 1.1 jruoho envsys_data_t sc_sensor_i; 80 1.1 jruoho envsys_data_t sc_sensor_o; 81 1.1 jruoho uint32_t sc_cap[ACPIPMTR_CAP_COUNT]; 82 1.1 jruoho int32_t sc_interval; 83 1.4 jruoho kmutex_t sc_mtx; 84 1.1 jruoho }; 85 1.1 jruoho 86 1.9 thorpej static const struct device_compatible_entry compat_data[] = { 87 1.9 thorpej { .compat = "ACPI000D" }, 88 1.9 thorpej DEVICE_COMPAT_EOL 89 1.1 jruoho }; 90 1.1 jruoho 91 1.1 jruoho static int acpipmtr_match(device_t, cfdata_t, void *); 92 1.1 jruoho static void acpipmtr_attach(device_t, device_t, void *); 93 1.1 jruoho static int acpipmtr_detach(device_t, int); 94 1.1 jruoho static bool acpipmtr_cap_get(device_t, bool); 95 1.1 jruoho static bool acpipmtr_dev_print(device_t); 96 1.1 jruoho static bool acpipmtr_sensor_init(device_t); 97 1.1 jruoho static void acpipmtr_sensor_type(device_t); 98 1.1 jruoho static int32_t acpipmtr_sensor_get(device_t, const char *); 99 1.1 jruoho static int32_t acpipmtr_sensor_get_reading(device_t); 100 1.1 jruoho static int32_t acpipmtr_sensor_get_interval(device_t); 101 1.1 jruoho static void acpipmtr_sensor_refresh(struct sysmon_envsys*,envsys_data_t *); 102 1.1 jruoho static void acpipmtr_notify(ACPI_HANDLE, uint32_t, void *); 103 1.1 jruoho 104 1.1 jruoho CFATTACH_DECL_NEW(acpipmtr, sizeof(struct acpipmtr_softc), 105 1.1 jruoho acpipmtr_match, acpipmtr_attach, acpipmtr_detach, NULL); 106 1.1 jruoho 107 1.1 jruoho static int 108 1.1 jruoho acpipmtr_match(device_t parent, cfdata_t match, void *aux) 109 1.1 jruoho { 110 1.1 jruoho struct acpi_attach_args *aa = aux; 111 1.1 jruoho 112 1.9 thorpej return acpi_compatible_match(aa, compat_data); 113 1.1 jruoho } 114 1.1 jruoho 115 1.1 jruoho static void 116 1.1 jruoho acpipmtr_attach(device_t parent, device_t self, void *aux) 117 1.1 jruoho { 118 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 119 1.1 jruoho struct acpi_attach_args *aa = aux; 120 1.1 jruoho uint32_t acc; 121 1.1 jruoho 122 1.1 jruoho sc->sc_sme = NULL; 123 1.1 jruoho sc->sc_dev = self; 124 1.1 jruoho sc->sc_node = aa->aa_node; 125 1.1 jruoho 126 1.1 jruoho aprint_naive("\n"); 127 1.1 jruoho aprint_normal(": ACPI Power Meter\n"); 128 1.1 jruoho 129 1.1 jruoho (void)pmf_device_register(self, NULL, NULL); 130 1.4 jruoho mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE); 131 1.1 jruoho 132 1.1 jruoho if (acpipmtr_cap_get(self, true) != true) 133 1.1 jruoho return; 134 1.1 jruoho 135 1.1 jruoho if (acpipmtr_sensor_init(self) != true) 136 1.1 jruoho return; 137 1.1 jruoho 138 1.1 jruoho (void)acpipmtr_dev_print(self); 139 1.1 jruoho (void)acpi_register_notify(sc->sc_node, acpipmtr_notify); 140 1.1 jruoho 141 1.1 jruoho if ((acc = sc->sc_cap[ACPIPMTR_CAP_ACCURACY]) == 0) 142 1.1 jruoho acc = 100000; 143 1.1 jruoho 144 1.1 jruoho aprint_verbose_dev(self, 145 1.1 jruoho "measuring %s power at %u.%u %% accuracy, %u ms sampling\n", 146 1.1 jruoho (sc->sc_cap[ACPIPMTR_CAP_TYPE] != 0) ? "output" : "input", 147 1.1 jruoho acc / 1000, acc % 1000, sc->sc_cap[ACPIPMTR_CAP_SAMPLING]); 148 1.1 jruoho 149 1.1 jruoho aprint_debug_dev(self, "%s hw-limits, capabilities 0x%02x\n", 150 1.1 jruoho (sc->sc_cap[ACPIPMTR_CAP_HWLIMIT] != 0) ? "rw" : "ro", 151 1.1 jruoho sc->sc_cap[ACPIPMTR_CAP_FLAGS]); 152 1.1 jruoho } 153 1.1 jruoho 154 1.1 jruoho static int 155 1.1 jruoho acpipmtr_detach(device_t self, int flags) 156 1.1 jruoho { 157 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 158 1.1 jruoho 159 1.1 jruoho pmf_device_deregister(self); 160 1.1 jruoho acpi_deregister_notify(sc->sc_node); 161 1.1 jruoho 162 1.1 jruoho if (sc->sc_sme != NULL) 163 1.1 jruoho sysmon_envsys_unregister(sc->sc_sme); 164 1.1 jruoho 165 1.4 jruoho mutex_destroy(&sc->sc_mtx); 166 1.4 jruoho 167 1.1 jruoho return 0; 168 1.1 jruoho } 169 1.1 jruoho 170 1.1 jruoho static bool 171 1.1 jruoho acpipmtr_cap_get(device_t self, bool print) 172 1.1 jruoho { 173 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 174 1.1 jruoho ACPI_OBJECT *elm, *obj; 175 1.1 jruoho ACPI_BUFFER buf; 176 1.1 jruoho ACPI_STATUS rv; 177 1.1 jruoho uint32_t i; 178 1.1 jruoho 179 1.1 jruoho for (i = 0; i < __arraycount(sc->sc_cap); i++) 180 1.1 jruoho sc->sc_cap[i] = 0; 181 1.1 jruoho 182 1.1 jruoho rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PMC", &buf); 183 1.1 jruoho 184 1.1 jruoho if (ACPI_FAILURE(rv)) 185 1.1 jruoho goto out; 186 1.1 jruoho 187 1.1 jruoho obj = buf.Pointer; 188 1.1 jruoho 189 1.1 jruoho if (obj->Type != ACPI_TYPE_PACKAGE) { 190 1.1 jruoho rv = AE_TYPE; 191 1.1 jruoho goto out; 192 1.1 jruoho } 193 1.1 jruoho 194 1.1 jruoho elm = obj->Package.Elements; 195 1.1 jruoho 196 1.1 jruoho if (obj->Package.Count != 14) { 197 1.1 jruoho rv = AE_LIMIT; 198 1.1 jruoho goto out; 199 1.1 jruoho } 200 1.1 jruoho 201 1.1 jruoho CTASSERT(__arraycount(sc->sc_cap) == 11); 202 1.1 jruoho 203 1.1 jruoho for (i = 0; i < __arraycount(sc->sc_cap); i++) { 204 1.1 jruoho 205 1.1 jruoho if (elm[i].Type != ACPI_TYPE_INTEGER) { 206 1.1 jruoho rv = AE_TYPE; 207 1.1 jruoho goto out; 208 1.1 jruoho } 209 1.1 jruoho 210 1.1 jruoho if (elm[i].Integer.Value > UINT32_MAX) { 211 1.1 jruoho rv = AE_AML_NUMERIC_OVERFLOW; 212 1.1 jruoho goto out; 213 1.1 jruoho } 214 1.1 jruoho 215 1.1 jruoho sc->sc_cap[i] = elm[i].Integer.Value; 216 1.1 jruoho } 217 1.1 jruoho 218 1.1 jruoho if (print != true) 219 1.1 jruoho goto out; 220 1.1 jruoho 221 1.1 jruoho for (; i < 14; i++) { 222 1.1 jruoho 223 1.1 jruoho if (elm[i].Type != ACPI_TYPE_STRING) 224 1.1 jruoho goto out; 225 1.1 jruoho 226 1.1 jruoho if (elm[i].String.Pointer == NULL) 227 1.1 jruoho goto out; 228 1.1 jruoho 229 1.1 jruoho if (elm[i].String.Pointer[0] == '\0') 230 1.1 jruoho goto out; 231 1.1 jruoho } 232 1.1 jruoho 233 1.1 jruoho aprint_debug_dev(self, "%s, serial %s, " 234 1.1 jruoho "model %s\n", elm[13].String.Pointer, 235 1.1 jruoho elm[12].String.Pointer, elm[11].String.Pointer); 236 1.1 jruoho 237 1.1 jruoho out: 238 1.1 jruoho if (ACPI_FAILURE(rv)) 239 1.1 jruoho aprint_error_dev(self, "failed to evaluate _PMC: %s\n", 240 1.1 jruoho AcpiFormatException(rv)); 241 1.1 jruoho 242 1.1 jruoho if (buf.Pointer != NULL) 243 1.1 jruoho ACPI_FREE(buf.Pointer); 244 1.1 jruoho 245 1.1 jruoho return (rv != AE_OK) ? false : true; 246 1.1 jruoho } 247 1.1 jruoho 248 1.1 jruoho static bool 249 1.1 jruoho acpipmtr_dev_print(device_t self) 250 1.1 jruoho { 251 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 252 1.1 jruoho struct acpi_devnode *ad; 253 1.1 jruoho ACPI_OBJECT *elm, *obj; 254 1.1 jruoho ACPI_BUFFER buf; 255 1.1 jruoho ACPI_HANDLE hdl; 256 1.1 jruoho ACPI_STATUS rv; 257 1.1 jruoho uint32_t i, n; 258 1.1 jruoho 259 1.1 jruoho /* 260 1.1 jruoho * The _PMD method returns a package of devices whose total power 261 1.1 jruoho * drawn should roughly correspond with the readings from the meter. 262 1.1 jruoho */ 263 1.1 jruoho rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PMD", &buf); 264 1.1 jruoho 265 1.1 jruoho if (ACPI_FAILURE(rv)) 266 1.1 jruoho goto out; 267 1.1 jruoho 268 1.1 jruoho obj = buf.Pointer; 269 1.1 jruoho 270 1.1 jruoho if (obj->Type != ACPI_TYPE_PACKAGE) { 271 1.1 jruoho rv = AE_TYPE; 272 1.1 jruoho goto out; 273 1.1 jruoho } 274 1.1 jruoho 275 1.1 jruoho n = obj->Package.Count; 276 1.1 jruoho 277 1.1 jruoho if (n == 0) { 278 1.1 jruoho rv = AE_LIMIT; 279 1.1 jruoho goto out; 280 1.1 jruoho } 281 1.1 jruoho 282 1.1 jruoho aprint_debug_dev(self, "measured devices: "); 283 1.1 jruoho 284 1.1 jruoho for (i = 0; i < n; i++) { 285 1.1 jruoho 286 1.1 jruoho elm = &obj->Package.Elements[i]; 287 1.1 jruoho rv = acpi_eval_reference_handle(elm, &hdl); 288 1.1 jruoho 289 1.1 jruoho if (ACPI_FAILURE(rv)) 290 1.1 jruoho continue; 291 1.1 jruoho 292 1.6 jruoho ad = acpi_match_node(hdl); 293 1.1 jruoho 294 1.2 jruoho if (ad == NULL) 295 1.1 jruoho continue; 296 1.1 jruoho 297 1.1 jruoho aprint_debug("%s ", ad->ad_name); 298 1.1 jruoho } 299 1.1 jruoho 300 1.1 jruoho aprint_debug("\n"); 301 1.1 jruoho 302 1.1 jruoho out: 303 1.1 jruoho if (ACPI_FAILURE(rv)) 304 1.1 jruoho aprint_debug_dev(self, "failed to evaluate _PMD: %s\n", 305 1.1 jruoho AcpiFormatException(rv)); 306 1.1 jruoho 307 1.1 jruoho if (buf.Pointer != NULL) 308 1.1 jruoho ACPI_FREE(buf.Pointer); 309 1.1 jruoho 310 1.1 jruoho return (rv != AE_OK) ? false : true; 311 1.1 jruoho } 312 1.1 jruoho 313 1.1 jruoho static bool 314 1.1 jruoho acpipmtr_sensor_init(device_t self) 315 1.1 jruoho { 316 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 317 1.1 jruoho const size_t siz = sizeof(sc->sc_sensor_i.desc); 318 1.1 jruoho int32_t val; 319 1.1 jruoho 320 1.1 jruoho val = acpipmtr_sensor_get_reading(self); 321 1.1 jruoho sc->sc_interval = acpipmtr_sensor_get_interval(self); 322 1.1 jruoho 323 1.1 jruoho if (val < 0) { 324 1.1 jruoho aprint_error_dev(self, "failed to get sensor reading\n"); 325 1.1 jruoho return false; 326 1.1 jruoho } 327 1.1 jruoho 328 1.1 jruoho /* Always mW in ACPI 4.0. */ 329 1.1 jruoho if (sc->sc_cap[ACPIPMTR_CAP_UNIT] != 0) 330 1.1 jruoho aprint_error_dev(self, "invalid measurement unit\n"); 331 1.1 jruoho 332 1.1 jruoho sc->sc_sme = sysmon_envsys_create(); 333 1.1 jruoho 334 1.1 jruoho sc->sc_sensor_i.units = ENVSYS_SWATTS; 335 1.1 jruoho sc->sc_sensor_o.units = ENVSYS_SWATTS; 336 1.1 jruoho sc->sc_sensor_i.value_cur = val * 1000; 337 1.1 jruoho sc->sc_sensor_o.value_cur = val * 1000; 338 1.1 jruoho 339 1.1 jruoho acpipmtr_sensor_type(self); 340 1.1 jruoho 341 1.1 jruoho (void)strlcpy(sc->sc_sensor_i.desc, "input power", siz); 342 1.1 jruoho (void)strlcpy(sc->sc_sensor_o.desc, "output power", siz); 343 1.1 jruoho 344 1.1 jruoho sc->sc_sme->sme_cookie = self; 345 1.1 jruoho sc->sc_sme->sme_flags = SME_POLL_ONLY; 346 1.1 jruoho sc->sc_sme->sme_name = device_xname(self); 347 1.1 jruoho sc->sc_sme->sme_refresh = acpipmtr_sensor_refresh; 348 1.1 jruoho 349 1.1 jruoho if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_i) != 0) 350 1.1 jruoho goto fail; 351 1.1 jruoho 352 1.1 jruoho if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_o) != 0) 353 1.1 jruoho goto fail; 354 1.1 jruoho 355 1.1 jruoho if (sysmon_envsys_register(sc->sc_sme) != 0) 356 1.1 jruoho goto fail; 357 1.1 jruoho 358 1.1 jruoho return true; 359 1.1 jruoho 360 1.1 jruoho fail: 361 1.1 jruoho aprint_error_dev(self, "failed to initialize sysmon\n"); 362 1.1 jruoho 363 1.1 jruoho sysmon_envsys_destroy(sc->sc_sme); 364 1.1 jruoho sc->sc_sme = NULL; 365 1.1 jruoho 366 1.1 jruoho return false; 367 1.1 jruoho } 368 1.1 jruoho 369 1.1 jruoho static void 370 1.1 jruoho acpipmtr_sensor_type(device_t self) 371 1.1 jruoho { 372 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 373 1.1 jruoho 374 1.4 jruoho mutex_enter(&sc->sc_mtx); 375 1.4 jruoho 376 1.1 jruoho switch (sc->sc_cap[ACPIPMTR_CAP_TYPE]) { 377 1.1 jruoho 378 1.1 jruoho case ACPIPMTR_POWER_INPUT: 379 1.1 jruoho sc->sc_sensor_i.state = ENVSYS_SVALID; 380 1.1 jruoho sc->sc_sensor_o.state = ENVSYS_SINVALID; 381 1.1 jruoho break; 382 1.1 jruoho 383 1.1 jruoho case ACPIPMTR_POWER_OUTPUT: 384 1.1 jruoho sc->sc_sensor_i.state = ENVSYS_SINVALID; 385 1.1 jruoho sc->sc_sensor_o.state = ENVSYS_SVALID; 386 1.1 jruoho break; 387 1.1 jruoho 388 1.1 jruoho default: 389 1.1 jruoho sc->sc_sensor_i.state = ENVSYS_SINVALID; 390 1.1 jruoho sc->sc_sensor_o.state = ENVSYS_SINVALID; 391 1.1 jruoho break; 392 1.1 jruoho } 393 1.4 jruoho 394 1.4 jruoho mutex_exit(&sc->sc_mtx); 395 1.1 jruoho } 396 1.1 jruoho 397 1.1 jruoho static int32_t 398 1.1 jruoho acpipmtr_sensor_get(device_t self, const char *path) 399 1.1 jruoho { 400 1.1 jruoho struct acpipmtr_softc *sc = device_private(self); 401 1.1 jruoho ACPI_INTEGER val = 0; 402 1.1 jruoho ACPI_STATUS rv; 403 1.1 jruoho 404 1.1 jruoho rv = acpi_eval_integer(sc->sc_node->ad_handle, path, &val); 405 1.1 jruoho 406 1.1 jruoho if (ACPI_FAILURE(rv)) 407 1.1 jruoho goto fail; 408 1.1 jruoho 409 1.1 jruoho if (val == 0 || val > INT32_MAX) { 410 1.1 jruoho rv = AE_LIMIT; 411 1.1 jruoho goto fail; 412 1.1 jruoho } 413 1.1 jruoho 414 1.1 jruoho return val; 415 1.1 jruoho 416 1.1 jruoho fail: 417 1.1 jruoho aprint_debug_dev(self, "failed to evaluate " 418 1.1 jruoho "%s: %s\n", path, AcpiFormatException(rv)); 419 1.1 jruoho 420 1.1 jruoho return -1; 421 1.1 jruoho } 422 1.1 jruoho 423 1.1 jruoho static int32_t 424 1.1 jruoho acpipmtr_sensor_get_reading(device_t self) 425 1.1 jruoho { 426 1.1 jruoho return acpipmtr_sensor_get(self, "_PMM"); 427 1.1 jruoho } 428 1.1 jruoho 429 1.1 jruoho static int32_t 430 1.1 jruoho acpipmtr_sensor_get_interval(device_t self) 431 1.1 jruoho { 432 1.1 jruoho return acpipmtr_sensor_get(self, "_GAI"); 433 1.1 jruoho } 434 1.1 jruoho 435 1.1 jruoho static void 436 1.1 jruoho acpipmtr_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 437 1.1 jruoho { 438 1.1 jruoho device_t self = sme->sme_cookie; 439 1.1 jruoho struct acpipmtr_softc *sc; 440 1.1 jruoho int32_t val; 441 1.1 jruoho 442 1.1 jruoho sc = device_private(self); 443 1.1 jruoho 444 1.1 jruoho sc->sc_sensor_i.state = ENVSYS_SINVALID; 445 1.1 jruoho sc->sc_sensor_o.state = ENVSYS_SINVALID; 446 1.1 jruoho 447 1.1 jruoho val = acpipmtr_sensor_get_reading(self) * 1000; 448 1.1 jruoho 449 1.1 jruoho if (val < 0) 450 1.1 jruoho return; 451 1.1 jruoho 452 1.1 jruoho sc->sc_sensor_i.value_cur = val; 453 1.1 jruoho sc->sc_sensor_o.value_cur = val; 454 1.1 jruoho 455 1.1 jruoho acpipmtr_sensor_type(self); 456 1.1 jruoho } 457 1.1 jruoho 458 1.1 jruoho static void 459 1.1 jruoho acpipmtr_notify(ACPI_HANDLE hdl, uint32_t evt, void *aux) 460 1.1 jruoho { 461 1.1 jruoho struct acpipmtr_softc *sc; 462 1.1 jruoho device_t self = aux; 463 1.1 jruoho int32_t val; 464 1.1 jruoho 465 1.1 jruoho sc = device_private(self); 466 1.1 jruoho 467 1.1 jruoho switch (evt) { 468 1.1 jruoho 469 1.1 jruoho case ACPIPMTR_NOTIFY_CAP: 470 1.1 jruoho 471 1.4 jruoho mutex_enter(&sc->sc_mtx); 472 1.4 jruoho 473 1.4 jruoho if (acpipmtr_cap_get(self, false) != true) { 474 1.4 jruoho mutex_exit(&sc->sc_mtx); 475 1.1 jruoho break; 476 1.4 jruoho } 477 1.4 jruoho 478 1.4 jruoho mutex_exit(&sc->sc_mtx); 479 1.1 jruoho 480 1.1 jruoho acpipmtr_sensor_type(self); 481 1.1 jruoho break; 482 1.1 jruoho 483 1.1 jruoho case ACPIPMTR_NOTIFY_INTERVAL: 484 1.1 jruoho val = acpipmtr_sensor_get_interval(self); 485 1.1 jruoho 486 1.1 jruoho if (val < 0 || val == sc->sc_interval) 487 1.1 jruoho break; 488 1.1 jruoho 489 1.1 jruoho aprint_debug_dev(self, "averaging interval changed " 490 1.1 jruoho "from %u ms to %u ms\n", sc->sc_interval, val); 491 1.1 jruoho 492 1.1 jruoho sc->sc_interval = val; 493 1.1 jruoho break; 494 1.1 jruoho 495 1.1 jruoho case ACPIPMTR_NOTIFY_TRIP: /* AE_SUPPORT */ 496 1.1 jruoho case ACPIPMTR_NOTIFY_HWLIMIT1: /* AE_SUPPORT */ 497 1.1 jruoho case ACPIPMTR_NOTIFY_HWLIMIT2: /* AE_SUPPORT */ 498 1.1 jruoho break; 499 1.1 jruoho 500 1.1 jruoho default: 501 1.1 jruoho aprint_debug_dev(self, "unknown notify 0x%02x\n", evt); 502 1.1 jruoho } 503 1.1 jruoho } 504 1.1 jruoho 505 1.8 pgoyette MODULE(MODULE_CLASS_DRIVER, acpipmtr, "sysmon_envsys"); 506 1.1 jruoho 507 1.3 jruoho #ifdef _MODULE 508 1.1 jruoho #include "ioconf.c" 509 1.3 jruoho #endif 510 1.1 jruoho 511 1.1 jruoho static int 512 1.3 jruoho acpipmtr_modcmd(modcmd_t cmd, void *aux) 513 1.1 jruoho { 514 1.3 jruoho int rv = 0; 515 1.1 jruoho 516 1.1 jruoho switch (cmd) { 517 1.1 jruoho 518 1.1 jruoho case MODULE_CMD_INIT: 519 1.3 jruoho 520 1.3 jruoho #ifdef _MODULE 521 1.3 jruoho rv = config_init_component(cfdriver_ioconf_acpipmtr, 522 1.1 jruoho cfattach_ioconf_acpipmtr, cfdata_ioconf_acpipmtr); 523 1.3 jruoho #endif 524 1.3 jruoho break; 525 1.1 jruoho 526 1.1 jruoho case MODULE_CMD_FINI: 527 1.3 jruoho 528 1.3 jruoho #ifdef _MODULE 529 1.3 jruoho rv = config_fini_component(cfdriver_ioconf_acpipmtr, 530 1.1 jruoho cfattach_ioconf_acpipmtr, cfdata_ioconf_acpipmtr); 531 1.3 jruoho #endif 532 1.3 jruoho break; 533 1.1 jruoho 534 1.1 jruoho default: 535 1.3 jruoho rv = ENOTTY; 536 1.1 jruoho } 537 1.3 jruoho 538 1.3 jruoho return rv; 539 1.1 jruoho } 540