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 #include <netinet/in.h> 55 56 #include <contrib/dev/acpica/include/acpi.h> 57 58 #include <dev/acpica/acpivar.h> 59 #include <dev/asmc/asmcvar.h> 60 61 #include <dev/backlight/backlight.h> 62 #include "backlight_if.h" 63 64 /* 65 * Device interface. 66 */ 67 static int asmc_probe(device_t dev); 68 static int asmc_attach(device_t dev); 69 static int asmc_detach(device_t dev); 70 static int asmc_resume(device_t dev); 71 72 /* 73 * Backlight interface. 74 */ 75 static int asmc_backlight_update_status(device_t dev, 76 struct backlight_props *props); 77 static int asmc_backlight_get_status(device_t dev, 78 struct backlight_props *props); 79 static int asmc_backlight_get_info(device_t dev, struct backlight_info *info); 80 81 /* 82 * SMC functions. 83 */ 84 static int asmc_init(device_t dev); 85 static int asmc_command(device_t dev, uint8_t command); 86 static int asmc_wait(device_t dev, uint8_t val); 87 static int asmc_wait_ack(device_t dev, uint8_t val, int amount); 88 static int asmc_key_write(device_t dev, const char *key, uint8_t *buf, 89 uint8_t len); 90 static int asmc_key_read(device_t dev, const char *key, uint8_t *buf, 91 uint8_t); 92 static int asmc_fan_count(device_t dev); 93 static int asmc_fan_getvalue(device_t dev, const char *key, int fan); 94 static int asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed); 95 static int asmc_temp_getvalue(device_t dev, const char *key); 96 static int asmc_sms_read(device_t, const char *key, int16_t *val); 97 static void asmc_sms_calibrate(device_t dev); 98 static int asmc_sms_intrfast(void *arg); 99 static void asmc_sms_printintr(device_t dev, uint8_t); 100 static void asmc_sms_task(void *arg, int pending); 101 #ifdef ASMC_DEBUG 102 void asmc_dumpall(device_t); 103 static int asmc_key_dump(device_t, int); 104 #endif 105 106 /* 107 * Model functions. 108 */ 109 static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS); 110 static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS); 111 static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS); 112 static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS); 113 static int asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS); 114 static int asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS); 115 static int asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS); 116 static int asmc_temp_sysctl(SYSCTL_HANDLER_ARGS); 117 static int asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS); 118 static int asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS); 119 static int asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS); 120 static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS); 121 static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS); 122 static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS); 123 static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS); 124 static int asmc_wol_sysctl(SYSCTL_HANDLER_ARGS); 125 126 #ifdef ASMC_DEBUG 127 /* Raw key access */ 128 static int asmc_key_getinfo(device_t, const char *, uint8_t *, char *); 129 static int asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS); 130 static int asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS); 131 static int asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS); 132 static int asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS); 133 #endif 134 135 struct asmc_model { 136 const char *smc_model; /* smbios.system.product env var. */ 137 const char *smc_desc; /* driver description */ 138 139 /* Helper functions */ 140 int (*smc_sms_x)(SYSCTL_HANDLER_ARGS); 141 int (*smc_sms_y)(SYSCTL_HANDLER_ARGS); 142 int (*smc_sms_z)(SYSCTL_HANDLER_ARGS); 143 int (*smc_fan_id)(SYSCTL_HANDLER_ARGS); 144 int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS); 145 int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS); 146 int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS); 147 int (*smc_fan_maxspeed)(SYSCTL_HANDLER_ARGS); 148 int (*smc_fan_targetspeed)(SYSCTL_HANDLER_ARGS); 149 int (*smc_light_left)(SYSCTL_HANDLER_ARGS); 150 int (*smc_light_right)(SYSCTL_HANDLER_ARGS); 151 int (*smc_light_control)(SYSCTL_HANDLER_ARGS); 152 153 const char *smc_temps[ASMC_TEMP_MAX]; 154 const char *smc_tempnames[ASMC_TEMP_MAX]; 155 const char *smc_tempdescs[ASMC_TEMP_MAX]; 156 }; 157 158 static const struct asmc_model *asmc_match(device_t dev); 159 160 #define ASMC_SMS_FUNCS \ 161 .smc_sms_x = asmc_mb_sysctl_sms_x, \ 162 .smc_sms_y = asmc_mb_sysctl_sms_y, \ 163 .smc_sms_z = asmc_mb_sysctl_sms_z 164 165 #define ASMC_SMS_FUNCS_DISABLED \ 166 .smc_sms_x = NULL, \ 167 .smc_sms_y = NULL, \ 168 .smc_sms_z = NULL 169 170 #define ASMC_FAN_FUNCS \ 171 .smc_fan_id = asmc_mb_sysctl_fanid, \ 172 .smc_fan_speed = asmc_mb_sysctl_fanspeed, \ 173 .smc_fan_safespeed = asmc_mb_sysctl_fansafespeed, \ 174 .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \ 175 .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \ 176 .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed 177 178 #define ASMC_FAN_FUNCS2 \ 179 .smc_fan_id = asmc_mb_sysctl_fanid, \ 180 .smc_fan_speed = asmc_mb_sysctl_fanspeed, \ 181 .smc_fan_safespeed = NULL, \ 182 .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \ 183 .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \ 184 .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed 185 186 #define ASMC_LIGHT_FUNCS \ 187 .smc_light_left = asmc_mbp_sysctl_light_left, \ 188 .smc_light_right = asmc_mbp_sysctl_light_right, \ 189 .smc_light_control = asmc_mbp_sysctl_light_control 190 191 #define ASMC_LIGHT_FUNCS_10BYTE \ 192 .smc_light_left = asmc_mbp_sysctl_light_left_10byte, \ 193 .smc_light_right = NULL, \ 194 .smc_light_control = asmc_mbp_sysctl_light_control 195 196 #define ASMC_LIGHT_FUNCS_DISABLED \ 197 .smc_light_left = NULL, \ 198 .smc_light_right = NULL, \ 199 .smc_light_control = NULL 200 201 #define ASMC_TEMPS_FUNCS_DISABLED \ 202 .smc_temps = {}, \ 203 .smc_tempnames = {}, \ 204 .smc_tempdescs = {} \ 205 206 static const struct asmc_model asmc_models[] = { 207 { 208 "MacBook1,1", "Apple SMC MacBook Core Duo", 209 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 210 ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS 211 }, 212 213 { 214 "MacBook2,1", "Apple SMC MacBook Core 2 Duo", 215 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 216 ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS 217 }, 218 219 { 220 "MacBook3,1", "Apple SMC MacBook Core 2 Duo", 221 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 222 ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS 223 }, 224 225 { 226 "MacBook7,1", "Apple SMC MacBook Core 2 Duo (mid 2010)", 227 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS_DISABLED, 228 ASMC_MB71_TEMPS, ASMC_MB71_TEMPNAMES, ASMC_MB71_TEMPDESCS 229 }, 230 231 { 232 "MacBookPro1,1", "Apple SMC MacBook Pro Core Duo (15-inch)", 233 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 234 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 235 }, 236 237 { 238 "MacBookPro1,2", "Apple SMC MacBook Pro Core Duo (17-inch)", 239 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 240 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 241 }, 242 243 { 244 "MacBookPro2,1", "Apple SMC MacBook Pro Core 2 Duo (17-inch)", 245 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 246 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 247 }, 248 249 { 250 "MacBookPro2,2", "Apple SMC MacBook Pro Core 2 Duo (15-inch)", 251 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 252 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 253 }, 254 255 { 256 "MacBookPro3,1", "Apple SMC MacBook Pro Core 2 Duo (15-inch LED)", 257 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 258 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 259 }, 260 261 { 262 "MacBookPro3,2", "Apple SMC MacBook Pro Core 2 Duo (17-inch HD)", 263 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 264 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 265 }, 266 267 { 268 "MacBookPro4,1", "Apple SMC MacBook Pro Core 2 Duo (Penryn)", 269 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 270 ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS 271 }, 272 273 { 274 "MacBookPro5,1", "Apple SMC MacBook Pro Core 2 Duo (2008/2009)", 275 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 276 ASMC_MBP51_TEMPS, ASMC_MBP51_TEMPNAMES, ASMC_MBP51_TEMPDESCS 277 }, 278 279 { 280 "MacBookPro5,5", "Apple SMC MacBook Pro Core 2 Duo (Mid 2009)", 281 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 282 ASMC_MBP55_TEMPS, ASMC_MBP55_TEMPNAMES, ASMC_MBP55_TEMPDESCS 283 }, 284 285 { 286 "MacBookPro6,2", "Apple SMC MacBook Pro (Mid 2010, 15-inch)", 287 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 288 ASMC_MBP62_TEMPS, ASMC_MBP62_TEMPNAMES, ASMC_MBP62_TEMPDESCS 289 }, 290 291 { 292 "MacBookPro8,1", "Apple SMC MacBook Pro (early 2011, 13-inch)", 293 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 294 ASMC_MBP81_TEMPS, ASMC_MBP81_TEMPNAMES, ASMC_MBP81_TEMPDESCS 295 }, 296 297 { 298 "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)", 299 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 300 ASMC_MBP82_TEMPS, ASMC_MBP82_TEMPNAMES, ASMC_MBP82_TEMPDESCS 301 }, 302 303 { 304 "MacBookPro8,3", "Apple SMC MacBook Pro (early 2011, 17-inch)", 305 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 306 ASMC_MBP83_TEMPS, ASMC_MBP83_TEMPNAMES, ASMC_MBP83_TEMPDESCS 307 }, 308 309 { 310 "MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)", 311 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 312 ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS 313 }, 314 315 { 316 "MacBookPro9,2", "Apple SMC MacBook Pro (mid 2012, 13-inch)", 317 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 318 ASMC_MBP92_TEMPS, ASMC_MBP92_TEMPNAMES, ASMC_MBP92_TEMPDESCS 319 }, 320 321 { 322 "MacBookPro11,2", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)", 323 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 324 ASMC_MBP112_TEMPS, ASMC_MBP112_TEMPNAMES, ASMC_MBP112_TEMPDESCS 325 }, 326 327 { 328 "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)", 329 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 330 ASMC_MBP113_TEMPS, ASMC_MBP113_TEMPNAMES, ASMC_MBP113_TEMPDESCS 331 }, 332 333 { 334 "MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)", 335 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 336 ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS 337 }, 338 339 { 340 "MacBookPro11,5", 341 "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch, AMD GPU)", 342 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 343 ASMC_MBP115_TEMPS, ASMC_MBP115_TEMPNAMES, ASMC_MBP115_TEMPDESCS 344 }, 345 346 { 347 "MacBookPro13,1", "Apple SMC MacBook Pro Retina Core i5 (late 2016, 13-inch)", 348 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 349 ASMC_MBP131_TEMPS, ASMC_MBP131_TEMPNAMES, ASMC_MBP131_TEMPDESCS 350 }, 351 352 /* The Mac Mini has no SMS */ 353 { 354 "Macmini1,1", "Apple SMC Mac Mini", 355 ASMC_SMS_FUNCS_DISABLED, 356 ASMC_FAN_FUNCS, 357 ASMC_LIGHT_FUNCS_DISABLED, 358 ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS 359 }, 360 361 /* The Mac Mini 2,1 has no SMS */ 362 { 363 "Macmini2,1", "Apple SMC Mac Mini 2,1", 364 ASMC_SMS_FUNCS_DISABLED, 365 ASMC_FAN_FUNCS, 366 ASMC_LIGHT_FUNCS_DISABLED, 367 ASMC_MM21_TEMPS, ASMC_MM21_TEMPNAMES, ASMC_MM21_TEMPDESCS 368 }, 369 370 /* The Mac Mini 3,1 has no SMS */ 371 { 372 "Macmini3,1", "Apple SMC Mac Mini 3,1", 373 ASMC_SMS_FUNCS_DISABLED, 374 ASMC_FAN_FUNCS, 375 ASMC_LIGHT_FUNCS_DISABLED, 376 ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS 377 }, 378 379 /* The Mac Mini 4,1 (Mid-2010) has no SMS */ 380 { 381 "Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)", 382 ASMC_SMS_FUNCS_DISABLED, 383 ASMC_FAN_FUNCS2, 384 ASMC_LIGHT_FUNCS_DISABLED, 385 ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS 386 }, 387 388 /* The Mac Mini 5,1 has no SMS */ 389 /* - same sensors as Mac Mini 5,2 */ 390 { 391 "Macmini5,1", "Apple SMC Mac Mini 5,1", 392 ASMC_SMS_FUNCS_DISABLED, 393 ASMC_FAN_FUNCS2, 394 ASMC_LIGHT_FUNCS_DISABLED, 395 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 396 }, 397 398 /* The Mac Mini 5,2 has no SMS */ 399 { 400 "Macmini5,2", "Apple SMC Mac Mini 5,2", 401 ASMC_SMS_FUNCS_DISABLED, 402 ASMC_FAN_FUNCS2, 403 ASMC_LIGHT_FUNCS_DISABLED, 404 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 405 }, 406 407 /* The Mac Mini 5,3 has no SMS */ 408 /* - same sensors as Mac Mini 5,2 */ 409 { 410 "Macmini5,3", "Apple SMC Mac Mini 5,3", 411 ASMC_SMS_FUNCS_DISABLED, 412 ASMC_FAN_FUNCS2, 413 ASMC_LIGHT_FUNCS_DISABLED, 414 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 415 }, 416 417 /* The Mac Mini 6,1 has no SMS */ 418 { 419 "Macmini6,1", "Apple SMC Mac Mini 6,1", 420 ASMC_SMS_FUNCS_DISABLED, 421 ASMC_FAN_FUNCS2, 422 ASMC_LIGHT_FUNCS_DISABLED, 423 ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS 424 }, 425 426 /* The Mac Mini 6,2 has no SMS */ 427 { 428 "Macmini6,2", "Apple SMC Mac Mini 6,2", 429 ASMC_SMS_FUNCS_DISABLED, 430 ASMC_FAN_FUNCS2, 431 ASMC_LIGHT_FUNCS_DISABLED, 432 ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS 433 }, 434 435 /* The Mac Mini 7,1 has no SMS */ 436 { 437 "Macmini7,1", "Apple SMC Mac Mini 7,1", 438 ASMC_SMS_FUNCS_DISABLED, 439 ASMC_FAN_FUNCS2, 440 ASMC_LIGHT_FUNCS_DISABLED, 441 ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS 442 }, 443 444 /* Idem for the Mac Pro "Quad Core" (original) */ 445 { 446 "MacPro1,1", "Apple SMC Mac Pro (Quad Core)", 447 ASMC_SMS_FUNCS_DISABLED, 448 ASMC_FAN_FUNCS, 449 ASMC_LIGHT_FUNCS_DISABLED, 450 ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS 451 }, 452 453 /* Idem for the Mac Pro (Early 2008) */ 454 { 455 "MacPro3,1", "Apple SMC Mac Pro (Early 2008)", 456 ASMC_SMS_FUNCS_DISABLED, 457 ASMC_FAN_FUNCS, 458 ASMC_LIGHT_FUNCS_DISABLED, 459 ASMC_MP31_TEMPS, ASMC_MP31_TEMPNAMES, ASMC_MP31_TEMPDESCS 460 }, 461 462 /* Idem for the Mac Pro (8-core) */ 463 { 464 "MacPro2", "Apple SMC Mac Pro (8-core)", 465 ASMC_SMS_FUNCS_DISABLED, 466 ASMC_FAN_FUNCS, 467 ASMC_LIGHT_FUNCS_DISABLED, 468 ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS 469 }, 470 471 /* Idem for the MacPro 2010*/ 472 { 473 "MacPro5,1", "Apple SMC MacPro (2010)", 474 ASMC_SMS_FUNCS_DISABLED, 475 ASMC_FAN_FUNCS, 476 ASMC_LIGHT_FUNCS_DISABLED, 477 ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS 478 }, 479 480 /* Idem for the Mac Pro 2013 (cylinder) */ 481 { 482 "MacPro6,1", "Apple SMC Mac Pro (2013)", 483 ASMC_SMS_FUNCS_DISABLED, 484 ASMC_FAN_FUNCS2, 485 ASMC_LIGHT_FUNCS_DISABLED, 486 ASMC_MP6_TEMPS, ASMC_MP6_TEMPNAMES, ASMC_MP6_TEMPDESCS 487 }, 488 489 { 490 "MacBookAir1,1", "Apple SMC MacBook Air", 491 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 492 ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS 493 }, 494 495 { 496 "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)", 497 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 498 ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS 499 }, 500 501 { 502 "MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)", 503 ASMC_SMS_FUNCS_DISABLED, 504 ASMC_FAN_FUNCS2, 505 ASMC_LIGHT_FUNCS, 506 ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS 507 }, 508 509 { 510 "MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)", 511 ASMC_SMS_FUNCS_DISABLED, 512 ASMC_FAN_FUNCS2, 513 ASMC_LIGHT_FUNCS, 514 ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS 515 }, 516 517 { 518 "MacBookAir5,1", "Apple SMC MacBook Air 11-inch (Mid 2012)", 519 ASMC_SMS_FUNCS_DISABLED, 520 ASMC_FAN_FUNCS2, 521 ASMC_LIGHT_FUNCS, 522 ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS 523 }, 524 525 { 526 "MacBookAir5,2", "Apple SMC MacBook Air 13-inch (Mid 2012)", 527 ASMC_SMS_FUNCS_DISABLED, 528 ASMC_FAN_FUNCS2, 529 ASMC_LIGHT_FUNCS, 530 ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS 531 }, 532 { 533 "MacBookAir6,1", "Apple SMC MacBook Air 11-inch (Early 2013)", 534 ASMC_SMS_FUNCS_DISABLED, 535 ASMC_FAN_FUNCS2, 536 ASMC_LIGHT_FUNCS_10BYTE, 537 ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS 538 }, 539 { 540 "MacBookAir6,2", "Apple SMC MacBook Air 13-inch (Early 2013)", 541 ASMC_SMS_FUNCS_DISABLED, 542 ASMC_FAN_FUNCS2, 543 ASMC_LIGHT_FUNCS_10BYTE, 544 ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS 545 }, 546 { 547 "MacBookAir7,1", "Apple SMC MacBook Air 11-inch (Early 2015)", 548 ASMC_SMS_FUNCS_DISABLED, 549 ASMC_FAN_FUNCS2, 550 ASMC_LIGHT_FUNCS, 551 ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS 552 }, 553 { 554 "MacBookAir7,2", "Apple SMC MacBook Air 13-inch (Early 2015)", 555 ASMC_SMS_FUNCS_DISABLED, 556 ASMC_FAN_FUNCS2, 557 ASMC_LIGHT_FUNCS, 558 ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS 559 } 560 }; 561 562 static const struct asmc_model asmc_generic_models[] = { 563 { 564 .smc_model = "MacBookAir", 565 .smc_desc = NULL, 566 ASMC_SMS_FUNCS_DISABLED, 567 ASMC_FAN_FUNCS2, 568 ASMC_LIGHT_FUNCS, 569 ASMC_TEMPS_FUNCS_DISABLED 570 }, 571 { 572 .smc_model = "MacBookPro", 573 .smc_desc = NULL, 574 ASMC_SMS_FUNCS_DISABLED, 575 ASMC_FAN_FUNCS2, 576 ASMC_LIGHT_FUNCS, 577 ASMC_TEMPS_FUNCS_DISABLED 578 }, 579 { 580 .smc_model = "MacPro", 581 .smc_desc = NULL, 582 ASMC_SMS_FUNCS_DISABLED, 583 ASMC_FAN_FUNCS2, 584 ASMC_LIGHT_FUNCS_DISABLED, 585 ASMC_TEMPS_FUNCS_DISABLED 586 }, 587 { 588 .smc_model = "Macmini", 589 .smc_desc = NULL, 590 ASMC_SMS_FUNCS_DISABLED, 591 ASMC_FAN_FUNCS2, 592 ASMC_LIGHT_FUNCS_DISABLED, 593 ASMC_TEMPS_FUNCS_DISABLED 594 } 595 }; 596 597 #undef ASMC_SMS_FUNCS 598 #undef ASMC_SMS_FUNCS_DISABLED 599 #undef ASMC_FAN_FUNCS 600 #undef ASMC_FAN_FUNCS2 601 #undef ASMC_LIGHT_FUNCS 602 603 /* 604 * Driver methods. 605 */ 606 static device_method_t asmc_methods[] = { 607 DEVMETHOD(device_probe, asmc_probe), 608 DEVMETHOD(device_attach, asmc_attach), 609 DEVMETHOD(device_detach, asmc_detach), 610 DEVMETHOD(device_resume, asmc_resume), 611 612 /* Backlight interface */ 613 DEVMETHOD(backlight_update_status, asmc_backlight_update_status), 614 DEVMETHOD(backlight_get_status, asmc_backlight_get_status), 615 DEVMETHOD(backlight_get_info, asmc_backlight_get_info), 616 617 DEVMETHOD_END 618 }; 619 620 static driver_t asmc_driver = { 621 "asmc", 622 asmc_methods, 623 sizeof(struct asmc_softc) 624 }; 625 626 /* 627 * Debugging 628 */ 629 #define _COMPONENT ACPI_OEM 630 ACPI_MODULE_NAME("ASMC") 631 #ifdef ASMC_DEBUG 632 #define ASMC_DPRINTF(str, ...) device_printf(dev, str, ##__VA_ARGS__) 633 #else 634 #define ASMC_DPRINTF(str, ...) 635 #endif 636 637 /* NB: can't be const */ 638 static char *asmc_ids[] = { "APP0001", NULL }; 639 640 static unsigned int light_control = 0; 641 642 ACPI_PNP_INFO(asmc_ids); 643 DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL); 644 MODULE_DEPEND(asmc, acpi, 1, 1, 1); 645 MODULE_DEPEND(asmc, backlight, 1, 1, 1); 646 647 static const struct asmc_model * 648 asmc_match(device_t dev) 649 { 650 const struct asmc_model *model; 651 char *model_name; 652 int i; 653 654 model = NULL; 655 656 model_name = kern_getenv("smbios.system.product"); 657 if (model_name == NULL) 658 goto out; 659 660 for (i = 0; i < nitems(asmc_models); i++) { 661 if (strncmp(model_name, asmc_models[i].smc_model, 662 strlen(model_name)) == 0) { 663 model = &asmc_models[i]; 664 goto out; 665 } 666 } 667 for (i = 0; i < nitems(asmc_generic_models); i++) { 668 if (strncmp(model_name, asmc_generic_models[i].smc_model, 669 strlen(asmc_generic_models[i].smc_model)) == 0) { 670 model = &asmc_generic_models[i]; 671 goto out; 672 } 673 } 674 675 out: 676 freeenv(model_name); 677 return (model); 678 } 679 680 static int 681 asmc_probe(device_t dev) 682 { 683 const struct asmc_model *model; 684 const char *device_desc; 685 int rv; 686 687 if (resource_disabled("asmc", 0)) 688 return (ENXIO); 689 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids, NULL); 690 if (rv > 0) 691 return (rv); 692 693 model = asmc_match(dev); 694 if (model == NULL) { 695 device_printf(dev, "model not recognized\n"); 696 return (ENXIO); 697 } 698 device_desc = model->smc_desc == NULL ? 699 model->smc_model : model->smc_desc; 700 device_set_desc(dev, device_desc); 701 702 return (rv); 703 } 704 705 static int 706 asmc_attach(device_t dev) 707 { 708 int i, j; 709 int ret; 710 char name[2]; 711 struct asmc_softc *sc = device_get_softc(dev); 712 struct sysctl_ctx_list *sysctlctx; 713 struct sysctl_oid *sysctlnode; 714 const struct asmc_model *model; 715 716 sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 717 &sc->sc_rid_port, RF_ACTIVE); 718 if (sc->sc_ioport == NULL) { 719 device_printf(dev, "unable to allocate IO port\n"); 720 return (ENOMEM); 721 } 722 723 sysctlctx = device_get_sysctl_ctx(dev); 724 sysctlnode = device_get_sysctl_tree(dev); 725 726 model = asmc_match(dev); 727 728 mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN); 729 730 sc->sc_model = model; 731 asmc_init(dev); 732 733 /* 734 * dev.asmc.n.fan.* tree. 735 */ 736 sc->sc_fan_tree[0] = SYSCTL_ADD_NODE(sysctlctx, 737 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "fan", 738 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Root Tree"); 739 740 for (i = 1; i <= sc->sc_nfan; i++) { 741 j = i - 1; 742 name[0] = '0' + j; 743 name[1] = 0; 744 sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx, 745 SYSCTL_CHILDREN(sc->sc_fan_tree[0]), OID_AUTO, name, 746 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Subtree"); 747 748 SYSCTL_ADD_PROC(sysctlctx, 749 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 750 OID_AUTO, "id", 751 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 752 model->smc_fan_id, "I", "Fan ID"); 753 754 SYSCTL_ADD_PROC(sysctlctx, 755 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 756 OID_AUTO, "speed", 757 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 758 model->smc_fan_speed, "I", "Fan speed in RPM"); 759 760 SYSCTL_ADD_PROC(sysctlctx, 761 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 762 OID_AUTO, "safespeed", 763 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 764 model->smc_fan_safespeed, "I", "Fan safe speed in RPM"); 765 766 SYSCTL_ADD_PROC(sysctlctx, 767 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 768 OID_AUTO, "minspeed", 769 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 770 model->smc_fan_minspeed, "I", "Fan minimum speed in RPM"); 771 772 SYSCTL_ADD_PROC(sysctlctx, 773 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 774 OID_AUTO, "maxspeed", 775 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 776 model->smc_fan_maxspeed, "I", "Fan maximum speed in RPM"); 777 778 SYSCTL_ADD_PROC(sysctlctx, 779 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 780 OID_AUTO, "targetspeed", 781 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 782 model->smc_fan_targetspeed, "I", "Fan target speed in RPM"); 783 784 SYSCTL_ADD_PROC(sysctlctx, 785 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 786 OID_AUTO, "manual", 787 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 788 asmc_mb_sysctl_fanmanual, "I", 789 "Fan manual mode (0=auto, 1=manual)"); 790 } 791 792 /* 793 * dev.asmc.n.temp tree. 794 */ 795 sc->sc_temp_tree = SYSCTL_ADD_NODE(sysctlctx, 796 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "temp", 797 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Temperature sensors"); 798 799 for (i = 0; model->smc_temps[i]; i++) { 800 SYSCTL_ADD_PROC(sysctlctx, 801 SYSCTL_CHILDREN(sc->sc_temp_tree), 802 OID_AUTO, model->smc_tempnames[i], 803 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i, 804 asmc_temp_sysctl, "I", 805 model->smc_tempdescs[i]); 806 } 807 808 /* 809 * dev.asmc.n.light 810 */ 811 if (model->smc_light_left) { 812 sc->sc_light_tree = SYSCTL_ADD_NODE(sysctlctx, 813 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "light", 814 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 815 "Keyboard backlight sensors"); 816 817 SYSCTL_ADD_PROC(sysctlctx, 818 SYSCTL_CHILDREN(sc->sc_light_tree), 819 OID_AUTO, "left", 820 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 821 dev, 0, model->smc_light_left, "I", 822 "Keyboard backlight left sensor"); 823 824 SYSCTL_ADD_PROC(sysctlctx, 825 SYSCTL_CHILDREN(sc->sc_light_tree), 826 OID_AUTO, "right", 827 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, 828 model->smc_light_right, "I", 829 "Keyboard backlight right sensor"); 830 831 SYSCTL_ADD_PROC(sysctlctx, 832 SYSCTL_CHILDREN(sc->sc_light_tree), 833 OID_AUTO, "control", 834 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, 835 dev, 0, model->smc_light_control, "I", 836 "Keyboard backlight brightness control"); 837 838 sc->sc_kbd_bkl = backlight_register("asmc", dev); 839 if (sc->sc_kbd_bkl == NULL) { 840 device_printf(dev, "Can not register backlight\n"); 841 ret = ENXIO; 842 goto err; 843 } 844 } 845 846 #ifdef ASMC_DEBUG 847 /* 848 * Raw SMC key access for debugging. 849 */ 850 sc->sc_raw_tree = SYSCTL_ADD_NODE(sysctlctx, 851 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 852 "raw", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Raw SMC key access"); 853 854 SYSCTL_ADD_PROC(sysctlctx, 855 SYSCTL_CHILDREN(sc->sc_raw_tree), 856 OID_AUTO, "key", 857 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 858 dev, 0, asmc_raw_key_sysctl, "A", 859 "SMC key name (4 chars)"); 860 861 SYSCTL_ADD_PROC(sysctlctx, 862 SYSCTL_CHILDREN(sc->sc_raw_tree), 863 OID_AUTO, "value", 864 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 865 dev, 0, asmc_raw_value_sysctl, "A", 866 "SMC key value (hex string)"); 867 868 SYSCTL_ADD_PROC(sysctlctx, 869 SYSCTL_CHILDREN(sc->sc_raw_tree), 870 OID_AUTO, "len", 871 CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, 872 dev, 0, asmc_raw_len_sysctl, "CU", 873 "SMC key value length"); 874 875 SYSCTL_ADD_PROC(sysctlctx, 876 SYSCTL_CHILDREN(sc->sc_raw_tree), 877 OID_AUTO, "type", 878 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 879 dev, 0, asmc_raw_type_sysctl, "A", 880 "SMC key type (4 chars)"); 881 #endif 882 883 if (model->smc_sms_x == NULL) 884 goto nosms; 885 886 /* 887 * dev.asmc.n.sms tree. 888 */ 889 sc->sc_sms_tree = SYSCTL_ADD_NODE(sysctlctx, 890 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "sms", 891 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Sudden Motion Sensor"); 892 893 SYSCTL_ADD_PROC(sysctlctx, 894 SYSCTL_CHILDREN(sc->sc_sms_tree), 895 OID_AUTO, "x", 896 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 897 dev, 0, model->smc_sms_x, "I", 898 "Sudden Motion Sensor X value"); 899 900 SYSCTL_ADD_PROC(sysctlctx, 901 SYSCTL_CHILDREN(sc->sc_sms_tree), 902 OID_AUTO, "y", 903 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 904 dev, 0, model->smc_sms_y, "I", 905 "Sudden Motion Sensor Y value"); 906 907 SYSCTL_ADD_PROC(sysctlctx, 908 SYSCTL_CHILDREN(sc->sc_sms_tree), 909 OID_AUTO, "z", 910 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 911 dev, 0, model->smc_sms_z, "I", 912 "Sudden Motion Sensor Z value"); 913 914 /* 915 * Need a taskqueue to send devctl_notify() events 916 * when the SMS interrupt us. 917 * 918 * PI_REALTIME is used due to the sensitivity of the 919 * interrupt. An interrupt from the SMS means that the 920 * disk heads should be turned off as quickly as possible. 921 * 922 * We only need to do this for the non INTR_FILTER case. 923 */ 924 sc->sc_sms_tq = NULL; 925 TASK_INIT(&sc->sc_sms_task, 0, asmc_sms_task, sc); 926 sc->sc_sms_tq = taskqueue_create_fast("asmc_taskq", M_WAITOK, 927 taskqueue_thread_enqueue, &sc->sc_sms_tq); 928 taskqueue_start_threads(&sc->sc_sms_tq, 1, PI_REALTIME, "%s sms taskq", 929 device_get_nameunit(dev)); 930 /* 931 * Allocate an IRQ for the SMS. 932 */ 933 sc->sc_rid_irq = 0; 934 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, 935 RF_ACTIVE); 936 if (sc->sc_irq == NULL) { 937 device_printf(dev, "unable to allocate IRQ resource\n"); 938 ret = ENXIO; 939 goto err; 940 } 941 942 ret = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, 943 asmc_sms_intrfast, NULL, dev, &sc->sc_cookie); 944 if (ret) { 945 device_printf(dev, "unable to setup SMS IRQ\n"); 946 goto err; 947 } 948 949 nosms: 950 return (0); 951 952 err: 953 asmc_detach(dev); 954 955 return (ret); 956 } 957 958 static int 959 asmc_detach(device_t dev) 960 { 961 struct asmc_softc *sc = device_get_softc(dev); 962 963 if (sc->sc_kbd_bkl != NULL) 964 backlight_destroy(sc->sc_kbd_bkl); 965 966 if (sc->sc_sms_tq) { 967 taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task); 968 taskqueue_free(sc->sc_sms_tq); 969 sc->sc_sms_tq = NULL; 970 } 971 if (sc->sc_cookie) { 972 bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie); 973 sc->sc_cookie = NULL; 974 } 975 if (sc->sc_irq) { 976 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, 977 sc->sc_irq); 978 sc->sc_irq = NULL; 979 } 980 if (sc->sc_ioport) { 981 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, 982 sc->sc_ioport); 983 sc->sc_ioport = NULL; 984 } 985 if (mtx_initialized(&sc->sc_mtx)) { 986 mtx_destroy(&sc->sc_mtx); 987 } 988 989 return (0); 990 } 991 992 static int 993 asmc_resume(device_t dev) 994 { 995 uint8_t buf[2]; 996 997 buf[0] = light_control; 998 buf[1] = 0x00; 999 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 1000 1001 return (0); 1002 } 1003 1004 #ifdef ASMC_DEBUG 1005 void 1006 asmc_dumpall(device_t dev) 1007 { 1008 struct asmc_softc *sc = device_get_softc(dev); 1009 int i; 1010 1011 if (sc->sc_nkeys == 0) { 1012 device_printf(dev, "asmc_dumpall: key count not available\n"); 1013 return; 1014 } 1015 1016 device_printf(dev, "asmc_dumpall: dumping %d keys\n", sc->sc_nkeys); 1017 for (i = 0; i < sc->sc_nkeys; i++) 1018 asmc_key_dump(dev, i); 1019 } 1020 #endif 1021 1022 static int 1023 asmc_init(device_t dev) 1024 { 1025 struct asmc_softc *sc = device_get_softc(dev); 1026 struct sysctl_ctx_list *sysctlctx; 1027 uint8_t buf[6]; 1028 int i, error = 1; 1029 1030 sysctlctx = device_get_sysctl_ctx(dev); 1031 1032 error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6); 1033 if (error != 0) 1034 goto out_err; 1035 device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2], 1036 ntohs(*(uint16_t *)buf + 4)); 1037 1038 if (sc->sc_model->smc_sms_x == NULL) 1039 goto nosms; 1040 1041 /* 1042 * We are ready to receive interrupts from the SMS. 1043 */ 1044 buf[0] = 0x01; 1045 ASMC_DPRINTF(("intok key\n")); 1046 asmc_key_write(dev, ASMC_KEY_INTOK, buf, 1); 1047 DELAY(50); 1048 1049 /* 1050 * Initiate the polling intervals. 1051 */ 1052 buf[0] = 20; /* msecs */ 1053 ASMC_DPRINTF(("low int key\n")); 1054 asmc_key_write(dev, ASMC_KEY_SMS_LOW_INT, buf, 1); 1055 DELAY(200); 1056 1057 buf[0] = 20; /* msecs */ 1058 ASMC_DPRINTF(("high int key\n")); 1059 asmc_key_write(dev, ASMC_KEY_SMS_HIGH_INT, buf, 1); 1060 DELAY(200); 1061 1062 buf[0] = 0x00; 1063 buf[1] = 0x60; 1064 ASMC_DPRINTF(("sms low key\n")); 1065 asmc_key_write(dev, ASMC_KEY_SMS_LOW, buf, 2); 1066 DELAY(200); 1067 1068 buf[0] = 0x01; 1069 buf[1] = 0xc0; 1070 ASMC_DPRINTF(("sms high key\n")); 1071 asmc_key_write(dev, ASMC_KEY_SMS_HIGH, buf, 2); 1072 DELAY(200); 1073 1074 /* 1075 * I'm not sure what this key does, but it seems to be 1076 * required. 1077 */ 1078 buf[0] = 0x01; 1079 ASMC_DPRINTF(("sms flag key\n")); 1080 asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1); 1081 DELAY(100); 1082 1083 sc->sc_sms_intr_works = 0; 1084 1085 /* 1086 * Retry SMS initialization 1000 times 1087 * (takes approx. 2 seconds in worst case) 1088 */ 1089 for (i = 0; i < 1000; i++) { 1090 if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 && 1091 (buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) { 1092 error = 0; 1093 sc->sc_sms_intr_works = 1; 1094 goto out; 1095 } 1096 buf[0] = ASMC_SMS_INIT1; 1097 buf[1] = ASMC_SMS_INIT2; 1098 ASMC_DPRINTF(("sms key\n")); 1099 asmc_key_write(dev, ASMC_KEY_SMS, buf, 2); 1100 DELAY(50); 1101 } 1102 device_printf(dev, "WARNING: Sudden Motion Sensor not initialized!\n"); 1103 1104 out: 1105 asmc_sms_calibrate(dev); 1106 nosms: 1107 /* Wake-on-LAN convenience sysctl */ 1108 if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) { 1109 SYSCTL_ADD_PROC(sysctlctx, 1110 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1111 OID_AUTO, "wol", 1112 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 1113 dev, 0, asmc_wol_sysctl, "I", 1114 "Wake-on-LAN enable (0=off, 1=on)"); 1115 } 1116 1117 sc->sc_nfan = asmc_fan_count(dev); 1118 if (sc->sc_nfan > ASMC_MAXFANS) { 1119 device_printf(dev, 1120 "more than %d fans were detected. Please report this.\n", 1121 ASMC_MAXFANS); 1122 sc->sc_nfan = ASMC_MAXFANS; 1123 } 1124 1125 /* 1126 * Read and cache the number of SMC keys (32 bit buffer) 1127 */ 1128 if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) { 1129 sc->sc_nkeys = be32dec(buf); 1130 if (bootverbose) 1131 device_printf(dev, "number of keys: %d\n", 1132 sc->sc_nkeys); 1133 } else { 1134 sc->sc_nkeys = 0; 1135 } 1136 1137 out_err: 1138 #ifdef ASMC_DEBUG 1139 asmc_dumpall(dev); 1140 #endif 1141 return (error); 1142 } 1143 1144 /* 1145 * We need to make sure that the SMC acks the byte sent. 1146 * Just wait up to (amount * 10) ms. 1147 */ 1148 static int 1149 asmc_wait_ack(device_t dev, uint8_t val, int amount) 1150 { 1151 struct asmc_softc *sc = device_get_softc(dev); 1152 u_int i; 1153 1154 val = val & ASMC_STATUS_MASK; 1155 1156 for (i = 0; i < amount; i++) { 1157 if ((ASMC_CMDPORT_READ(sc) & ASMC_STATUS_MASK) == val) 1158 return (0); 1159 DELAY(10); 1160 } 1161 1162 return (1); 1163 } 1164 1165 /* 1166 * We need to make sure that the SMC acks the byte sent. 1167 * Just wait up to 100 ms. 1168 */ 1169 static int 1170 asmc_wait(device_t dev, uint8_t val) 1171 { 1172 #ifdef ASMC_DEBUG 1173 struct asmc_softc *sc; 1174 #endif 1175 1176 if (asmc_wait_ack(dev, val, 1000) == 0) 1177 return (0); 1178 1179 #ifdef ASMC_DEBUG 1180 sc = device_get_softc(dev); 1181 1182 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, 1183 val & ASMC_STATUS_MASK, ASMC_CMDPORT_READ(sc)); 1184 #endif 1185 return (1); 1186 } 1187 1188 /* 1189 * Send the given command, retrying up to 10 times if 1190 * the acknowledgement fails. 1191 */ 1192 static int 1193 asmc_command(device_t dev, uint8_t command) 1194 { 1195 int i; 1196 struct asmc_softc *sc = device_get_softc(dev); 1197 1198 for (i = 0; i < 10; i++) { 1199 ASMC_CMDPORT_WRITE(sc, command); 1200 if (asmc_wait_ack(dev, 0x0c, 100) == 0) { 1201 return (0); 1202 } 1203 } 1204 1205 #ifdef ASMC_DEBUG 1206 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, command, 1207 ASMC_CMDPORT_READ(sc)); 1208 #endif 1209 return (1); 1210 } 1211 1212 static int 1213 asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1214 { 1215 int i, error = 1, try = 0; 1216 struct asmc_softc *sc = device_get_softc(dev); 1217 1218 mtx_lock_spin(&sc->sc_mtx); 1219 1220 begin: 1221 if (asmc_command(dev, ASMC_CMDREAD)) 1222 goto out; 1223 1224 for (i = 0; i < 4; i++) { 1225 ASMC_DATAPORT_WRITE(sc, key[i]); 1226 if (asmc_wait(dev, 0x04)) 1227 goto out; 1228 } 1229 1230 ASMC_DATAPORT_WRITE(sc, len); 1231 1232 for (i = 0; i < len; i++) { 1233 if (asmc_wait(dev, 0x05)) 1234 goto out; 1235 buf[i] = ASMC_DATAPORT_READ(sc); 1236 } 1237 1238 error = 0; 1239 out: 1240 if (error) { 1241 if (++try < 10) 1242 goto begin; 1243 device_printf(dev, "%s for key %s failed %d times, giving up\n", 1244 __func__, key, try); 1245 } 1246 1247 mtx_unlock_spin(&sc->sc_mtx); 1248 1249 return (error); 1250 } 1251 1252 #ifdef ASMC_DEBUG 1253 static int 1254 asmc_key_dump(device_t dev, int number) 1255 { 1256 struct asmc_softc *sc = device_get_softc(dev); 1257 char key[ASMC_KEYLEN + 1] = { 0 }; 1258 char type[ASMC_KEYINFO_RESPLEN + 1] = { 0 }; 1259 uint8_t index[4]; 1260 uint8_t v[ASMC_MAXVAL]; 1261 uint8_t maxlen; 1262 int i, error = 1, try = 0; 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 if (maxlen > sizeof(v)) 1325 maxlen = sizeof(v); 1326 1327 memset(v, 0, sizeof(v)); 1328 error = asmc_key_read(dev, key, v, maxlen); 1329 if (error) 1330 return (error); 1331 1332 device_printf(dev, "key %d: %s, type%s (len %d), data", 1333 number, key, type, maxlen); 1334 for (i = 0; i < maxlen; i++) 1335 printf(" %02x", v[i]); 1336 printf("\n"); 1337 1338 return (0); 1339 } 1340 1341 /* 1342 * Get key info (length and type) from SMC using command 0x13. 1343 * Returns 0 on success, -1 on failure. 1344 * If len is non-NULL, stores the key's value length. 1345 * If type is non-NULL, stores the 4-char type string (must be at least 5 bytes). 1346 */ 1347 static int 1348 asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type) 1349 { 1350 struct asmc_softc *sc = device_get_softc(dev); 1351 uint8_t info[ASMC_KEYINFO_RESPLEN]; 1352 int i, error = -1, try = 0; 1353 1354 mtx_lock_spin(&sc->sc_mtx); 1355 1356 begin: 1357 if (asmc_command(dev, ASMC_CMDGETINFO)) 1358 goto out; 1359 1360 for (i = 0; i < ASMC_KEYLEN; i++) { 1361 ASMC_DATAPORT_WRITE(sc, key[i]); 1362 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1363 goto out; 1364 } 1365 1366 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1367 1368 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1369 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1370 goto out; 1371 info[i] = ASMC_DATAPORT_READ(sc); 1372 } 1373 1374 error = 0; 1375 out: 1376 if (error && ++try < ASMC_MAXRETRIES) 1377 goto begin; 1378 mtx_unlock_spin(&sc->sc_mtx); 1379 1380 if (error == 0) { 1381 if (len != NULL) 1382 *len = info[0]; 1383 if (type != NULL) { 1384 for (i = 0; i < ASMC_TYPELEN; i++) 1385 type[i] = info[i + 1]; 1386 type[ASMC_TYPELEN] = '\0'; 1387 } 1388 } 1389 return (error); 1390 } 1391 1392 /* 1393 * Raw SMC key access sysctls - enables reading/writing any SMC key by name 1394 * Usage: 1395 * sysctl dev.asmc.0.raw.key=AUPO # Set key, auto-detects length 1396 * sysctl dev.asmc.0.raw.value # Read current value (hex bytes) 1397 * sysctl dev.asmc.0.raw.value=01 # Write new value 1398 */ 1399 static int 1400 asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS) 1401 { 1402 device_t dev = (device_t) arg1; 1403 struct asmc_softc *sc = device_get_softc(dev); 1404 char newkey[ASMC_KEYLEN + 1]; 1405 uint8_t keylen; 1406 int error; 1407 1408 strlcpy(newkey, sc->sc_rawkey, sizeof(newkey)); 1409 error = sysctl_handle_string(oidp, newkey, sizeof(newkey), req); 1410 if (error || req->newptr == NULL) 1411 return (error); 1412 1413 if (strlen(newkey) != ASMC_KEYLEN) 1414 return (EINVAL); 1415 1416 /* Get key info to auto-detect length and type */ 1417 if (asmc_key_getinfo(dev, newkey, &keylen, sc->sc_rawtype) != 0) 1418 return (ENOENT); 1419 1420 if (keylen > ASMC_MAXVAL) 1421 keylen = ASMC_MAXVAL; 1422 1423 strlcpy(sc->sc_rawkey, newkey, sizeof(sc->sc_rawkey)); 1424 sc->sc_rawlen = keylen; 1425 memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); 1426 1427 /* Read the key value */ 1428 asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen); 1429 1430 return (0); 1431 } 1432 1433 static int 1434 asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS) 1435 { 1436 device_t dev = (device_t) arg1; 1437 struct asmc_softc *sc = device_get_softc(dev); 1438 char hexbuf[ASMC_MAXVAL * 2 + 1]; 1439 int error, i; 1440 1441 /* Refresh from SMC if a key has been selected. */ 1442 if (sc->sc_rawkey[0] != '\0') { 1443 asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, 1444 sc->sc_rawlen > 0 ? sc->sc_rawlen : ASMC_MAXVAL); 1445 } 1446 1447 /* Format as hex string */ 1448 for (i = 0; i < sc->sc_rawlen && i < ASMC_MAXVAL; i++) 1449 snprintf(hexbuf + i * 2, 3, "%02x", sc->sc_rawval[i]); 1450 hexbuf[i * 2] = '\0'; 1451 1452 error = sysctl_handle_string(oidp, hexbuf, sizeof(hexbuf), req); 1453 if (error || req->newptr == NULL) 1454 return (error); 1455 1456 /* Reject writes until a key is selected via raw.key. */ 1457 if (sc->sc_rawkey[0] == '\0') 1458 return (EINVAL); 1459 1460 memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); 1461 for (i = 0; i < sc->sc_rawlen && hexbuf[i*2] && hexbuf[i*2+1]; i++) { 1462 unsigned int val; 1463 char tmp[3] = { hexbuf[i*2], hexbuf[i*2+1], 0 }; 1464 if (sscanf(tmp, "%02x", &val) == 1) 1465 sc->sc_rawval[i] = (uint8_t)val; 1466 } 1467 1468 if (asmc_key_write(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen) != 0) 1469 return (EIO); 1470 1471 return (0); 1472 } 1473 1474 static int 1475 asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS) 1476 { 1477 device_t dev = (device_t) arg1; 1478 struct asmc_softc *sc = device_get_softc(dev); 1479 1480 return (sysctl_handle_8(oidp, &sc->sc_rawlen, 0, req)); 1481 } 1482 1483 static int 1484 asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS) 1485 { 1486 device_t dev = (device_t) arg1; 1487 struct asmc_softc *sc = device_get_softc(dev); 1488 1489 return (sysctl_handle_string(oidp, sc->sc_rawtype, 1490 sizeof(sc->sc_rawtype), req)); 1491 } 1492 #endif 1493 1494 static int 1495 asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1496 { 1497 int i, error = -1, try = 0; 1498 struct asmc_softc *sc = device_get_softc(dev); 1499 1500 mtx_lock_spin(&sc->sc_mtx); 1501 1502 begin: 1503 ASMC_DPRINTF(("cmd port: cmd write\n")); 1504 if (asmc_command(dev, ASMC_CMDWRITE)) 1505 goto out; 1506 1507 ASMC_DPRINTF(("data port: key\n")); 1508 for (i = 0; i < 4; i++) { 1509 ASMC_DATAPORT_WRITE(sc, key[i]); 1510 if (asmc_wait(dev, 0x04)) 1511 goto out; 1512 } 1513 ASMC_DPRINTF(("data port: length\n")); 1514 ASMC_DATAPORT_WRITE(sc, len); 1515 1516 ASMC_DPRINTF(("data port: buffer\n")); 1517 for (i = 0; i < len; i++) { 1518 if (asmc_wait(dev, 0x04)) 1519 goto out; 1520 ASMC_DATAPORT_WRITE(sc, buf[i]); 1521 } 1522 1523 error = 0; 1524 out: 1525 if (error) { 1526 if (++try < 10) 1527 goto begin; 1528 device_printf(dev, "%s for key %s failed %d times, giving up\n", 1529 __func__, key, try); 1530 } 1531 1532 mtx_unlock_spin(&sc->sc_mtx); 1533 1534 return (error); 1535 } 1536 1537 /* 1538 * Fan control functions. 1539 */ 1540 static int 1541 asmc_fan_count(device_t dev) 1542 { 1543 uint8_t buf[1]; 1544 1545 if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof(buf)) != 0) 1546 return (-1); 1547 1548 return (buf[0]); 1549 } 1550 1551 static int 1552 asmc_fan_getvalue(device_t dev, const char *key, int fan) 1553 { 1554 int speed; 1555 uint8_t buf[2]; 1556 char fankey[5]; 1557 1558 snprintf(fankey, sizeof(fankey), key, fan); 1559 if (asmc_key_read(dev, fankey, buf, sizeof(buf)) != 0) 1560 return (-1); 1561 speed = (buf[0] << 6) | (buf[1] >> 2); 1562 1563 return (speed); 1564 } 1565 1566 static char * 1567 asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, 1568 uint8_t buflen) 1569 { 1570 char fankey[5]; 1571 char *desc; 1572 1573 snprintf(fankey, sizeof(fankey), key, fan); 1574 if (asmc_key_read(dev, fankey, buf, buflen) != 0) 1575 return (NULL); 1576 desc = buf + 4; 1577 1578 return (desc); 1579 } 1580 1581 static int 1582 asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed) 1583 { 1584 uint8_t buf[2]; 1585 char fankey[5]; 1586 1587 speed *= 4; 1588 1589 buf[0] = speed >> 8; 1590 buf[1] = speed; 1591 1592 snprintf(fankey, sizeof(fankey), key, fan); 1593 if (asmc_key_write(dev, fankey, buf, sizeof(buf)) < 0) 1594 return (-1); 1595 1596 return (0); 1597 } 1598 1599 static int 1600 asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS) 1601 { 1602 device_t dev = (device_t)arg1; 1603 int fan = arg2; 1604 int error; 1605 int32_t v; 1606 1607 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSPEED, fan); 1608 error = sysctl_handle_int(oidp, &v, 0, req); 1609 1610 return (error); 1611 } 1612 1613 static int 1614 asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS) 1615 { 1616 uint8_t buf[16]; 1617 device_t dev = (device_t)arg1; 1618 int fan = arg2; 1619 int error = true; 1620 char *desc; 1621 1622 desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf)); 1623 1624 if (desc != NULL) 1625 error = sysctl_handle_string(oidp, desc, 0, req); 1626 1627 return (error); 1628 } 1629 1630 static int 1631 asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS) 1632 { 1633 device_t dev = (device_t)arg1; 1634 int fan = arg2; 1635 int error; 1636 int32_t v; 1637 1638 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSAFESPEED, fan); 1639 error = sysctl_handle_int(oidp, &v, 0, req); 1640 1641 return (error); 1642 } 1643 1644 static int 1645 asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS) 1646 { 1647 device_t dev = (device_t)arg1; 1648 int fan = arg2; 1649 int error; 1650 int32_t v; 1651 1652 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan); 1653 error = sysctl_handle_int(oidp, &v, 0, req); 1654 1655 if (error == 0 && req->newptr != NULL) { 1656 unsigned int newspeed = v; 1657 asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed); 1658 } 1659 1660 return (error); 1661 } 1662 1663 static int 1664 asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS) 1665 { 1666 device_t dev = (device_t)arg1; 1667 int fan = arg2; 1668 int error; 1669 int32_t v; 1670 1671 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan); 1672 error = sysctl_handle_int(oidp, &v, 0, req); 1673 1674 if (error == 0 && req->newptr != NULL) { 1675 unsigned int newspeed = v; 1676 asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed); 1677 } 1678 1679 return (error); 1680 } 1681 1682 static int 1683 asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS) 1684 { 1685 device_t dev = (device_t)arg1; 1686 int fan = arg2; 1687 int error; 1688 int32_t v; 1689 1690 v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan); 1691 error = sysctl_handle_int(oidp, &v, 0, req); 1692 1693 if (error == 0 && req->newptr != NULL) { 1694 unsigned int newspeed = v; 1695 asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed); 1696 } 1697 1698 return (error); 1699 } 1700 1701 static int 1702 asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) 1703 { 1704 device_t dev = (device_t)arg1; 1705 int fan = arg2; 1706 int error; 1707 int32_t v; 1708 uint8_t buf[2]; 1709 uint16_t val; 1710 1711 /* Read current FS! bitmask (asmc_key_read locks internally) */ 1712 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); 1713 if (error != 0) 1714 return (error); 1715 1716 /* Extract manual bit for this fan (big-endian) */ 1717 val = (buf[0] << 8) | buf[1]; 1718 v = (val >> fan) & 0x01; 1719 1720 /* Let sysctl handle the value */ 1721 error = sysctl_handle_int(oidp, &v, 0, req); 1722 1723 if (error == 0 && req->newptr != NULL) { 1724 /* Validate input (0 = auto, 1 = manual) */ 1725 if (v != 0 && v != 1) 1726 return (EINVAL); 1727 /* Read-modify-write of FS! bitmask */ 1728 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, 1729 sizeof(buf)); 1730 if (error == 0) { 1731 val = (buf[0] << 8) | buf[1]; 1732 1733 /* Modify single bit */ 1734 if (v) 1735 val |= (1 << fan); /* Set to manual */ 1736 else 1737 val &= ~(1 << fan); /* Set to auto */ 1738 1739 /* Write back */ 1740 buf[0] = val >> 8; 1741 buf[1] = val & 0xff; 1742 error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf, 1743 sizeof(buf)); 1744 } 1745 } 1746 1747 return (error); 1748 } 1749 1750 /* 1751 * Temperature functions. 1752 */ 1753 static int 1754 asmc_temp_getvalue(device_t dev, const char *key) 1755 { 1756 uint8_t buf[2]; 1757 1758 /* 1759 * Check for invalid temperatures. 1760 */ 1761 if (asmc_key_read(dev, key, buf, sizeof(buf)) != 0) 1762 return (-1); 1763 1764 return (buf[0]); 1765 } 1766 1767 static int 1768 asmc_temp_sysctl(SYSCTL_HANDLER_ARGS) 1769 { 1770 device_t dev = (device_t)arg1; 1771 struct asmc_softc *sc = device_get_softc(dev); 1772 int error, val; 1773 1774 val = asmc_temp_getvalue(dev, sc->sc_model->smc_temps[arg2]); 1775 error = sysctl_handle_int(oidp, &val, 0, req); 1776 1777 return (error); 1778 } 1779 1780 /* 1781 * Sudden Motion Sensor functions. 1782 */ 1783 static int 1784 asmc_sms_read(device_t dev, const char *key, int16_t *val) 1785 { 1786 uint8_t buf[2]; 1787 int error; 1788 1789 /* no need to do locking here as asmc_key_read() already does it */ 1790 switch (key[3]) { 1791 case 'X': 1792 case 'Y': 1793 case 'Z': 1794 error = asmc_key_read(dev, key, buf, sizeof(buf)); 1795 break; 1796 default: 1797 device_printf(dev, "%s called with invalid argument %s\n", 1798 __func__, key); 1799 error = EINVAL; 1800 goto out; 1801 } 1802 *val = ((int16_t)buf[0] << 8) | buf[1]; 1803 out: 1804 return (error); 1805 } 1806 1807 static void 1808 asmc_sms_calibrate(device_t dev) 1809 { 1810 struct asmc_softc *sc = device_get_softc(dev); 1811 1812 asmc_sms_read(dev, ASMC_KEY_SMS_X, &sc->sms_rest_x); 1813 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &sc->sms_rest_y); 1814 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &sc->sms_rest_z); 1815 } 1816 1817 static int 1818 asmc_sms_intrfast(void *arg) 1819 { 1820 uint8_t type; 1821 device_t dev = (device_t)arg; 1822 struct asmc_softc *sc = device_get_softc(dev); 1823 if (!sc->sc_sms_intr_works) 1824 return (FILTER_HANDLED); 1825 1826 mtx_lock_spin(&sc->sc_mtx); 1827 type = ASMC_INTPORT_READ(sc); 1828 mtx_unlock_spin(&sc->sc_mtx); 1829 1830 sc->sc_sms_intrtype = type; 1831 asmc_sms_printintr(dev, type); 1832 1833 taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task); 1834 return (FILTER_HANDLED); 1835 } 1836 1837 static void 1838 asmc_sms_printintr(device_t dev, uint8_t type) 1839 { 1840 struct asmc_softc *sc = device_get_softc(dev); 1841 1842 switch (type) { 1843 case ASMC_SMS_INTFF: 1844 device_printf(dev, "WARNING: possible free fall!\n"); 1845 break; 1846 case ASMC_SMS_INTHA: 1847 device_printf(dev, "WARNING: high acceleration detected!\n"); 1848 break; 1849 case ASMC_SMS_INTSH: 1850 device_printf(dev, "WARNING: possible shock!\n"); 1851 break; 1852 case ASMC_ALSL_INT2A: 1853 /* 1854 * This suppresses console and log messages for the ambient 1855 * light sensor for models known to generate this interrupt. 1856 */ 1857 if (strcmp(sc->sc_model->smc_model, "MacBookPro5,5") == 0 || 1858 strcmp(sc->sc_model->smc_model, "MacBookPro6,2") == 0) 1859 break; 1860 /* FALLTHROUGH */ 1861 default: 1862 device_printf(dev, "unknown interrupt: 0x%x\n", type); 1863 } 1864 } 1865 1866 static void 1867 asmc_sms_task(void *arg, int pending) 1868 { 1869 struct asmc_softc *sc = (struct asmc_softc *)arg; 1870 char notify[16]; 1871 int type; 1872 1873 switch (sc->sc_sms_intrtype) { 1874 case ASMC_SMS_INTFF: 1875 type = 2; 1876 break; 1877 case ASMC_SMS_INTHA: 1878 type = 1; 1879 break; 1880 case ASMC_SMS_INTSH: 1881 type = 0; 1882 break; 1883 default: 1884 type = 255; 1885 } 1886 1887 snprintf(notify, sizeof(notify), " notify=0x%x", type); 1888 devctl_notify("ACPI", "asmc", "SMS", notify); 1889 } 1890 1891 static int 1892 asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS) 1893 { 1894 device_t dev = (device_t)arg1; 1895 int error; 1896 int16_t val; 1897 int32_t v; 1898 1899 asmc_sms_read(dev, ASMC_KEY_SMS_X, &val); 1900 v = (int32_t)val; 1901 error = sysctl_handle_int(oidp, &v, 0, req); 1902 1903 return (error); 1904 } 1905 1906 static int 1907 asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS) 1908 { 1909 device_t dev = (device_t)arg1; 1910 int error; 1911 int16_t val; 1912 int32_t v; 1913 1914 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val); 1915 v = (int32_t)val; 1916 error = sysctl_handle_int(oidp, &v, 0, req); 1917 1918 return (error); 1919 } 1920 1921 static int 1922 asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS) 1923 { 1924 device_t dev = (device_t)arg1; 1925 int error; 1926 int16_t val; 1927 int32_t v; 1928 1929 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val); 1930 v = (int32_t)val; 1931 error = sysctl_handle_int(oidp, &v, 0, req); 1932 1933 return (error); 1934 } 1935 1936 static int 1937 asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS) 1938 { 1939 device_t dev = (device_t)arg1; 1940 uint8_t buf[6]; 1941 int error; 1942 int32_t v; 1943 1944 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); 1945 v = buf[2]; 1946 error = sysctl_handle_int(oidp, &v, 0, req); 1947 1948 return (error); 1949 } 1950 1951 static int 1952 asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS) 1953 { 1954 device_t dev = (device_t)arg1; 1955 uint8_t buf[6]; 1956 int error; 1957 int32_t v; 1958 1959 asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof(buf)); 1960 v = buf[2]; 1961 error = sysctl_handle_int(oidp, &v, 0, req); 1962 1963 return (error); 1964 } 1965 1966 static int 1967 asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) 1968 { 1969 device_t dev = (device_t)arg1; 1970 struct asmc_softc *sc = device_get_softc(dev); 1971 uint8_t buf[2]; 1972 int error; 1973 int v; 1974 1975 v = light_control; 1976 error = sysctl_handle_int(oidp, &v, 0, req); 1977 1978 if (error == 0 && req->newptr != NULL) { 1979 if (v < 0 || v > 255) 1980 return (EINVAL); 1981 light_control = v; 1982 sc->sc_kbd_bkl_level = v * 100 / 255; 1983 buf[0] = light_control; 1984 buf[1] = 0x00; 1985 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 1986 } 1987 return (error); 1988 } 1989 1990 static int 1991 asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS) 1992 { 1993 device_t dev = (device_t)arg1; 1994 uint8_t buf[10]; 1995 int error; 1996 uint32_t v; 1997 1998 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); 1999 2000 /* 2001 * This seems to be a 32 bit big endian value from buf[6] -> buf[9]. 2002 * 2003 * Extract it out manually here, then shift/clamp it. 2004 */ 2005 v = be32dec(&buf[6]); 2006 2007 /* 2008 * Shift out, clamp at 255; that way it looks like the 2009 * earlier SMC firmware version responses. 2010 */ 2011 v = v >> 8; 2012 if (v > 255) 2013 v = 255; 2014 2015 error = sysctl_handle_int(oidp, &v, 0, req); 2016 2017 return (error); 2018 } 2019 2020 /* 2021 * Wake-on-LAN convenience sysctl. 2022 * Reading returns 1 if WoL is enabled, 0 if disabled. 2023 * Writing 1 enables WoL, 0 disables it. 2024 */ 2025 static int 2026 asmc_wol_sysctl(SYSCTL_HANDLER_ARGS) 2027 { 2028 device_t dev = (device_t)arg1; 2029 uint8_t aupo; 2030 int val, error; 2031 2032 /* Read current AUPO value */ 2033 if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) 2034 return (EIO); 2035 2036 val = (aupo != 0) ? 1 : 0; 2037 error = sysctl_handle_int(oidp, &val, 0, req); 2038 if (error != 0 || req->newptr == NULL) 2039 return (error); 2040 2041 /* Clamp to 0 or 1 */ 2042 aupo = (val != 0) ? 1 : 0; 2043 2044 /* Write AUPO */ 2045 if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) 2046 return (EIO); 2047 2048 return (0); 2049 } 2050 2051 static int 2052 asmc_backlight_update_status(device_t dev, struct backlight_props *props) 2053 { 2054 struct asmc_softc *sc = device_get_softc(dev); 2055 uint8_t buf[2]; 2056 2057 sc->sc_kbd_bkl_level = props->brightness; 2058 light_control = props->brightness * 255 / 100; 2059 buf[0] = light_control; 2060 buf[1] = 0x00; 2061 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 2062 2063 return (0); 2064 } 2065 2066 static int 2067 asmc_backlight_get_status(device_t dev, struct backlight_props *props) 2068 { 2069 struct asmc_softc *sc = device_get_softc(dev); 2070 2071 props->brightness = sc->sc_kbd_bkl_level; 2072 props->nlevels = 0; 2073 2074 return (0); 2075 } 2076 2077 static int 2078 asmc_backlight_get_info(device_t dev, struct backlight_info *info) 2079 { 2080 info->type = BACKLIGHT_TYPE_KEYBOARD; 2081 strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH); 2082 2083 return (0); 2084 } 2085