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