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