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