1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 /* 31 * Driver for Apple's System Management Console (SMC). 32 * SMC can be found on the MacBook, MacBook Pro and Mac Mini. 33 * 34 * Inspired by the Linux applesmc driver. 35 */ 36 37 #include "opt_asmc.h" 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/conf.h> 42 #include <sys/endian.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/module.h> 47 #include <sys/mutex.h> 48 #include <sys/sbuf.h> 49 #include <sys/sysctl.h> 50 #include <sys/systm.h> 51 #include <sys/taskqueue.h> 52 #include <sys/rman.h> 53 54 #include <machine/resource.h> 55 #include <netinet/in.h> 56 57 #include <contrib/dev/acpica/include/acpi.h> 58 59 #include <dev/acpica/acpivar.h> 60 #include <dev/asmc/asmcvar.h> 61 #include <dev/asmc/asmcmmio.h> 62 63 #include <dev/backlight/backlight.h> 64 #include "backlight_if.h" 65 66 /* 67 * Device interface. 68 */ 69 static int asmc_probe(device_t dev); 70 static int asmc_attach(device_t dev); 71 static int asmc_detach(device_t dev); 72 static int asmc_resume(device_t dev); 73 74 /* 75 * Backlight interface. 76 */ 77 static int asmc_backlight_update_status(device_t dev, 78 struct backlight_props *props); 79 static int asmc_backlight_get_status(device_t dev, 80 struct backlight_props *props); 81 static int asmc_backlight_get_info(device_t dev, struct backlight_info *info); 82 83 /* 84 * SMC functions. 85 */ 86 static int asmc_init(device_t dev); 87 static int asmc_command(device_t dev, uint8_t command); 88 static int asmc_wait(device_t dev, uint8_t val); 89 static int asmc_wait_ack(device_t dev, uint8_t val, int amount); 90 static int asmc_key_write(device_t dev, const char *key, uint8_t *buf, 91 uint8_t len); 92 static int asmc_key_read(device_t dev, const char *key, uint8_t *buf, 93 uint8_t); 94 static int asmc_fan_count(device_t dev); 95 static int asmc_fan_getvalue(device_t dev, const char *key, int fan); 96 static int asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed); 97 static int asmc_temp_getvalue(device_t dev, const char *key); 98 static int asmc_sms_read(device_t, const char *key, int16_t *val); 99 static void asmc_sms_calibrate(device_t dev); 100 static int asmc_sms_intrfast(void *arg); 101 static void asmc_sms_printintr(device_t dev, uint8_t); 102 static void asmc_sms_task(void *arg, int pending); 103 static void asmc_sms_init(device_t dev); 104 static void asmc_detect_capabilities(device_t dev); 105 #ifdef ASMC_DEBUG 106 void asmc_dumpall(device_t); 107 static int asmc_key_dump(device_t, int); 108 #endif 109 110 /* 111 * Sysctl handlers. 112 */ 113 static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS); 114 static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS); 115 static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS); 116 static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS); 117 static int asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS); 118 static int asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS); 119 static int asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS); 120 static int asmc_temp_sysctl(SYSCTL_HANDLER_ARGS); 121 static int asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS); 122 static int asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS); 123 static int asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS); 124 static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS); 125 static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS); 126 static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS); 127 static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS); 128 static int asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS); 129 130 static int asmc_key_getinfo(device_t, const char *, uint8_t *, char *); 131 132 /* System state / board identity sysctls */ 133 static int asmc_cause_sysctl(SYSCTL_HANDLER_ARGS); 134 static int asmc_msal_sysctl(SYSCTL_HANDLER_ARGS); 135 static int asmc_clkt_sysctl(SYSCTL_HANDLER_ARGS); 136 static int asmc_msps_sysctl(SYSCTL_HANDLER_ARGS); 137 static int asmc_rplt_sysctl(SYSCTL_HANDLER_ARGS); 138 static int asmc_rgen_sysctl(SYSCTL_HANDLER_ARGS); 139 140 #ifdef ASMC_DEBUG 141 /* Raw key access */ 142 static int asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS); 143 static int asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS); 144 static int asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS); 145 static int asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS); 146 #endif 147 148 /* Voltage/Current/Power/Light sensor support */ 149 static int asmc_sensor_read(device_t, const char *, int *); 150 static int asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS); 151 static int asmc_detect_sensors(device_t); 152 static int asmc_key_dump_by_index(device_t, int, char *, char *, uint8_t *); 153 static int asmc_key_search(device_t, const char *, unsigned int *); 154 static const char *asmc_temp_desc(const char *key); 155 156 /* 157 * SMC temperature key descriptions. 158 * These are universal across all Intel Apple hardware. 159 */ 160 static const struct { 161 const char *key; 162 const char *desc; 163 } asmc_temp_descs[] = { 164 /* Ambient / airflow */ 165 { "TA0P", "Ambient" }, 166 { "TA0S", "PCIe Slot 1 Ambient" }, 167 { "TA0p", "Ambient Air" }, 168 { "TA1P", "Ambient 2" }, 169 { "TA1S", "PCIe Slot 1 PCB" }, 170 { "TA1p", "Ambient Air 2" }, 171 { "TA2P", "Ambient 3" }, 172 { "TA2S", "PCIe Slot 2 Ambient" }, 173 { "TA3S", "PCIe Slot 2 PCB" }, 174 { "TA0V", "Ambient" }, 175 { "TALP", "Ambient Light Proximity" }, 176 { "TaLC", "Airflow Left" }, 177 { "TaRC", "Airflow Right" }, 178 { "Ta0P", "Airflow Proximity" }, 179 /* Battery / enclosure */ 180 { "TB0T", "Enclosure Bottom" }, 181 { "TB1T", "Battery 1" }, 182 { "TB2T", "Battery 2" }, 183 { "TB3T", "Battery 3" }, 184 { "TBXT", "Battery" }, 185 { "Tb0P", "BLC Proximity" }, 186 /* CPU */ 187 { "TC0C", "CPU Core 1" }, 188 { "TC0D", "CPU Die" }, 189 { "TC0E", "CPU 1" }, 190 { "TC0F", "CPU 2" }, 191 { "TC0G", "CPU Package GPU" }, 192 { "TC0H", "CPU Heatsink" }, 193 { "TC0h", "CPU Heatsink" }, 194 { "TC0J", "CPU" }, 195 { "TC0P", "CPU Proximity" }, 196 { "TC0c", "CPU Core 1 PECI" }, 197 { "TC0d", "CPU Die PECI" }, 198 { "TC0p", "CPU Proximity" }, 199 { "TC1C", "CPU Core 2" }, 200 { "TC1c", "CPU Core 2 PECI" }, 201 { "TC1P", "CPU Proximity 2" }, 202 { "TC2C", "CPU Core 3" }, 203 { "TC2P", "CPU Proximity 3" }, 204 { "TC2c", "CPU Core 3 PECI" }, 205 { "TC3C", "CPU Core 4" }, 206 { "TC3P", "CPU Proximity 4" }, 207 { "TC3c", "CPU Core 4 PECI" }, 208 { "TC4C", "CPU Core 5" }, 209 { "TC5C", "CPU Core 6" }, 210 { "TC6C", "CPU Core 7" }, 211 { "TC7C", "CPU Core 8" }, 212 { "TC8C", "CPU Core 9" }, 213 { "TCGC", "PECI GPU" }, 214 { "TCGc", "PECI GPU" }, 215 { "TCHP", "Charger Proximity" }, 216 { "TCSA", "PECI SA" }, 217 { "TCSC", "PECI SA" }, 218 { "TCSc", "PECI SA" }, 219 { "TCTD", "CPU DTS" }, 220 { "TCXC", "PECI CPU" }, 221 { "TCXc", "PECI CPU" }, 222 { "TCPG", "CPU Package GPU" }, 223 { "TCXR", "CPU PECI DTS" }, 224 /* CPU dual-socket (Mac Pro) */ 225 { "TCAG", "CPU A Package" }, 226 { "TCAH", "CPU A Heatsink" }, 227 { "TCBG", "CPU B Package" }, 228 { "TCBH", "CPU B Heatsink" }, 229 /* GPU */ 230 { "TG0C", "GPU Core" }, 231 { "TG0D", "GPU Diode" }, 232 { "TG0H", "GPU Heatsink" }, 233 { "TG0M", "GPU Memory" }, 234 { "TG0P", "GPU Proximity" }, 235 { "TG0T", "GPU Diode" }, 236 { "TG0V", "GPU" }, 237 { "TG0d", "GPU Die" }, 238 { "TG0h", "GPU Heatsink" }, 239 { "TG0p", "GPU Proximity" }, 240 { "TGTV", "GPU" }, 241 { "TG1D", "GPU 2 Diode" }, 242 { "TG1H", "GPU 2 Heatsink" }, 243 { "TG1P", "GPU 2 Proximity" }, 244 { "TG1d", "GPU 2 Die" }, 245 { "TGVP", "GPU Memory Proximity" }, 246 /* Storage */ 247 { "TH0A", "SSD A" }, 248 { "TH0B", "SSD B" }, 249 { "TH0C", "SSD C" }, 250 { "TH0F", "SSD" }, 251 { "TH0O", "HDD" }, 252 { "TH0P", "HDD Proximity" }, 253 { "TH0R", "SSD" }, 254 { "TH0V", "SSD" }, 255 { "TH0a", "SSD A" }, 256 { "TH0b", "SSD B" }, 257 { "TH0c", "SSD C" }, 258 { "TH1O", "HDD 2" }, 259 { "TH1P", "HDD Bay 2" }, 260 { "TH2P", "HDD Bay 3" }, 261 { "TH3P", "HDD Bay 4" }, 262 { "Th0H", "Heatpipe 1" }, 263 { "Th0N", "SSD" }, 264 { "Th1H", "Heatpipe 2" }, 265 { "Th2H", "Heatpipe 3" }, 266 /* Thunderbolt */ 267 { "THSP", "Thunderbolt Proximity" }, 268 { "TI0P", "Thunderbolt 1" }, 269 { "TI0p", "Thunderbolt 1" }, 270 { "TI1P", "Thunderbolt 2" }, 271 { "TI1p", "Thunderbolt 2" }, 272 { "TTLD", "Thunderbolt Left" }, 273 { "TTRD", "Thunderbolt Right" }, 274 { "Te0T", "Thunderbolt Diode" }, 275 { "Te0t", "Thunderbolt Diode" }, 276 /* LCD */ 277 { "TL0P", "LCD Proximity" }, 278 { "TL0V", "LCD" }, 279 { "TL0p", "LCD Proximity" }, 280 { "TL1P", "LCD Panel 1" }, 281 { "TL1V", "LCD 1" }, 282 { "TL1p", "LCD Panel 1" }, 283 { "TL1v", "LCD 1" }, 284 { "TL2V", "LCD 2" }, 285 { "TLAV", "LCD" }, 286 { "TLBV", "LCD" }, 287 { "TLCV", "LCD" }, 288 /* Memory */ 289 { "TM0P", "Memory Proximity" }, 290 { "TM0S", "Memory Slot 1" }, 291 { "TM0p", "Memory Proximity" }, 292 { "TM1P", "Memory Riser A 2" }, 293 { "TM1S", "Memory Slot 2" }, 294 { "Tm0P", "Memory Proximity" }, 295 { "Tm0p", "Memory Proximity" }, 296 { "Tm1P", "Memory Proximity 2" }, 297 { "TMBS", "Memory Bank" }, 298 { "TMCD", "Memory DIMM" }, 299 /* Northbridge / MCH */ 300 { "TN0C", "Northbridge Core" }, 301 { "TN0D", "Northbridge Diode" }, 302 { "TN0H", "MCH Heatsink" }, 303 { "TN0P", "Northbridge Proximity" }, 304 { "TN1D", "MCH Die 2" }, 305 { "TN1P", "Northbridge Proximity 2" }, 306 /* PCH */ 307 { "TP0P", "PCH Proximity" }, 308 { "TP0p", "PCH Proximity" }, 309 { "TPCD", "PCH Die" }, 310 { "TPCd", "PCH Die" }, 311 /* Optical drive */ 312 { "TO0P", "Optical Drive" }, 313 { "TO0p", "Optical Drive" }, 314 /* Power supply */ 315 { "Tp0C", "Power Supply" }, 316 { "Tp0P", "Power Supply Proximity" }, 317 { "Tp1C", "Power Supply 2" }, 318 { "Tp1P", "Power Supply Component" }, 319 { "Tp1p", "Power Supply Component" }, 320 { "Tp2P", "Power Supply 2" }, 321 { "Tp2h", "Power Supply 2" }, 322 { "Tp2H", "Power Supply 2" }, 323 { "Tp3P", "Power Supply 3 Inlet" }, 324 { "Tp3h", "Power Supply 3" }, 325 { "Tp3H", "Power Supply 3" }, 326 { "Tp4P", "Power Supply 4" }, 327 { "Tp5P", "Power Supply 5" }, 328 /* Palm rest / trackpad */ 329 { "Ts0P", "Palm Rest" }, 330 { "Ts0S", "Memory Proximity" }, 331 { "Ts1P", "Palm Rest 2" }, 332 { "Ts1S", "Palm Rest 2" }, 333 /* Wireless */ 334 { "TW0P", "Wireless Proximity" }, 335 { "TW0p", "Wireless Proximity" }, 336 { "TBLR", "Bluetooth" }, 337 /* Camera */ 338 { "TS2P", "Camera Proximity" }, 339 { "TS2V", "Camera" }, 340 { "TS2p", "Camera Proximity" }, 341 /* Expansion */ 342 { "TS0C", "Expansion Slots" }, 343 { "TS0P", "Expansion Proximity" }, 344 { "TS0V", "Expansion" }, 345 { "TS0p", "Expansion Proximity" }, 346 /* Air vent */ 347 { "TV0P", "Air Vent" }, 348 /* VRM */ 349 { "Tv0S", "VRM 1" }, 350 { "Tv1S", "VRM 2" }, 351 /* Misc */ 352 { "TTF0", "Fan" }, 353 { "TMLB", "Logic Board" }, 354 }; 355 356 static const char * 357 asmc_temp_desc(const char *key) 358 { 359 unsigned int i; 360 361 for (i = 0; i < nitems(asmc_temp_descs); i++) { 362 if (strcmp(asmc_temp_descs[i].key, key) == 0) 363 return (asmc_temp_descs[i].desc); 364 } 365 return ("Temperature"); 366 } 367 368 /* 369 * Driver methods. 370 */ 371 static device_method_t asmc_methods[] = { 372 DEVMETHOD(device_probe, asmc_probe), 373 DEVMETHOD(device_attach, asmc_attach), 374 DEVMETHOD(device_detach, asmc_detach), 375 DEVMETHOD(device_resume, asmc_resume), 376 377 /* Backlight interface */ 378 DEVMETHOD(backlight_update_status, asmc_backlight_update_status), 379 DEVMETHOD(backlight_get_status, asmc_backlight_get_status), 380 DEVMETHOD(backlight_get_info, asmc_backlight_get_info), 381 382 DEVMETHOD_END 383 }; 384 385 static driver_t asmc_driver = { 386 "asmc", 387 asmc_methods, 388 sizeof(struct asmc_softc) 389 }; 390 391 /* 392 * Debugging 393 */ 394 #define _COMPONENT ACPI_OEM 395 ACPI_MODULE_NAME("ASMC") 396 #ifdef ASMC_DEBUG 397 #define ASMC_DPRINTF(str, ...) device_printf(dev, str, ##__VA_ARGS__) 398 #else 399 #define ASMC_DPRINTF(str, ...) 400 #endif 401 402 /* NB: can't be const */ 403 static char *asmc_ids[] = { "APP0001", NULL }; 404 405 static unsigned int light_control = 0; 406 407 ACPI_PNP_INFO(asmc_ids); 408 DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL); 409 MODULE_DEPEND(asmc, acpi, 1, 1, 1); 410 MODULE_DEPEND(asmc, backlight, 1, 1, 1); 411 412 static int 413 asmc_probe(device_t dev) 414 { 415 char *product; 416 int rv; 417 418 if (resource_disabled("asmc", 0)) 419 return (ENXIO); 420 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids, NULL); 421 if (rv > 0) 422 return (rv); 423 product = kern_getenv("smbios.system.product"); 424 device_set_descf(dev, "Apple %s", product ? product : "SMC"); 425 freeenv(product); 426 return (rv); 427 } 428 429 /* 430 * Try MMIO first; the legacy PIO range can be claimable but dead. 431 * Fall back to PIO if MMIO probe fails or the resource is absent. 432 */ 433 static int 434 asmc_try_probe(device_t dev) 435 { 436 struct asmc_softc *sc = device_get_softc(dev); 437 438 sc->sc_rid_mem = 0; 439 sc->sc_iomem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 440 &sc->sc_rid_mem, RF_ACTIVE); 441 if (sc->sc_iomem != NULL) { 442 if (asmc_mmio_probe(dev) == 0) { 443 sc->sc_is_mmio = true; 444 if (bootverbose) 445 device_printf(dev, "using MMIO backend\n"); 446 return (0); 447 } 448 bus_release_resource(dev, SYS_RES_MEMORY, 449 sc->sc_rid_mem, sc->sc_iomem); 450 sc->sc_iomem = NULL; 451 } 452 453 sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 454 &sc->sc_rid_port, RF_ACTIVE); 455 if (sc->sc_ioport != NULL) 456 return (0); 457 458 device_printf(dev, "unable to allocate IO port or MMIO\n"); 459 return (ENOMEM); 460 } 461 462 static int 463 asmc_attach(device_t dev) 464 { 465 int i, j; 466 int ret; 467 char name[2]; 468 struct asmc_softc *sc = device_get_softc(dev); 469 struct sysctl_ctx_list *sysctlctx; 470 struct sysctl_oid *sysctlnode; 471 472 ret = asmc_try_probe(dev); 473 if (ret != 0) 474 goto err; 475 476 sysctlctx = device_get_sysctl_ctx(dev); 477 sysctlnode = device_get_sysctl_tree(dev); 478 479 /* Mutex may already be initialized by asmc_mmio_probe() */ 480 if (!mtx_initialized(&sc->sc_mtx)) 481 mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN); 482 483 /* Read SMC revision, key count, fan count */ 484 ret = asmc_init(dev); 485 if (ret != 0) { 486 device_printf(dev, "SMC not responding\n"); 487 goto err; 488 } 489 490 /* Probe SMC keys to detect capabilities */ 491 asmc_detect_capabilities(dev); 492 493 /* Auto-detect and register voltage/current/power/ambient/temp sensors */ 494 asmc_detect_sensors(dev); 495 496 /* 497 * dev.asmc.n.fan.* tree. 498 */ 499 sc->sc_fan_tree[0] = SYSCTL_ADD_NODE(sysctlctx, 500 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "fan", 501 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Root Tree"); 502 503 for (i = 1; i <= sc->sc_nfan; i++) { 504 j = i - 1; 505 name[0] = '0' + j; 506 name[1] = 0; 507 sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx, 508 SYSCTL_CHILDREN(sc->sc_fan_tree[0]), OID_AUTO, name, 509 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Subtree"); 510 511 SYSCTL_ADD_PROC(sysctlctx, 512 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 513 OID_AUTO, "id", 514 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 515 asmc_mb_sysctl_fanid, "I", "Fan ID"); 516 517 SYSCTL_ADD_PROC(sysctlctx, 518 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 519 OID_AUTO, "speed", 520 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 521 asmc_mb_sysctl_fanspeed, "I", "Fan speed in RPM"); 522 523 if (sc->sc_has_safespeed) { 524 SYSCTL_ADD_PROC(sysctlctx, 525 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 526 OID_AUTO, "safespeed", 527 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 528 asmc_mb_sysctl_fansafespeed, "I", 529 "Fan safe speed in RPM"); 530 } 531 532 SYSCTL_ADD_PROC(sysctlctx, 533 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 534 OID_AUTO, "minspeed", 535 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 536 asmc_mb_sysctl_fanminspeed, "I", 537 "Fan minimum speed in RPM"); 538 539 SYSCTL_ADD_PROC(sysctlctx, 540 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 541 OID_AUTO, "maxspeed", 542 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 543 asmc_mb_sysctl_fanmaxspeed, "I", 544 "Fan maximum speed in RPM"); 545 546 SYSCTL_ADD_PROC(sysctlctx, 547 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 548 OID_AUTO, "targetspeed", 549 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 550 asmc_mb_sysctl_fantargetspeed, "I", 551 "Fan target speed in RPM"); 552 553 SYSCTL_ADD_PROC(sysctlctx, 554 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 555 OID_AUTO, "manual", 556 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 557 asmc_mb_sysctl_fanmanual, "I", 558 "Fan manual mode (0=auto, 1=manual)"); 559 } 560 561 /* 562 * dev.asmc.n.temp tree. 563 */ 564 sc->sc_temp_tree = SYSCTL_ADD_NODE(sysctlctx, 565 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "temp", 566 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Temperature sensors"); 567 568 for (i = 0; i < sc->sc_temp_count; i++) { 569 SYSCTL_ADD_PROC(sysctlctx, 570 SYSCTL_CHILDREN(sc->sc_temp_tree), 571 OID_AUTO, sc->sc_temp_sensors[i], 572 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i, 573 asmc_temp_sysctl, "I", 574 asmc_temp_desc(sc->sc_temp_sensors[i])); 575 } 576 577 /* 578 * dev.asmc.n.light 579 */ 580 if (sc->sc_has_light) { 581 sc->sc_light_tree = SYSCTL_ADD_NODE(sysctlctx, 582 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "light", 583 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 584 "Keyboard backlight sensors"); 585 586 SYSCTL_ADD_PROC(sysctlctx, 587 SYSCTL_CHILDREN(sc->sc_light_tree), 588 OID_AUTO, "left", 589 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 590 dev, 0, 591 sc->sc_light_len == ASMC_LIGHT_LONGLEN ? 592 asmc_mbp_sysctl_light_left_10byte : 593 asmc_mbp_sysctl_light_left, 594 "I", "Keyboard backlight left sensor"); 595 596 if (sc->sc_light_len != ASMC_LIGHT_LONGLEN && 597 asmc_key_getinfo(dev, ASMC_KEY_LIGHTRIGHT, 598 NULL, NULL) == 0) { 599 SYSCTL_ADD_PROC(sysctlctx, 600 SYSCTL_CHILDREN(sc->sc_light_tree), 601 OID_AUTO, "right", 602 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 603 dev, 0, 604 asmc_mbp_sysctl_light_right, "I", 605 "Keyboard backlight right sensor"); 606 } 607 608 SYSCTL_ADD_PROC(sysctlctx, 609 SYSCTL_CHILDREN(sc->sc_light_tree), 610 OID_AUTO, "control", 611 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, 612 dev, 0, asmc_mbp_sysctl_light_control, "I", 613 "Keyboard backlight brightness control"); 614 615 sc->sc_kbd_bkl = backlight_register("asmc", dev); 616 if (sc->sc_kbd_bkl == NULL) { 617 device_printf(dev, "Can not register backlight\n"); 618 ret = ENXIO; 619 goto err; 620 } 621 } 622 623 #ifdef ASMC_DEBUG 624 /* 625 * Raw SMC key access for debugging. 626 */ 627 sc->sc_raw_tree = SYSCTL_ADD_NODE(sysctlctx, 628 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 629 "raw", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Raw SMC key access"); 630 631 SYSCTL_ADD_PROC(sysctlctx, 632 SYSCTL_CHILDREN(sc->sc_raw_tree), 633 OID_AUTO, "key", 634 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 635 dev, 0, asmc_raw_key_sysctl, "A", 636 "SMC key name (4 chars)"); 637 638 SYSCTL_ADD_PROC(sysctlctx, 639 SYSCTL_CHILDREN(sc->sc_raw_tree), 640 OID_AUTO, "value", 641 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 642 dev, 0, asmc_raw_value_sysctl, "A", 643 "SMC key value (hex string)"); 644 645 SYSCTL_ADD_PROC(sysctlctx, 646 SYSCTL_CHILDREN(sc->sc_raw_tree), 647 OID_AUTO, "len", 648 CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, 649 dev, 0, asmc_raw_len_sysctl, "CU", 650 "SMC key value length"); 651 652 SYSCTL_ADD_PROC(sysctlctx, 653 SYSCTL_CHILDREN(sc->sc_raw_tree), 654 OID_AUTO, "type", 655 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 656 dev, 0, asmc_raw_type_sysctl, "A", 657 "SMC key type (4 chars)"); 658 #endif 659 660 /* 661 * Battery charge limit (T2 Macs). 662 */ 663 if (sc->sc_is_t2 && 664 asmc_key_getinfo(dev, ASMC_KEY_BCLM, NULL, NULL) == 0) { 665 SYSCTL_ADD_PROC(sysctlctx, 666 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "battery_charge_limit", 667 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 668 dev, 0, asmc_bclm_sysctl, "I", 669 "Battery charge limit (0-100)"); 670 } 671 672 /* System state / board identity subtree. */ 673 { 674 struct sysctl_oid *sys_tree; 675 uint8_t msps_len; 676 677 sys_tree = SYSCTL_ADD_NODE(sysctlctx, 678 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 679 "system", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 680 "System state and board identity"); 681 if (sys_tree == NULL) { 682 device_printf(dev, 683 "failed to create system sysctl node\n"); 684 goto nosms; 685 } 686 687 if (asmc_key_getinfo(dev, ASMC_KEY_MSSD, NULL, NULL) == 0) 688 SYSCTL_ADD_PROC(sysctlctx, 689 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "shutdown_cause", 690 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 691 dev, 0, asmc_cause_sysctl, "A", 692 "Last shutdown cause (MSSD)"); 693 694 if (asmc_key_getinfo(dev, ASMC_KEY_MSSP, NULL, NULL) == 0) 695 SYSCTL_ADD_PROC(sysctlctx, 696 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "sleep_cause", 697 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 698 dev, 1, asmc_cause_sysctl, "A", 699 "Last sleep cause (MSSP)"); 700 701 if (asmc_key_getinfo(dev, ASMC_KEY_MSAL, NULL, NULL) == 0) 702 SYSCTL_ADD_PROC(sysctlctx, 703 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "thermal_status", 704 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 705 dev, 0, asmc_msal_sysctl, "A", 706 "Thermal subsystem status flags (MSAL)"); 707 708 if (asmc_key_getinfo(dev, ASMC_KEY_CLKT, NULL, NULL) == 0) 709 SYSCTL_ADD_PROC(sysctlctx, 710 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "time_of_day", 711 CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, 712 dev, 0, asmc_clkt_sysctl, "IU", 713 "Seconds since midnight per SMC clock (CLKT)"); 714 715 if (asmc_key_getinfo(dev, ASMC_KEY_MSPS, &msps_len, NULL) == 0 && 716 (msps_len == 1 || msps_len == 2)) 717 SYSCTL_ADD_PROC(sysctlctx, 718 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "power_state", 719 CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, 720 dev, 0, asmc_msps_sysctl, "IU", 721 "SMC power state index (MSPS)"); 722 723 if (asmc_key_getinfo(dev, ASMC_KEY_RPLT, NULL, NULL) == 0) 724 SYSCTL_ADD_PROC(sysctlctx, 725 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "board_id", 726 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 727 dev, 0, asmc_rplt_sysctl, "A", 728 "Apple internal board codename (RPlt)"); 729 730 if (asmc_key_getinfo(dev, ASMC_KEY_RGEN, NULL, NULL) == 0) 731 SYSCTL_ADD_PROC(sysctlctx, 732 SYSCTL_CHILDREN(sys_tree), OID_AUTO, "chip_gen", 733 CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, 734 dev, 0, asmc_rgen_sysctl, "IU", 735 "Apple security chip generation (RGEN; 3=T2)"); 736 } 737 738 if (!sc->sc_has_sms) 739 goto nosms; 740 741 /* 742 * Initialize SMS hardware. 743 */ 744 asmc_sms_init(dev); 745 746 /* 747 * dev.asmc.n.sms tree. 748 */ 749 sc->sc_sms_tree = SYSCTL_ADD_NODE(sysctlctx, 750 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "sms", 751 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Sudden Motion Sensor"); 752 753 SYSCTL_ADD_PROC(sysctlctx, 754 SYSCTL_CHILDREN(sc->sc_sms_tree), 755 OID_AUTO, "x", 756 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 757 dev, 0, asmc_mb_sysctl_sms_x, "I", 758 "Sudden Motion Sensor X value"); 759 760 SYSCTL_ADD_PROC(sysctlctx, 761 SYSCTL_CHILDREN(sc->sc_sms_tree), 762 OID_AUTO, "y", 763 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 764 dev, 0, asmc_mb_sysctl_sms_y, "I", 765 "Sudden Motion Sensor Y value"); 766 767 SYSCTL_ADD_PROC(sysctlctx, 768 SYSCTL_CHILDREN(sc->sc_sms_tree), 769 OID_AUTO, "z", 770 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 771 dev, 0, asmc_mb_sysctl_sms_z, "I", 772 "Sudden Motion Sensor Z value"); 773 774 /* 775 * Need a taskqueue to send devctl_notify() events 776 * when the SMS interrupt us. 777 * 778 * PI_REALTIME is used due to the sensitivity of the 779 * interrupt. An interrupt from the SMS means that the 780 * disk heads should be turned off as quickly as possible. 781 * 782 * We only need to do this for the non INTR_FILTER case. 783 */ 784 sc->sc_sms_tq = NULL; 785 TASK_INIT(&sc->sc_sms_task, 0, asmc_sms_task, sc); 786 sc->sc_sms_tq = taskqueue_create_fast("asmc_taskq", M_WAITOK, 787 taskqueue_thread_enqueue, &sc->sc_sms_tq); 788 taskqueue_start_threads(&sc->sc_sms_tq, 1, PI_REALTIME, "%s sms taskq", 789 device_get_nameunit(dev)); 790 /* 791 * Allocate an IRQ for the SMS. 792 */ 793 sc->sc_rid_irq = 0; 794 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, 795 RF_ACTIVE); 796 if (sc->sc_irq == NULL) { 797 device_printf(dev, "unable to allocate IRQ resource\n"); 798 ret = ENXIO; 799 goto err; 800 } 801 802 ret = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, 803 asmc_sms_intrfast, NULL, dev, &sc->sc_cookie); 804 if (ret) { 805 device_printf(dev, "unable to setup SMS IRQ\n"); 806 goto err; 807 } 808 809 nosms: 810 return (0); 811 812 err: 813 asmc_detach(dev); 814 815 return (ret); 816 } 817 818 static int 819 asmc_detach(device_t dev) 820 { 821 struct asmc_softc *sc = device_get_softc(dev); 822 823 if (sc->sc_kbd_bkl != NULL) 824 backlight_destroy(sc->sc_kbd_bkl); 825 826 /* Free temperature sensor key arrays */ 827 for (int i = 0; i < sc->sc_temp_count; i++) 828 free(sc->sc_temp_sensors[i], M_DEVBUF); 829 830 /* Free sensor key arrays */ 831 for (int i = 0; i < sc->sc_voltage_count; i++) 832 free(sc->sc_voltage_sensors[i], M_DEVBUF); 833 for (int i = 0; i < sc->sc_current_count; i++) 834 free(sc->sc_current_sensors[i], M_DEVBUF); 835 for (int i = 0; i < sc->sc_power_count; i++) 836 free(sc->sc_power_sensors[i], M_DEVBUF); 837 for (int i = 0; i < sc->sc_light_count; i++) 838 free(sc->sc_light_sensors[i], M_DEVBUF); 839 840 if (sc->sc_sms_tq) { 841 taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task); 842 taskqueue_free(sc->sc_sms_tq); 843 sc->sc_sms_tq = NULL; 844 } 845 if (sc->sc_cookie) { 846 bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie); 847 sc->sc_cookie = NULL; 848 } 849 if (sc->sc_irq) { 850 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, 851 sc->sc_irq); 852 sc->sc_irq = NULL; 853 } 854 if (sc->sc_ioport) { 855 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, 856 sc->sc_ioport); 857 sc->sc_ioport = NULL; 858 } 859 asmc_mmio_detach(dev, sc); 860 if (mtx_initialized(&sc->sc_mtx)) { 861 mtx_destroy(&sc->sc_mtx); 862 } 863 864 return (0); 865 } 866 867 static int 868 asmc_resume(device_t dev) 869 { 870 uint8_t buf[2]; 871 872 buf[0] = light_control; 873 buf[1] = 0x00; 874 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 875 876 return (0); 877 } 878 879 #ifdef ASMC_DEBUG 880 void 881 asmc_dumpall(device_t dev) 882 { 883 struct asmc_softc *sc = device_get_softc(dev); 884 int i; 885 886 if (sc->sc_nkeys == 0) { 887 device_printf(dev, "asmc_dumpall: key count not available\n"); 888 return; 889 } 890 891 device_printf(dev, "asmc_dumpall: dumping %d keys\n", sc->sc_nkeys); 892 for (i = 0; i < sc->sc_nkeys; i++) 893 asmc_key_dump(dev, i); 894 } 895 #endif 896 897 /* 898 * Initialize SMC: read revision, key count, fan count. 899 * SMS initialization is handled separately in asmc_sms_init(). 900 */ 901 static int 902 asmc_init(device_t dev) 903 { 904 struct asmc_softc *sc = device_get_softc(dev); 905 struct sysctl_ctx_list *sysctlctx; 906 uint8_t buf[6]; 907 int error; 908 909 sysctlctx = device_get_sysctl_ctx(dev); 910 911 error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6); 912 if (error != 0) { 913 /* 914 * Could not read REV key; T2 Macs may not have it. 915 * Use #KEY as a liveness check instead. 916 */ 917 if (sc->sc_is_t2) { 918 error = asmc_key_read(dev, ASMC_NKEYS, buf, 4); 919 if (error != 0) 920 goto out; 921 device_printf(dev, "T2 SMC: %d keys\n", 922 be32dec(buf)); 923 } else { 924 goto out; 925 } 926 } else { 927 device_printf(dev, "SMC revision: %x.%x%x%x\n", 928 buf[0], buf[1], buf[2], 929 ntohs(*(uint16_t *)buf + 4)); 930 } 931 932 /* Auto power-on after AC power loss (AUPO). */ 933 if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) { 934 SYSCTL_ADD_PROC(sysctlctx, 935 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 936 OID_AUTO, "auto_poweron", 937 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 938 dev, 0, asmc_aupo_sysctl, "I", 939 "Auto power-on after AC power loss (0=off, 1=on)"); 940 } 941 942 sc->sc_nfan = asmc_fan_count(dev); 943 if (sc->sc_nfan > ASMC_MAXFANS) { 944 device_printf(dev, 945 "more than %d fans were detected. Please report this.\n", 946 ASMC_MAXFANS); 947 sc->sc_nfan = ASMC_MAXFANS; 948 } 949 950 /* 951 * Read and cache the number of SMC keys (32 bit buffer) 952 */ 953 if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) { 954 sc->sc_nkeys = be32dec(buf); 955 if (bootverbose) 956 device_printf(dev, "number of keys: %d\n", 957 sc->sc_nkeys); 958 } else { 959 sc->sc_nkeys = 0; 960 } 961 962 out: 963 #ifdef ASMC_DEBUG 964 asmc_dumpall(dev); 965 #endif 966 return (error); 967 } 968 969 /* 970 * Initialize the Sudden Motion Sensor hardware. 971 * Called from asmc_attach() after capabilities are detected. 972 */ 973 static void 974 asmc_sms_init(device_t dev) 975 { 976 struct asmc_softc *sc = device_get_softc(dev); 977 uint8_t buf[2]; 978 int i; 979 980 /* 981 * We are ready to receive interrupts from the SMS. 982 */ 983 buf[0] = 0x01; 984 ASMC_DPRINTF(("intok key\n")); 985 asmc_key_write(dev, ASMC_KEY_INTOK, buf, 1); 986 DELAY(50); 987 988 /* 989 * Initiate the polling intervals. 990 */ 991 buf[0] = 20; /* msecs */ 992 ASMC_DPRINTF(("low int key\n")); 993 asmc_key_write(dev, ASMC_KEY_SMS_LOW_INT, buf, 1); 994 DELAY(200); 995 996 buf[0] = 20; /* msecs */ 997 ASMC_DPRINTF(("high int key\n")); 998 asmc_key_write(dev, ASMC_KEY_SMS_HIGH_INT, buf, 1); 999 DELAY(200); 1000 1001 buf[0] = 0x00; 1002 buf[1] = 0x60; 1003 ASMC_DPRINTF(("sms low key\n")); 1004 asmc_key_write(dev, ASMC_KEY_SMS_LOW, buf, 2); 1005 DELAY(200); 1006 1007 buf[0] = 0x01; 1008 buf[1] = 0xc0; 1009 ASMC_DPRINTF(("sms high key\n")); 1010 asmc_key_write(dev, ASMC_KEY_SMS_HIGH, buf, 2); 1011 DELAY(200); 1012 1013 /* 1014 * I'm not sure what this key does, but it seems to be 1015 * required. 1016 */ 1017 buf[0] = 0x01; 1018 ASMC_DPRINTF(("sms flag key\n")); 1019 asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1); 1020 DELAY(100); 1021 1022 sc->sc_sms_intr_works = 0; 1023 1024 /* 1025 * Retry SMS initialization 1000 times 1026 * (takes approx. 2 seconds in worst case) 1027 */ 1028 for (i = 0; i < 1000; i++) { 1029 if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 && 1030 (buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) { 1031 sc->sc_sms_intr_works = 1; 1032 goto done; 1033 } 1034 buf[0] = ASMC_SMS_INIT1; 1035 buf[1] = ASMC_SMS_INIT2; 1036 ASMC_DPRINTF(("sms key\n")); 1037 asmc_key_write(dev, ASMC_KEY_SMS, buf, 2); 1038 DELAY(50); 1039 } 1040 device_printf(dev, "WARNING: Sudden Motion Sensor not initialized!\n"); 1041 1042 done: 1043 asmc_sms_calibrate(dev); 1044 } 1045 1046 /* 1047 * Probe SMC keys to detect hardware capabilities. 1048 */ 1049 static void 1050 asmc_detect_capabilities(device_t dev) 1051 { 1052 struct asmc_softc *sc = device_get_softc(dev); 1053 uint8_t len; 1054 char type[ASMC_TYPELEN + 1]; 1055 1056 /* SMS: require all keys used by asmc_sms_init() */ 1057 sc->sc_has_sms = 1058 (asmc_key_getinfo(dev, ASMC_KEY_SMS, 1059 &len, type) == 0 && 1060 asmc_key_getinfo(dev, ASMC_KEY_SMS_X, 1061 &len, type) == 0 && 1062 asmc_key_getinfo(dev, ASMC_KEY_SMS_Y, 1063 &len, type) == 0 && 1064 asmc_key_getinfo(dev, ASMC_KEY_SMS_Z, 1065 &len, type) == 0 && 1066 asmc_key_getinfo(dev, ASMC_KEY_SMS_LOW, 1067 &len, type) == 0 && 1068 asmc_key_getinfo(dev, ASMC_KEY_SMS_HIGH, 1069 &len, type) == 0 && 1070 asmc_key_getinfo(dev, ASMC_KEY_SMS_LOW_INT, 1071 &len, type) == 0 && 1072 asmc_key_getinfo(dev, ASMC_KEY_SMS_HIGH_INT, 1073 &len, type) == 0 && 1074 asmc_key_getinfo(dev, ASMC_KEY_SMS_FLAG, 1075 &len, type) == 0 && 1076 asmc_key_getinfo(dev, ASMC_KEY_INTOK, 1077 &len, type) == 0); 1078 1079 /* Light sensor: require ALV0 (len 6 or 10) and LKSB */ 1080 if (asmc_key_getinfo(dev, ASMC_KEY_LIGHTLEFT, 1081 &len, type) == 0 && 1082 (len == ASMC_LIGHT_SHORTLEN || len == ASMC_LIGHT_LONGLEN) && 1083 asmc_key_getinfo(dev, ASMC_KEY_LIGHTVALUE, 1084 NULL, NULL) == 0) { 1085 sc->sc_has_light = 1; 1086 sc->sc_light_len = len; 1087 } else { 1088 sc->sc_has_light = 0; 1089 sc->sc_light_len = 0; 1090 } 1091 1092 /* Fan safe speed */ 1093 sc->sc_has_safespeed = 1094 (asmc_key_getinfo(dev, ASMC_KEY_FANSAFESPEED0, 1095 &len, type) == 0); 1096 1097 /* Ambient light interrupt source */ 1098 sc->sc_has_alsl = 1099 (asmc_key_getinfo(dev, ASMC_KEY_LIGHTSRC, 1100 &len, type) == 0); 1101 1102 if (bootverbose) 1103 device_printf(dev, 1104 "capabilities: sms=%d light=%d (len=%d) safespeed=%d alsl=%d\n", 1105 sc->sc_has_sms, sc->sc_has_light, sc->sc_light_len, 1106 sc->sc_has_safespeed, sc->sc_has_alsl); 1107 } 1108 1109 /* 1110 * We need to make sure that the SMC acks the byte sent. 1111 * Just wait up to (amount * 10) ms. 1112 */ 1113 static int 1114 asmc_wait_ack(device_t dev, uint8_t val, int amount) 1115 { 1116 struct asmc_softc *sc = device_get_softc(dev); 1117 u_int i; 1118 1119 val = val & ASMC_STATUS_MASK; 1120 1121 for (i = 0; i < amount; i++) { 1122 if ((ASMC_CMDPORT_READ(sc) & ASMC_STATUS_MASK) == val) 1123 return (0); 1124 DELAY(10); 1125 } 1126 1127 return (1); 1128 } 1129 1130 /* 1131 * We need to make sure that the SMC acks the byte sent. 1132 * Just wait up to 100 ms. 1133 */ 1134 static int 1135 asmc_wait(device_t dev, uint8_t val) 1136 { 1137 #ifdef ASMC_DEBUG 1138 struct asmc_softc *sc; 1139 #endif 1140 1141 if (asmc_wait_ack(dev, val, 1000) == 0) 1142 return (0); 1143 1144 #ifdef ASMC_DEBUG 1145 sc = device_get_softc(dev); 1146 1147 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, 1148 val & ASMC_STATUS_MASK, ASMC_CMDPORT_READ(sc)); 1149 #endif 1150 return (1); 1151 } 1152 1153 /* 1154 * Send the given command, retrying up to 10 times if 1155 * the acknowledgement fails. 1156 */ 1157 static int 1158 asmc_command(device_t dev, uint8_t command) 1159 { 1160 int i; 1161 struct asmc_softc *sc = device_get_softc(dev); 1162 1163 for (i = 0; i < 10; i++) { 1164 ASMC_CMDPORT_WRITE(sc, command); 1165 if (asmc_wait_ack(dev, 0x0c, 100) == 0) { 1166 return (0); 1167 } 1168 } 1169 1170 #ifdef ASMC_DEBUG 1171 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, command, 1172 ASMC_CMDPORT_READ(sc)); 1173 #endif 1174 return (1); 1175 } 1176 1177 static int 1178 asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1179 { 1180 struct asmc_softc *sc = device_get_softc(dev); 1181 int i, error = 1, try = 0; 1182 1183 if (sc->sc_is_mmio) 1184 return (asmc_mmio_key_read(dev, key, buf, len)); 1185 1186 mtx_lock_spin(&sc->sc_mtx); 1187 1188 begin: 1189 if (asmc_command(dev, ASMC_CMDREAD)) 1190 goto out; 1191 1192 for (i = 0; i < 4; i++) { 1193 ASMC_DATAPORT_WRITE(sc, key[i]); 1194 if (asmc_wait(dev, 0x04)) 1195 goto out; 1196 } 1197 1198 ASMC_DATAPORT_WRITE(sc, len); 1199 1200 for (i = 0; i < len; i++) { 1201 if (asmc_wait(dev, 0x05)) 1202 goto out; 1203 buf[i] = ASMC_DATAPORT_READ(sc); 1204 } 1205 1206 error = 0; 1207 out: 1208 if (error) { 1209 if (++try < 10) 1210 goto begin; 1211 device_printf(dev, "%s for key %s failed %d times, giving up\n", 1212 __func__, key, try); 1213 } 1214 1215 mtx_unlock_spin(&sc->sc_mtx); 1216 1217 return (error); 1218 } 1219 1220 #ifdef ASMC_DEBUG 1221 static int 1222 asmc_key_dump(device_t dev, int number) 1223 { 1224 struct asmc_softc *sc = device_get_softc(dev); 1225 char key[ASMC_KEYLEN + 1] = { 0 }; 1226 char type[ASMC_KEYINFO_RESPLEN + 1] = { 0 }; 1227 uint8_t index[4]; 1228 uint8_t v[ASMC_MAXVAL]; 1229 uint8_t maxlen; 1230 int i, error = 1, try = 0; 1231 1232 if (sc->sc_is_mmio) { 1233 uint8_t len = 0; 1234 char mmio_type[ASMC_TYPELEN + 1] = { 0 }; 1235 if (asmc_key_dump_by_index(dev, number, key, mmio_type, &len)) 1236 return (1); 1237 memset(v, 0, sizeof(v)); 1238 len = MIN(len, sizeof(v)); 1239 asmc_key_read(dev, key, v, len); 1240 struct sbuf sb; 1241 char buf[128]; 1242 sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); 1243 sbuf_printf(&sb, "key %d: %s, type %s (len %d), data", 1244 number, key, mmio_type, len); 1245 for (i = 0; i < len; i++) 1246 sbuf_printf(&sb, " %02x", v[i]); 1247 sbuf_finish(&sb); 1248 device_printf(dev, "%s\n", sbuf_data(&sb)); 1249 sbuf_delete(&sb); 1250 return (0); 1251 } 1252 1253 mtx_lock_spin(&sc->sc_mtx); 1254 1255 index[0] = (number >> 24) & 0xff; 1256 index[1] = (number >> 16) & 0xff; 1257 index[2] = (number >> 8) & 0xff; 1258 index[3] = number & 0xff; 1259 1260 begin: 1261 if (asmc_command(dev, ASMC_CMDGETBYINDEX)) 1262 goto out; 1263 1264 for (i = 0; i < ASMC_KEYLEN; i++) { 1265 ASMC_DATAPORT_WRITE(sc, index[i]); 1266 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1267 goto out; 1268 } 1269 1270 ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN); 1271 1272 for (i = 0; i < ASMC_KEYLEN; i++) { 1273 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1274 goto out; 1275 key[i] = ASMC_DATAPORT_READ(sc); 1276 } 1277 1278 /* Get key info (length + type). */ 1279 if (asmc_command(dev, ASMC_CMDGETINFO)) 1280 goto out; 1281 1282 for (i = 0; i < ASMC_KEYLEN; i++) { 1283 ASMC_DATAPORT_WRITE(sc, key[i]); 1284 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1285 goto out; 1286 } 1287 1288 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1289 1290 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1291 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1292 goto out; 1293 type[i] = ASMC_DATAPORT_READ(sc); 1294 } 1295 1296 error = 0; 1297 out: 1298 if (error) { 1299 if (++try < ASMC_MAXRETRIES) 1300 goto begin; 1301 device_printf(dev, 1302 "%s for key %d failed %d times, giving up\n", 1303 __func__, number, try); 1304 } 1305 mtx_unlock_spin(&sc->sc_mtx); 1306 1307 if (error) 1308 return (error); 1309 1310 maxlen = type[0]; 1311 type[0] = ' '; 1312 type[5] = '\0'; 1313 maxlen = MIN(maxlen, sizeof(v)); 1314 1315 memset(v, 0, sizeof(v)); 1316 error = asmc_key_read(dev, key, v, maxlen); 1317 if (error) 1318 return (error); 1319 1320 struct sbuf sb; 1321 char buf[128]; 1322 sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); 1323 sbuf_printf(&sb, "key %d: %s, type%s (len %d), data", 1324 number, key, type, maxlen); 1325 for (i = 0; i < maxlen; i++) 1326 sbuf_printf(&sb, " %02x", v[i]); 1327 sbuf_finish(&sb); 1328 device_printf(dev, "%s\n", sbuf_data(&sb)); 1329 sbuf_delete(&sb); 1330 1331 return (0); 1332 } 1333 #endif /* ASMC_DEBUG */ 1334 1335 /* 1336 * Get key info (length and type) from SMC using command 0x13. 1337 * If len is non-NULL, stores the key's value length. 1338 * If type is non-NULL, stores the 4-char type string (must be at least 5 bytes). 1339 */ 1340 static int 1341 asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type) 1342 { 1343 struct asmc_softc *sc = device_get_softc(dev); 1344 uint8_t info[ASMC_KEYINFO_RESPLEN]; 1345 int i, error = -1, try = 0; 1346 1347 if (sc->sc_is_mmio) 1348 return (asmc_mmio_key_getinfo(dev, key, len, type)); 1349 1350 mtx_lock_spin(&sc->sc_mtx); 1351 1352 begin: 1353 if (asmc_command(dev, ASMC_CMDGETINFO)) 1354 goto out; 1355 1356 for (i = 0; i < ASMC_KEYLEN; i++) { 1357 ASMC_DATAPORT_WRITE(sc, key[i]); 1358 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1359 goto out; 1360 } 1361 1362 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1363 1364 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1365 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1366 goto out; 1367 info[i] = ASMC_DATAPORT_READ(sc); 1368 } 1369 1370 error = 0; 1371 out: 1372 if (error && ++try < ASMC_MAXRETRIES) 1373 goto begin; 1374 mtx_unlock_spin(&sc->sc_mtx); 1375 1376 if (error == 0) { 1377 if (len != NULL) 1378 *len = info[0]; 1379 if (type != NULL) { 1380 for (i = 0; i < ASMC_TYPELEN; i++) 1381 type[i] = info[i + 1]; 1382 type[ASMC_TYPELEN] = '\0'; 1383 } 1384 } 1385 return (error); 1386 } 1387 1388 #ifdef ASMC_DEBUG 1389 /* 1390 * Raw SMC key access sysctls - enables reading/writing any SMC key by name 1391 * Usage: 1392 * sysctl dev.asmc.0.raw.key=TC0P # Set key, auto-detects length 1393 * sysctl dev.asmc.0.raw.value # Read current value (hex bytes) 1394 * sysctl dev.asmc.0.raw.value=01 # Write new value 1395 */ 1396 static int 1397 asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS) 1398 { 1399 device_t dev = (device_t) arg1; 1400 struct asmc_softc *sc = device_get_softc(dev); 1401 char newkey[ASMC_KEYLEN + 1]; 1402 uint8_t keylen; 1403 int error; 1404 1405 strlcpy(newkey, sc->sc_rawkey, sizeof(newkey)); 1406 error = sysctl_handle_string(oidp, newkey, sizeof(newkey), req); 1407 if (error || req->newptr == NULL) 1408 return (error); 1409 1410 if (strlen(newkey) != ASMC_KEYLEN) 1411 return (EINVAL); 1412 1413 /* Get key info to auto-detect length and type */ 1414 if (asmc_key_getinfo(dev, newkey, &keylen, sc->sc_rawtype) != 0) 1415 return (ENOENT); 1416 1417 if (keylen > ASMC_MAXVAL) 1418 keylen = ASMC_MAXVAL; 1419 1420 strlcpy(sc->sc_rawkey, newkey, sizeof(sc->sc_rawkey)); 1421 sc->sc_rawlen = keylen; 1422 memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); 1423 1424 /* Read the key value */ 1425 asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen); 1426 1427 return (0); 1428 } 1429 1430 static int 1431 asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS) 1432 { 1433 device_t dev = (device_t) arg1; 1434 struct asmc_softc *sc = device_get_softc(dev); 1435 char hexbuf[ASMC_MAXVAL * 2 + 1]; 1436 int error, i; 1437 1438 /* Refresh from SMC if a key has been selected. */ 1439 if (sc->sc_rawkey[0] != '\0') { 1440 asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, 1441 sc->sc_rawlen > 0 ? sc->sc_rawlen : ASMC_MAXVAL); 1442 } 1443 1444 /* Format as hex string */ 1445 for (i = 0; i < sc->sc_rawlen && i < ASMC_MAXVAL; i++) 1446 snprintf(hexbuf + i * 2, 3, "%02x", sc->sc_rawval[i]); 1447 hexbuf[i * 2] = '\0'; 1448 1449 error = sysctl_handle_string(oidp, hexbuf, sizeof(hexbuf), req); 1450 if (error || req->newptr == NULL) 1451 return (error); 1452 1453 /* Reject writes until a key is selected via raw.key. */ 1454 if (sc->sc_rawkey[0] == '\0') 1455 return (EINVAL); 1456 1457 memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); 1458 for (i = 0; i < sc->sc_rawlen && hexbuf[i*2] && hexbuf[i*2+1]; i++) { 1459 unsigned int val; 1460 char tmp[3] = { hexbuf[i*2], hexbuf[i*2+1], 0 }; 1461 if (sscanf(tmp, "%02x", &val) == 1) 1462 sc->sc_rawval[i] = (uint8_t)val; 1463 } 1464 1465 if (asmc_key_write(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen) != 0) 1466 return (EIO); 1467 1468 return (0); 1469 } 1470 1471 static int 1472 asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS) 1473 { 1474 device_t dev = (device_t) arg1; 1475 struct asmc_softc *sc = device_get_softc(dev); 1476 1477 return (sysctl_handle_8(oidp, &sc->sc_rawlen, 0, req)); 1478 } 1479 1480 static int 1481 asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS) 1482 { 1483 device_t dev = (device_t) arg1; 1484 struct asmc_softc *sc = device_get_softc(dev); 1485 1486 return (sysctl_handle_string(oidp, sc->sc_rawtype, 1487 sizeof(sc->sc_rawtype), req)); 1488 } 1489 #endif 1490 1491 /* SMC sensor type table: type string to fixed-point divisor. */ 1492 static const struct { 1493 const char type[5]; 1494 int divisor; 1495 } asmc_sensor_types[] = { 1496 { "sp78", 256 }, 1497 { "sp87", 128 }, 1498 { "sp4b", 2048 }, 1499 { "sp5a", 1024 }, 1500 { "sp69", 512 }, 1501 { "sp96", 64 }, 1502 { "sp2d", 8192 }, 1503 { "ui16", 1 }, 1504 { "", 0 }, 1505 }; 1506 1507 /* Convert a 2-byte SMC value to milli-units. */ 1508 static bool 1509 asmc_sensor_convert(const char *type, const uint8_t *buf, int *millivalue) 1510 { 1511 int i; 1512 1513 for (i = 0; asmc_sensor_types[i].divisor != 0; i++) { 1514 if (strncmp(type, asmc_sensor_types[i].type, 4) != 0) 1515 continue; 1516 if (asmc_sensor_types[i].divisor == 1) 1517 *millivalue = be16dec(buf); 1518 else 1519 *millivalue = ((int)(int16_t)be16dec(buf) * 1000) / 1520 asmc_sensor_types[i].divisor; 1521 return (true); 1522 } 1523 return (false); 1524 } 1525 1526 static bool 1527 asmc_sensor_type_supported(const char *type) 1528 { 1529 int i; 1530 1531 for (i = 0; asmc_sensor_types[i].divisor != 0; i++) 1532 if (strncmp(type, asmc_sensor_types[i].type, 4) == 0) 1533 return (true); 1534 return (false); 1535 } 1536 1537 /* 1538 * Generic sensor value reader with automatic type conversion. 1539 * Reads an SMC key, detects its type, and converts to millivalue. 1540 */ 1541 static int 1542 asmc_sensor_read(device_t dev, const char *key, int *millivalue) 1543 { 1544 uint8_t buf[2]; 1545 char type[ASMC_TYPELEN + 1]; 1546 uint8_t len; 1547 int error; 1548 1549 error = asmc_key_getinfo(dev, key, &len, type); 1550 if (error != 0) 1551 return (error); 1552 1553 if (len != 2) { 1554 if (bootverbose) 1555 device_printf(dev, 1556 "%s: key %s unexpected length %d\n", 1557 __func__, key, len); 1558 return (ENXIO); 1559 } 1560 1561 error = asmc_key_read(dev, key, buf, sizeof(buf)); 1562 if (error != 0) 1563 return (error); 1564 1565 if (!asmc_sensor_convert(type, buf, millivalue)) { 1566 if (bootverbose) 1567 device_printf(dev, 1568 "%s: unknown type '%s' for key %s\n", 1569 __func__, type, key); 1570 return (ENXIO); 1571 } 1572 1573 return (0); 1574 } 1575 1576 /* 1577 * Generic sensor sysctl handler for voltage/current/power/light sensors. 1578 * arg2 encodes: sensor_type (high byte) | sensor_index (low byte) 1579 * Sensor types: 'V'=voltage, 'I'=current, 'P'=power, 'L'=light 1580 */ 1581 static int 1582 asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS) 1583 { 1584 device_t dev = (device_t) arg1; 1585 struct asmc_softc *sc = device_get_softc(dev); 1586 int error, val; 1587 int sensor_type = (arg2 >> 8) & 0xFF; 1588 int sensor_idx = arg2 & 0xFF; 1589 const char *key = NULL; 1590 1591 /* Select sensor based on type and index */ 1592 switch (sensor_type) { 1593 case 'V': /* Voltage */ 1594 if (sensor_idx < sc->sc_voltage_count) 1595 key = sc->sc_voltage_sensors[sensor_idx]; 1596 break; 1597 case 'I': /* Current */ 1598 if (sensor_idx < sc->sc_current_count) 1599 key = sc->sc_current_sensors[sensor_idx]; 1600 break; 1601 case 'P': /* Power */ 1602 if (sensor_idx < sc->sc_power_count) 1603 key = sc->sc_power_sensors[sensor_idx]; 1604 break; 1605 case 'L': /* Light */ 1606 if (sensor_idx < sc->sc_light_count) 1607 key = sc->sc_light_sensors[sensor_idx]; 1608 break; 1609 default: 1610 return (EINVAL); 1611 } 1612 1613 if (key == NULL) 1614 return (ENOENT); 1615 1616 error = asmc_sensor_read(dev, key, &val); 1617 if (error != 0) 1618 return (error); 1619 1620 return (sysctl_handle_int(oidp, &val, 0, req)); 1621 } 1622 1623 /* 1624 * Scan a range of SMC key indices, adding matching sensors. 1625 * Only considers 2-byte keys with a supported type. 1626 */ 1627 static void 1628 asmc_scan_sensor_range(device_t dev, unsigned int start, 1629 unsigned int end, char prefix, int *countp, char **sensors, 1630 int maxcount) 1631 { 1632 char key[ASMC_KEYLEN + 1]; 1633 char type[ASMC_TYPELEN + 1]; 1634 uint8_t len; 1635 unsigned int i; 1636 char *sensor_key; 1637 1638 for (i = start; i < end; i++) { 1639 if (asmc_key_dump_by_index(dev, i, key, type, &len)) 1640 continue; 1641 if (key[0] != prefix || len != 2) 1642 continue; 1643 if (!asmc_sensor_type_supported(type)) 1644 continue; 1645 if (*countp >= maxcount) 1646 break; 1647 sensor_key = malloc(ASMC_KEYLEN + 1, 1648 M_DEVBUF, M_WAITOK); 1649 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1650 sensors[(*countp)++] = sensor_key; 1651 } 1652 } 1653 1654 static int 1655 asmc_detect_sensors(device_t dev) 1656 { 1657 struct asmc_softc *sc = device_get_softc(dev); 1658 struct sysctl_ctx_list *sysctlctx; 1659 struct sysctl_oid *tree_node; 1660 char key[ASMC_KEYLEN + 1]; 1661 char type[ASMC_TYPELEN + 1]; 1662 uint8_t len; 1663 unsigned int start, end, i; 1664 int error; 1665 char *sensor_key; 1666 1667 sc->sc_voltage_count = 0; 1668 sc->sc_current_count = 0; 1669 sc->sc_power_count = 0; 1670 sc->sc_light_count = 0; 1671 sc->sc_temp_count = 0; 1672 1673 if (sc->sc_nkeys == 0) 1674 return (0); 1675 1676 /* 1677 * Temperature sensors: binary search for T..U range, 1678 * then filter by type sp78. 1679 */ 1680 error = asmc_key_search(dev, "T\0\0\0", &start); 1681 if (error == 0) 1682 error = asmc_key_search(dev, "U\0\0\0", &end); 1683 if (error == 0) { 1684 for (i = start; i < end; i++) { 1685 if (asmc_key_dump_by_index(dev, i, 1686 key, type, &len)) 1687 continue; 1688 if (len != 2 || 1689 strncmp(type, "sp78", 4) != 0) 1690 continue; 1691 if (sc->sc_temp_count >= ASMC_TEMP_MAX) 1692 break; 1693 sensor_key = malloc(ASMC_KEYLEN + 1, 1694 M_DEVBUF, M_WAITOK); 1695 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1696 sc->sc_temp_sensors[sc->sc_temp_count++] = 1697 sensor_key; 1698 } 1699 } 1700 1701 /* Voltage/Current/Power sensors */ 1702 static const struct { 1703 const char *range_start; 1704 const char *range_end; 1705 char prefix; 1706 } sensor_ranges[] = { 1707 { "V\0\0\0", "W\0\0\0", 'V' }, /* Voltage */ 1708 { "I\0\0\0", "J\0\0\0", 'I' }, /* Current */ 1709 { "P\0\0\0", "Q\0\0\0", 'P' }, /* Power */ 1710 }; 1711 static const size_t nsensor_ranges = nitems(sensor_ranges); 1712 1713 int *sensor_counts[] = { 1714 &sc->sc_voltage_count, &sc->sc_current_count, 1715 &sc->sc_power_count }; 1716 char **sensor_arrays[] = { 1717 sc->sc_voltage_sensors, sc->sc_current_sensors, 1718 sc->sc_power_sensors }; 1719 1720 for (unsigned int r = 0; r < nsensor_ranges; r++) { 1721 error = asmc_key_search(dev, sensor_ranges[r].range_start, 1722 &start); 1723 if (error == 0) 1724 error = asmc_key_search(dev, 1725 sensor_ranges[r].range_end, &end); 1726 if (error == 0) 1727 asmc_scan_sensor_range(dev, start, end, 1728 sensor_ranges[r].prefix, sensor_counts[r], 1729 sensor_arrays[r], ASMC_MAX_SENSORS); 1730 } 1731 1732 /* Ambient light sensors: AL* in A..B range */ 1733 error = asmc_key_search(dev, "A\0\0\0", &start); 1734 if (error == 0) 1735 error = asmc_key_search(dev, "B\0\0\0", &end); 1736 if (error == 0) { 1737 for (i = start; i < end; i++) { 1738 if (asmc_key_dump_by_index(dev, i, 1739 key, type, &len)) 1740 continue; 1741 if (key[0] != 'A' || key[1] != 'L' || 1742 (key[2] != 'V' && key[2] != 'S') || 1743 len != 2) 1744 continue; 1745 if (!asmc_sensor_type_supported(type)) 1746 continue; 1747 if (sc->sc_light_count >= ASMC_MAX_SENSORS) 1748 break; 1749 sensor_key = malloc(ASMC_KEYLEN + 1, 1750 M_DEVBUF, M_WAITOK); 1751 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1752 sc->sc_light_sensors[sc->sc_light_count++] = 1753 sensor_key; 1754 } 1755 } 1756 1757 if (bootverbose) 1758 device_printf(dev, 1759 "detected %d temp, %d voltage, %d current, " 1760 "%d power, %d light sensors\n", 1761 sc->sc_temp_count, sc->sc_voltage_count, 1762 sc->sc_current_count, 1763 sc->sc_power_count, sc->sc_light_count); 1764 1765 /* Register sysctls for detected sensors */ 1766 sysctlctx = device_get_sysctl_ctx(dev); 1767 1768 static const struct { 1769 const char *node_name; 1770 const char *node_desc; 1771 char tag; 1772 const char *leaf_desc; 1773 } sensor_sysctl[] = { 1774 { "voltage", "Voltage sensors (millivolts)", 'V', 1775 "Voltage sensor (millivolts)" }, 1776 { "current", "Current sensors (milliamps)", 'I', 1777 "Current sensor (milliamps)" }, 1778 { "power", "Power sensors (milliwatts)", 'P', 1779 "Power sensor (milliwatts)" }, 1780 { "ambient", "Ambient light sensors", 'L', 1781 "Light sensor value" }, 1782 }; 1783 1784 int *sysctl_counts[] = { 1785 &sc->sc_voltage_count, &sc->sc_current_count, 1786 &sc->sc_power_count, &sc->sc_light_count }; 1787 char **sysctl_arrays[] = { 1788 sc->sc_voltage_sensors, sc->sc_current_sensors, 1789 sc->sc_power_sensors, sc->sc_light_sensors }; 1790 1791 for (unsigned int s = 0; s < nitems(sensor_sysctl); s++) { 1792 int count = *sysctl_counts[s]; 1793 if (count <= 0) 1794 continue; 1795 tree_node = SYSCTL_ADD_NODE(sysctlctx, 1796 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1797 sensor_sysctl[s].node_name, 1798 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 1799 sensor_sysctl[s].node_desc); 1800 for (i = 0; i < count; i++) { 1801 SYSCTL_ADD_PROC(sysctlctx, 1802 SYSCTL_CHILDREN(tree_node), 1803 OID_AUTO, sysctl_arrays[s][i], 1804 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 1805 dev, (sensor_sysctl[s].tag << 8) | i, 1806 asmc_sensor_sysctl, "I", 1807 sensor_sysctl[s].leaf_desc); 1808 } 1809 } 1810 1811 return (0); 1812 } 1813 1814 /* 1815 * Helper function to get key info by index (for sensor detection). 1816 */ 1817 static int 1818 asmc_key_dump_by_index(device_t dev, int index, char *key_out, 1819 char *type_out, uint8_t *len_out) 1820 { 1821 struct asmc_softc *sc = device_get_softc(dev); 1822 uint8_t index_buf[ASMC_KEYLEN]; 1823 uint8_t key_buf[ASMC_KEYLEN]; 1824 uint8_t info_buf[ASMC_KEYINFO_RESPLEN]; 1825 int error = ENXIO, try = 0; 1826 int i; 1827 1828 if (sc->sc_is_mmio) { 1829 error = asmc_mmio_key_getbyindex(dev, index, key_out); 1830 if (error != 0) 1831 return (error); 1832 return (asmc_mmio_key_getinfo(dev, key_out, len_out, 1833 type_out)); 1834 } 1835 1836 mtx_lock_spin(&sc->sc_mtx); 1837 1838 index_buf[0] = (index >> 24) & 0xff; 1839 index_buf[1] = (index >> 16) & 0xff; 1840 index_buf[2] = (index >> 8) & 0xff; 1841 index_buf[3] = index & 0xff; 1842 1843 begin: 1844 if (asmc_command(dev, ASMC_CMDGETBYINDEX)) 1845 goto out; 1846 1847 for (i = 0; i < ASMC_KEYLEN; i++) { 1848 ASMC_DATAPORT_WRITE(sc, index_buf[i]); 1849 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1850 goto out; 1851 } 1852 1853 ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN); 1854 1855 for (i = 0; i < ASMC_KEYLEN; i++) { 1856 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1857 goto out; 1858 key_buf[i] = ASMC_DATAPORT_READ(sc); 1859 } 1860 1861 if (asmc_command(dev, ASMC_CMDGETINFO)) 1862 goto out; 1863 1864 for (i = 0; i < ASMC_KEYLEN; i++) { 1865 ASMC_DATAPORT_WRITE(sc, key_buf[i]); 1866 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1867 goto out; 1868 } 1869 1870 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1871 1872 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1873 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1874 goto out; 1875 info_buf[i] = ASMC_DATAPORT_READ(sc); 1876 } 1877 1878 memcpy(key_out, key_buf, ASMC_KEYLEN); 1879 key_out[ASMC_KEYLEN] = '\0'; 1880 *len_out = info_buf[0]; 1881 memcpy(type_out, &info_buf[1], ASMC_TYPELEN); 1882 type_out[ASMC_TYPELEN] = '\0'; 1883 error = 0; 1884 1885 out: 1886 if (error) { 1887 if (++try < ASMC_MAXRETRIES) 1888 goto begin; 1889 } 1890 1891 mtx_unlock_spin(&sc->sc_mtx); 1892 return (error); 1893 } 1894 1895 /* 1896 * Binary search for the first key index >= prefix. 1897 * SMC keys are sorted, so this finds the lower bound efficiently. 1898 */ 1899 static int 1900 asmc_key_search(device_t dev, const char *prefix, unsigned int *idx) 1901 { 1902 struct asmc_softc *sc = device_get_softc(dev); 1903 unsigned int lo, hi, mid; 1904 char key[ASMC_KEYLEN + 1]; 1905 char type[ASMC_TYPELEN + 1]; 1906 uint8_t len; 1907 int error; 1908 1909 lo = 0; 1910 hi = sc->sc_nkeys; 1911 while (lo < hi) { 1912 mid = lo + (hi - lo) / 2; 1913 error = asmc_key_dump_by_index(dev, mid, 1914 key, type, &len); 1915 if (error != 0) 1916 return (error); 1917 if (strncmp(key, prefix, ASMC_KEYLEN) < 0) 1918 lo = mid + 1; 1919 else 1920 hi = mid; 1921 } 1922 *idx = lo; 1923 return (0); 1924 } 1925 1926 static int 1927 asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1928 { 1929 struct asmc_softc *sc = device_get_softc(dev); 1930 int i, error = -1, try = 0; 1931 1932 if (sc->sc_is_mmio) 1933 return (asmc_mmio_key_write(dev, key, buf, len)); 1934 1935 mtx_lock_spin(&sc->sc_mtx); 1936 1937 begin: 1938 ASMC_DPRINTF(("cmd port: cmd write\n")); 1939 if (asmc_command(dev, ASMC_CMDWRITE)) 1940 goto out; 1941 1942 ASMC_DPRINTF(("data port: key\n")); 1943 for (i = 0; i < 4; i++) { 1944 ASMC_DATAPORT_WRITE(sc, key[i]); 1945 if (asmc_wait(dev, 0x04)) 1946 goto out; 1947 } 1948 ASMC_DPRINTF(("data port: length\n")); 1949 ASMC_DATAPORT_WRITE(sc, len); 1950 1951 ASMC_DPRINTF(("data port: buffer\n")); 1952 for (i = 0; i < len; i++) { 1953 if (asmc_wait(dev, 0x04)) 1954 goto out; 1955 ASMC_DATAPORT_WRITE(sc, buf[i]); 1956 } 1957 1958 error = 0; 1959 out: 1960 if (error) { 1961 if (++try < 10) 1962 goto begin; 1963 device_printf(dev, "%s for key %s failed %d times, giving up\n", 1964 __func__, key, try); 1965 } 1966 1967 mtx_unlock_spin(&sc->sc_mtx); 1968 1969 return (error); 1970 } 1971 1972 /* 1973 * Fan control functions. 1974 */ 1975 static int 1976 asmc_fan_count(device_t dev) 1977 { 1978 uint8_t buf[1]; 1979 1980 if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof(buf)) != 0) 1981 return (-1); 1982 1983 return (buf[0]); 1984 } 1985 1986 static int 1987 asmc_fan_getvalue(device_t dev, const char *key, int fan) 1988 { 1989 struct asmc_softc *sc = device_get_softc(dev); 1990 int speed; 1991 uint8_t buf[4]; 1992 char fankey[5]; 1993 char type[ASMC_TYPELEN + 1]; 1994 1995 snprintf(fankey, sizeof(fankey), key, fan); 1996 1997 /* 1998 * T2 Macs use IEEE 754 float ("flt ") for fan speeds, 1999 * stored little-endian in the MMIO data register. 2000 * Standard Macs use s14.2 fixed-point ("fpe2", 2 bytes). 2001 */ 2002 if (sc->sc_is_t2 && 2003 asmc_key_getinfo(dev, fankey, NULL, type) == 0 && 2004 strncmp(type, "flt ", 4) == 0) { 2005 if (asmc_key_read(dev, fankey, buf, 4) != 0) 2006 return (-1); 2007 speed = (int)asmc_float_to_u32(le32dec(buf)); 2008 } else { 2009 if (asmc_key_read(dev, fankey, buf, 2) != 0) 2010 return (-1); 2011 speed = (buf[0] << 6) | (buf[1] >> 2); 2012 } 2013 2014 return (speed); 2015 } 2016 2017 static char * 2018 asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, 2019 uint8_t buflen) 2020 { 2021 char fankey[5]; 2022 char *desc; 2023 2024 snprintf(fankey, sizeof(fankey), key, fan); 2025 if (asmc_key_read(dev, fankey, buf, buflen) != 0) 2026 return (NULL); 2027 desc = buf + 4; 2028 2029 return (desc); 2030 } 2031 2032 static int 2033 asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed) 2034 { 2035 struct asmc_softc *sc = device_get_softc(dev); 2036 uint8_t buf[4]; 2037 char fankey[5]; 2038 char type[ASMC_TYPELEN + 1]; 2039 2040 snprintf(fankey, sizeof(fankey), key, fan); 2041 2042 if (sc->sc_is_t2 && 2043 asmc_key_getinfo(dev, fankey, NULL, type) == 0 && 2044 strncmp(type, "flt ", 4) == 0) { 2045 uint32_t fval; 2046 speed = MAX(speed, 0); 2047 speed = MIN(speed, 65535); 2048 fval = asmc_u32_to_float((uint32_t)speed); 2049 le32enc(buf, fval); 2050 if (asmc_key_write(dev, fankey, buf, 4) != 0) 2051 return (-1); 2052 } else { 2053 speed *= 4; 2054 buf[0] = speed >> 8; 2055 buf[1] = speed; 2056 if (asmc_key_write(dev, fankey, buf, 2) != 0) 2057 return (-1); 2058 } 2059 2060 return (0); 2061 } 2062 2063 static int 2064 asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS) 2065 { 2066 device_t dev = (device_t)arg1; 2067 int fan = arg2; 2068 int error; 2069 int32_t v; 2070 2071 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSPEED, fan); 2072 error = sysctl_handle_int(oidp, &v, 0, req); 2073 2074 return (error); 2075 } 2076 2077 static int 2078 asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS) 2079 { 2080 uint8_t buf[16]; 2081 device_t dev = (device_t)arg1; 2082 int fan = arg2; 2083 int error = true; 2084 char *desc; 2085 2086 desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf)); 2087 2088 if (desc != NULL) 2089 error = sysctl_handle_string(oidp, desc, 0, req); 2090 2091 return (error); 2092 } 2093 2094 static int 2095 asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS) 2096 { 2097 device_t dev = (device_t)arg1; 2098 int fan = arg2; 2099 int error; 2100 int32_t v; 2101 2102 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSAFESPEED, fan); 2103 error = sysctl_handle_int(oidp, &v, 0, req); 2104 2105 return (error); 2106 } 2107 2108 static int 2109 asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS) 2110 { 2111 device_t dev = (device_t)arg1; 2112 int fan = arg2; 2113 int error; 2114 int32_t v; 2115 2116 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan); 2117 error = sysctl_handle_int(oidp, &v, 0, req); 2118 2119 if (error == 0 && req->newptr != NULL) { 2120 unsigned int newspeed = v; 2121 asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed); 2122 } 2123 2124 return (error); 2125 } 2126 2127 static int 2128 asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS) 2129 { 2130 device_t dev = (device_t)arg1; 2131 int fan = arg2; 2132 int error; 2133 int32_t v; 2134 2135 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan); 2136 error = sysctl_handle_int(oidp, &v, 0, req); 2137 2138 if (error == 0 && req->newptr != NULL) { 2139 unsigned int newspeed = v; 2140 asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed); 2141 } 2142 2143 return (error); 2144 } 2145 2146 static int 2147 asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS) 2148 { 2149 device_t dev = (device_t)arg1; 2150 int fan = arg2; 2151 int error; 2152 int32_t v; 2153 2154 v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan); 2155 error = sysctl_handle_int(oidp, &v, 0, req); 2156 2157 if (error == 0 && req->newptr != NULL) { 2158 unsigned int newspeed = v; 2159 asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed); 2160 } 2161 2162 return (error); 2163 } 2164 2165 static int 2166 asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) 2167 { 2168 device_t dev = (device_t)arg1; 2169 struct asmc_softc *sc = device_get_softc(dev); 2170 int fan = arg2; 2171 int error; 2172 int32_t v; 2173 uint8_t buf[2]; 2174 uint16_t val; 2175 char fmkey[5]; 2176 2177 /* 2178 * T2 Macs use per-fan F%dMd keys (1 byte each). 2179 * Standard Macs use FS! bitmask (2 bytes). 2180 */ 2181 snprintf(fmkey, sizeof(fmkey), ASMC_KEY_FANMANUAL_T2, fan); 2182 if (sc->sc_is_t2 && 2183 asmc_key_getinfo(dev, fmkey, NULL, NULL) == 0) { 2184 error = asmc_key_read(dev, fmkey, buf, 1); 2185 if (error != 0) 2186 return (error); 2187 v = buf[0] ? 1 : 0; 2188 2189 error = sysctl_handle_int(oidp, &v, 0, req); 2190 if (error == 0 && req->newptr != NULL) { 2191 if (v != 0 && v != 1) 2192 return (EINVAL); 2193 buf[0] = (uint8_t)v; 2194 error = asmc_key_write(dev, fmkey, buf, 1); 2195 } 2196 return (error); 2197 } 2198 2199 /* Read current FS! bitmask (asmc_key_read locks internally) */ 2200 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); 2201 if (error != 0) 2202 return (error); 2203 2204 /* Extract manual bit for this fan (big-endian) */ 2205 val = (buf[0] << 8) | buf[1]; 2206 v = (val >> fan) & 0x01; 2207 2208 /* Let sysctl handle the value */ 2209 error = sysctl_handle_int(oidp, &v, 0, req); 2210 2211 if (error == 0 && req->newptr != NULL) { 2212 /* Validate input (0 = auto, 1 = manual) */ 2213 if (v != 0 && v != 1) 2214 return (EINVAL); 2215 /* Read-modify-write of FS! bitmask */ 2216 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, 2217 sizeof(buf)); 2218 if (error == 0) { 2219 val = (buf[0] << 8) | buf[1]; 2220 2221 /* Modify single bit */ 2222 if (v) 2223 val |= (1 << fan); /* Set to manual */ 2224 else 2225 val &= ~(1 << fan); /* Set to auto */ 2226 2227 /* Write back */ 2228 buf[0] = val >> 8; 2229 buf[1] = val & 0xff; 2230 error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf, 2231 sizeof(buf)); 2232 } 2233 } 2234 2235 return (error); 2236 } 2237 2238 /* 2239 * Temperature functions. 2240 */ 2241 static int 2242 asmc_temp_getvalue(device_t dev, const char *key) 2243 { 2244 uint8_t buf[2]; 2245 2246 /* 2247 * Check for invalid temperatures. 2248 */ 2249 if (asmc_key_read(dev, key, buf, sizeof(buf)) != 0) 2250 return (-1); 2251 2252 return (buf[0]); 2253 } 2254 2255 static int 2256 asmc_temp_sysctl(SYSCTL_HANDLER_ARGS) 2257 { 2258 device_t dev = (device_t)arg1; 2259 struct asmc_softc *sc = device_get_softc(dev); 2260 int error, val; 2261 2262 if (arg2 < 0 || arg2 >= sc->sc_temp_count) 2263 return (EINVAL); 2264 2265 val = asmc_temp_getvalue(dev, sc->sc_temp_sensors[arg2]); 2266 error = sysctl_handle_int(oidp, &val, 0, req); 2267 2268 return (error); 2269 } 2270 2271 /* 2272 * Sudden Motion Sensor functions. 2273 */ 2274 static int 2275 asmc_sms_read(device_t dev, const char *key, int16_t *val) 2276 { 2277 uint8_t buf[2]; 2278 int error; 2279 2280 /* no need to do locking here as asmc_key_read() already does it */ 2281 switch (key[3]) { 2282 case 'X': 2283 case 'Y': 2284 case 'Z': 2285 error = asmc_key_read(dev, key, buf, sizeof(buf)); 2286 break; 2287 default: 2288 device_printf(dev, "%s called with invalid argument %s\n", 2289 __func__, key); 2290 error = EINVAL; 2291 goto out; 2292 } 2293 *val = ((int16_t)buf[0] << 8) | buf[1]; 2294 out: 2295 return (error); 2296 } 2297 2298 static void 2299 asmc_sms_calibrate(device_t dev) 2300 { 2301 struct asmc_softc *sc = device_get_softc(dev); 2302 2303 asmc_sms_read(dev, ASMC_KEY_SMS_X, &sc->sms_rest_x); 2304 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &sc->sms_rest_y); 2305 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &sc->sms_rest_z); 2306 } 2307 2308 static int 2309 asmc_sms_intrfast(void *arg) 2310 { 2311 uint8_t type; 2312 device_t dev = (device_t)arg; 2313 struct asmc_softc *sc = device_get_softc(dev); 2314 if (!sc->sc_sms_intr_works) 2315 return (FILTER_HANDLED); 2316 2317 mtx_lock_spin(&sc->sc_mtx); 2318 type = ASMC_INTPORT_READ(sc); 2319 mtx_unlock_spin(&sc->sc_mtx); 2320 2321 sc->sc_sms_intrtype = type; 2322 asmc_sms_printintr(dev, type); 2323 2324 /* Don't queue SMS task for ambient light interrupts */ 2325 if (type == ASMC_ALSL_INT2A && sc->sc_has_alsl) 2326 return (FILTER_HANDLED); 2327 2328 taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task); 2329 return (FILTER_HANDLED); 2330 } 2331 2332 static void 2333 asmc_sms_printintr(device_t dev, uint8_t type) 2334 { 2335 struct asmc_softc *sc = device_get_softc(dev); 2336 2337 switch (type) { 2338 case ASMC_SMS_INTFF: 2339 device_printf(dev, "WARNING: possible free fall!\n"); 2340 break; 2341 case ASMC_SMS_INTHA: 2342 device_printf(dev, "WARNING: high acceleration detected!\n"); 2343 break; 2344 case ASMC_SMS_INTSH: 2345 device_printf(dev, "WARNING: possible shock!\n"); 2346 break; 2347 case ASMC_ALSL_INT2A: 2348 /* 2349 * This suppresses console and log messages for the ambient 2350 * light sensor interrupt on models that have ALSL. 2351 */ 2352 if (sc->sc_has_alsl) 2353 break; 2354 /* FALLTHROUGH */ 2355 default: 2356 device_printf(dev, "unknown interrupt: 0x%x\n", type); 2357 } 2358 } 2359 2360 static void 2361 asmc_sms_task(void *arg, int pending) 2362 { 2363 struct asmc_softc *sc = (struct asmc_softc *)arg; 2364 char notify[16]; 2365 int type; 2366 2367 switch (sc->sc_sms_intrtype) { 2368 case ASMC_SMS_INTFF: 2369 type = 2; 2370 break; 2371 case ASMC_SMS_INTHA: 2372 type = 1; 2373 break; 2374 case ASMC_SMS_INTSH: 2375 type = 0; 2376 break; 2377 default: 2378 type = 255; 2379 } 2380 2381 snprintf(notify, sizeof(notify), " notify=0x%x", type); 2382 devctl_notify("ACPI", "asmc", "SMS", notify); 2383 } 2384 2385 static int 2386 asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS) 2387 { 2388 device_t dev = (device_t)arg1; 2389 int error; 2390 int16_t val; 2391 int32_t v; 2392 2393 asmc_sms_read(dev, ASMC_KEY_SMS_X, &val); 2394 v = (int32_t)val; 2395 error = sysctl_handle_int(oidp, &v, 0, req); 2396 2397 return (error); 2398 } 2399 2400 static int 2401 asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS) 2402 { 2403 device_t dev = (device_t)arg1; 2404 int error; 2405 int16_t val; 2406 int32_t v; 2407 2408 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val); 2409 v = (int32_t)val; 2410 error = sysctl_handle_int(oidp, &v, 0, req); 2411 2412 return (error); 2413 } 2414 2415 static int 2416 asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS) 2417 { 2418 device_t dev = (device_t)arg1; 2419 int error; 2420 int16_t val; 2421 int32_t v; 2422 2423 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val); 2424 v = (int32_t)val; 2425 error = sysctl_handle_int(oidp, &v, 0, req); 2426 2427 return (error); 2428 } 2429 2430 static int 2431 asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS) 2432 { 2433 device_t dev = (device_t)arg1; 2434 uint8_t buf[6]; 2435 int error; 2436 int32_t v; 2437 2438 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); 2439 v = buf[2]; 2440 error = sysctl_handle_int(oidp, &v, 0, req); 2441 2442 return (error); 2443 } 2444 2445 static int 2446 asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS) 2447 { 2448 device_t dev = (device_t)arg1; 2449 uint8_t buf[6]; 2450 int error; 2451 int32_t v; 2452 2453 asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof(buf)); 2454 v = buf[2]; 2455 error = sysctl_handle_int(oidp, &v, 0, req); 2456 2457 return (error); 2458 } 2459 2460 static int 2461 asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) 2462 { 2463 device_t dev = (device_t)arg1; 2464 struct asmc_softc *sc = device_get_softc(dev); 2465 uint8_t buf[2]; 2466 int error; 2467 int v; 2468 2469 v = light_control; 2470 error = sysctl_handle_int(oidp, &v, 0, req); 2471 2472 if (error == 0 && req->newptr != NULL) { 2473 if (v < 0 || v > 255) 2474 return (EINVAL); 2475 light_control = v; 2476 sc->sc_kbd_bkl_level = v * 100 / 255; 2477 buf[0] = light_control; 2478 buf[1] = 0x00; 2479 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 2480 } 2481 return (error); 2482 } 2483 2484 static int 2485 asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS) 2486 { 2487 device_t dev = (device_t)arg1; 2488 uint8_t buf[10]; 2489 int error; 2490 uint32_t v; 2491 2492 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); 2493 2494 /* 2495 * This seems to be a 32 bit big endian value from buf[6] -> buf[9]. 2496 * 2497 * Extract it out manually here, then shift/clamp it. 2498 */ 2499 v = be32dec(&buf[6]); 2500 2501 /* 2502 * Shift out, clamp at 255; that way it looks like the 2503 * earlier SMC firmware version responses. 2504 */ 2505 v = v >> 8; 2506 if (v > 255) 2507 v = 255; 2508 2509 error = sysctl_handle_int(oidp, &v, 0, req); 2510 2511 return (error); 2512 } 2513 2514 /* 2515 * Auto power-on after AC power loss (AUPO key). 2516 * When non-zero the machine boots automatically when AC is restored 2517 * after an unclean power loss. Useful for always-on servers / home labs. 2518 */ 2519 static int 2520 asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS) 2521 { 2522 device_t dev = (device_t)arg1; 2523 uint8_t aupo; 2524 int val, error; 2525 2526 if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) 2527 return (EIO); 2528 2529 val = (aupo != 0) ? 1 : 0; 2530 error = sysctl_handle_int(oidp, &val, 0, req); 2531 if (error != 0 || req->newptr == NULL) 2532 return (error); 2533 2534 aupo = (val != 0) ? 1 : 0; 2535 if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) 2536 return (EIO); 2537 2538 return (0); 2539 } 2540 2541 static int 2542 asmc_backlight_update_status(device_t dev, struct backlight_props *props) 2543 { 2544 struct asmc_softc *sc = device_get_softc(dev); 2545 uint8_t buf[2]; 2546 2547 sc->sc_kbd_bkl_level = props->brightness; 2548 light_control = props->brightness * 255 / 100; 2549 buf[0] = light_control; 2550 buf[1] = 0x00; 2551 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 2552 2553 return (0); 2554 } 2555 2556 static int 2557 asmc_backlight_get_status(device_t dev, struct backlight_props *props) 2558 { 2559 struct asmc_softc *sc = device_get_softc(dev); 2560 2561 props->brightness = sc->sc_kbd_bkl_level; 2562 props->nlevels = 0; 2563 2564 return (0); 2565 } 2566 2567 static int 2568 asmc_backlight_get_info(device_t dev, struct backlight_info *info) 2569 { 2570 info->type = BACKLIGHT_TYPE_KEYBOARD; 2571 strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH); 2572 2573 return (0); 2574 } 2575 2576 static const char * 2577 asmc_cause_str(int8_t cause, bool is_sleep) 2578 { 2579 size_t i; 2580 2581 for (i = 0; i < nitems(asmc_cause_table); i++) { 2582 if (asmc_cause_table[i].code != cause) 2583 continue; 2584 if (is_sleep && asmc_cause_table[i].sleep_desc != NULL) 2585 return (asmc_cause_table[i].sleep_desc); 2586 return (asmc_cause_table[i].desc); 2587 } 2588 return (NULL); 2589 } 2590 2591 /* MSSD/MSSP: last shutdown/sleep cause. arg2: 0=shutdown, 1=sleep. */ 2592 static int 2593 asmc_cause_sysctl(SYSCTL_HANDLER_ARGS) 2594 { 2595 device_t dev = (device_t)arg1; 2596 bool is_sleep = (arg2 != 0); 2597 const char *key = is_sleep ? ASMC_KEY_MSSP : ASMC_KEY_MSSD; 2598 int8_t cause; 2599 const char *desc; 2600 char buf[ASMC_CAUSE_BUFLEN]; 2601 2602 /* EIO: SMC I/O bus did not respond to key read. */ 2603 if (asmc_key_read(dev, key, (uint8_t *)&cause, 1) != 0) 2604 return (EIO); 2605 2606 desc = asmc_cause_str(cause, is_sleep); 2607 if (desc != NULL) 2608 snprintf(buf, sizeof(buf), "%d (%s)", (int)cause, desc); 2609 else 2610 snprintf(buf, sizeof(buf), "%d", (int)cause); 2611 2612 return (sysctl_handle_string(oidp, buf, sizeof(buf), req)); 2613 } 2614 2615 static int 2616 asmc_msal_sysctl(SYSCTL_HANDLER_ARGS) 2617 { 2618 device_t dev = (device_t)arg1; 2619 uint8_t msal; 2620 char buf[80]; 2621 2622 /* EIO: SMC I/O bus did not respond to key read. */ 2623 if (asmc_key_read(dev, ASMC_KEY_MSAL, &msal, 1) != 0) 2624 return (EIO); 2625 2626 snprintf(buf, sizeof(buf), 2627 "0x%02x (tss=%d therm_valid=%d calib_valid=%d prochot=%d plimits=%d)", 2628 msal, 2629 (msal & ASMC_MSAL_TSS) != 0, 2630 (msal & ASMC_MSAL_THERM_VALID) != 0, 2631 (msal & ASMC_MSAL_CALIB_VALID) != 0, 2632 (msal & ASMC_MSAL_PROCHOT) != 0, 2633 (msal & ASMC_MSAL_PLIMITS) != 0); 2634 2635 return (sysctl_handle_string(oidp, buf, sizeof(buf), req)); 2636 } 2637 2638 static int 2639 asmc_clkt_sysctl(SYSCTL_HANDLER_ARGS) 2640 { 2641 device_t dev = (device_t)arg1; 2642 uint8_t buf[4]; 2643 uint32_t secs; 2644 2645 if (asmc_key_read(dev, ASMC_KEY_CLKT, buf, 4) != 0) 2646 return (EIO); 2647 2648 secs = be32dec(buf); 2649 return (sysctl_handle_32(oidp, &secs, 0, req)); 2650 } 2651 2652 static int 2653 asmc_msps_sysctl(SYSCTL_HANDLER_ARGS) 2654 { 2655 device_t dev = (device_t)arg1; 2656 uint8_t buf[2], len; 2657 uint32_t state; 2658 2659 if (asmc_key_getinfo(dev, ASMC_KEY_MSPS, &len, NULL) != 0) 2660 return (EIO); 2661 if (len != 1 && len != 2) 2662 return (EIO); 2663 2664 memset(buf, 0, sizeof(buf)); 2665 if (asmc_key_read(dev, ASMC_KEY_MSPS, buf, len) != 0) 2666 return (EIO); 2667 2668 state = (len == 1) ? buf[0] : be16dec(buf); 2669 return (sysctl_handle_32(oidp, &state, 0, req)); 2670 } 2671 2672 static int 2673 asmc_rplt_sysctl(SYSCTL_HANDLER_ARGS) 2674 { 2675 device_t dev = (device_t)arg1; 2676 uint8_t buf[ASMC_RPLT_MAXLEN + 1]; 2677 char name[ASMC_RPLT_MAXLEN + 1]; 2678 2679 memset(buf, 0, sizeof(buf)); 2680 if (asmc_key_read(dev, ASMC_KEY_RPLT, buf, ASMC_RPLT_MAXLEN) != 0) 2681 return (EIO); 2682 2683 memcpy(name, buf, ASMC_RPLT_MAXLEN); 2684 name[ASMC_RPLT_MAXLEN] = '\0'; 2685 2686 return (sysctl_handle_string(oidp, name, sizeof(name), req)); 2687 } 2688 2689 static int 2690 asmc_rgen_sysctl(SYSCTL_HANDLER_ARGS) 2691 { 2692 device_t dev = (device_t)arg1; 2693 uint8_t gen; 2694 uint32_t val; 2695 2696 if (asmc_key_read(dev, ASMC_KEY_RGEN, &gen, 1) != 0) 2697 return (EIO); 2698 2699 val = gen; 2700 return (sysctl_handle_32(oidp, &val, 0, req)); 2701 } 2702