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/sysctl.h> 49 #include <sys/systm.h> 50 #include <sys/taskqueue.h> 51 #include <sys/rman.h> 52 53 #include <machine/resource.h> 54 55 #include <contrib/dev/acpica/include/acpi.h> 56 57 #include <dev/acpica/acpivar.h> 58 #include <dev/asmc/asmcvar.h> 59 60 /* 61 * Device interface. 62 */ 63 static int asmc_probe(device_t dev); 64 static int asmc_attach(device_t dev); 65 static int asmc_detach(device_t dev); 66 static int asmc_resume(device_t dev); 67 68 /* 69 * SMC functions. 70 */ 71 static int asmc_init(device_t dev); 72 static int asmc_command(device_t dev, uint8_t command); 73 static int asmc_wait(device_t dev, uint8_t val); 74 static int asmc_wait_ack(device_t dev, uint8_t val, int amount); 75 static int asmc_key_write(device_t dev, const char *key, uint8_t *buf, 76 uint8_t len); 77 static int asmc_key_read(device_t dev, const char *key, uint8_t *buf, 78 uint8_t); 79 static int asmc_fan_count(device_t dev); 80 static int asmc_fan_getvalue(device_t dev, const char *key, int fan); 81 static int asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed); 82 static int asmc_temp_getvalue(device_t dev, const char *key); 83 static int asmc_sms_read(device_t, const char *key, int16_t *val); 84 static void asmc_sms_calibrate(device_t dev); 85 static int asmc_sms_intrfast(void *arg); 86 static void asmc_sms_printintr(device_t dev, uint8_t); 87 static void asmc_sms_task(void *arg, int pending); 88 #ifdef ASMC_DEBUG 89 void asmc_dumpall(device_t); 90 static int asmc_key_dump(device_t, int); 91 #endif 92 93 /* 94 * Model functions. 95 */ 96 static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS); 97 static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS); 98 static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS); 99 static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS); 100 static int asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS); 101 static int asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS); 102 static int asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS); 103 static int asmc_temp_sysctl(SYSCTL_HANDLER_ARGS); 104 static int asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS); 105 static int asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS); 106 static int asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS); 107 static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS); 108 static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS); 109 static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS); 110 static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS); 111 112 struct asmc_model { 113 const char *smc_model; /* smbios.system.product env var. */ 114 const char *smc_desc; /* driver description */ 115 116 /* Helper functions */ 117 int (*smc_sms_x)(SYSCTL_HANDLER_ARGS); 118 int (*smc_sms_y)(SYSCTL_HANDLER_ARGS); 119 int (*smc_sms_z)(SYSCTL_HANDLER_ARGS); 120 int (*smc_fan_id)(SYSCTL_HANDLER_ARGS); 121 int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS); 122 int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS); 123 int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS); 124 int (*smc_fan_maxspeed)(SYSCTL_HANDLER_ARGS); 125 int (*smc_fan_targetspeed)(SYSCTL_HANDLER_ARGS); 126 int (*smc_light_left)(SYSCTL_HANDLER_ARGS); 127 int (*smc_light_right)(SYSCTL_HANDLER_ARGS); 128 int (*smc_light_control)(SYSCTL_HANDLER_ARGS); 129 130 const char *smc_temps[ASMC_TEMP_MAX]; 131 const char *smc_tempnames[ASMC_TEMP_MAX]; 132 const char *smc_tempdescs[ASMC_TEMP_MAX]; 133 }; 134 135 static const struct asmc_model *asmc_match(device_t dev); 136 137 #define ASMC_SMS_FUNCS asmc_mb_sysctl_sms_x, asmc_mb_sysctl_sms_y, \ 138 asmc_mb_sysctl_sms_z 139 140 #define ASMC_SMS_FUNCS_DISABLED NULL,NULL,NULL 141 142 #define ASMC_FAN_FUNCS asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, asmc_mb_sysctl_fansafespeed, \ 143 asmc_mb_sysctl_fanminspeed, \ 144 asmc_mb_sysctl_fanmaxspeed, \ 145 asmc_mb_sysctl_fantargetspeed 146 147 #define ASMC_FAN_FUNCS2 asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, NULL, \ 148 asmc_mb_sysctl_fanminspeed, \ 149 asmc_mb_sysctl_fanmaxspeed, \ 150 asmc_mb_sysctl_fantargetspeed 151 152 #define ASMC_LIGHT_FUNCS asmc_mbp_sysctl_light_left, \ 153 asmc_mbp_sysctl_light_right, \ 154 asmc_mbp_sysctl_light_control 155 156 #define ASMC_LIGHT_FUNCS_10BYTE \ 157 asmc_mbp_sysctl_light_left_10byte, \ 158 NULL, \ 159 asmc_mbp_sysctl_light_control 160 161 #define ASMC_LIGHT_FUNCS_DISABLED NULL, NULL, NULL 162 163 static const struct asmc_model asmc_models[] = { 164 { 165 "MacBook1,1", "Apple SMC MacBook Core Duo", 166 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, 167 ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS 168 }, 169 170 { 171 "MacBook2,1", "Apple SMC MacBook Core 2 Duo", 172 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, 173 ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS 174 }, 175 176 { 177 "MacBook3,1", "Apple SMC MacBook Core 2 Duo", 178 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, 179 ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS 180 }, 181 182 { 183 "MacBook7,1", "Apple SMC MacBook Core 2 Duo (mid 2010)", 184 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS_DISABLED, 185 ASMC_MB71_TEMPS, ASMC_MB71_TEMPNAMES, ASMC_MB71_TEMPDESCS 186 }, 187 188 { 189 "MacBookPro1,1", "Apple SMC MacBook Pro Core Duo (15-inch)", 190 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 191 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 192 }, 193 194 { 195 "MacBookPro1,2", "Apple SMC MacBook Pro Core Duo (17-inch)", 196 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 197 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 198 }, 199 200 { 201 "MacBookPro2,1", "Apple SMC MacBook Pro Core 2 Duo (17-inch)", 202 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 203 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 204 }, 205 206 { 207 "MacBookPro2,2", "Apple SMC MacBook Pro Core 2 Duo (15-inch)", 208 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 209 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 210 }, 211 212 { 213 "MacBookPro3,1", "Apple SMC MacBook Pro Core 2 Duo (15-inch LED)", 214 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 215 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 216 }, 217 218 { 219 "MacBookPro3,2", "Apple SMC MacBook Pro Core 2 Duo (17-inch HD)", 220 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 221 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 222 }, 223 224 { 225 "MacBookPro4,1", "Apple SMC MacBook Pro Core 2 Duo (Penryn)", 226 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 227 ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS 228 }, 229 230 { 231 "MacBookPro5,1", "Apple SMC MacBook Pro Core 2 Duo (2008/2009)", 232 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 233 ASMC_MBP51_TEMPS, ASMC_MBP51_TEMPNAMES, ASMC_MBP51_TEMPDESCS 234 }, 235 236 { 237 "MacBookPro5,5", "Apple SMC MacBook Pro Core 2 Duo (Mid 2009)", 238 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 239 ASMC_MBP55_TEMPS, ASMC_MBP55_TEMPNAMES, ASMC_MBP55_TEMPDESCS 240 }, 241 242 { 243 "MacBookPro6,2", "Apple SMC MacBook Pro (Mid 2010, 15-inch)", 244 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 245 ASMC_MBP62_TEMPS, ASMC_MBP62_TEMPNAMES, ASMC_MBP62_TEMPDESCS 246 }, 247 248 { 249 "MacBookPro8,1", "Apple SMC MacBook Pro (early 2011, 13-inch)", 250 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 251 ASMC_MBP81_TEMPS, ASMC_MBP81_TEMPNAMES, ASMC_MBP81_TEMPDESCS 252 }, 253 254 { 255 "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)", 256 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 257 ASMC_MBP82_TEMPS, ASMC_MBP82_TEMPNAMES, ASMC_MBP82_TEMPDESCS 258 }, 259 260 { 261 "MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)", 262 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 263 ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS 264 }, 265 266 { 267 "MacBookPro9,2", "Apple SMC MacBook Pro (mid 2012, 13-inch)", 268 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 269 ASMC_MBP92_TEMPS, ASMC_MBP92_TEMPNAMES, ASMC_MBP92_TEMPDESCS 270 }, 271 272 { 273 "MacBookPro11,2", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)", 274 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 275 ASMC_MBP112_TEMPS, ASMC_MBP112_TEMPNAMES, ASMC_MBP112_TEMPDESCS 276 }, 277 278 { 279 "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)", 280 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 281 ASMC_MBP113_TEMPS, ASMC_MBP113_TEMPNAMES, ASMC_MBP113_TEMPDESCS 282 }, 283 284 { 285 "MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)", 286 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 287 ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS 288 }, 289 290 /* The Mac Mini has no SMS */ 291 { 292 "Macmini1,1", "Apple SMC Mac Mini", 293 NULL, NULL, NULL, 294 ASMC_FAN_FUNCS, 295 NULL, NULL, NULL, 296 ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS 297 }, 298 299 /* The Mac Mini 2,1 has no SMS */ 300 { 301 "Macmini2,1", "Apple SMC Mac Mini 2,1", 302 ASMC_SMS_FUNCS_DISABLED, 303 ASMC_FAN_FUNCS, 304 ASMC_LIGHT_FUNCS_DISABLED, 305 ASMC_MM21_TEMPS, ASMC_MM21_TEMPNAMES, ASMC_MM21_TEMPDESCS 306 }, 307 308 /* The Mac Mini 3,1 has no SMS */ 309 { 310 "Macmini3,1", "Apple SMC Mac Mini 3,1", 311 NULL, NULL, NULL, 312 ASMC_FAN_FUNCS, 313 NULL, NULL, NULL, 314 ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS 315 }, 316 317 /* The Mac Mini 4,1 (Mid-2010) has no SMS */ 318 { 319 "Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)", 320 ASMC_SMS_FUNCS_DISABLED, 321 ASMC_FAN_FUNCS, 322 ASMC_LIGHT_FUNCS_DISABLED, 323 ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS 324 }, 325 326 /* The Mac Mini 5,1 has no SMS */ 327 /* - same sensors as Mac Mini 5,2 */ 328 { 329 "Macmini5,1", "Apple SMC Mac Mini 5,1", 330 NULL, NULL, NULL, 331 ASMC_FAN_FUNCS2, 332 NULL, NULL, NULL, 333 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 334 }, 335 336 /* The Mac Mini 5,2 has no SMS */ 337 { 338 "Macmini5,2", "Apple SMC Mac Mini 5,2", 339 NULL, NULL, NULL, 340 ASMC_FAN_FUNCS2, 341 NULL, NULL, NULL, 342 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 343 }, 344 345 /* The Mac Mini 5,3 has no SMS */ 346 /* - same sensors as Mac Mini 5,2 */ 347 { 348 "Macmini5,3", "Apple SMC Mac Mini 5,3", 349 NULL, NULL, NULL, 350 ASMC_FAN_FUNCS2, 351 NULL, NULL, NULL, 352 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 353 }, 354 355 /* The Mac Mini 6,1 has no SMS */ 356 { 357 "Macmini6,1", "Apple SMC Mac Mini 6,1", 358 NULL, NULL, NULL, 359 ASMC_FAN_FUNCS2, 360 NULL, NULL, NULL, 361 ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS 362 }, 363 364 /* The Mac Mini 6,2 has no SMS */ 365 { 366 "Macmini6,2", "Apple SMC Mac Mini 6,2", 367 NULL, NULL, NULL, 368 ASMC_FAN_FUNCS2, 369 NULL, NULL, NULL, 370 ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS 371 }, 372 373 /* The Mac Mini 7,1 has no SMS */ 374 { 375 "Macmini7,1", "Apple SMC Mac Mini 7,1", 376 NULL, NULL, NULL, 377 ASMC_FAN_FUNCS2, 378 NULL, NULL, NULL, 379 ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS 380 }, 381 382 /* Idem for the Mac Pro "Quad Core" (original) */ 383 { 384 "MacPro1,1", "Apple SMC Mac Pro (Quad Core)", 385 NULL, NULL, NULL, 386 ASMC_FAN_FUNCS, 387 NULL, NULL, NULL, 388 ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS 389 }, 390 391 /* Idem for the Mac Pro (8-core) */ 392 { 393 "MacPro2", "Apple SMC Mac Pro (8-core)", 394 NULL, NULL, NULL, 395 ASMC_FAN_FUNCS, 396 NULL, NULL, NULL, 397 ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS 398 }, 399 400 /* Idem for the MacPro 2010*/ 401 { 402 "MacPro5,1", "Apple SMC MacPro (2010)", 403 NULL, NULL, NULL, 404 ASMC_FAN_FUNCS, 405 NULL, NULL, NULL, 406 ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS 407 }, 408 409 /* Idem for the Mac Pro 2013 (cylinder) */ 410 { 411 "MacPro6,1", "Apple SMC Mac Pro (2013)", 412 ASMC_SMS_FUNCS_DISABLED, 413 ASMC_FAN_FUNCS2, 414 ASMC_LIGHT_FUNCS_DISABLED, 415 ASMC_MP6_TEMPS, ASMC_MP6_TEMPNAMES, ASMC_MP6_TEMPDESCS 416 }, 417 418 { 419 "MacBookAir1,1", "Apple SMC MacBook Air", 420 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, 421 ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS 422 }, 423 424 { 425 "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)", 426 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, 427 ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS 428 }, 429 430 { 431 "MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)", 432 ASMC_SMS_FUNCS_DISABLED, 433 ASMC_FAN_FUNCS2, 434 ASMC_LIGHT_FUNCS, 435 ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS 436 }, 437 438 { 439 "MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)", 440 ASMC_SMS_FUNCS_DISABLED, 441 ASMC_FAN_FUNCS2, 442 ASMC_LIGHT_FUNCS, 443 ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS 444 }, 445 446 { 447 "MacBookAir5,1", "Apple SMC MacBook Air 11-inch (Mid 2012)", 448 ASMC_SMS_FUNCS_DISABLED, 449 ASMC_FAN_FUNCS2, 450 ASMC_LIGHT_FUNCS, 451 ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS 452 }, 453 454 { 455 "MacBookAir5,2", "Apple SMC MacBook Air 13-inch (Mid 2012)", 456 ASMC_SMS_FUNCS_DISABLED, 457 ASMC_FAN_FUNCS2, 458 ASMC_LIGHT_FUNCS, 459 ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS 460 }, 461 { 462 "MacBookAir6,1", "Apple SMC MacBook Air 11-inch (Early 2013)", 463 ASMC_SMS_FUNCS_DISABLED, 464 ASMC_FAN_FUNCS2, 465 ASMC_LIGHT_FUNCS_10BYTE, 466 ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS 467 }, 468 { 469 "MacBookAir6,2", "Apple SMC MacBook Air 13-inch (Early 2013)", 470 ASMC_SMS_FUNCS_DISABLED, 471 ASMC_FAN_FUNCS2, 472 ASMC_LIGHT_FUNCS_10BYTE, 473 ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS 474 }, 475 { 476 "MacBookAir7,1", "Apple SMC MacBook Air 11-inch (Early 2015)", 477 ASMC_SMS_FUNCS_DISABLED, 478 ASMC_FAN_FUNCS2, 479 ASMC_LIGHT_FUNCS, 480 ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS 481 }, 482 { 483 "MacBookAir7,2", "Apple SMC MacBook Air 13-inch (Early 2015)", 484 ASMC_SMS_FUNCS_DISABLED, 485 ASMC_FAN_FUNCS2, 486 ASMC_LIGHT_FUNCS, 487 ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS 488 }, 489 { NULL, NULL } 490 }; 491 492 #undef ASMC_SMS_FUNCS 493 #undef ASMC_SMS_FUNCS_DISABLED 494 #undef ASMC_FAN_FUNCS 495 #undef ASMC_FAN_FUNCS2 496 #undef ASMC_LIGHT_FUNCS 497 498 /* 499 * Driver methods. 500 */ 501 static device_method_t asmc_methods[] = { 502 DEVMETHOD(device_probe, asmc_probe), 503 DEVMETHOD(device_attach, asmc_attach), 504 DEVMETHOD(device_detach, asmc_detach), 505 DEVMETHOD(device_resume, asmc_resume), 506 { 0, 0 } 507 }; 508 509 static driver_t asmc_driver = { 510 "asmc", 511 asmc_methods, 512 sizeof(struct asmc_softc) 513 }; 514 515 /* 516 * Debugging 517 */ 518 #define _COMPONENT ACPI_OEM 519 ACPI_MODULE_NAME("ASMC") 520 #ifdef ASMC_DEBUG 521 #define ASMC_DPRINTF(str) device_printf(dev, str) 522 #else 523 #define ASMC_DPRINTF(str) 524 #endif 525 526 /* NB: can't be const */ 527 static char *asmc_ids[] = { "APP0001", NULL }; 528 529 static unsigned int light_control = 0; 530 531 DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL); 532 MODULE_DEPEND(asmc, acpi, 1, 1, 1); 533 534 static const struct asmc_model * 535 asmc_match(device_t dev) 536 { 537 int i; 538 char *model; 539 540 model = kern_getenv("smbios.system.product"); 541 if (model == NULL) 542 return (NULL); 543 544 for (i = 0; asmc_models[i].smc_model; i++) { 545 if (!strncmp(model, asmc_models[i].smc_model, strlen(model))) { 546 freeenv(model); 547 return (&asmc_models[i]); 548 } 549 } 550 freeenv(model); 551 552 return (NULL); 553 } 554 555 static int 556 asmc_probe(device_t dev) 557 { 558 const struct asmc_model *model; 559 int rv; 560 561 if (resource_disabled("asmc", 0)) 562 return (ENXIO); 563 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids, NULL); 564 if (rv > 0) 565 return (rv); 566 567 model = asmc_match(dev); 568 if (!model) { 569 device_printf(dev, "model not recognized\n"); 570 return (ENXIO); 571 } 572 device_set_desc(dev, model->smc_desc); 573 574 return (rv); 575 } 576 577 static int 578 asmc_attach(device_t dev) 579 { 580 int i, j; 581 int ret; 582 char name[2]; 583 struct asmc_softc *sc = device_get_softc(dev); 584 struct sysctl_ctx_list *sysctlctx; 585 struct sysctl_oid *sysctlnode; 586 const struct asmc_model *model; 587 588 sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 589 &sc->sc_rid_port, RF_ACTIVE); 590 if (sc->sc_ioport == NULL) { 591 device_printf(dev, "unable to allocate IO port\n"); 592 return (ENOMEM); 593 } 594 595 sysctlctx = device_get_sysctl_ctx(dev); 596 sysctlnode = device_get_sysctl_tree(dev); 597 598 model = asmc_match(dev); 599 600 mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN); 601 602 sc->sc_model = model; 603 asmc_init(dev); 604 605 /* 606 * dev.asmc.n.fan.* tree. 607 */ 608 sc->sc_fan_tree[0] = SYSCTL_ADD_NODE(sysctlctx, 609 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "fan", 610 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Root Tree"); 611 612 for (i = 1; i <= sc->sc_nfan; i++) { 613 j = i - 1; 614 name[0] = '0' + j; 615 name[1] = 0; 616 sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx, 617 SYSCTL_CHILDREN(sc->sc_fan_tree[0]), 618 OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 619 "Fan Subtree"); 620 621 SYSCTL_ADD_PROC(sysctlctx, 622 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 623 OID_AUTO, "id", 624 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 625 dev, j, model->smc_fan_id, "I", 626 "Fan ID"); 627 628 SYSCTL_ADD_PROC(sysctlctx, 629 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 630 OID_AUTO, "speed", 631 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 632 dev, j, model->smc_fan_speed, "I", 633 "Fan speed in RPM"); 634 635 SYSCTL_ADD_PROC(sysctlctx, 636 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 637 OID_AUTO, "safespeed", 638 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 639 dev, j, model->smc_fan_safespeed, "I", 640 "Fan safe speed in RPM"); 641 642 SYSCTL_ADD_PROC(sysctlctx, 643 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 644 OID_AUTO, "minspeed", 645 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 646 dev, j, model->smc_fan_minspeed, "I", 647 "Fan minimum speed in RPM"); 648 649 SYSCTL_ADD_PROC(sysctlctx, 650 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 651 OID_AUTO, "maxspeed", 652 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 653 dev, j, model->smc_fan_maxspeed, "I", 654 "Fan maximum speed in RPM"); 655 656 SYSCTL_ADD_PROC(sysctlctx, 657 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 658 OID_AUTO, "targetspeed", 659 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 660 dev, j, model->smc_fan_targetspeed, "I", 661 "Fan target speed in RPM"); 662 663 SYSCTL_ADD_PROC(sysctlctx, 664 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 665 OID_AUTO, "manual", 666 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 667 dev, j, asmc_mb_sysctl_fanmanual, "I", 668 "Fan manual mode (0=auto, 1=manual)"); 669 } 670 671 /* 672 * dev.asmc.n.temp tree. 673 */ 674 sc->sc_temp_tree = SYSCTL_ADD_NODE(sysctlctx, 675 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "temp", 676 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Temperature sensors"); 677 678 for (i = 0; model->smc_temps[i]; i++) { 679 SYSCTL_ADD_PROC(sysctlctx, 680 SYSCTL_CHILDREN(sc->sc_temp_tree), 681 OID_AUTO, model->smc_tempnames[i], 682 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 683 dev, i, asmc_temp_sysctl, "I", 684 model->smc_tempdescs[i]); 685 } 686 687 /* 688 * dev.asmc.n.light 689 */ 690 if (model->smc_light_left) { 691 sc->sc_light_tree = SYSCTL_ADD_NODE(sysctlctx, 692 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "light", 693 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 694 "Keyboard backlight sensors"); 695 696 SYSCTL_ADD_PROC(sysctlctx, 697 SYSCTL_CHILDREN(sc->sc_light_tree), 698 OID_AUTO, "left", 699 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 700 dev, 0, model->smc_light_left, "I", 701 "Keyboard backlight left sensor"); 702 703 SYSCTL_ADD_PROC(sysctlctx, 704 SYSCTL_CHILDREN(sc->sc_light_tree), 705 OID_AUTO, "right", 706 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 707 dev, 0, model->smc_light_right, "I", 708 "Keyboard backlight right sensor"); 709 710 SYSCTL_ADD_PROC(sysctlctx, 711 SYSCTL_CHILDREN(sc->sc_light_tree), 712 OID_AUTO, "control", 713 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | 714 CTLFLAG_NEEDGIANT, dev, 0, 715 model->smc_light_control, "I", 716 "Keyboard backlight brightness control"); 717 } 718 719 if (model->smc_sms_x == NULL) 720 goto nosms; 721 722 /* 723 * dev.asmc.n.sms tree. 724 */ 725 sc->sc_sms_tree = SYSCTL_ADD_NODE(sysctlctx, 726 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "sms", 727 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Sudden Motion Sensor"); 728 729 SYSCTL_ADD_PROC(sysctlctx, 730 SYSCTL_CHILDREN(sc->sc_sms_tree), 731 OID_AUTO, "x", 732 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 733 dev, 0, model->smc_sms_x, "I", 734 "Sudden Motion Sensor X value"); 735 736 SYSCTL_ADD_PROC(sysctlctx, 737 SYSCTL_CHILDREN(sc->sc_sms_tree), 738 OID_AUTO, "y", 739 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 740 dev, 0, model->smc_sms_y, "I", 741 "Sudden Motion Sensor Y value"); 742 743 SYSCTL_ADD_PROC(sysctlctx, 744 SYSCTL_CHILDREN(sc->sc_sms_tree), 745 OID_AUTO, "z", 746 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 747 dev, 0, model->smc_sms_z, "I", 748 "Sudden Motion Sensor Z value"); 749 750 /* 751 * Need a taskqueue to send devctl_notify() events 752 * when the SMS interrupt us. 753 * 754 * PI_REALTIME is used due to the sensitivity of the 755 * interrupt. An interrupt from the SMS means that the 756 * disk heads should be turned off as quickly as possible. 757 * 758 * We only need to do this for the non INTR_FILTER case. 759 */ 760 sc->sc_sms_tq = NULL; 761 TASK_INIT(&sc->sc_sms_task, 0, asmc_sms_task, sc); 762 sc->sc_sms_tq = taskqueue_create_fast("asmc_taskq", M_WAITOK, 763 taskqueue_thread_enqueue, &sc->sc_sms_tq); 764 taskqueue_start_threads(&sc->sc_sms_tq, 1, PI_REALTIME, "%s sms taskq", 765 device_get_nameunit(dev)); 766 /* 767 * Allocate an IRQ for the SMS. 768 */ 769 sc->sc_rid_irq = 0; 770 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 771 &sc->sc_rid_irq, RF_ACTIVE); 772 if (sc->sc_irq == NULL) { 773 device_printf(dev, "unable to allocate IRQ resource\n"); 774 ret = ENXIO; 775 goto err2; 776 } 777 778 ret = bus_setup_intr(dev, sc->sc_irq, 779 INTR_TYPE_MISC | INTR_MPSAFE, 780 asmc_sms_intrfast, NULL, 781 dev, &sc->sc_cookie); 782 783 if (ret) { 784 device_printf(dev, "unable to setup SMS IRQ\n"); 785 goto err1; 786 } 787 nosms: 788 return (0); 789 err1: 790 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, sc->sc_irq); 791 err2: 792 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, 793 sc->sc_ioport); 794 mtx_destroy(&sc->sc_mtx); 795 if (sc->sc_sms_tq) 796 taskqueue_free(sc->sc_sms_tq); 797 798 return (ret); 799 } 800 801 static int 802 asmc_detach(device_t dev) 803 { 804 struct asmc_softc *sc = device_get_softc(dev); 805 806 if (sc->sc_sms_tq) { 807 taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task); 808 taskqueue_free(sc->sc_sms_tq); 809 } 810 if (sc->sc_cookie) 811 bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie); 812 if (sc->sc_irq) 813 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, 814 sc->sc_irq); 815 if (sc->sc_ioport) 816 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, 817 sc->sc_ioport); 818 mtx_destroy(&sc->sc_mtx); 819 820 return (0); 821 } 822 823 static int 824 asmc_resume(device_t dev) 825 { 826 uint8_t buf[2]; 827 buf[0] = light_control; 828 buf[1] = 0x00; 829 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf); 830 return (0); 831 } 832 833 #ifdef ASMC_DEBUG 834 void asmc_dumpall(device_t dev) 835 { 836 struct asmc_softc *sc = device_get_softc(dev); 837 int i; 838 839 if (sc->sc_nkeys == 0) { 840 device_printf(dev, "asmc_dumpall: key count not available\n"); 841 return; 842 } 843 844 device_printf(dev, "asmc_dumpall: dumping %d keys\n", sc->sc_nkeys); 845 for (i = 0; i < sc->sc_nkeys; i++) 846 asmc_key_dump(dev, i); 847 } 848 #endif 849 850 static int 851 asmc_init(device_t dev) 852 { 853 struct asmc_softc *sc = device_get_softc(dev); 854 int i, error = 1; 855 uint8_t buf[4]; 856 857 if (sc->sc_model->smc_sms_x == NULL) 858 goto nosms; 859 860 /* 861 * We are ready to receive interrupts from the SMS. 862 */ 863 buf[0] = 0x01; 864 ASMC_DPRINTF(("intok key\n")); 865 asmc_key_write(dev, ASMC_KEY_INTOK, buf, 1); 866 DELAY(50); 867 868 /* 869 * Initiate the polling intervals. 870 */ 871 buf[0] = 20; /* msecs */ 872 ASMC_DPRINTF(("low int key\n")); 873 asmc_key_write(dev, ASMC_KEY_SMS_LOW_INT, buf, 1); 874 DELAY(200); 875 876 buf[0] = 20; /* msecs */ 877 ASMC_DPRINTF(("high int key\n")); 878 asmc_key_write(dev, ASMC_KEY_SMS_HIGH_INT, buf, 1); 879 DELAY(200); 880 881 buf[0] = 0x00; 882 buf[1] = 0x60; 883 ASMC_DPRINTF(("sms low key\n")); 884 asmc_key_write(dev, ASMC_KEY_SMS_LOW, buf, 2); 885 DELAY(200); 886 887 buf[0] = 0x01; 888 buf[1] = 0xc0; 889 ASMC_DPRINTF(("sms high key\n")); 890 asmc_key_write(dev, ASMC_KEY_SMS_HIGH, buf, 2); 891 DELAY(200); 892 893 /* 894 * I'm not sure what this key does, but it seems to be 895 * required. 896 */ 897 buf[0] = 0x01; 898 ASMC_DPRINTF(("sms flag key\n")); 899 asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1); 900 DELAY(100); 901 902 sc->sc_sms_intr_works = 0; 903 904 /* 905 * Retry SMS initialization 1000 times 906 * (takes approx. 2 seconds in worst case) 907 */ 908 for (i = 0; i < 1000; i++) { 909 if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 && 910 (buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) { 911 error = 0; 912 sc->sc_sms_intr_works = 1; 913 goto out; 914 } 915 buf[0] = ASMC_SMS_INIT1; 916 buf[1] = ASMC_SMS_INIT2; 917 ASMC_DPRINTF(("sms key\n")); 918 asmc_key_write(dev, ASMC_KEY_SMS, buf, 2); 919 DELAY(50); 920 } 921 device_printf(dev, "WARNING: Sudden Motion Sensor not initialized!\n"); 922 923 out: 924 asmc_sms_calibrate(dev); 925 nosms: 926 sc->sc_nfan = asmc_fan_count(dev); 927 if (sc->sc_nfan > ASMC_MAXFANS) { 928 device_printf(dev, "more than %d fans were detected. Please " 929 "report this.\n", ASMC_MAXFANS); 930 sc->sc_nfan = ASMC_MAXFANS; 931 } 932 933 /* 934 * Read and cache the number of SMC keys (32 bit buffer) 935 */ 936 if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) { 937 sc->sc_nkeys = be32dec(buf); 938 if (bootverbose) 939 device_printf(dev, "number of keys: %d\n", sc->sc_nkeys); 940 } else { 941 sc->sc_nkeys = 0; 942 } 943 944 #ifdef ASMC_DEBUG 945 asmc_dumpall(dev); 946 #endif 947 948 return (error); 949 } 950 951 /* 952 * We need to make sure that the SMC acks the byte sent. 953 * Just wait up to (amount * 10) ms. 954 */ 955 static int 956 asmc_wait_ack(device_t dev, uint8_t val, int amount) 957 { 958 struct asmc_softc *sc = device_get_softc(dev); 959 u_int i; 960 961 val = val & ASMC_STATUS_MASK; 962 963 for (i = 0; i < amount; i++) { 964 if ((ASMC_CMDPORT_READ(sc) & ASMC_STATUS_MASK) == val) 965 return (0); 966 DELAY(10); 967 } 968 969 return (1); 970 } 971 972 /* 973 * We need to make sure that the SMC acks the byte sent. 974 * Just wait up to 100 ms. 975 */ 976 static int 977 asmc_wait(device_t dev, uint8_t val) 978 { 979 #ifdef ASMC_DEBUG 980 struct asmc_softc *sc; 981 #endif 982 983 if (asmc_wait_ack(dev, val, 1000) == 0) 984 return (0); 985 986 #ifdef ASMC_DEBUG 987 sc = device_get_softc(dev); 988 #endif 989 val = val & ASMC_STATUS_MASK; 990 991 #ifdef ASMC_DEBUG 992 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, val, 993 ASMC_CMDPORT_READ(sc)); 994 #endif 995 return (1); 996 } 997 998 /* 999 * Send the given command, retrying up to 10 times if 1000 * the acknowledgement fails. 1001 */ 1002 static int 1003 asmc_command(device_t dev, uint8_t command) { 1004 int i; 1005 struct asmc_softc *sc = device_get_softc(dev); 1006 1007 for (i=0; i < 10; i++) { 1008 ASMC_CMDPORT_WRITE(sc, command); 1009 if (asmc_wait_ack(dev, 0x0c, 100) == 0) { 1010 return (0); 1011 } 1012 } 1013 1014 #ifdef ASMC_DEBUG 1015 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, command, 1016 ASMC_CMDPORT_READ(sc)); 1017 #endif 1018 return (1); 1019 } 1020 1021 static int 1022 asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1023 { 1024 int i, error = 1, try = 0; 1025 struct asmc_softc *sc = device_get_softc(dev); 1026 1027 mtx_lock_spin(&sc->sc_mtx); 1028 1029 begin: 1030 if (asmc_command(dev, ASMC_CMDREAD)) 1031 goto out; 1032 1033 for (i = 0; i < 4; i++) { 1034 ASMC_DATAPORT_WRITE(sc, key[i]); 1035 if (asmc_wait(dev, 0x04)) 1036 goto out; 1037 } 1038 1039 ASMC_DATAPORT_WRITE(sc, len); 1040 1041 for (i = 0; i < len; i++) { 1042 if (asmc_wait(dev, 0x05)) 1043 goto out; 1044 buf[i] = ASMC_DATAPORT_READ(sc); 1045 } 1046 1047 error = 0; 1048 out: 1049 if (error) { 1050 if (++try < 10) goto begin; 1051 device_printf(dev,"%s for key %s failed %d times, giving up\n", 1052 __func__, key, try); 1053 } 1054 1055 mtx_unlock_spin(&sc->sc_mtx); 1056 1057 return (error); 1058 } 1059 1060 #ifdef ASMC_DEBUG 1061 static int 1062 asmc_key_dump(device_t dev, int number) 1063 { 1064 struct asmc_softc *sc = device_get_softc(dev); 1065 char key[5] = { 0 }; 1066 char type[7] = { 0 }; 1067 uint8_t index[4]; 1068 uint8_t v[32]; 1069 uint8_t maxlen; 1070 int i, error = 1, try = 0; 1071 1072 mtx_lock_spin(&sc->sc_mtx); 1073 1074 index[0] = (number >> 24) & 0xff; 1075 index[1] = (number >> 16) & 0xff; 1076 index[2] = (number >> 8) & 0xff; 1077 index[3] = (number) & 0xff; 1078 1079 begin: 1080 if (asmc_command(dev, 0x12)) 1081 goto out; 1082 1083 for (i = 0; i < 4; i++) { 1084 ASMC_DATAPORT_WRITE(sc, index[i]); 1085 if (asmc_wait(dev, 0x04)) 1086 goto out; 1087 } 1088 1089 ASMC_DATAPORT_WRITE(sc, 4); 1090 1091 for (i = 0; i < 4; i++) { 1092 if (asmc_wait(dev, 0x05)) 1093 goto out; 1094 key[i] = ASMC_DATAPORT_READ(sc); 1095 } 1096 1097 /* get type */ 1098 if (asmc_command(dev, 0x13)) 1099 goto out; 1100 1101 for (i = 0; i < 4; i++) { 1102 ASMC_DATAPORT_WRITE(sc, key[i]); 1103 if (asmc_wait(dev, 0x04)) 1104 goto out; 1105 } 1106 1107 ASMC_DATAPORT_WRITE(sc, 6); 1108 1109 for (i = 0; i < 6; i++) { 1110 if (asmc_wait(dev, 0x05)) 1111 goto out; 1112 type[i] = ASMC_DATAPORT_READ(sc); 1113 } 1114 1115 error = 0; 1116 out: 1117 if (error) { 1118 if (++try < 10) goto begin; 1119 device_printf(dev,"%s for key %s failed %d times, giving up\n", 1120 __func__, key, try); 1121 mtx_unlock_spin(&sc->sc_mtx); 1122 } 1123 else { 1124 char buf[1024]; 1125 char buf2[8]; 1126 mtx_unlock_spin(&sc->sc_mtx); 1127 maxlen = type[0]; 1128 type[0] = ' '; 1129 type[5] = 0; 1130 if (maxlen > sizeof(v)) { 1131 device_printf(dev, 1132 "WARNING: cropping maxlen from %d to %zu\n", 1133 maxlen, sizeof(v)); 1134 maxlen = sizeof(v); 1135 } 1136 for (i = 0; i < sizeof(v); i++) { 1137 v[i] = 0; 1138 } 1139 asmc_key_read(dev, key, v, maxlen); 1140 snprintf(buf, sizeof(buf), "key %d is: %s, type %s " 1141 "(len %d), data", number, key, type, maxlen); 1142 for (i = 0; i < maxlen; i++) { 1143 snprintf(buf2, sizeof(buf2), " %02x", v[i]); 1144 strlcat(buf, buf2, sizeof(buf)); 1145 } 1146 strlcat(buf, " \n", sizeof(buf)); 1147 device_printf(dev, "%s", buf); 1148 } 1149 1150 return (error); 1151 } 1152 #endif 1153 1154 static int 1155 asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1156 { 1157 int i, error = -1, try = 0; 1158 struct asmc_softc *sc = device_get_softc(dev); 1159 1160 mtx_lock_spin(&sc->sc_mtx); 1161 1162 begin: 1163 ASMC_DPRINTF(("cmd port: cmd write\n")); 1164 if (asmc_command(dev, ASMC_CMDWRITE)) 1165 goto out; 1166 1167 ASMC_DPRINTF(("data port: key\n")); 1168 for (i = 0; i < 4; i++) { 1169 ASMC_DATAPORT_WRITE(sc, key[i]); 1170 if (asmc_wait(dev, 0x04)) 1171 goto out; 1172 } 1173 ASMC_DPRINTF(("data port: length\n")); 1174 ASMC_DATAPORT_WRITE(sc, len); 1175 1176 ASMC_DPRINTF(("data port: buffer\n")); 1177 for (i = 0; i < len; i++) { 1178 if (asmc_wait(dev, 0x04)) 1179 goto out; 1180 ASMC_DATAPORT_WRITE(sc, buf[i]); 1181 } 1182 1183 error = 0; 1184 out: 1185 if (error) { 1186 if (++try < 10) goto begin; 1187 device_printf(dev,"%s for key %s failed %d times, giving up\n", 1188 __func__, key, try); 1189 } 1190 1191 mtx_unlock_spin(&sc->sc_mtx); 1192 1193 return (error); 1194 1195 } 1196 1197 /* 1198 * Fan control functions. 1199 */ 1200 static int 1201 asmc_fan_count(device_t dev) 1202 { 1203 uint8_t buf[1]; 1204 1205 if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof buf) != 0) 1206 return (-1); 1207 1208 return (buf[0]); 1209 } 1210 1211 static int 1212 asmc_fan_getvalue(device_t dev, const char *key, int fan) 1213 { 1214 int speed; 1215 uint8_t buf[2]; 1216 char fankey[5]; 1217 1218 snprintf(fankey, sizeof(fankey), key, fan); 1219 if (asmc_key_read(dev, fankey, buf, sizeof buf) != 0) 1220 return (-1); 1221 speed = (buf[0] << 6) | (buf[1] >> 2); 1222 1223 return (speed); 1224 } 1225 1226 static char* 1227 asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, uint8_t buflen) 1228 { 1229 char fankey[5]; 1230 char* desc; 1231 1232 snprintf(fankey, sizeof(fankey), key, fan); 1233 if (asmc_key_read(dev, fankey, buf, buflen) != 0) 1234 return (NULL); 1235 desc = buf+4; 1236 1237 return (desc); 1238 } 1239 1240 static int 1241 asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed) 1242 { 1243 uint8_t buf[2]; 1244 char fankey[5]; 1245 1246 speed *= 4; 1247 1248 buf[0] = speed>>8; 1249 buf[1] = speed; 1250 1251 snprintf(fankey, sizeof(fankey), key, fan); 1252 if (asmc_key_write(dev, fankey, buf, sizeof buf) < 0) 1253 return (-1); 1254 1255 return (0); 1256 } 1257 1258 static int 1259 asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS) 1260 { 1261 device_t dev = (device_t) arg1; 1262 int fan = arg2; 1263 int error; 1264 int32_t v; 1265 1266 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSPEED, fan); 1267 error = sysctl_handle_int(oidp, &v, 0, req); 1268 1269 return (error); 1270 } 1271 1272 static int 1273 asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS) 1274 { 1275 uint8_t buf[16]; 1276 device_t dev = (device_t) arg1; 1277 int fan = arg2; 1278 int error = true; 1279 char* desc; 1280 1281 desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf)); 1282 1283 if (desc != NULL) 1284 error = sysctl_handle_string(oidp, desc, 0, req); 1285 1286 return (error); 1287 } 1288 1289 static int 1290 asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS) 1291 { 1292 device_t dev = (device_t) arg1; 1293 int fan = arg2; 1294 int error; 1295 int32_t v; 1296 1297 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSAFESPEED, fan); 1298 error = sysctl_handle_int(oidp, &v, 0, req); 1299 1300 return (error); 1301 } 1302 1303 static int 1304 asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS) 1305 { 1306 device_t dev = (device_t) arg1; 1307 int fan = arg2; 1308 int error; 1309 int32_t v; 1310 1311 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan); 1312 error = sysctl_handle_int(oidp, &v, 0, req); 1313 1314 if (error == 0 && req->newptr != NULL) { 1315 unsigned int newspeed = v; 1316 asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed); 1317 } 1318 1319 return (error); 1320 } 1321 1322 static int 1323 asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS) 1324 { 1325 device_t dev = (device_t) arg1; 1326 int fan = arg2; 1327 int error; 1328 int32_t v; 1329 1330 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan); 1331 error = sysctl_handle_int(oidp, &v, 0, req); 1332 1333 if (error == 0 && req->newptr != NULL) { 1334 unsigned int newspeed = v; 1335 asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed); 1336 } 1337 1338 return (error); 1339 } 1340 1341 static int 1342 asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS) 1343 { 1344 device_t dev = (device_t) arg1; 1345 int fan = arg2; 1346 int error; 1347 int32_t v; 1348 1349 v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan); 1350 error = sysctl_handle_int(oidp, &v, 0, req); 1351 1352 if (error == 0 && req->newptr != NULL) { 1353 unsigned int newspeed = v; 1354 asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed); 1355 } 1356 1357 return (error); 1358 } 1359 1360 static int 1361 asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) 1362 { 1363 device_t dev = (device_t) arg1; 1364 int fan = arg2; 1365 int error; 1366 int32_t v; 1367 uint8_t buf[2]; 1368 uint16_t val; 1369 1370 /* Read current FS! bitmask (asmc_key_read locks internally) */ 1371 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); 1372 if (error != 0) 1373 return (error); 1374 1375 /* Extract manual bit for this fan (big-endian) */ 1376 val = (buf[0] << 8) | buf[1]; 1377 v = (val >> fan) & 0x01; 1378 1379 /* Let sysctl handle the value */ 1380 error = sysctl_handle_int(oidp, &v, 0, req); 1381 1382 if (error == 0 && req->newptr != NULL) { 1383 /* Validate input (0 = auto, 1 = manual) */ 1384 if (v != 0 && v != 1) 1385 return (EINVAL); 1386 /* Read-modify-write of FS! bitmask */ 1387 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); 1388 if (error == 0) { 1389 val = (buf[0] << 8) | buf[1]; 1390 1391 /* Modify single bit */ 1392 if (v) 1393 val |= (1 << fan); /* Set to manual */ 1394 else 1395 val &= ~(1 << fan); /* Set to auto */ 1396 1397 /* Write back */ 1398 buf[0] = val >> 8; 1399 buf[1] = val & 0xff; 1400 error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); 1401 } 1402 } 1403 1404 return (error); 1405 } 1406 1407 /* 1408 * Temperature functions. 1409 */ 1410 static int 1411 asmc_temp_getvalue(device_t dev, const char *key) 1412 { 1413 uint8_t buf[2]; 1414 1415 /* 1416 * Check for invalid temperatures. 1417 */ 1418 if (asmc_key_read(dev, key, buf, sizeof buf) != 0) 1419 return (-1); 1420 1421 return (buf[0]); 1422 } 1423 1424 static int 1425 asmc_temp_sysctl(SYSCTL_HANDLER_ARGS) 1426 { 1427 device_t dev = (device_t) arg1; 1428 struct asmc_softc *sc = device_get_softc(dev); 1429 int error, val; 1430 1431 val = asmc_temp_getvalue(dev, sc->sc_model->smc_temps[arg2]); 1432 error = sysctl_handle_int(oidp, &val, 0, req); 1433 1434 return (error); 1435 } 1436 1437 /* 1438 * Sudden Motion Sensor functions. 1439 */ 1440 static int 1441 asmc_sms_read(device_t dev, const char *key, int16_t *val) 1442 { 1443 uint8_t buf[2]; 1444 int error; 1445 1446 /* no need to do locking here as asmc_key_read() already does it */ 1447 switch (key[3]) { 1448 case 'X': 1449 case 'Y': 1450 case 'Z': 1451 error = asmc_key_read(dev, key, buf, sizeof buf); 1452 break; 1453 default: 1454 device_printf(dev, "%s called with invalid argument %s\n", 1455 __func__, key); 1456 error = 1; 1457 goto out; 1458 } 1459 *val = ((int16_t)buf[0] << 8) | buf[1]; 1460 out: 1461 return (error); 1462 } 1463 1464 static void 1465 asmc_sms_calibrate(device_t dev) 1466 { 1467 struct asmc_softc *sc = device_get_softc(dev); 1468 1469 asmc_sms_read(dev, ASMC_KEY_SMS_X, &sc->sms_rest_x); 1470 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &sc->sms_rest_y); 1471 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &sc->sms_rest_z); 1472 } 1473 1474 static int 1475 asmc_sms_intrfast(void *arg) 1476 { 1477 uint8_t type; 1478 device_t dev = (device_t) arg; 1479 struct asmc_softc *sc = device_get_softc(dev); 1480 if (!sc->sc_sms_intr_works) 1481 return (FILTER_HANDLED); 1482 1483 mtx_lock_spin(&sc->sc_mtx); 1484 type = ASMC_INTPORT_READ(sc); 1485 mtx_unlock_spin(&sc->sc_mtx); 1486 1487 sc->sc_sms_intrtype = type; 1488 asmc_sms_printintr(dev, type); 1489 1490 taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task); 1491 return (FILTER_HANDLED); 1492 } 1493 1494 static void 1495 asmc_sms_printintr(device_t dev, uint8_t type) 1496 { 1497 struct asmc_softc *sc = device_get_softc(dev); 1498 1499 switch (type) { 1500 case ASMC_SMS_INTFF: 1501 device_printf(dev, "WARNING: possible free fall!\n"); 1502 break; 1503 case ASMC_SMS_INTHA: 1504 device_printf(dev, "WARNING: high acceleration detected!\n"); 1505 break; 1506 case ASMC_SMS_INTSH: 1507 device_printf(dev, "WARNING: possible shock!\n"); 1508 break; 1509 case ASMC_ALSL_INT2A: 1510 /* 1511 * This suppresses console and log messages for the ambient 1512 * light sensor for models known to generate this interrupt. 1513 */ 1514 if (strcmp(sc->sc_model->smc_model, "MacBookPro5,5") == 0 || 1515 strcmp(sc->sc_model->smc_model, "MacBookPro6,2") == 0) 1516 break; 1517 /* FALLTHROUGH */ 1518 default: 1519 device_printf(dev, "unknown interrupt: 0x%x\n", type); 1520 } 1521 } 1522 1523 static void 1524 asmc_sms_task(void *arg, int pending) 1525 { 1526 struct asmc_softc *sc = (struct asmc_softc *)arg; 1527 char notify[16]; 1528 int type; 1529 1530 switch (sc->sc_sms_intrtype) { 1531 case ASMC_SMS_INTFF: 1532 type = 2; 1533 break; 1534 case ASMC_SMS_INTHA: 1535 type = 1; 1536 break; 1537 case ASMC_SMS_INTSH: 1538 type = 0; 1539 break; 1540 default: 1541 type = 255; 1542 } 1543 1544 snprintf(notify, sizeof(notify), " notify=0x%x", type); 1545 devctl_notify("ACPI", "asmc", "SMS", notify); 1546 } 1547 1548 static int 1549 asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS) 1550 { 1551 device_t dev = (device_t) arg1; 1552 int error; 1553 int16_t val; 1554 int32_t v; 1555 1556 asmc_sms_read(dev, ASMC_KEY_SMS_X, &val); 1557 v = (int32_t) val; 1558 error = sysctl_handle_int(oidp, &v, 0, req); 1559 1560 return (error); 1561 } 1562 1563 static int 1564 asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS) 1565 { 1566 device_t dev = (device_t) arg1; 1567 int error; 1568 int16_t val; 1569 int32_t v; 1570 1571 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val); 1572 v = (int32_t) val; 1573 error = sysctl_handle_int(oidp, &v, 0, req); 1574 1575 return (error); 1576 } 1577 1578 static int 1579 asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS) 1580 { 1581 device_t dev = (device_t) arg1; 1582 int error; 1583 int16_t val; 1584 int32_t v; 1585 1586 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val); 1587 v = (int32_t) val; 1588 error = sysctl_handle_int(oidp, &v, 0, req); 1589 1590 return (error); 1591 } 1592 1593 static int 1594 asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS) 1595 { 1596 device_t dev = (device_t) arg1; 1597 uint8_t buf[6]; 1598 int error; 1599 int32_t v; 1600 1601 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf); 1602 v = buf[2]; 1603 error = sysctl_handle_int(oidp, &v, 0, req); 1604 1605 return (error); 1606 } 1607 1608 static int 1609 asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS) 1610 { 1611 device_t dev = (device_t) arg1; 1612 uint8_t buf[6]; 1613 int error; 1614 int32_t v; 1615 1616 asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof buf); 1617 v = buf[2]; 1618 error = sysctl_handle_int(oidp, &v, 0, req); 1619 1620 return (error); 1621 } 1622 1623 static int 1624 asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) 1625 { 1626 device_t dev = (device_t) arg1; 1627 uint8_t buf[2]; 1628 int error; 1629 int v; 1630 1631 v = light_control; 1632 error = sysctl_handle_int(oidp, &v, 0, req); 1633 1634 if (error == 0 && req->newptr != NULL) { 1635 if (v < 0 || v > 255) 1636 return (EINVAL); 1637 light_control = v; 1638 buf[0] = light_control; 1639 buf[1] = 0x00; 1640 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf); 1641 } 1642 return (error); 1643 } 1644 1645 static int 1646 asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS) 1647 { 1648 device_t dev = (device_t) arg1; 1649 uint8_t buf[10]; 1650 int error; 1651 uint32_t v; 1652 1653 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf); 1654 1655 /* 1656 * This seems to be a 32 bit big endian value from buf[6] -> buf[9]. 1657 * 1658 * Extract it out manually here, then shift/clamp it. 1659 */ 1660 v = be32dec(&buf[6]); 1661 1662 /* 1663 * Shift out, clamp at 255; that way it looks like the 1664 * earlier SMC firmware version responses. 1665 */ 1666 v = v >> 8; 1667 if (v > 255) 1668 v = 255; 1669 1670 error = sysctl_handle_int(oidp, &v, 0, req); 1671 1672 return (error); 1673 } 1674