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