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