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 static int asmc_key_getinfo(device_t, const char *, uint8_t *, char *); 127 128 #ifdef ASMC_DEBUG 129 /* Raw key access */ 130 static int asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS); 131 static int asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS); 132 static int asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS); 133 static int asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS); 134 #endif 135 136 /* Voltage/Current/Power/Light sensor support */ 137 static int asmc_sensor_read(device_t, const char *, int *); 138 static int asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS); 139 static int asmc_detect_sensors(device_t); 140 static int asmc_key_dump_by_index(device_t, int, char *, char *, uint8_t *); 141 142 struct asmc_model { 143 const char *smc_model; /* smbios.system.product env var. */ 144 const char *smc_desc; /* driver description */ 145 146 /* Helper functions */ 147 int (*smc_sms_x)(SYSCTL_HANDLER_ARGS); 148 int (*smc_sms_y)(SYSCTL_HANDLER_ARGS); 149 int (*smc_sms_z)(SYSCTL_HANDLER_ARGS); 150 int (*smc_fan_id)(SYSCTL_HANDLER_ARGS); 151 int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS); 152 int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS); 153 int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS); 154 int (*smc_fan_maxspeed)(SYSCTL_HANDLER_ARGS); 155 int (*smc_fan_targetspeed)(SYSCTL_HANDLER_ARGS); 156 int (*smc_light_left)(SYSCTL_HANDLER_ARGS); 157 int (*smc_light_right)(SYSCTL_HANDLER_ARGS); 158 int (*smc_light_control)(SYSCTL_HANDLER_ARGS); 159 160 const char *smc_temps[ASMC_TEMP_MAX]; 161 const char *smc_tempnames[ASMC_TEMP_MAX]; 162 const char *smc_tempdescs[ASMC_TEMP_MAX]; 163 }; 164 165 static const struct asmc_model *asmc_match(device_t dev); 166 167 #define ASMC_SMS_FUNCS \ 168 .smc_sms_x = asmc_mb_sysctl_sms_x, \ 169 .smc_sms_y = asmc_mb_sysctl_sms_y, \ 170 .smc_sms_z = asmc_mb_sysctl_sms_z 171 172 #define ASMC_SMS_FUNCS_DISABLED \ 173 .smc_sms_x = NULL, \ 174 .smc_sms_y = NULL, \ 175 .smc_sms_z = NULL 176 177 #define ASMC_FAN_FUNCS \ 178 .smc_fan_id = asmc_mb_sysctl_fanid, \ 179 .smc_fan_speed = asmc_mb_sysctl_fanspeed, \ 180 .smc_fan_safespeed = asmc_mb_sysctl_fansafespeed, \ 181 .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \ 182 .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \ 183 .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed 184 185 #define ASMC_FAN_FUNCS2 \ 186 .smc_fan_id = asmc_mb_sysctl_fanid, \ 187 .smc_fan_speed = asmc_mb_sysctl_fanspeed, \ 188 .smc_fan_safespeed = NULL, \ 189 .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \ 190 .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \ 191 .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed 192 193 #define ASMC_LIGHT_FUNCS \ 194 .smc_light_left = asmc_mbp_sysctl_light_left, \ 195 .smc_light_right = asmc_mbp_sysctl_light_right, \ 196 .smc_light_control = asmc_mbp_sysctl_light_control 197 198 #define ASMC_LIGHT_FUNCS_10BYTE \ 199 .smc_light_left = asmc_mbp_sysctl_light_left_10byte, \ 200 .smc_light_right = NULL, \ 201 .smc_light_control = asmc_mbp_sysctl_light_control 202 203 #define ASMC_LIGHT_FUNCS_DISABLED \ 204 .smc_light_left = NULL, \ 205 .smc_light_right = NULL, \ 206 .smc_light_control = NULL 207 208 #define ASMC_TEMPS_FUNCS_DISABLED \ 209 .smc_temps = {}, \ 210 .smc_tempnames = {}, \ 211 .smc_tempdescs = {} \ 212 213 static const struct asmc_model asmc_models[] = { 214 { 215 "MacBook1,1", "Apple SMC MacBook Core Duo", 216 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 217 ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS 218 }, 219 220 { 221 "MacBook2,1", "Apple SMC MacBook Core 2 Duo", 222 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 223 ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS 224 }, 225 226 { 227 "MacBook3,1", "Apple SMC MacBook Core 2 Duo", 228 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 229 ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS 230 }, 231 232 { 233 "MacBook7,1", "Apple SMC MacBook Core 2 Duo (mid 2010)", 234 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS_DISABLED, 235 ASMC_MB71_TEMPS, ASMC_MB71_TEMPNAMES, ASMC_MB71_TEMPDESCS 236 }, 237 238 { 239 "MacBookPro1,1", "Apple SMC MacBook Pro Core Duo (15-inch)", 240 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 241 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 242 }, 243 244 { 245 "MacBookPro1,2", "Apple SMC MacBook Pro Core Duo (17-inch)", 246 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 247 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 248 }, 249 250 { 251 "MacBookPro2,1", "Apple SMC MacBook Pro Core 2 Duo (17-inch)", 252 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 253 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 254 }, 255 256 { 257 "MacBookPro2,2", "Apple SMC MacBook Pro Core 2 Duo (15-inch)", 258 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 259 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 260 }, 261 262 { 263 "MacBookPro3,1", "Apple SMC MacBook Pro Core 2 Duo (15-inch LED)", 264 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 265 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 266 }, 267 268 { 269 "MacBookPro3,2", "Apple SMC MacBook Pro Core 2 Duo (17-inch HD)", 270 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 271 ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS 272 }, 273 274 { 275 "MacBookPro4,1", "Apple SMC MacBook Pro Core 2 Duo (Penryn)", 276 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 277 ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS 278 }, 279 280 { 281 "MacBookPro5,1", "Apple SMC MacBook Pro Core 2 Duo (2008/2009)", 282 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 283 ASMC_MBP51_TEMPS, ASMC_MBP51_TEMPNAMES, ASMC_MBP51_TEMPDESCS 284 }, 285 286 { 287 "MacBookPro5,5", "Apple SMC MacBook Pro Core 2 Duo (Mid 2009)", 288 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 289 ASMC_MBP55_TEMPS, ASMC_MBP55_TEMPNAMES, ASMC_MBP55_TEMPDESCS 290 }, 291 292 { 293 "MacBookPro6,2", "Apple SMC MacBook Pro (Mid 2010, 15-inch)", 294 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 295 ASMC_MBP62_TEMPS, ASMC_MBP62_TEMPNAMES, ASMC_MBP62_TEMPDESCS 296 }, 297 298 { 299 "MacBookPro8,1", "Apple SMC MacBook Pro (early 2011, 13-inch)", 300 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 301 ASMC_MBP81_TEMPS, ASMC_MBP81_TEMPNAMES, ASMC_MBP81_TEMPDESCS 302 }, 303 304 { 305 "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)", 306 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 307 ASMC_MBP82_TEMPS, ASMC_MBP82_TEMPNAMES, ASMC_MBP82_TEMPDESCS 308 }, 309 310 { 311 "MacBookPro8,3", "Apple SMC MacBook Pro (early 2011, 17-inch)", 312 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 313 ASMC_MBP83_TEMPS, ASMC_MBP83_TEMPNAMES, ASMC_MBP83_TEMPDESCS 314 }, 315 316 { 317 "MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)", 318 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 319 ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS 320 }, 321 322 { 323 "MacBookPro9,2", "Apple SMC MacBook Pro (mid 2012, 13-inch)", 324 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 325 ASMC_MBP92_TEMPS, ASMC_MBP92_TEMPNAMES, ASMC_MBP92_TEMPDESCS 326 }, 327 328 { 329 "MacBookPro11,2", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)", 330 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 331 ASMC_MBP112_TEMPS, ASMC_MBP112_TEMPNAMES, ASMC_MBP112_TEMPDESCS 332 }, 333 334 { 335 "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)", 336 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, 337 ASMC_MBP113_TEMPS, ASMC_MBP113_TEMPNAMES, ASMC_MBP113_TEMPDESCS 338 }, 339 340 { 341 "MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)", 342 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 343 ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS 344 }, 345 346 { 347 "MacBookPro11,5", 348 "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch, AMD GPU)", 349 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 350 ASMC_MBP115_TEMPS, ASMC_MBP115_TEMPNAMES, ASMC_MBP115_TEMPDESCS 351 }, 352 353 { 354 "MacBookPro13,1", "Apple SMC MacBook Pro Retina Core i5 (late 2016, 13-inch)", 355 ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, 356 ASMC_MBP131_TEMPS, ASMC_MBP131_TEMPNAMES, ASMC_MBP131_TEMPDESCS 357 }, 358 359 /* The Mac Mini has no SMS */ 360 { 361 "Macmini1,1", "Apple SMC Mac Mini", 362 ASMC_SMS_FUNCS_DISABLED, 363 ASMC_FAN_FUNCS, 364 ASMC_LIGHT_FUNCS_DISABLED, 365 ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS 366 }, 367 368 /* The Mac Mini 2,1 has no SMS */ 369 { 370 "Macmini2,1", "Apple SMC Mac Mini 2,1", 371 ASMC_SMS_FUNCS_DISABLED, 372 ASMC_FAN_FUNCS, 373 ASMC_LIGHT_FUNCS_DISABLED, 374 ASMC_MM21_TEMPS, ASMC_MM21_TEMPNAMES, ASMC_MM21_TEMPDESCS 375 }, 376 377 /* The Mac Mini 3,1 has no SMS */ 378 { 379 "Macmini3,1", "Apple SMC Mac Mini 3,1", 380 ASMC_SMS_FUNCS_DISABLED, 381 ASMC_FAN_FUNCS, 382 ASMC_LIGHT_FUNCS_DISABLED, 383 ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS 384 }, 385 386 /* The Mac Mini 4,1 (Mid-2010) has no SMS */ 387 { 388 "Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)", 389 ASMC_SMS_FUNCS_DISABLED, 390 ASMC_FAN_FUNCS2, 391 ASMC_LIGHT_FUNCS_DISABLED, 392 ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS 393 }, 394 395 /* The Mac Mini 5,1 has no SMS */ 396 /* - same sensors as Mac Mini 5,2 */ 397 { 398 "Macmini5,1", "Apple SMC Mac Mini 5,1", 399 ASMC_SMS_FUNCS_DISABLED, 400 ASMC_FAN_FUNCS2, 401 ASMC_LIGHT_FUNCS_DISABLED, 402 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 403 }, 404 405 /* The Mac Mini 5,2 has no SMS */ 406 { 407 "Macmini5,2", "Apple SMC Mac Mini 5,2", 408 ASMC_SMS_FUNCS_DISABLED, 409 ASMC_FAN_FUNCS2, 410 ASMC_LIGHT_FUNCS_DISABLED, 411 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 412 }, 413 414 /* The Mac Mini 5,3 has no SMS */ 415 /* - same sensors as Mac Mini 5,2 */ 416 { 417 "Macmini5,3", "Apple SMC Mac Mini 5,3", 418 ASMC_SMS_FUNCS_DISABLED, 419 ASMC_FAN_FUNCS2, 420 ASMC_LIGHT_FUNCS_DISABLED, 421 ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS 422 }, 423 424 /* The Mac Mini 6,1 has no SMS */ 425 { 426 "Macmini6,1", "Apple SMC Mac Mini 6,1", 427 ASMC_SMS_FUNCS_DISABLED, 428 ASMC_FAN_FUNCS2, 429 ASMC_LIGHT_FUNCS_DISABLED, 430 ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS 431 }, 432 433 /* The Mac Mini 6,2 has no SMS */ 434 { 435 "Macmini6,2", "Apple SMC Mac Mini 6,2", 436 ASMC_SMS_FUNCS_DISABLED, 437 ASMC_FAN_FUNCS2, 438 ASMC_LIGHT_FUNCS_DISABLED, 439 ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS 440 }, 441 442 /* The Mac Mini 7,1 has no SMS */ 443 { 444 "Macmini7,1", "Apple SMC Mac Mini 7,1", 445 ASMC_SMS_FUNCS_DISABLED, 446 ASMC_FAN_FUNCS2, 447 ASMC_LIGHT_FUNCS_DISABLED, 448 ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS 449 }, 450 451 /* Idem for the Mac Pro "Quad Core" (original) */ 452 { 453 "MacPro1,1", "Apple SMC Mac Pro (Quad Core)", 454 ASMC_SMS_FUNCS_DISABLED, 455 ASMC_FAN_FUNCS, 456 ASMC_LIGHT_FUNCS_DISABLED, 457 ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS 458 }, 459 460 /* Idem for the Mac Pro (Early 2008) */ 461 { 462 "MacPro3,1", "Apple SMC Mac Pro (Early 2008)", 463 ASMC_SMS_FUNCS_DISABLED, 464 ASMC_FAN_FUNCS, 465 ASMC_LIGHT_FUNCS_DISABLED, 466 ASMC_MP31_TEMPS, ASMC_MP31_TEMPNAMES, ASMC_MP31_TEMPDESCS 467 }, 468 469 /* Idem for the Mac Pro (8-core) */ 470 { 471 "MacPro2", "Apple SMC Mac Pro (8-core)", 472 ASMC_SMS_FUNCS_DISABLED, 473 ASMC_FAN_FUNCS, 474 ASMC_LIGHT_FUNCS_DISABLED, 475 ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS 476 }, 477 478 /* Idem for the MacPro 2010*/ 479 { 480 "MacPro5,1", "Apple SMC MacPro (2010)", 481 ASMC_SMS_FUNCS_DISABLED, 482 ASMC_FAN_FUNCS, 483 ASMC_LIGHT_FUNCS_DISABLED, 484 ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS 485 }, 486 487 /* Idem for the Mac Pro 2013 (cylinder) */ 488 { 489 "MacPro6,1", "Apple SMC Mac Pro (2013)", 490 ASMC_SMS_FUNCS_DISABLED, 491 ASMC_FAN_FUNCS2, 492 ASMC_LIGHT_FUNCS_DISABLED, 493 ASMC_MP6_TEMPS, ASMC_MP6_TEMPNAMES, ASMC_MP6_TEMPDESCS 494 }, 495 496 { 497 "MacBookAir1,1", "Apple SMC MacBook Air", 498 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 499 ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS 500 }, 501 502 { 503 "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)", 504 ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, 505 ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS 506 }, 507 508 { 509 "MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)", 510 ASMC_SMS_FUNCS_DISABLED, 511 ASMC_FAN_FUNCS2, 512 ASMC_LIGHT_FUNCS, 513 ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS 514 }, 515 516 { 517 "MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)", 518 ASMC_SMS_FUNCS_DISABLED, 519 ASMC_FAN_FUNCS2, 520 ASMC_LIGHT_FUNCS, 521 ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS 522 }, 523 524 { 525 "MacBookAir5,1", "Apple SMC MacBook Air 11-inch (Mid 2012)", 526 ASMC_SMS_FUNCS_DISABLED, 527 ASMC_FAN_FUNCS2, 528 ASMC_LIGHT_FUNCS, 529 ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS 530 }, 531 532 { 533 "MacBookAir5,2", "Apple SMC MacBook Air 13-inch (Mid 2012)", 534 ASMC_SMS_FUNCS_DISABLED, 535 ASMC_FAN_FUNCS2, 536 ASMC_LIGHT_FUNCS, 537 ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS 538 }, 539 { 540 "MacBookAir6,1", "Apple SMC MacBook Air 11-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 "MacBookAir6,2", "Apple SMC MacBook Air 13-inch (Early 2013)", 548 ASMC_SMS_FUNCS_DISABLED, 549 ASMC_FAN_FUNCS2, 550 ASMC_LIGHT_FUNCS_10BYTE, 551 ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS 552 }, 553 { 554 "MacBookAir7,1", "Apple SMC MacBook Air 11-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 "MacBookAir7,2", "Apple SMC MacBook Air 13-inch (Early 2015)", 562 ASMC_SMS_FUNCS_DISABLED, 563 ASMC_FAN_FUNCS2, 564 ASMC_LIGHT_FUNCS, 565 ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS 566 } 567 }; 568 569 static const struct asmc_model asmc_generic_models[] = { 570 { 571 .smc_model = "MacBookAir", 572 .smc_desc = NULL, 573 ASMC_SMS_FUNCS_DISABLED, 574 ASMC_FAN_FUNCS2, 575 ASMC_LIGHT_FUNCS, 576 ASMC_TEMPS_FUNCS_DISABLED 577 }, 578 { 579 .smc_model = "MacBookPro", 580 .smc_desc = NULL, 581 ASMC_SMS_FUNCS_DISABLED, 582 ASMC_FAN_FUNCS2, 583 ASMC_LIGHT_FUNCS, 584 ASMC_TEMPS_FUNCS_DISABLED 585 }, 586 { 587 .smc_model = "MacPro", 588 .smc_desc = NULL, 589 ASMC_SMS_FUNCS_DISABLED, 590 ASMC_FAN_FUNCS2, 591 ASMC_LIGHT_FUNCS_DISABLED, 592 ASMC_TEMPS_FUNCS_DISABLED 593 }, 594 { 595 .smc_model = "Macmini", 596 .smc_desc = NULL, 597 ASMC_SMS_FUNCS_DISABLED, 598 ASMC_FAN_FUNCS2, 599 ASMC_LIGHT_FUNCS_DISABLED, 600 ASMC_TEMPS_FUNCS_DISABLED 601 } 602 }; 603 604 #undef ASMC_SMS_FUNCS 605 #undef ASMC_SMS_FUNCS_DISABLED 606 #undef ASMC_FAN_FUNCS 607 #undef ASMC_FAN_FUNCS2 608 #undef ASMC_LIGHT_FUNCS 609 610 /* 611 * Driver methods. 612 */ 613 static device_method_t asmc_methods[] = { 614 DEVMETHOD(device_probe, asmc_probe), 615 DEVMETHOD(device_attach, asmc_attach), 616 DEVMETHOD(device_detach, asmc_detach), 617 DEVMETHOD(device_resume, asmc_resume), 618 619 /* Backlight interface */ 620 DEVMETHOD(backlight_update_status, asmc_backlight_update_status), 621 DEVMETHOD(backlight_get_status, asmc_backlight_get_status), 622 DEVMETHOD(backlight_get_info, asmc_backlight_get_info), 623 624 DEVMETHOD_END 625 }; 626 627 static driver_t asmc_driver = { 628 "asmc", 629 asmc_methods, 630 sizeof(struct asmc_softc) 631 }; 632 633 /* 634 * Debugging 635 */ 636 #define _COMPONENT ACPI_OEM 637 ACPI_MODULE_NAME("ASMC") 638 #ifdef ASMC_DEBUG 639 #define ASMC_DPRINTF(str, ...) device_printf(dev, str, ##__VA_ARGS__) 640 #else 641 #define ASMC_DPRINTF(str, ...) 642 #endif 643 644 /* NB: can't be const */ 645 static char *asmc_ids[] = { "APP0001", NULL }; 646 647 static unsigned int light_control = 0; 648 649 ACPI_PNP_INFO(asmc_ids); 650 DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL); 651 MODULE_DEPEND(asmc, acpi, 1, 1, 1); 652 MODULE_DEPEND(asmc, backlight, 1, 1, 1); 653 654 static const struct asmc_model * 655 asmc_match(device_t dev) 656 { 657 const struct asmc_model *model; 658 char *model_name; 659 int i; 660 661 model = NULL; 662 663 model_name = kern_getenv("smbios.system.product"); 664 if (model_name == NULL) 665 goto out; 666 667 for (i = 0; i < nitems(asmc_models); i++) { 668 if (strncmp(model_name, asmc_models[i].smc_model, 669 strlen(model_name)) == 0) { 670 model = &asmc_models[i]; 671 goto out; 672 } 673 } 674 for (i = 0; i < nitems(asmc_generic_models); i++) { 675 if (strncmp(model_name, asmc_generic_models[i].smc_model, 676 strlen(asmc_generic_models[i].smc_model)) == 0) { 677 model = &asmc_generic_models[i]; 678 goto out; 679 } 680 } 681 682 out: 683 freeenv(model_name); 684 return (model); 685 } 686 687 static int 688 asmc_probe(device_t dev) 689 { 690 const struct asmc_model *model; 691 const char *device_desc; 692 int rv; 693 694 if (resource_disabled("asmc", 0)) 695 return (ENXIO); 696 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids, NULL); 697 if (rv > 0) 698 return (rv); 699 700 model = asmc_match(dev); 701 if (model == NULL) { 702 device_printf(dev, "model not recognized\n"); 703 return (ENXIO); 704 } 705 device_desc = model->smc_desc == NULL ? 706 model->smc_model : model->smc_desc; 707 device_set_desc(dev, device_desc); 708 709 return (rv); 710 } 711 712 static int 713 asmc_attach(device_t dev) 714 { 715 int i, j; 716 int ret; 717 char name[2]; 718 struct asmc_softc *sc = device_get_softc(dev); 719 struct sysctl_ctx_list *sysctlctx; 720 struct sysctl_oid *sysctlnode; 721 const struct asmc_model *model; 722 723 sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 724 &sc->sc_rid_port, RF_ACTIVE); 725 if (sc->sc_ioport == NULL) { 726 device_printf(dev, "unable to allocate IO port\n"); 727 return (ENOMEM); 728 } 729 730 sysctlctx = device_get_sysctl_ctx(dev); 731 sysctlnode = device_get_sysctl_tree(dev); 732 733 model = asmc_match(dev); 734 735 mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN); 736 737 sc->sc_model = model; 738 asmc_init(dev); 739 740 /* 741 * dev.asmc.n.fan.* tree. 742 */ 743 sc->sc_fan_tree[0] = SYSCTL_ADD_NODE(sysctlctx, 744 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "fan", 745 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Root Tree"); 746 747 for (i = 1; i <= sc->sc_nfan; i++) { 748 j = i - 1; 749 name[0] = '0' + j; 750 name[1] = 0; 751 sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx, 752 SYSCTL_CHILDREN(sc->sc_fan_tree[0]), OID_AUTO, name, 753 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Subtree"); 754 755 SYSCTL_ADD_PROC(sysctlctx, 756 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 757 OID_AUTO, "id", 758 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 759 model->smc_fan_id, "I", "Fan ID"); 760 761 SYSCTL_ADD_PROC(sysctlctx, 762 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 763 OID_AUTO, "speed", 764 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 765 model->smc_fan_speed, "I", "Fan speed in RPM"); 766 767 SYSCTL_ADD_PROC(sysctlctx, 768 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 769 OID_AUTO, "safespeed", 770 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, 771 model->smc_fan_safespeed, "I", "Fan safe speed in RPM"); 772 773 SYSCTL_ADD_PROC(sysctlctx, 774 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 775 OID_AUTO, "minspeed", 776 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 777 model->smc_fan_minspeed, "I", "Fan minimum speed in RPM"); 778 779 SYSCTL_ADD_PROC(sysctlctx, 780 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 781 OID_AUTO, "maxspeed", 782 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 783 model->smc_fan_maxspeed, "I", "Fan maximum speed in RPM"); 784 785 SYSCTL_ADD_PROC(sysctlctx, 786 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 787 OID_AUTO, "targetspeed", 788 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 789 model->smc_fan_targetspeed, "I", "Fan target speed in RPM"); 790 791 SYSCTL_ADD_PROC(sysctlctx, 792 SYSCTL_CHILDREN(sc->sc_fan_tree[i]), 793 OID_AUTO, "manual", 794 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, 795 asmc_mb_sysctl_fanmanual, "I", 796 "Fan manual mode (0=auto, 1=manual)"); 797 } 798 799 /* 800 * dev.asmc.n.temp tree. 801 */ 802 sc->sc_temp_tree = SYSCTL_ADD_NODE(sysctlctx, 803 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "temp", 804 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Temperature sensors"); 805 806 for (i = 0; model->smc_temps[i]; i++) { 807 SYSCTL_ADD_PROC(sysctlctx, 808 SYSCTL_CHILDREN(sc->sc_temp_tree), 809 OID_AUTO, model->smc_tempnames[i], 810 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i, 811 asmc_temp_sysctl, "I", 812 model->smc_tempdescs[i]); 813 } 814 815 /* 816 * dev.asmc.n.light 817 */ 818 if (model->smc_light_left) { 819 sc->sc_light_tree = SYSCTL_ADD_NODE(sysctlctx, 820 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "light", 821 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 822 "Keyboard backlight sensors"); 823 824 SYSCTL_ADD_PROC(sysctlctx, 825 SYSCTL_CHILDREN(sc->sc_light_tree), 826 OID_AUTO, "left", 827 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 828 dev, 0, model->smc_light_left, "I", 829 "Keyboard backlight left sensor"); 830 831 SYSCTL_ADD_PROC(sysctlctx, 832 SYSCTL_CHILDREN(sc->sc_light_tree), 833 OID_AUTO, "right", 834 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, 835 model->smc_light_right, "I", 836 "Keyboard backlight right sensor"); 837 838 SYSCTL_ADD_PROC(sysctlctx, 839 SYSCTL_CHILDREN(sc->sc_light_tree), 840 OID_AUTO, "control", 841 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, 842 dev, 0, model->smc_light_control, "I", 843 "Keyboard backlight brightness control"); 844 845 sc->sc_kbd_bkl = backlight_register("asmc", dev); 846 if (sc->sc_kbd_bkl == NULL) { 847 device_printf(dev, "Can not register backlight\n"); 848 ret = ENXIO; 849 goto err; 850 } 851 } 852 853 #ifdef ASMC_DEBUG 854 /* 855 * Raw SMC key access for debugging. 856 */ 857 sc->sc_raw_tree = SYSCTL_ADD_NODE(sysctlctx, 858 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 859 "raw", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Raw SMC key access"); 860 861 SYSCTL_ADD_PROC(sysctlctx, 862 SYSCTL_CHILDREN(sc->sc_raw_tree), 863 OID_AUTO, "key", 864 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 865 dev, 0, asmc_raw_key_sysctl, "A", 866 "SMC key name (4 chars)"); 867 868 SYSCTL_ADD_PROC(sysctlctx, 869 SYSCTL_CHILDREN(sc->sc_raw_tree), 870 OID_AUTO, "value", 871 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 872 dev, 0, asmc_raw_value_sysctl, "A", 873 "SMC key value (hex string)"); 874 875 SYSCTL_ADD_PROC(sysctlctx, 876 SYSCTL_CHILDREN(sc->sc_raw_tree), 877 OID_AUTO, "len", 878 CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, 879 dev, 0, asmc_raw_len_sysctl, "CU", 880 "SMC key value length"); 881 882 SYSCTL_ADD_PROC(sysctlctx, 883 SYSCTL_CHILDREN(sc->sc_raw_tree), 884 OID_AUTO, "type", 885 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 886 dev, 0, asmc_raw_type_sysctl, "A", 887 "SMC key type (4 chars)"); 888 #endif 889 890 if (model->smc_sms_x == NULL) 891 goto nosms; 892 893 /* 894 * dev.asmc.n.sms tree. 895 */ 896 sc->sc_sms_tree = SYSCTL_ADD_NODE(sysctlctx, 897 SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "sms", 898 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Sudden Motion Sensor"); 899 900 SYSCTL_ADD_PROC(sysctlctx, 901 SYSCTL_CHILDREN(sc->sc_sms_tree), 902 OID_AUTO, "x", 903 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 904 dev, 0, model->smc_sms_x, "I", 905 "Sudden Motion Sensor X value"); 906 907 SYSCTL_ADD_PROC(sysctlctx, 908 SYSCTL_CHILDREN(sc->sc_sms_tree), 909 OID_AUTO, "y", 910 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 911 dev, 0, model->smc_sms_y, "I", 912 "Sudden Motion Sensor Y value"); 913 914 SYSCTL_ADD_PROC(sysctlctx, 915 SYSCTL_CHILDREN(sc->sc_sms_tree), 916 OID_AUTO, "z", 917 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 918 dev, 0, model->smc_sms_z, "I", 919 "Sudden Motion Sensor Z value"); 920 921 /* 922 * Need a taskqueue to send devctl_notify() events 923 * when the SMS interrupt us. 924 * 925 * PI_REALTIME is used due to the sensitivity of the 926 * interrupt. An interrupt from the SMS means that the 927 * disk heads should be turned off as quickly as possible. 928 * 929 * We only need to do this for the non INTR_FILTER case. 930 */ 931 sc->sc_sms_tq = NULL; 932 TASK_INIT(&sc->sc_sms_task, 0, asmc_sms_task, sc); 933 sc->sc_sms_tq = taskqueue_create_fast("asmc_taskq", M_WAITOK, 934 taskqueue_thread_enqueue, &sc->sc_sms_tq); 935 taskqueue_start_threads(&sc->sc_sms_tq, 1, PI_REALTIME, "%s sms taskq", 936 device_get_nameunit(dev)); 937 /* 938 * Allocate an IRQ for the SMS. 939 */ 940 sc->sc_rid_irq = 0; 941 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, 942 RF_ACTIVE); 943 if (sc->sc_irq == NULL) { 944 device_printf(dev, "unable to allocate IRQ resource\n"); 945 ret = ENXIO; 946 goto err; 947 } 948 949 ret = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, 950 asmc_sms_intrfast, NULL, dev, &sc->sc_cookie); 951 if (ret) { 952 device_printf(dev, "unable to setup SMS IRQ\n"); 953 goto err; 954 } 955 956 nosms: 957 return (0); 958 959 err: 960 asmc_detach(dev); 961 962 return (ret); 963 } 964 965 static int 966 asmc_detach(device_t dev) 967 { 968 struct asmc_softc *sc = device_get_softc(dev); 969 970 if (sc->sc_kbd_bkl != NULL) 971 backlight_destroy(sc->sc_kbd_bkl); 972 973 /* Free sensor key arrays */ 974 for (int i = 0; i < sc->sc_voltage_count; i++) 975 free(sc->sc_voltage_sensors[i], M_DEVBUF); 976 for (int i = 0; i < sc->sc_current_count; i++) 977 free(sc->sc_current_sensors[i], M_DEVBUF); 978 for (int i = 0; i < sc->sc_power_count; i++) 979 free(sc->sc_power_sensors[i], M_DEVBUF); 980 for (int i = 0; i < sc->sc_light_count; i++) 981 free(sc->sc_light_sensors[i], M_DEVBUF); 982 983 if (sc->sc_sms_tq) { 984 taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task); 985 taskqueue_free(sc->sc_sms_tq); 986 sc->sc_sms_tq = NULL; 987 } 988 if (sc->sc_cookie) { 989 bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie); 990 sc->sc_cookie = NULL; 991 } 992 if (sc->sc_irq) { 993 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, 994 sc->sc_irq); 995 sc->sc_irq = NULL; 996 } 997 if (sc->sc_ioport) { 998 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, 999 sc->sc_ioport); 1000 sc->sc_ioport = NULL; 1001 } 1002 if (mtx_initialized(&sc->sc_mtx)) { 1003 mtx_destroy(&sc->sc_mtx); 1004 } 1005 1006 return (0); 1007 } 1008 1009 static int 1010 asmc_resume(device_t dev) 1011 { 1012 uint8_t buf[2]; 1013 1014 buf[0] = light_control; 1015 buf[1] = 0x00; 1016 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 1017 1018 return (0); 1019 } 1020 1021 #ifdef ASMC_DEBUG 1022 void 1023 asmc_dumpall(device_t dev) 1024 { 1025 struct asmc_softc *sc = device_get_softc(dev); 1026 int i; 1027 1028 if (sc->sc_nkeys == 0) { 1029 device_printf(dev, "asmc_dumpall: key count not available\n"); 1030 return; 1031 } 1032 1033 device_printf(dev, "asmc_dumpall: dumping %d keys\n", sc->sc_nkeys); 1034 for (i = 0; i < sc->sc_nkeys; i++) 1035 asmc_key_dump(dev, i); 1036 } 1037 #endif 1038 1039 static int 1040 asmc_init(device_t dev) 1041 { 1042 struct asmc_softc *sc = device_get_softc(dev); 1043 struct sysctl_ctx_list *sysctlctx; 1044 uint8_t buf[6]; 1045 int i, error = 1; 1046 1047 sysctlctx = device_get_sysctl_ctx(dev); 1048 1049 error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6); 1050 if (error != 0) 1051 goto out_err; 1052 device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2], 1053 ntohs(*(uint16_t *)buf + 4)); 1054 1055 if (sc->sc_model->smc_sms_x == NULL) 1056 goto nosms; 1057 1058 /* 1059 * We are ready to receive interrupts from the SMS. 1060 */ 1061 buf[0] = 0x01; 1062 ASMC_DPRINTF(("intok key\n")); 1063 asmc_key_write(dev, ASMC_KEY_INTOK, buf, 1); 1064 DELAY(50); 1065 1066 /* 1067 * Initiate the polling intervals. 1068 */ 1069 buf[0] = 20; /* msecs */ 1070 ASMC_DPRINTF(("low int key\n")); 1071 asmc_key_write(dev, ASMC_KEY_SMS_LOW_INT, buf, 1); 1072 DELAY(200); 1073 1074 buf[0] = 20; /* msecs */ 1075 ASMC_DPRINTF(("high int key\n")); 1076 asmc_key_write(dev, ASMC_KEY_SMS_HIGH_INT, buf, 1); 1077 DELAY(200); 1078 1079 buf[0] = 0x00; 1080 buf[1] = 0x60; 1081 ASMC_DPRINTF(("sms low key\n")); 1082 asmc_key_write(dev, ASMC_KEY_SMS_LOW, buf, 2); 1083 DELAY(200); 1084 1085 buf[0] = 0x01; 1086 buf[1] = 0xc0; 1087 ASMC_DPRINTF(("sms high key\n")); 1088 asmc_key_write(dev, ASMC_KEY_SMS_HIGH, buf, 2); 1089 DELAY(200); 1090 1091 /* 1092 * I'm not sure what this key does, but it seems to be 1093 * required. 1094 */ 1095 buf[0] = 0x01; 1096 ASMC_DPRINTF(("sms flag key\n")); 1097 asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1); 1098 DELAY(100); 1099 1100 sc->sc_sms_intr_works = 0; 1101 1102 /* 1103 * Retry SMS initialization 1000 times 1104 * (takes approx. 2 seconds in worst case) 1105 */ 1106 for (i = 0; i < 1000; i++) { 1107 if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 && 1108 (buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) { 1109 error = 0; 1110 sc->sc_sms_intr_works = 1; 1111 goto out; 1112 } 1113 buf[0] = ASMC_SMS_INIT1; 1114 buf[1] = ASMC_SMS_INIT2; 1115 ASMC_DPRINTF(("sms key\n")); 1116 asmc_key_write(dev, ASMC_KEY_SMS, buf, 2); 1117 DELAY(50); 1118 } 1119 device_printf(dev, "WARNING: Sudden Motion Sensor not initialized!\n"); 1120 1121 out: 1122 asmc_sms_calibrate(dev); 1123 nosms: 1124 /* Wake-on-LAN convenience sysctl */ 1125 if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) { 1126 SYSCTL_ADD_PROC(sysctlctx, 1127 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1128 OID_AUTO, "wol", 1129 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 1130 dev, 0, asmc_wol_sysctl, "I", 1131 "Wake-on-LAN enable (0=off, 1=on)"); 1132 } 1133 1134 sc->sc_nfan = asmc_fan_count(dev); 1135 if (sc->sc_nfan > ASMC_MAXFANS) { 1136 device_printf(dev, 1137 "more than %d fans were detected. Please report this.\n", 1138 ASMC_MAXFANS); 1139 sc->sc_nfan = ASMC_MAXFANS; 1140 } 1141 1142 /* 1143 * Read and cache the number of SMC keys (32 bit buffer) 1144 */ 1145 if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) { 1146 sc->sc_nkeys = be32dec(buf); 1147 if (bootverbose) 1148 device_printf(dev, "number of keys: %d\n", 1149 sc->sc_nkeys); 1150 } else { 1151 sc->sc_nkeys = 0; 1152 } 1153 1154 /* 1155 * Auto-detect and register voltage/current/power/ambient sensors. 1156 * Scans SMC keys and creates sysctls for detected sensors. 1157 */ 1158 asmc_detect_sensors(dev); 1159 1160 out_err: 1161 #ifdef ASMC_DEBUG 1162 asmc_dumpall(dev); 1163 #endif 1164 return (error); 1165 } 1166 1167 /* 1168 * We need to make sure that the SMC acks the byte sent. 1169 * Just wait up to (amount * 10) ms. 1170 */ 1171 static int 1172 asmc_wait_ack(device_t dev, uint8_t val, int amount) 1173 { 1174 struct asmc_softc *sc = device_get_softc(dev); 1175 u_int i; 1176 1177 val = val & ASMC_STATUS_MASK; 1178 1179 for (i = 0; i < amount; i++) { 1180 if ((ASMC_CMDPORT_READ(sc) & ASMC_STATUS_MASK) == val) 1181 return (0); 1182 DELAY(10); 1183 } 1184 1185 return (1); 1186 } 1187 1188 /* 1189 * We need to make sure that the SMC acks the byte sent. 1190 * Just wait up to 100 ms. 1191 */ 1192 static int 1193 asmc_wait(device_t dev, uint8_t val) 1194 { 1195 #ifdef ASMC_DEBUG 1196 struct asmc_softc *sc; 1197 #endif 1198 1199 if (asmc_wait_ack(dev, val, 1000) == 0) 1200 return (0); 1201 1202 #ifdef ASMC_DEBUG 1203 sc = device_get_softc(dev); 1204 1205 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, 1206 val & ASMC_STATUS_MASK, ASMC_CMDPORT_READ(sc)); 1207 #endif 1208 return (1); 1209 } 1210 1211 /* 1212 * Send the given command, retrying up to 10 times if 1213 * the acknowledgement fails. 1214 */ 1215 static int 1216 asmc_command(device_t dev, uint8_t command) 1217 { 1218 int i; 1219 struct asmc_softc *sc = device_get_softc(dev); 1220 1221 for (i = 0; i < 10; i++) { 1222 ASMC_CMDPORT_WRITE(sc, command); 1223 if (asmc_wait_ack(dev, 0x0c, 100) == 0) { 1224 return (0); 1225 } 1226 } 1227 1228 #ifdef ASMC_DEBUG 1229 device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, command, 1230 ASMC_CMDPORT_READ(sc)); 1231 #endif 1232 return (1); 1233 } 1234 1235 static int 1236 asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1237 { 1238 int i, error = 1, try = 0; 1239 struct asmc_softc *sc = device_get_softc(dev); 1240 1241 mtx_lock_spin(&sc->sc_mtx); 1242 1243 begin: 1244 if (asmc_command(dev, ASMC_CMDREAD)) 1245 goto out; 1246 1247 for (i = 0; i < 4; i++) { 1248 ASMC_DATAPORT_WRITE(sc, key[i]); 1249 if (asmc_wait(dev, 0x04)) 1250 goto out; 1251 } 1252 1253 ASMC_DATAPORT_WRITE(sc, len); 1254 1255 for (i = 0; i < len; i++) { 1256 if (asmc_wait(dev, 0x05)) 1257 goto out; 1258 buf[i] = ASMC_DATAPORT_READ(sc); 1259 } 1260 1261 error = 0; 1262 out: 1263 if (error) { 1264 if (++try < 10) 1265 goto begin; 1266 device_printf(dev, "%s for key %s failed %d times, giving up\n", 1267 __func__, key, try); 1268 } 1269 1270 mtx_unlock_spin(&sc->sc_mtx); 1271 1272 return (error); 1273 } 1274 1275 #ifdef ASMC_DEBUG 1276 static int 1277 asmc_key_dump(device_t dev, int number) 1278 { 1279 struct asmc_softc *sc = device_get_softc(dev); 1280 char key[ASMC_KEYLEN + 1] = { 0 }; 1281 char type[ASMC_KEYINFO_RESPLEN + 1] = { 0 }; 1282 uint8_t index[4]; 1283 uint8_t v[ASMC_MAXVAL]; 1284 uint8_t maxlen; 1285 int i, error = 1, try = 0; 1286 1287 mtx_lock_spin(&sc->sc_mtx); 1288 1289 index[0] = (number >> 24) & 0xff; 1290 index[1] = (number >> 16) & 0xff; 1291 index[2] = (number >> 8) & 0xff; 1292 index[3] = number & 0xff; 1293 1294 begin: 1295 if (asmc_command(dev, ASMC_CMDGETBYINDEX)) 1296 goto out; 1297 1298 for (i = 0; i < ASMC_KEYLEN; i++) { 1299 ASMC_DATAPORT_WRITE(sc, index[i]); 1300 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1301 goto out; 1302 } 1303 1304 ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN); 1305 1306 for (i = 0; i < ASMC_KEYLEN; i++) { 1307 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1308 goto out; 1309 key[i] = ASMC_DATAPORT_READ(sc); 1310 } 1311 1312 /* Get key info (length + type). */ 1313 if (asmc_command(dev, ASMC_CMDGETINFO)) 1314 goto out; 1315 1316 for (i = 0; i < ASMC_KEYLEN; i++) { 1317 ASMC_DATAPORT_WRITE(sc, key[i]); 1318 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1319 goto out; 1320 } 1321 1322 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1323 1324 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1325 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1326 goto out; 1327 type[i] = ASMC_DATAPORT_READ(sc); 1328 } 1329 1330 error = 0; 1331 out: 1332 if (error) { 1333 if (++try < ASMC_MAXRETRIES) 1334 goto begin; 1335 device_printf(dev, 1336 "%s for key %d failed %d times, giving up\n", 1337 __func__, number, try); 1338 } 1339 mtx_unlock_spin(&sc->sc_mtx); 1340 1341 if (error) 1342 return (error); 1343 1344 maxlen = type[0]; 1345 type[0] = ' '; 1346 type[5] = '\0'; 1347 if (maxlen > sizeof(v)) 1348 maxlen = sizeof(v); 1349 1350 memset(v, 0, sizeof(v)); 1351 error = asmc_key_read(dev, key, v, maxlen); 1352 if (error) 1353 return (error); 1354 1355 device_printf(dev, "key %d: %s, type%s (len %d), data", 1356 number, key, type, maxlen); 1357 for (i = 0; i < maxlen; i++) 1358 printf(" %02x", v[i]); 1359 printf("\n"); 1360 1361 return (0); 1362 } 1363 #endif /* ASMC_DEBUG */ 1364 1365 /* 1366 * Get key info (length and type) from SMC using command 0x13. 1367 * If len is non-NULL, stores the key's value length. 1368 * If type is non-NULL, stores the 4-char type string (must be at least 5 bytes). 1369 */ 1370 static int 1371 asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type) 1372 { 1373 struct asmc_softc *sc = device_get_softc(dev); 1374 uint8_t info[ASMC_KEYINFO_RESPLEN]; 1375 int i, error = -1, try = 0; 1376 1377 mtx_lock_spin(&sc->sc_mtx); 1378 1379 begin: 1380 if (asmc_command(dev, ASMC_CMDGETINFO)) 1381 goto out; 1382 1383 for (i = 0; i < ASMC_KEYLEN; i++) { 1384 ASMC_DATAPORT_WRITE(sc, key[i]); 1385 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1386 goto out; 1387 } 1388 1389 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1390 1391 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1392 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1393 goto out; 1394 info[i] = ASMC_DATAPORT_READ(sc); 1395 } 1396 1397 error = 0; 1398 out: 1399 if (error && ++try < ASMC_MAXRETRIES) 1400 goto begin; 1401 mtx_unlock_spin(&sc->sc_mtx); 1402 1403 if (error == 0) { 1404 if (len != NULL) 1405 *len = info[0]; 1406 if (type != NULL) { 1407 for (i = 0; i < ASMC_TYPELEN; i++) 1408 type[i] = info[i + 1]; 1409 type[ASMC_TYPELEN] = '\0'; 1410 } 1411 } 1412 return (error); 1413 } 1414 1415 #ifdef ASMC_DEBUG 1416 /* 1417 * Raw SMC key access sysctls - enables reading/writing any SMC key by name 1418 * Usage: 1419 * sysctl dev.asmc.0.raw.key=AUPO # Set key, auto-detects length 1420 * sysctl dev.asmc.0.raw.value # Read current value (hex bytes) 1421 * sysctl dev.asmc.0.raw.value=01 # Write new value 1422 */ 1423 static int 1424 asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS) 1425 { 1426 device_t dev = (device_t) arg1; 1427 struct asmc_softc *sc = device_get_softc(dev); 1428 char newkey[ASMC_KEYLEN + 1]; 1429 uint8_t keylen; 1430 int error; 1431 1432 strlcpy(newkey, sc->sc_rawkey, sizeof(newkey)); 1433 error = sysctl_handle_string(oidp, newkey, sizeof(newkey), req); 1434 if (error || req->newptr == NULL) 1435 return (error); 1436 1437 if (strlen(newkey) != ASMC_KEYLEN) 1438 return (EINVAL); 1439 1440 /* Get key info to auto-detect length and type */ 1441 if (asmc_key_getinfo(dev, newkey, &keylen, sc->sc_rawtype) != 0) 1442 return (ENOENT); 1443 1444 if (keylen > ASMC_MAXVAL) 1445 keylen = ASMC_MAXVAL; 1446 1447 strlcpy(sc->sc_rawkey, newkey, sizeof(sc->sc_rawkey)); 1448 sc->sc_rawlen = keylen; 1449 memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); 1450 1451 /* Read the key value */ 1452 asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen); 1453 1454 return (0); 1455 } 1456 1457 static int 1458 asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS) 1459 { 1460 device_t dev = (device_t) arg1; 1461 struct asmc_softc *sc = device_get_softc(dev); 1462 char hexbuf[ASMC_MAXVAL * 2 + 1]; 1463 int error, i; 1464 1465 /* Refresh from SMC if a key has been selected. */ 1466 if (sc->sc_rawkey[0] != '\0') { 1467 asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, 1468 sc->sc_rawlen > 0 ? sc->sc_rawlen : ASMC_MAXVAL); 1469 } 1470 1471 /* Format as hex string */ 1472 for (i = 0; i < sc->sc_rawlen && i < ASMC_MAXVAL; i++) 1473 snprintf(hexbuf + i * 2, 3, "%02x", sc->sc_rawval[i]); 1474 hexbuf[i * 2] = '\0'; 1475 1476 error = sysctl_handle_string(oidp, hexbuf, sizeof(hexbuf), req); 1477 if (error || req->newptr == NULL) 1478 return (error); 1479 1480 /* Reject writes until a key is selected via raw.key. */ 1481 if (sc->sc_rawkey[0] == '\0') 1482 return (EINVAL); 1483 1484 memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); 1485 for (i = 0; i < sc->sc_rawlen && hexbuf[i*2] && hexbuf[i*2+1]; i++) { 1486 unsigned int val; 1487 char tmp[3] = { hexbuf[i*2], hexbuf[i*2+1], 0 }; 1488 if (sscanf(tmp, "%02x", &val) == 1) 1489 sc->sc_rawval[i] = (uint8_t)val; 1490 } 1491 1492 if (asmc_key_write(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen) != 0) 1493 return (EIO); 1494 1495 return (0); 1496 } 1497 1498 static int 1499 asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS) 1500 { 1501 device_t dev = (device_t) arg1; 1502 struct asmc_softc *sc = device_get_softc(dev); 1503 1504 return (sysctl_handle_8(oidp, &sc->sc_rawlen, 0, req)); 1505 } 1506 1507 static int 1508 asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS) 1509 { 1510 device_t dev = (device_t) arg1; 1511 struct asmc_softc *sc = device_get_softc(dev); 1512 1513 return (sysctl_handle_string(oidp, sc->sc_rawtype, 1514 sizeof(sc->sc_rawtype), req)); 1515 } 1516 #endif 1517 1518 /* 1519 * Convert signed fixed-point SMC values to milli-units. 1520 * Format "spXY" means signed with X integer bits and Y fraction bits. 1521 */ 1522 static int 1523 asmc_sp78_to_milli(const uint8_t *buf) 1524 { 1525 int16_t val = (int16_t)be16dec(buf); 1526 1527 return ((int)val * 1000) / 256; 1528 } 1529 1530 static int 1531 asmc_sp87_to_milli(const uint8_t *buf) 1532 { 1533 int16_t val = (int16_t)be16dec(buf); 1534 1535 return ((int)val * 1000) / 128; 1536 } 1537 1538 static int 1539 asmc_sp4b_to_milli(const uint8_t *buf) 1540 { 1541 int16_t val = (int16_t)be16dec(buf); 1542 1543 return ((int)val * 1000) / 2048; 1544 } 1545 1546 static int 1547 asmc_sp5a_to_milli(const uint8_t *buf) 1548 { 1549 int16_t val = (int16_t)be16dec(buf); 1550 1551 return ((int)val * 1000) / 1024; 1552 } 1553 1554 static int 1555 asmc_sp69_to_milli(const uint8_t *buf) 1556 { 1557 int16_t val = (int16_t)be16dec(buf); 1558 1559 return ((int)val * 1000) / 512; 1560 } 1561 1562 static int 1563 asmc_sp96_to_milli(const uint8_t *buf) 1564 { 1565 int16_t val = (int16_t)be16dec(buf); 1566 1567 return ((int)val * 1000) / 64; 1568 } 1569 1570 static int 1571 asmc_sp2d_to_milli(const uint8_t *buf) 1572 { 1573 int16_t val = (int16_t)be16dec(buf); 1574 1575 return ((int)val * 1000) / 8192; 1576 } 1577 1578 static bool 1579 asmc_sensor_type_supported(const char *type) 1580 { 1581 1582 return (strncmp(type, "sp78", 4) == 0 || 1583 strncmp(type, "sp87", 4) == 0 || 1584 strncmp(type, "sp4b", 4) == 0 || 1585 strncmp(type, "sp5a", 4) == 0 || 1586 strncmp(type, "sp69", 4) == 0 || 1587 strncmp(type, "sp96", 4) == 0 || 1588 strncmp(type, "sp2d", 4) == 0 || 1589 strncmp(type, "ui16", 4) == 0); 1590 } 1591 1592 /* 1593 * Generic sensor value reader with automatic type conversion. 1594 * Reads an SMC key, detects its type, and converts to millivalue. 1595 */ 1596 static int 1597 asmc_sensor_read(device_t dev, const char *key, int *millivalue) 1598 { 1599 uint8_t buf[2]; 1600 char type[ASMC_TYPELEN + 1]; 1601 uint8_t len; 1602 int error; 1603 1604 error = asmc_key_getinfo(dev, key, &len, type); 1605 if (error != 0) 1606 return (error); 1607 1608 if (len != 2) { 1609 if (bootverbose) 1610 device_printf(dev, 1611 "%s: key %s unexpected length %d\n", 1612 __func__, key, len); 1613 return (ENXIO); 1614 } 1615 1616 error = asmc_key_read(dev, key, buf, sizeof(buf)); 1617 if (error != 0) 1618 return (error); 1619 1620 if (strncmp(type, "sp78", 4) == 0) { 1621 *millivalue = asmc_sp78_to_milli(buf); 1622 } else if (strncmp(type, "sp87", 4) == 0) { 1623 *millivalue = asmc_sp87_to_milli(buf); 1624 } else if (strncmp(type, "sp4b", 4) == 0) { 1625 *millivalue = asmc_sp4b_to_milli(buf); 1626 } else if (strncmp(type, "sp5a", 4) == 0) { 1627 *millivalue = asmc_sp5a_to_milli(buf); 1628 } else if (strncmp(type, "sp69", 4) == 0) { 1629 *millivalue = asmc_sp69_to_milli(buf); 1630 } else if (strncmp(type, "sp96", 4) == 0) { 1631 *millivalue = asmc_sp96_to_milli(buf); 1632 } else if (strncmp(type, "sp2d", 4) == 0) { 1633 *millivalue = asmc_sp2d_to_milli(buf); 1634 } else if (strncmp(type, "ui16", 4) == 0) { 1635 *millivalue = be16dec(buf); 1636 } else { 1637 if (bootverbose) 1638 device_printf(dev, 1639 "%s: unknown type '%s' for key %s\n", 1640 __func__, type, key); 1641 return (ENXIO); 1642 } 1643 1644 return (0); 1645 } 1646 1647 /* 1648 * Generic sensor sysctl handler for voltage/current/power/light sensors. 1649 * arg2 encodes: sensor_type (high byte) | sensor_index (low byte) 1650 * Sensor types: 'V'=voltage, 'I'=current, 'P'=power, 'L'=light 1651 */ 1652 static int 1653 asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS) 1654 { 1655 device_t dev = (device_t) arg1; 1656 struct asmc_softc *sc = device_get_softc(dev); 1657 int error, val; 1658 int sensor_type = (arg2 >> 8) & 0xFF; 1659 int sensor_idx = arg2 & 0xFF; 1660 const char *key = NULL; 1661 1662 /* Select sensor based on type and index */ 1663 switch (sensor_type) { 1664 case 'V': /* Voltage */ 1665 if (sensor_idx < sc->sc_voltage_count) 1666 key = sc->sc_voltage_sensors[sensor_idx]; 1667 break; 1668 case 'I': /* Current */ 1669 if (sensor_idx < sc->sc_current_count) 1670 key = sc->sc_current_sensors[sensor_idx]; 1671 break; 1672 case 'P': /* Power */ 1673 if (sensor_idx < sc->sc_power_count) 1674 key = sc->sc_power_sensors[sensor_idx]; 1675 break; 1676 case 'L': /* Light */ 1677 if (sensor_idx < sc->sc_light_count) 1678 key = sc->sc_light_sensors[sensor_idx]; 1679 break; 1680 default: 1681 return (EINVAL); 1682 } 1683 1684 if (key == NULL) 1685 return (ENOENT); 1686 1687 error = asmc_sensor_read(dev, key, &val); 1688 if (error != 0) 1689 return (error); 1690 1691 return (sysctl_handle_int(oidp, &val, 0, req)); 1692 } 1693 1694 /* 1695 * Detect and register voltage/current/power/ambient sensors. 1696 * Scans all SMC keys and identifies sensor keys by prefix. 1697 * Returns 0 on success, -1 on error. 1698 */ 1699 static int 1700 asmc_detect_sensors(device_t dev) 1701 { 1702 struct asmc_softc *sc = device_get_softc(dev); 1703 struct sysctl_ctx_list *sysctlctx; 1704 struct sysctl_oid *tree_node; 1705 char key[ASMC_KEYLEN + 1]; 1706 char type[ASMC_TYPELEN + 1]; 1707 uint8_t len; 1708 unsigned int nkeys; 1709 unsigned int i; 1710 int error; 1711 char *sensor_key; 1712 1713 /* Initialize counts */ 1714 sc->sc_voltage_count = 0; 1715 sc->sc_current_count = 0; 1716 sc->sc_power_count = 0; 1717 sc->sc_light_count = 0; 1718 1719 if (sc->sc_nkeys == 0) 1720 return (0); 1721 nkeys = sc->sc_nkeys; 1722 1723 /* Scan all keys for voltage/current/power/ambient light sensors */ 1724 for (i = 0; i < nkeys; i++) { 1725 /* Get key name by index */ 1726 error = asmc_key_dump_by_index(dev, i, key, type, &len); 1727 if (error != 0) 1728 continue; 1729 if (!asmc_sensor_type_supported(type)) 1730 continue; 1731 1732 /* Voltage sensors (VC*, VD*, VG*, VP*, VI*) */ 1733 if (key[0] == 'V' && (key[1] == 'C' || key[1] == 'D' || 1734 key[1] == 'G' || key[1] == 'P' || key[1] == 'I') && 1735 len == 2) { 1736 if (sc->sc_voltage_count >= ASMC_MAX_SENSORS) 1737 continue; 1738 sensor_key = malloc(ASMC_KEYLEN + 1, 1739 M_DEVBUF, M_WAITOK); 1740 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1741 sc->sc_voltage_sensors[sc->sc_voltage_count++] = 1742 sensor_key; 1743 } else if (key[0] == 'I' && (key[1] == 'C' || 1744 key[1] == 'D' || key[1] == 'G' || key[1] == 'M' || 1745 key[1] == 'N' || key[1] == 'O' || key[1] == 'H' || 1746 key[1] == 'P' || key[1] == 'B' || key[1] == 'A' || 1747 key[1] == 'L') && len == 2) { 1748 /* Current sensors */ 1749 if (sc->sc_current_count >= ASMC_MAX_SENSORS) 1750 continue; 1751 sensor_key = malloc(ASMC_KEYLEN + 1, 1752 M_DEVBUF, M_WAITOK); 1753 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1754 sc->sc_current_sensors[sc->sc_current_count++] = 1755 sensor_key; 1756 } else if (key[0] == 'P' && (key[1] == 'C' || 1757 key[1] == 'D' || key[1] == 'N' || key[1] == 'S' || 1758 key[1] == 'T' || key[1] == 'H' || key[1] == 'F' || 1759 key[1] == 'Z' || key[1] == 'z') && len == 2) { 1760 /* Power sensors */ 1761 if (sc->sc_power_count >= ASMC_MAX_SENSORS) 1762 continue; 1763 sensor_key = malloc(ASMC_KEYLEN + 1, 1764 M_DEVBUF, M_WAITOK); 1765 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1766 sc->sc_power_sensors[sc->sc_power_count++] = 1767 sensor_key; 1768 } else if (key[0] == 'A' && key[1] == 'L' && 1769 (key[2] == 'V' || key[2] == 'S') && len == 2) { 1770 /* Ambient light sensors */ 1771 if (sc->sc_light_count >= ASMC_MAX_SENSORS) 1772 continue; 1773 sensor_key = malloc(ASMC_KEYLEN + 1, 1774 M_DEVBUF, M_WAITOK); 1775 memcpy(sensor_key, key, ASMC_KEYLEN + 1); 1776 sc->sc_light_sensors[sc->sc_light_count++] = 1777 sensor_key; 1778 } 1779 } 1780 1781 if (bootverbose) 1782 device_printf(dev, 1783 "detected %d voltage, %d current, " 1784 "%d power, %d light sensors\n", 1785 sc->sc_voltage_count, sc->sc_current_count, 1786 sc->sc_power_count, sc->sc_light_count); 1787 1788 /* Register sysctls for detected sensors */ 1789 sysctlctx = device_get_sysctl_ctx(dev); 1790 1791 /* Voltage sensors */ 1792 if (sc->sc_voltage_count > 0) { 1793 tree_node = SYSCTL_ADD_NODE(sysctlctx, 1794 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1795 "voltage", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Voltage sensors (millivolts)"); 1796 1797 for (i = 0; i < sc->sc_voltage_count; i++) { 1798 SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), 1799 OID_AUTO, sc->sc_voltage_sensors[i], 1800 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 1801 dev, ('V' << 8) | i, asmc_sensor_sysctl, "I", 1802 "Voltage sensor (millivolts)"); 1803 } 1804 } 1805 1806 /* Current sensors */ 1807 if (sc->sc_current_count > 0) { 1808 tree_node = SYSCTL_ADD_NODE(sysctlctx, 1809 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1810 "current", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Current sensors (milliamps)"); 1811 1812 for (i = 0; i < sc->sc_current_count; i++) { 1813 SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), 1814 OID_AUTO, sc->sc_current_sensors[i], 1815 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 1816 dev, ('I' << 8) | i, asmc_sensor_sysctl, "I", 1817 "Current sensor (milliamps)"); 1818 } 1819 } 1820 1821 /* Power sensors */ 1822 if (sc->sc_power_count > 0) { 1823 tree_node = SYSCTL_ADD_NODE(sysctlctx, 1824 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1825 "power", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Power sensors (milliwatts)"); 1826 1827 for (i = 0; i < sc->sc_power_count; i++) { 1828 SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), 1829 OID_AUTO, sc->sc_power_sensors[i], 1830 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 1831 dev, ('P' << 8) | i, asmc_sensor_sysctl, "I", 1832 "Power sensor (milliwatts)"); 1833 } 1834 } 1835 1836 /* Ambient light sensors */ 1837 if (sc->sc_light_count > 0) { 1838 tree_node = SYSCTL_ADD_NODE(sysctlctx, 1839 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1840 "ambient", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Ambient light sensors"); 1841 1842 for (i = 0; i < sc->sc_light_count; i++) { 1843 SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), 1844 OID_AUTO, sc->sc_light_sensors[i], 1845 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 1846 dev, ('L' << 8) | i, asmc_sensor_sysctl, "I", 1847 "Light sensor value"); 1848 } 1849 } 1850 1851 return (0); 1852 } 1853 1854 /* 1855 * Helper function to get key info by index (for sensor detection). 1856 */ 1857 static int 1858 asmc_key_dump_by_index(device_t dev, int index, char *key_out, 1859 char *type_out, uint8_t *len_out) 1860 { 1861 struct asmc_softc *sc = device_get_softc(dev); 1862 uint8_t index_buf[ASMC_KEYLEN]; 1863 uint8_t key_buf[ASMC_KEYLEN]; 1864 uint8_t info_buf[ASMC_KEYINFO_RESPLEN]; 1865 int error = ENXIO, try = 0; 1866 int i; 1867 1868 mtx_lock_spin(&sc->sc_mtx); 1869 1870 index_buf[0] = (index >> 24) & 0xff; 1871 index_buf[1] = (index >> 16) & 0xff; 1872 index_buf[2] = (index >> 8) & 0xff; 1873 index_buf[3] = index & 0xff; 1874 1875 begin: 1876 if (asmc_command(dev, ASMC_CMDGETBYINDEX)) 1877 goto out; 1878 1879 for (i = 0; i < ASMC_KEYLEN; i++) { 1880 ASMC_DATAPORT_WRITE(sc, index_buf[i]); 1881 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1882 goto out; 1883 } 1884 1885 ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN); 1886 1887 for (i = 0; i < ASMC_KEYLEN; i++) { 1888 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1889 goto out; 1890 key_buf[i] = ASMC_DATAPORT_READ(sc); 1891 } 1892 1893 if (asmc_command(dev, ASMC_CMDGETINFO)) 1894 goto out; 1895 1896 for (i = 0; i < ASMC_KEYLEN; i++) { 1897 ASMC_DATAPORT_WRITE(sc, key_buf[i]); 1898 if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) 1899 goto out; 1900 } 1901 1902 ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); 1903 1904 for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { 1905 if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) 1906 goto out; 1907 info_buf[i] = ASMC_DATAPORT_READ(sc); 1908 } 1909 1910 memcpy(key_out, key_buf, ASMC_KEYLEN); 1911 key_out[ASMC_KEYLEN] = '\0'; 1912 *len_out = info_buf[0]; 1913 memcpy(type_out, &info_buf[1], ASMC_TYPELEN); 1914 type_out[ASMC_TYPELEN] = '\0'; 1915 error = 0; 1916 1917 out: 1918 if (error) { 1919 if (++try < ASMC_MAXRETRIES) 1920 goto begin; 1921 } 1922 1923 mtx_unlock_spin(&sc->sc_mtx); 1924 return (error); 1925 } 1926 1927 static int 1928 asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len) 1929 { 1930 int i, error = -1, try = 0; 1931 struct asmc_softc *sc = device_get_softc(dev); 1932 1933 mtx_lock_spin(&sc->sc_mtx); 1934 1935 begin: 1936 ASMC_DPRINTF(("cmd port: cmd write\n")); 1937 if (asmc_command(dev, ASMC_CMDWRITE)) 1938 goto out; 1939 1940 ASMC_DPRINTF(("data port: key\n")); 1941 for (i = 0; i < 4; i++) { 1942 ASMC_DATAPORT_WRITE(sc, key[i]); 1943 if (asmc_wait(dev, 0x04)) 1944 goto out; 1945 } 1946 ASMC_DPRINTF(("data port: length\n")); 1947 ASMC_DATAPORT_WRITE(sc, len); 1948 1949 ASMC_DPRINTF(("data port: buffer\n")); 1950 for (i = 0; i < len; i++) { 1951 if (asmc_wait(dev, 0x04)) 1952 goto out; 1953 ASMC_DATAPORT_WRITE(sc, buf[i]); 1954 } 1955 1956 error = 0; 1957 out: 1958 if (error) { 1959 if (++try < 10) 1960 goto begin; 1961 device_printf(dev, "%s for key %s failed %d times, giving up\n", 1962 __func__, key, try); 1963 } 1964 1965 mtx_unlock_spin(&sc->sc_mtx); 1966 1967 return (error); 1968 } 1969 1970 /* 1971 * Fan control functions. 1972 */ 1973 static int 1974 asmc_fan_count(device_t dev) 1975 { 1976 uint8_t buf[1]; 1977 1978 if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof(buf)) != 0) 1979 return (-1); 1980 1981 return (buf[0]); 1982 } 1983 1984 static int 1985 asmc_fan_getvalue(device_t dev, const char *key, int fan) 1986 { 1987 int speed; 1988 uint8_t buf[2]; 1989 char fankey[5]; 1990 1991 snprintf(fankey, sizeof(fankey), key, fan); 1992 if (asmc_key_read(dev, fankey, buf, sizeof(buf)) != 0) 1993 return (-1); 1994 speed = (buf[0] << 6) | (buf[1] >> 2); 1995 1996 return (speed); 1997 } 1998 1999 static char * 2000 asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, 2001 uint8_t buflen) 2002 { 2003 char fankey[5]; 2004 char *desc; 2005 2006 snprintf(fankey, sizeof(fankey), key, fan); 2007 if (asmc_key_read(dev, fankey, buf, buflen) != 0) 2008 return (NULL); 2009 desc = buf + 4; 2010 2011 return (desc); 2012 } 2013 2014 static int 2015 asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed) 2016 { 2017 uint8_t buf[2]; 2018 char fankey[5]; 2019 2020 speed *= 4; 2021 2022 buf[0] = speed >> 8; 2023 buf[1] = speed; 2024 2025 snprintf(fankey, sizeof(fankey), key, fan); 2026 if (asmc_key_write(dev, fankey, buf, sizeof(buf)) < 0) 2027 return (-1); 2028 2029 return (0); 2030 } 2031 2032 static int 2033 asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS) 2034 { 2035 device_t dev = (device_t)arg1; 2036 int fan = arg2; 2037 int error; 2038 int32_t v; 2039 2040 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSPEED, fan); 2041 error = sysctl_handle_int(oidp, &v, 0, req); 2042 2043 return (error); 2044 } 2045 2046 static int 2047 asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS) 2048 { 2049 uint8_t buf[16]; 2050 device_t dev = (device_t)arg1; 2051 int fan = arg2; 2052 int error = true; 2053 char *desc; 2054 2055 desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf)); 2056 2057 if (desc != NULL) 2058 error = sysctl_handle_string(oidp, desc, 0, req); 2059 2060 return (error); 2061 } 2062 2063 static int 2064 asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS) 2065 { 2066 device_t dev = (device_t)arg1; 2067 int fan = arg2; 2068 int error; 2069 int32_t v; 2070 2071 v = asmc_fan_getvalue(dev, ASMC_KEY_FANSAFESPEED, fan); 2072 error = sysctl_handle_int(oidp, &v, 0, req); 2073 2074 return (error); 2075 } 2076 2077 static int 2078 asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS) 2079 { 2080 device_t dev = (device_t)arg1; 2081 int fan = arg2; 2082 int error; 2083 int32_t v; 2084 2085 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan); 2086 error = sysctl_handle_int(oidp, &v, 0, req); 2087 2088 if (error == 0 && req->newptr != NULL) { 2089 unsigned int newspeed = v; 2090 asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed); 2091 } 2092 2093 return (error); 2094 } 2095 2096 static int 2097 asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS) 2098 { 2099 device_t dev = (device_t)arg1; 2100 int fan = arg2; 2101 int error; 2102 int32_t v; 2103 2104 v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan); 2105 error = sysctl_handle_int(oidp, &v, 0, req); 2106 2107 if (error == 0 && req->newptr != NULL) { 2108 unsigned int newspeed = v; 2109 asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed); 2110 } 2111 2112 return (error); 2113 } 2114 2115 static int 2116 asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS) 2117 { 2118 device_t dev = (device_t)arg1; 2119 int fan = arg2; 2120 int error; 2121 int32_t v; 2122 2123 v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan); 2124 error = sysctl_handle_int(oidp, &v, 0, req); 2125 2126 if (error == 0 && req->newptr != NULL) { 2127 unsigned int newspeed = v; 2128 asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed); 2129 } 2130 2131 return (error); 2132 } 2133 2134 static int 2135 asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) 2136 { 2137 device_t dev = (device_t)arg1; 2138 int fan = arg2; 2139 int error; 2140 int32_t v; 2141 uint8_t buf[2]; 2142 uint16_t val; 2143 2144 /* Read current FS! bitmask (asmc_key_read locks internally) */ 2145 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); 2146 if (error != 0) 2147 return (error); 2148 2149 /* Extract manual bit for this fan (big-endian) */ 2150 val = (buf[0] << 8) | buf[1]; 2151 v = (val >> fan) & 0x01; 2152 2153 /* Let sysctl handle the value */ 2154 error = sysctl_handle_int(oidp, &v, 0, req); 2155 2156 if (error == 0 && req->newptr != NULL) { 2157 /* Validate input (0 = auto, 1 = manual) */ 2158 if (v != 0 && v != 1) 2159 return (EINVAL); 2160 /* Read-modify-write of FS! bitmask */ 2161 error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, 2162 sizeof(buf)); 2163 if (error == 0) { 2164 val = (buf[0] << 8) | buf[1]; 2165 2166 /* Modify single bit */ 2167 if (v) 2168 val |= (1 << fan); /* Set to manual */ 2169 else 2170 val &= ~(1 << fan); /* Set to auto */ 2171 2172 /* Write back */ 2173 buf[0] = val >> 8; 2174 buf[1] = val & 0xff; 2175 error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf, 2176 sizeof(buf)); 2177 } 2178 } 2179 2180 return (error); 2181 } 2182 2183 /* 2184 * Temperature functions. 2185 */ 2186 static int 2187 asmc_temp_getvalue(device_t dev, const char *key) 2188 { 2189 uint8_t buf[2]; 2190 2191 /* 2192 * Check for invalid temperatures. 2193 */ 2194 if (asmc_key_read(dev, key, buf, sizeof(buf)) != 0) 2195 return (-1); 2196 2197 return (buf[0]); 2198 } 2199 2200 static int 2201 asmc_temp_sysctl(SYSCTL_HANDLER_ARGS) 2202 { 2203 device_t dev = (device_t)arg1; 2204 struct asmc_softc *sc = device_get_softc(dev); 2205 int error, val; 2206 2207 val = asmc_temp_getvalue(dev, sc->sc_model->smc_temps[arg2]); 2208 error = sysctl_handle_int(oidp, &val, 0, req); 2209 2210 return (error); 2211 } 2212 2213 /* 2214 * Sudden Motion Sensor functions. 2215 */ 2216 static int 2217 asmc_sms_read(device_t dev, const char *key, int16_t *val) 2218 { 2219 uint8_t buf[2]; 2220 int error; 2221 2222 /* no need to do locking here as asmc_key_read() already does it */ 2223 switch (key[3]) { 2224 case 'X': 2225 case 'Y': 2226 case 'Z': 2227 error = asmc_key_read(dev, key, buf, sizeof(buf)); 2228 break; 2229 default: 2230 device_printf(dev, "%s called with invalid argument %s\n", 2231 __func__, key); 2232 error = EINVAL; 2233 goto out; 2234 } 2235 *val = ((int16_t)buf[0] << 8) | buf[1]; 2236 out: 2237 return (error); 2238 } 2239 2240 static void 2241 asmc_sms_calibrate(device_t dev) 2242 { 2243 struct asmc_softc *sc = device_get_softc(dev); 2244 2245 asmc_sms_read(dev, ASMC_KEY_SMS_X, &sc->sms_rest_x); 2246 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &sc->sms_rest_y); 2247 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &sc->sms_rest_z); 2248 } 2249 2250 static int 2251 asmc_sms_intrfast(void *arg) 2252 { 2253 uint8_t type; 2254 device_t dev = (device_t)arg; 2255 struct asmc_softc *sc = device_get_softc(dev); 2256 if (!sc->sc_sms_intr_works) 2257 return (FILTER_HANDLED); 2258 2259 mtx_lock_spin(&sc->sc_mtx); 2260 type = ASMC_INTPORT_READ(sc); 2261 mtx_unlock_spin(&sc->sc_mtx); 2262 2263 sc->sc_sms_intrtype = type; 2264 asmc_sms_printintr(dev, type); 2265 2266 taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task); 2267 return (FILTER_HANDLED); 2268 } 2269 2270 static void 2271 asmc_sms_printintr(device_t dev, uint8_t type) 2272 { 2273 struct asmc_softc *sc = device_get_softc(dev); 2274 2275 switch (type) { 2276 case ASMC_SMS_INTFF: 2277 device_printf(dev, "WARNING: possible free fall!\n"); 2278 break; 2279 case ASMC_SMS_INTHA: 2280 device_printf(dev, "WARNING: high acceleration detected!\n"); 2281 break; 2282 case ASMC_SMS_INTSH: 2283 device_printf(dev, "WARNING: possible shock!\n"); 2284 break; 2285 case ASMC_ALSL_INT2A: 2286 /* 2287 * This suppresses console and log messages for the ambient 2288 * light sensor for models known to generate this interrupt. 2289 */ 2290 if (strcmp(sc->sc_model->smc_model, "MacBookPro5,5") == 0 || 2291 strcmp(sc->sc_model->smc_model, "MacBookPro6,2") == 0) 2292 break; 2293 /* FALLTHROUGH */ 2294 default: 2295 device_printf(dev, "unknown interrupt: 0x%x\n", type); 2296 } 2297 } 2298 2299 static void 2300 asmc_sms_task(void *arg, int pending) 2301 { 2302 struct asmc_softc *sc = (struct asmc_softc *)arg; 2303 char notify[16]; 2304 int type; 2305 2306 switch (sc->sc_sms_intrtype) { 2307 case ASMC_SMS_INTFF: 2308 type = 2; 2309 break; 2310 case ASMC_SMS_INTHA: 2311 type = 1; 2312 break; 2313 case ASMC_SMS_INTSH: 2314 type = 0; 2315 break; 2316 default: 2317 type = 255; 2318 } 2319 2320 snprintf(notify, sizeof(notify), " notify=0x%x", type); 2321 devctl_notify("ACPI", "asmc", "SMS", notify); 2322 } 2323 2324 static int 2325 asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS) 2326 { 2327 device_t dev = (device_t)arg1; 2328 int error; 2329 int16_t val; 2330 int32_t v; 2331 2332 asmc_sms_read(dev, ASMC_KEY_SMS_X, &val); 2333 v = (int32_t)val; 2334 error = sysctl_handle_int(oidp, &v, 0, req); 2335 2336 return (error); 2337 } 2338 2339 static int 2340 asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS) 2341 { 2342 device_t dev = (device_t)arg1; 2343 int error; 2344 int16_t val; 2345 int32_t v; 2346 2347 asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val); 2348 v = (int32_t)val; 2349 error = sysctl_handle_int(oidp, &v, 0, req); 2350 2351 return (error); 2352 } 2353 2354 static int 2355 asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS) 2356 { 2357 device_t dev = (device_t)arg1; 2358 int error; 2359 int16_t val; 2360 int32_t v; 2361 2362 asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val); 2363 v = (int32_t)val; 2364 error = sysctl_handle_int(oidp, &v, 0, req); 2365 2366 return (error); 2367 } 2368 2369 static int 2370 asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS) 2371 { 2372 device_t dev = (device_t)arg1; 2373 uint8_t buf[6]; 2374 int error; 2375 int32_t v; 2376 2377 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); 2378 v = buf[2]; 2379 error = sysctl_handle_int(oidp, &v, 0, req); 2380 2381 return (error); 2382 } 2383 2384 static int 2385 asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS) 2386 { 2387 device_t dev = (device_t)arg1; 2388 uint8_t buf[6]; 2389 int error; 2390 int32_t v; 2391 2392 asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof(buf)); 2393 v = buf[2]; 2394 error = sysctl_handle_int(oidp, &v, 0, req); 2395 2396 return (error); 2397 } 2398 2399 static int 2400 asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) 2401 { 2402 device_t dev = (device_t)arg1; 2403 struct asmc_softc *sc = device_get_softc(dev); 2404 uint8_t buf[2]; 2405 int error; 2406 int v; 2407 2408 v = light_control; 2409 error = sysctl_handle_int(oidp, &v, 0, req); 2410 2411 if (error == 0 && req->newptr != NULL) { 2412 if (v < 0 || v > 255) 2413 return (EINVAL); 2414 light_control = v; 2415 sc->sc_kbd_bkl_level = v * 100 / 255; 2416 buf[0] = light_control; 2417 buf[1] = 0x00; 2418 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 2419 } 2420 return (error); 2421 } 2422 2423 static int 2424 asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS) 2425 { 2426 device_t dev = (device_t)arg1; 2427 uint8_t buf[10]; 2428 int error; 2429 uint32_t v; 2430 2431 asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); 2432 2433 /* 2434 * This seems to be a 32 bit big endian value from buf[6] -> buf[9]. 2435 * 2436 * Extract it out manually here, then shift/clamp it. 2437 */ 2438 v = be32dec(&buf[6]); 2439 2440 /* 2441 * Shift out, clamp at 255; that way it looks like the 2442 * earlier SMC firmware version responses. 2443 */ 2444 v = v >> 8; 2445 if (v > 255) 2446 v = 255; 2447 2448 error = sysctl_handle_int(oidp, &v, 0, req); 2449 2450 return (error); 2451 } 2452 2453 /* 2454 * Wake-on-LAN convenience sysctl. 2455 * Reading returns 1 if WoL is enabled, 0 if disabled. 2456 * Writing 1 enables WoL, 0 disables it. 2457 */ 2458 static int 2459 asmc_wol_sysctl(SYSCTL_HANDLER_ARGS) 2460 { 2461 device_t dev = (device_t)arg1; 2462 uint8_t aupo; 2463 int val, error; 2464 2465 /* Read current AUPO value */ 2466 if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) 2467 return (EIO); 2468 2469 val = (aupo != 0) ? 1 : 0; 2470 error = sysctl_handle_int(oidp, &val, 0, req); 2471 if (error != 0 || req->newptr == NULL) 2472 return (error); 2473 2474 /* Clamp to 0 or 1 */ 2475 aupo = (val != 0) ? 1 : 0; 2476 2477 /* Write AUPO */ 2478 if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) 2479 return (EIO); 2480 2481 return (0); 2482 } 2483 2484 static int 2485 asmc_backlight_update_status(device_t dev, struct backlight_props *props) 2486 { 2487 struct asmc_softc *sc = device_get_softc(dev); 2488 uint8_t buf[2]; 2489 2490 sc->sc_kbd_bkl_level = props->brightness; 2491 light_control = props->brightness * 255 / 100; 2492 buf[0] = light_control; 2493 buf[1] = 0x00; 2494 asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); 2495 2496 return (0); 2497 } 2498 2499 static int 2500 asmc_backlight_get_status(device_t dev, struct backlight_props *props) 2501 { 2502 struct asmc_softc *sc = device_get_softc(dev); 2503 2504 props->brightness = sc->sc_kbd_bkl_level; 2505 props->nlevels = 0; 2506 2507 return (0); 2508 } 2509 2510 static int 2511 asmc_backlight_get_info(device_t dev, struct backlight_info *info) 2512 { 2513 info->type = BACKLIGHT_TYPE_KEYBOARD; 2514 strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH); 2515 2516 return (0); 2517 } 2518