xref: /freebsd/sys/dev/asmc/asmc.c (revision aa462efde6dc009eed0e09272b5359950193b0be)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 /*
31  * Driver for Apple's System Management Console (SMC).
32  * SMC can be found on the MacBook, MacBook Pro and Mac Mini.
33  *
34  * Inspired by the Linux applesmc driver.
35  */
36 
37 #include "opt_asmc.h"
38 
39 #include <sys/param.h>
40 #include <sys/bus.h>
41 #include <sys/conf.h>
42 #include <sys/endian.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
48 #include <sys/sysctl.h>
49 #include <sys/systm.h>
50 #include <sys/taskqueue.h>
51 #include <sys/rman.h>
52 
53 #include <machine/resource.h>
54 #include <netinet/in.h>
55 
56 #include <contrib/dev/acpica/include/acpi.h>
57 
58 #include <dev/acpica/acpivar.h>
59 #include <dev/asmc/asmcvar.h>
60 
61 #include <dev/backlight/backlight.h>
62 #include "backlight_if.h"
63 
64 /*
65  * Device interface.
66  */
67 static int 	asmc_probe(device_t dev);
68 static int 	asmc_attach(device_t dev);
69 static int 	asmc_detach(device_t dev);
70 static int 	asmc_resume(device_t dev);
71 
72 /*
73  * Backlight interface.
74  */
75 static int	asmc_backlight_update_status(device_t dev,
76     struct backlight_props *props);
77 static int	asmc_backlight_get_status(device_t dev,
78     struct backlight_props *props);
79 static int	asmc_backlight_get_info(device_t dev, struct backlight_info *info);
80 
81 /*
82  * SMC functions.
83  */
84 static int 	asmc_init(device_t dev);
85 static int 	asmc_command(device_t dev, uint8_t command);
86 static int 	asmc_wait(device_t dev, uint8_t val);
87 static int 	asmc_wait_ack(device_t dev, uint8_t val, int amount);
88 static int 	asmc_key_write(device_t dev, const char *key, uint8_t *buf,
89     uint8_t len);
90 static int 	asmc_key_read(device_t dev, const char *key, uint8_t *buf,
91     uint8_t);
92 static int 	asmc_fan_count(device_t dev);
93 static int 	asmc_fan_getvalue(device_t dev, const char *key, int fan);
94 static int 	asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed);
95 static int 	asmc_temp_getvalue(device_t dev, const char *key);
96 static int 	asmc_sms_read(device_t, const char *key, int16_t *val);
97 static void 	asmc_sms_calibrate(device_t dev);
98 static int 	asmc_sms_intrfast(void *arg);
99 static void 	asmc_sms_printintr(device_t dev, uint8_t);
100 static void 	asmc_sms_task(void *arg, int pending);
101 #ifdef ASMC_DEBUG
102 void		asmc_dumpall(device_t);
103 static int	asmc_key_dump(device_t, int);
104 #endif
105 
106 /*
107  * Model functions.
108  */
109 static int 	asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS);
110 static int 	asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS);
111 static int 	asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS);
112 static int 	asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS);
113 static int 	asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS);
114 static int 	asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS);
115 static int 	asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS);
116 static int 	asmc_temp_sysctl(SYSCTL_HANDLER_ARGS);
117 static int 	asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS);
118 static int 	asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS);
119 static int 	asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS);
120 static int 	asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS);
121 static int 	asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS);
122 static int 	asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS);
123 static int 	asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS);
124 static int	asmc_wol_sysctl(SYSCTL_HANDLER_ARGS);
125 
126 #ifdef ASMC_DEBUG
127 /* Raw key access */
128 static int	asmc_key_getinfo(device_t, const char *, uint8_t *, char *);
129 static int	asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS);
130 static int	asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS);
131 static int	asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS);
132 static int	asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS);
133 #endif
134 
135 struct asmc_model {
136 	const char *smc_model; /* smbios.system.product env var. */
137 	const char *smc_desc;  /* driver description */
138 
139 	/* Helper functions */
140 	int (*smc_sms_x)(SYSCTL_HANDLER_ARGS);
141 	int (*smc_sms_y)(SYSCTL_HANDLER_ARGS);
142 	int (*smc_sms_z)(SYSCTL_HANDLER_ARGS);
143 	int (*smc_fan_id)(SYSCTL_HANDLER_ARGS);
144 	int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS);
145 	int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS);
146 	int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS);
147 	int (*smc_fan_maxspeed)(SYSCTL_HANDLER_ARGS);
148 	int (*smc_fan_targetspeed)(SYSCTL_HANDLER_ARGS);
149 	int (*smc_light_left)(SYSCTL_HANDLER_ARGS);
150 	int (*smc_light_right)(SYSCTL_HANDLER_ARGS);
151 	int (*smc_light_control)(SYSCTL_HANDLER_ARGS);
152 
153 	const char 	*smc_temps[ASMC_TEMP_MAX];
154 	const char 	*smc_tempnames[ASMC_TEMP_MAX];
155 	const char 	*smc_tempdescs[ASMC_TEMP_MAX];
156 };
157 
158 static const struct asmc_model *asmc_match(device_t dev);
159 
160 #define ASMC_SMS_FUNCS						\
161 			.smc_sms_x = asmc_mb_sysctl_sms_x,	\
162 			.smc_sms_y = asmc_mb_sysctl_sms_y,	\
163 			.smc_sms_z = asmc_mb_sysctl_sms_z
164 
165 #define ASMC_SMS_FUNCS_DISABLED			\
166 			.smc_sms_x = NULL,	\
167 			.smc_sms_y = NULL,	\
168 			.smc_sms_z = NULL
169 
170 #define ASMC_FAN_FUNCS	\
171 			.smc_fan_id = asmc_mb_sysctl_fanid, \
172 			.smc_fan_speed = asmc_mb_sysctl_fanspeed, \
173 			.smc_fan_safespeed = asmc_mb_sysctl_fansafespeed, \
174 			.smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \
175 			.smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \
176 			.smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed
177 
178 #define ASMC_FAN_FUNCS2	\
179 			.smc_fan_id = asmc_mb_sysctl_fanid, \
180 			.smc_fan_speed = asmc_mb_sysctl_fanspeed, \
181 			.smc_fan_safespeed = NULL, \
182 			.smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \
183 			.smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \
184 			.smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed
185 
186 #define ASMC_LIGHT_FUNCS \
187 			 .smc_light_left = asmc_mbp_sysctl_light_left, \
188 			 .smc_light_right = asmc_mbp_sysctl_light_right, \
189 			 .smc_light_control = asmc_mbp_sysctl_light_control
190 
191 #define ASMC_LIGHT_FUNCS_10BYTE \
192 			 .smc_light_left = asmc_mbp_sysctl_light_left_10byte, \
193 			 .smc_light_right = NULL, \
194 			 .smc_light_control = asmc_mbp_sysctl_light_control
195 
196 #define ASMC_LIGHT_FUNCS_DISABLED \
197 			 .smc_light_left = NULL, \
198 			 .smc_light_right = NULL, \
199 			 .smc_light_control = NULL
200 
201 #define	ASMC_TEMPS_FUNCS_DISABLED \
202 			  .smc_temps = {},		\
203 			  .smc_tempnames = {},		\
204 			  .smc_tempdescs = {}		\
205 
206 static const struct asmc_model asmc_models[] = {
207 	{
208 	  "MacBook1,1", "Apple SMC MacBook Core Duo",
209 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
210 	  ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS
211 	},
212 
213 	{
214 	  "MacBook2,1", "Apple SMC MacBook Core 2 Duo",
215 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
216 	  ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS
217 	},
218 
219 	{
220 	  "MacBook3,1", "Apple SMC MacBook Core 2 Duo",
221 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
222 	  ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS
223 	},
224 
225 	{
226 	  "MacBook7,1", "Apple SMC MacBook Core 2 Duo (mid 2010)",
227 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS_DISABLED,
228 	  ASMC_MB71_TEMPS, ASMC_MB71_TEMPNAMES, ASMC_MB71_TEMPDESCS
229 	},
230 
231 	{
232 	  "MacBookPro1,1", "Apple SMC MacBook Pro Core Duo (15-inch)",
233 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
234 	  ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
235 	},
236 
237 	{
238 	  "MacBookPro1,2", "Apple SMC MacBook Pro Core Duo (17-inch)",
239 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
240 	  ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
241 	},
242 
243 	{
244 	  "MacBookPro2,1", "Apple SMC MacBook Pro Core 2 Duo (17-inch)",
245 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
246 	  ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
247 	},
248 
249 	{
250 	  "MacBookPro2,2", "Apple SMC MacBook Pro Core 2 Duo (15-inch)",
251 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
252 	  ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
253 	},
254 
255 	{
256 	  "MacBookPro3,1", "Apple SMC MacBook Pro Core 2 Duo (15-inch LED)",
257 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
258 	  ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
259 	},
260 
261 	{
262 	  "MacBookPro3,2", "Apple SMC MacBook Pro Core 2 Duo (17-inch HD)",
263 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
264 	  ASMC_MBP_TEMPS, ASMC_MBP_TEMPNAMES, ASMC_MBP_TEMPDESCS
265 	},
266 
267 	{
268 	  "MacBookPro4,1", "Apple SMC MacBook Pro Core 2 Duo (Penryn)",
269 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
270 	  ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS
271 	},
272 
273 	{
274 	  "MacBookPro5,1", "Apple SMC MacBook Pro Core 2 Duo (2008/2009)",
275 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
276 	  ASMC_MBP51_TEMPS, ASMC_MBP51_TEMPNAMES, ASMC_MBP51_TEMPDESCS
277 	},
278 
279 	{
280 	  "MacBookPro5,5", "Apple SMC MacBook Pro Core 2 Duo (Mid 2009)",
281 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
282 	  ASMC_MBP55_TEMPS, ASMC_MBP55_TEMPNAMES, ASMC_MBP55_TEMPDESCS
283 	},
284 
285 	{
286 	  "MacBookPro6,2", "Apple SMC MacBook Pro (Mid 2010, 15-inch)",
287 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
288 	  ASMC_MBP62_TEMPS, ASMC_MBP62_TEMPNAMES, ASMC_MBP62_TEMPDESCS
289 	},
290 
291 	{
292 	  "MacBookPro8,1", "Apple SMC MacBook Pro (early 2011, 13-inch)",
293 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
294 	  ASMC_MBP81_TEMPS, ASMC_MBP81_TEMPNAMES, ASMC_MBP81_TEMPDESCS
295 	},
296 
297 	{
298 	  "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)",
299 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
300 	  ASMC_MBP82_TEMPS, ASMC_MBP82_TEMPNAMES, ASMC_MBP82_TEMPDESCS
301 	},
302 
303 	{
304 	  "MacBookPro8,3", "Apple SMC MacBook Pro (early 2011, 17-inch)",
305 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
306 	  ASMC_MBP83_TEMPS, ASMC_MBP83_TEMPNAMES, ASMC_MBP83_TEMPDESCS
307 	},
308 
309 	{
310 	  "MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)",
311 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
312 	  ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS
313 	},
314 
315 	{
316 	 "MacBookPro9,2", "Apple SMC MacBook Pro (mid 2012, 13-inch)",
317 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
318 	  ASMC_MBP92_TEMPS, ASMC_MBP92_TEMPNAMES, ASMC_MBP92_TEMPDESCS
319 	},
320 
321 	{
322 	  "MacBookPro11,2", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)",
323 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
324 	  ASMC_MBP112_TEMPS, ASMC_MBP112_TEMPNAMES, ASMC_MBP112_TEMPDESCS
325 	},
326 
327 	{
328 	  "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)",
329 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
330 	  ASMC_MBP113_TEMPS, ASMC_MBP113_TEMPNAMES, ASMC_MBP113_TEMPDESCS
331 	},
332 
333 	{
334 	  "MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)",
335 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
336 	  ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS
337 	},
338 
339 	{
340 	  "MacBookPro11,5",
341 	  "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch, AMD GPU)",
342 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
343 	  ASMC_MBP115_TEMPS, ASMC_MBP115_TEMPNAMES, ASMC_MBP115_TEMPDESCS
344 	},
345 
346 	{
347 	  "MacBookPro13,1", "Apple SMC MacBook Pro Retina Core i5 (late 2016, 13-inch)",
348 	  ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
349 	  ASMC_MBP131_TEMPS, ASMC_MBP131_TEMPNAMES, ASMC_MBP131_TEMPDESCS
350 	},
351 
352 	/* The Mac Mini has no SMS */
353 	{
354 	  "Macmini1,1", "Apple SMC Mac Mini",
355 	  ASMC_SMS_FUNCS_DISABLED,
356 	  ASMC_FAN_FUNCS,
357 	  ASMC_LIGHT_FUNCS_DISABLED,
358 	  ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS
359 	},
360 
361 	/* The Mac Mini 2,1 has no SMS */
362 	{
363 	  "Macmini2,1", "Apple SMC Mac Mini 2,1",
364 	  ASMC_SMS_FUNCS_DISABLED,
365 	  ASMC_FAN_FUNCS,
366 	  ASMC_LIGHT_FUNCS_DISABLED,
367 	  ASMC_MM21_TEMPS, ASMC_MM21_TEMPNAMES, ASMC_MM21_TEMPDESCS
368 	},
369 
370 	/* The Mac Mini 3,1 has no SMS */
371 	{
372 	  "Macmini3,1", "Apple SMC Mac Mini 3,1",
373 	  ASMC_SMS_FUNCS_DISABLED,
374 	  ASMC_FAN_FUNCS,
375 	  ASMC_LIGHT_FUNCS_DISABLED,
376 	  ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS
377 	},
378 
379 	/* The Mac Mini 4,1 (Mid-2010) has no SMS */
380 	{
381 	  "Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)",
382 	  ASMC_SMS_FUNCS_DISABLED,
383 	  ASMC_FAN_FUNCS2,
384 	  ASMC_LIGHT_FUNCS_DISABLED,
385 	  ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS
386 	},
387 
388 	/* The Mac Mini 5,1 has no SMS */
389 	/* - same sensors as Mac Mini 5,2 */
390 	{
391 	  "Macmini5,1", "Apple SMC Mac Mini 5,1",
392 	  ASMC_SMS_FUNCS_DISABLED,
393 	  ASMC_FAN_FUNCS2,
394 	  ASMC_LIGHT_FUNCS_DISABLED,
395 	  ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
396 	},
397 
398 	/* The Mac Mini 5,2 has no SMS */
399 	{
400 	  "Macmini5,2", "Apple SMC Mac Mini 5,2",
401 	  ASMC_SMS_FUNCS_DISABLED,
402 	  ASMC_FAN_FUNCS2,
403 	  ASMC_LIGHT_FUNCS_DISABLED,
404 	  ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
405 	},
406 
407 	/* The Mac Mini 5,3 has no SMS */
408 	/* - same sensors as Mac Mini 5,2 */
409 	{
410 	  "Macmini5,3", "Apple SMC Mac Mini 5,3",
411 	  ASMC_SMS_FUNCS_DISABLED,
412 	  ASMC_FAN_FUNCS2,
413 	  ASMC_LIGHT_FUNCS_DISABLED,
414 	  ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
415 	},
416 
417 	/* The Mac Mini 6,1 has no SMS */
418 	{
419 	  "Macmini6,1", "Apple SMC Mac Mini 6,1",
420 	  ASMC_SMS_FUNCS_DISABLED,
421 	  ASMC_FAN_FUNCS2,
422 	  ASMC_LIGHT_FUNCS_DISABLED,
423 	  ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS
424 	},
425 
426 	/* The Mac Mini 6,2 has no SMS */
427 	{
428 	  "Macmini6,2", "Apple SMC Mac Mini 6,2",
429 	  ASMC_SMS_FUNCS_DISABLED,
430 	  ASMC_FAN_FUNCS2,
431 	  ASMC_LIGHT_FUNCS_DISABLED,
432 	  ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS
433 	},
434 
435 	/* The Mac Mini 7,1 has no SMS */
436 	{
437 	  "Macmini7,1", "Apple SMC Mac Mini 7,1",
438 	  ASMC_SMS_FUNCS_DISABLED,
439 	  ASMC_FAN_FUNCS2,
440 	  ASMC_LIGHT_FUNCS_DISABLED,
441 	  ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS
442 	},
443 
444 	/* Idem for the Mac Pro "Quad Core" (original) */
445 	{
446 	  "MacPro1,1", "Apple SMC Mac Pro (Quad Core)",
447 	  ASMC_SMS_FUNCS_DISABLED,
448 	  ASMC_FAN_FUNCS,
449 	  ASMC_LIGHT_FUNCS_DISABLED,
450 	  ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS
451 	},
452 
453 	/* Idem for the Mac Pro (Early 2008) */
454 	{
455 	  "MacPro3,1", "Apple SMC Mac Pro (Early 2008)",
456 	  ASMC_SMS_FUNCS_DISABLED,
457 	  ASMC_FAN_FUNCS,
458 	  ASMC_LIGHT_FUNCS_DISABLED,
459 	  ASMC_MP31_TEMPS, ASMC_MP31_TEMPNAMES, ASMC_MP31_TEMPDESCS
460 	},
461 
462 	/* Idem for the Mac Pro (8-core) */
463 	{
464 	  "MacPro2", "Apple SMC Mac Pro (8-core)",
465 	  ASMC_SMS_FUNCS_DISABLED,
466 	  ASMC_FAN_FUNCS,
467 	  ASMC_LIGHT_FUNCS_DISABLED,
468 	  ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS
469 	},
470 
471 	/* Idem for the MacPro  2010*/
472 	{
473 	  "MacPro5,1", "Apple SMC MacPro (2010)",
474 	  ASMC_SMS_FUNCS_DISABLED,
475 	  ASMC_FAN_FUNCS,
476 	  ASMC_LIGHT_FUNCS_DISABLED,
477 	  ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS
478 	},
479 
480 	/* Idem for the Mac Pro 2013 (cylinder) */
481 	{
482 	  "MacPro6,1", "Apple SMC Mac Pro (2013)",
483 	  ASMC_SMS_FUNCS_DISABLED,
484 	  ASMC_FAN_FUNCS2,
485 	  ASMC_LIGHT_FUNCS_DISABLED,
486 	  ASMC_MP6_TEMPS, ASMC_MP6_TEMPNAMES, ASMC_MP6_TEMPDESCS
487 	},
488 
489 	{
490 	  "MacBookAir1,1", "Apple SMC MacBook Air",
491 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
492 	  ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS
493 	},
494 
495 	{
496 	  "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)",
497 	  ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
498 	  ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS
499 	},
500 
501 	{
502 	  "MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)",
503 	  ASMC_SMS_FUNCS_DISABLED,
504 	  ASMC_FAN_FUNCS2,
505 	  ASMC_LIGHT_FUNCS,
506 	  ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS
507 	},
508 
509 	{
510 	  "MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)",
511 	  ASMC_SMS_FUNCS_DISABLED,
512 	  ASMC_FAN_FUNCS2,
513 	  ASMC_LIGHT_FUNCS,
514 	  ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS
515 	},
516 
517 	{
518 	  "MacBookAir5,1", "Apple SMC MacBook Air 11-inch (Mid 2012)",
519 	  ASMC_SMS_FUNCS_DISABLED,
520 	  ASMC_FAN_FUNCS2,
521 	  ASMC_LIGHT_FUNCS,
522 	  ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS
523 	},
524 
525 	{
526 	  "MacBookAir5,2", "Apple SMC MacBook Air 13-inch (Mid 2012)",
527 	  ASMC_SMS_FUNCS_DISABLED,
528 	  ASMC_FAN_FUNCS2,
529 	  ASMC_LIGHT_FUNCS,
530 	  ASMC_MBA5_TEMPS, ASMC_MBA5_TEMPNAMES, ASMC_MBA5_TEMPDESCS
531 	},
532 	{
533 	  "MacBookAir6,1", "Apple SMC MacBook Air 11-inch (Early 2013)",
534 	  ASMC_SMS_FUNCS_DISABLED,
535 	  ASMC_FAN_FUNCS2,
536 	  ASMC_LIGHT_FUNCS_10BYTE,
537 	  ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS
538 	},
539 	{
540 	  "MacBookAir6,2", "Apple SMC MacBook Air 13-inch (Early 2013)",
541 	  ASMC_SMS_FUNCS_DISABLED,
542 	  ASMC_FAN_FUNCS2,
543 	  ASMC_LIGHT_FUNCS_10BYTE,
544 	  ASMC_MBA6_TEMPS, ASMC_MBA6_TEMPNAMES, ASMC_MBA6_TEMPDESCS
545 	},
546 	{
547 	  "MacBookAir7,1", "Apple SMC MacBook Air 11-inch (Early 2015)",
548 	  ASMC_SMS_FUNCS_DISABLED,
549 	  ASMC_FAN_FUNCS2,
550 	  ASMC_LIGHT_FUNCS,
551 	  ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS
552 	},
553 	{
554 	  "MacBookAir7,2", "Apple SMC MacBook Air 13-inch (Early 2015)",
555 	  ASMC_SMS_FUNCS_DISABLED,
556 	  ASMC_FAN_FUNCS2,
557 	  ASMC_LIGHT_FUNCS,
558 	  ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS
559 	}
560 };
561 
562 static const struct asmc_model asmc_generic_models[] = {
563 	{
564 	  .smc_model = "MacBookAir",
565 	  .smc_desc = NULL,
566 	  ASMC_SMS_FUNCS_DISABLED,
567 	  ASMC_FAN_FUNCS2,
568 	  ASMC_LIGHT_FUNCS,
569 	  ASMC_TEMPS_FUNCS_DISABLED
570 	},
571 	{
572 	  .smc_model = "MacBookPro",
573 	  .smc_desc = NULL,
574 	  ASMC_SMS_FUNCS_DISABLED,
575 	  ASMC_FAN_FUNCS2,
576 	  ASMC_LIGHT_FUNCS,
577 	  ASMC_TEMPS_FUNCS_DISABLED
578 	},
579 	{
580 	  .smc_model = "MacPro",
581 	  .smc_desc = NULL,
582 	  ASMC_SMS_FUNCS_DISABLED,
583 	  ASMC_FAN_FUNCS2,
584 	  ASMC_LIGHT_FUNCS_DISABLED,
585 	  ASMC_TEMPS_FUNCS_DISABLED
586 	},
587 	{
588 	  .smc_model = "Macmini",
589 	  .smc_desc = NULL,
590 	  ASMC_SMS_FUNCS_DISABLED,
591 	  ASMC_FAN_FUNCS2,
592 	  ASMC_LIGHT_FUNCS_DISABLED,
593 	  ASMC_TEMPS_FUNCS_DISABLED
594 	}
595 };
596 
597 #undef ASMC_SMS_FUNCS
598 #undef ASMC_SMS_FUNCS_DISABLED
599 #undef ASMC_FAN_FUNCS
600 #undef ASMC_FAN_FUNCS2
601 #undef ASMC_LIGHT_FUNCS
602 
603 /*
604  * Driver methods.
605  */
606 static device_method_t	asmc_methods[] = {
607 	DEVMETHOD(device_probe,		asmc_probe),
608 	DEVMETHOD(device_attach,	asmc_attach),
609 	DEVMETHOD(device_detach,	asmc_detach),
610 	DEVMETHOD(device_resume,	asmc_resume),
611 
612 	/* Backlight interface */
613 	DEVMETHOD(backlight_update_status, asmc_backlight_update_status),
614 	DEVMETHOD(backlight_get_status, asmc_backlight_get_status),
615 	DEVMETHOD(backlight_get_info, asmc_backlight_get_info),
616 
617 	DEVMETHOD_END
618 };
619 
620 static driver_t	asmc_driver = {
621 	"asmc",
622 	asmc_methods,
623 	sizeof(struct asmc_softc)
624 };
625 
626 /*
627  * Debugging
628  */
629 #define	_COMPONENT	ACPI_OEM
630 ACPI_MODULE_NAME("ASMC")
631 #ifdef ASMC_DEBUG
632 #define ASMC_DPRINTF(str, ...)	device_printf(dev, str, ##__VA_ARGS__)
633 #else
634 #define ASMC_DPRINTF(str, ...)
635 #endif
636 
637 /* NB: can't be const */
638 static char *asmc_ids[] = { "APP0001", NULL };
639 
640 static unsigned int light_control = 0;
641 
642 ACPI_PNP_INFO(asmc_ids);
643 DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL);
644 MODULE_DEPEND(asmc, acpi, 1, 1, 1);
645 MODULE_DEPEND(asmc, backlight, 1, 1, 1);
646 
647 static const struct asmc_model *
648 asmc_match(device_t dev)
649 {
650 	const struct asmc_model *model;
651 	char *model_name;
652 	int i;
653 
654 	model = NULL;
655 
656 	model_name = kern_getenv("smbios.system.product");
657 	if (model_name == NULL)
658 		goto out;
659 
660 	for (i = 0; i < nitems(asmc_models); i++) {
661 		if (strncmp(model_name, asmc_models[i].smc_model,
662 		    strlen(model_name)) == 0) {
663 			model = &asmc_models[i];
664 			goto out;
665 		}
666 	}
667 	for (i = 0; i < nitems(asmc_generic_models); i++) {
668 		if (strncmp(model_name, asmc_generic_models[i].smc_model,
669 		    strlen(asmc_generic_models[i].smc_model)) == 0) {
670 			model = &asmc_generic_models[i];
671 			goto out;
672 		}
673 	}
674 
675 out:
676 	freeenv(model_name);
677 	return (model);
678 }
679 
680 static int
681 asmc_probe(device_t dev)
682 {
683 	const struct asmc_model *model;
684 	const char *device_desc;
685 	int rv;
686 
687 	if (resource_disabled("asmc", 0))
688 		return (ENXIO);
689 	rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids, NULL);
690 	if (rv > 0)
691 		return (rv);
692 
693 	model = asmc_match(dev);
694 	if (model == NULL) {
695 		device_printf(dev, "model not recognized\n");
696 		return (ENXIO);
697 	}
698 	device_desc = model->smc_desc == NULL ?
699 	    model->smc_model : model->smc_desc;
700 	device_set_desc(dev, device_desc);
701 
702 	return (rv);
703 }
704 
705 static int
706 asmc_attach(device_t dev)
707 {
708 	int i, j;
709 	int ret;
710 	char name[2];
711 	struct asmc_softc *sc = device_get_softc(dev);
712 	struct sysctl_ctx_list *sysctlctx;
713 	struct sysctl_oid *sysctlnode;
714 	const struct asmc_model *model;
715 
716 	sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
717 	    &sc->sc_rid_port, RF_ACTIVE);
718 	if (sc->sc_ioport == NULL) {
719 		device_printf(dev, "unable to allocate IO port\n");
720 		return (ENOMEM);
721 	}
722 
723 	sysctlctx = device_get_sysctl_ctx(dev);
724 	sysctlnode = device_get_sysctl_tree(dev);
725 
726 	model = asmc_match(dev);
727 
728 	mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN);
729 
730 	sc->sc_model = model;
731 	asmc_init(dev);
732 
733 	/*
734 	 * dev.asmc.n.fan.* tree.
735 	 */
736 	sc->sc_fan_tree[0] = SYSCTL_ADD_NODE(sysctlctx,
737 	    SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "fan",
738 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Root Tree");
739 
740 	for (i = 1; i <= sc->sc_nfan; i++) {
741 		j = i - 1;
742 		name[0] = '0' + j;
743 		name[1] = 0;
744 		sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx,
745 		    SYSCTL_CHILDREN(sc->sc_fan_tree[0]), OID_AUTO, name,
746 		    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Subtree");
747 
748 		SYSCTL_ADD_PROC(sysctlctx,
749 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
750 		    OID_AUTO, "id",
751 		    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
752 		    model->smc_fan_id, "I", "Fan ID");
753 
754 		SYSCTL_ADD_PROC(sysctlctx,
755 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
756 		    OID_AUTO, "speed",
757 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
758 		    model->smc_fan_speed, "I", "Fan speed in RPM");
759 
760 		SYSCTL_ADD_PROC(sysctlctx,
761 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
762 		    OID_AUTO, "safespeed",
763 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
764 		    model->smc_fan_safespeed, "I", "Fan safe speed in RPM");
765 
766 		SYSCTL_ADD_PROC(sysctlctx,
767 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
768 		    OID_AUTO, "minspeed",
769 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
770 		    model->smc_fan_minspeed, "I", "Fan minimum speed in RPM");
771 
772 		SYSCTL_ADD_PROC(sysctlctx,
773 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
774 		    OID_AUTO, "maxspeed",
775 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
776 		    model->smc_fan_maxspeed, "I", "Fan maximum speed in RPM");
777 
778 		SYSCTL_ADD_PROC(sysctlctx,
779 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
780 		    OID_AUTO, "targetspeed",
781 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
782 		    model->smc_fan_targetspeed, "I", "Fan target speed in RPM");
783 
784 		SYSCTL_ADD_PROC(sysctlctx,
785 		    SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
786 		    OID_AUTO, "manual",
787 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
788 		    asmc_mb_sysctl_fanmanual, "I",
789 		    "Fan manual mode (0=auto, 1=manual)");
790 	}
791 
792 	/*
793 	 * dev.asmc.n.temp tree.
794 	 */
795 	sc->sc_temp_tree = SYSCTL_ADD_NODE(sysctlctx,
796 	    SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "temp",
797 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Temperature sensors");
798 
799 	for (i = 0; model->smc_temps[i]; i++) {
800 		SYSCTL_ADD_PROC(sysctlctx,
801 		    SYSCTL_CHILDREN(sc->sc_temp_tree),
802 		    OID_AUTO, model->smc_tempnames[i],
803 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i,
804 		    asmc_temp_sysctl, "I",
805 		    model->smc_tempdescs[i]);
806 	}
807 
808 	/*
809 	 * dev.asmc.n.light
810 	 */
811 	if (model->smc_light_left) {
812 		sc->sc_light_tree = SYSCTL_ADD_NODE(sysctlctx,
813 		    SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "light",
814 		    CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
815 		    "Keyboard backlight sensors");
816 
817 		SYSCTL_ADD_PROC(sysctlctx,
818 		    SYSCTL_CHILDREN(sc->sc_light_tree),
819 		    OID_AUTO, "left",
820 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
821 		    dev, 0, model->smc_light_left, "I",
822 		    "Keyboard backlight left sensor");
823 
824 		SYSCTL_ADD_PROC(sysctlctx,
825 		    SYSCTL_CHILDREN(sc->sc_light_tree),
826 		    OID_AUTO, "right",
827 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
828 		    model->smc_light_right, "I",
829 		    "Keyboard backlight right sensor");
830 
831 		SYSCTL_ADD_PROC(sysctlctx,
832 		    SYSCTL_CHILDREN(sc->sc_light_tree),
833 		    OID_AUTO, "control",
834 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
835 		    dev, 0, model->smc_light_control, "I",
836 		    "Keyboard backlight brightness control");
837 
838 		sc->sc_kbd_bkl = backlight_register("asmc", dev);
839 		if (sc->sc_kbd_bkl == NULL) {
840 			device_printf(dev, "Can not register backlight\n");
841 			ret = ENXIO;
842 			goto err;
843 		}
844 	}
845 
846 #ifdef ASMC_DEBUG
847 	/*
848 	 * Raw SMC key access for debugging.
849 	 */
850 	sc->sc_raw_tree = SYSCTL_ADD_NODE(sysctlctx,
851 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
852 	    "raw", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Raw SMC key access");
853 
854 	SYSCTL_ADD_PROC(sysctlctx,
855 	    SYSCTL_CHILDREN(sc->sc_raw_tree),
856 	    OID_AUTO, "key",
857 	    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
858 	    dev, 0, asmc_raw_key_sysctl, "A",
859 	    "SMC key name (4 chars)");
860 
861 	SYSCTL_ADD_PROC(sysctlctx,
862 	    SYSCTL_CHILDREN(sc->sc_raw_tree),
863 	    OID_AUTO, "value",
864 	    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
865 	    dev, 0, asmc_raw_value_sysctl, "A",
866 	    "SMC key value (hex string)");
867 
868 	SYSCTL_ADD_PROC(sysctlctx,
869 	    SYSCTL_CHILDREN(sc->sc_raw_tree),
870 	    OID_AUTO, "len",
871 	    CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE,
872 	    dev, 0, asmc_raw_len_sysctl, "CU",
873 	    "SMC key value length");
874 
875 	SYSCTL_ADD_PROC(sysctlctx,
876 	    SYSCTL_CHILDREN(sc->sc_raw_tree),
877 	    OID_AUTO, "type",
878 	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
879 	    dev, 0, asmc_raw_type_sysctl, "A",
880 	    "SMC key type (4 chars)");
881 #endif
882 
883 	if (model->smc_sms_x == NULL)
884 		goto nosms;
885 
886 	/*
887 	 * dev.asmc.n.sms tree.
888 	 */
889 	sc->sc_sms_tree = SYSCTL_ADD_NODE(sysctlctx,
890 	    SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "sms",
891 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Sudden Motion Sensor");
892 
893 	SYSCTL_ADD_PROC(sysctlctx,
894 	    SYSCTL_CHILDREN(sc->sc_sms_tree),
895 	    OID_AUTO, "x",
896 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
897 	    dev, 0, model->smc_sms_x, "I",
898 	    "Sudden Motion Sensor X value");
899 
900 	SYSCTL_ADD_PROC(sysctlctx,
901 	    SYSCTL_CHILDREN(sc->sc_sms_tree),
902 	    OID_AUTO, "y",
903 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
904 	    dev, 0, model->smc_sms_y, "I",
905 	    "Sudden Motion Sensor Y value");
906 
907 	SYSCTL_ADD_PROC(sysctlctx,
908 	    SYSCTL_CHILDREN(sc->sc_sms_tree),
909 	    OID_AUTO, "z",
910 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
911 	    dev, 0, model->smc_sms_z, "I",
912 	    "Sudden Motion Sensor Z value");
913 
914 	/*
915 	 * Need a taskqueue to send devctl_notify() events
916 	 * when the SMS interrupt us.
917 	 *
918 	 * PI_REALTIME is used due to the sensitivity of the
919 	 * interrupt. An interrupt from the SMS means that the
920 	 * disk heads should be turned off as quickly as possible.
921 	 *
922 	 * We only need to do this for the non INTR_FILTER case.
923 	 */
924 	sc->sc_sms_tq = NULL;
925 	TASK_INIT(&sc->sc_sms_task, 0, asmc_sms_task, sc);
926 	sc->sc_sms_tq = taskqueue_create_fast("asmc_taskq", M_WAITOK,
927 	    taskqueue_thread_enqueue, &sc->sc_sms_tq);
928 	taskqueue_start_threads(&sc->sc_sms_tq, 1, PI_REALTIME, "%s sms taskq",
929 	    device_get_nameunit(dev));
930 	/*
931 	 * Allocate an IRQ for the SMS.
932 	 */
933 	sc->sc_rid_irq = 0;
934 	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq,
935 	    RF_ACTIVE);
936 	if (sc->sc_irq == NULL) {
937 		device_printf(dev, "unable to allocate IRQ resource\n");
938 		ret = ENXIO;
939 		goto err;
940 	}
941 
942 	ret = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE,
943 	    asmc_sms_intrfast, NULL, dev, &sc->sc_cookie);
944 	if (ret) {
945 		device_printf(dev, "unable to setup SMS IRQ\n");
946 		goto err;
947 	}
948 
949 nosms:
950 	return (0);
951 
952 err:
953 	asmc_detach(dev);
954 
955 	return (ret);
956 }
957 
958 static int
959 asmc_detach(device_t dev)
960 {
961 	struct asmc_softc *sc = device_get_softc(dev);
962 
963 	if (sc->sc_kbd_bkl != NULL)
964 		backlight_destroy(sc->sc_kbd_bkl);
965 
966 	if (sc->sc_sms_tq) {
967 		taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task);
968 		taskqueue_free(sc->sc_sms_tq);
969 		sc->sc_sms_tq = NULL;
970 	}
971 	if (sc->sc_cookie) {
972 		bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie);
973 		sc->sc_cookie = NULL;
974 	}
975 	if (sc->sc_irq) {
976 		bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq,
977 		    sc->sc_irq);
978 		sc->sc_irq = NULL;
979 	}
980 	if (sc->sc_ioport) {
981 		bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port,
982 		    sc->sc_ioport);
983 		sc->sc_ioport = NULL;
984 	}
985 	if (mtx_initialized(&sc->sc_mtx)) {
986 		mtx_destroy(&sc->sc_mtx);
987 	}
988 
989 	return (0);
990 }
991 
992 static int
993 asmc_resume(device_t dev)
994 {
995 	uint8_t buf[2];
996 
997 	buf[0] = light_control;
998 	buf[1] = 0x00;
999 	asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf));
1000 
1001 	return (0);
1002 }
1003 
1004 #ifdef ASMC_DEBUG
1005 void
1006 asmc_dumpall(device_t dev)
1007 {
1008 	struct asmc_softc *sc = device_get_softc(dev);
1009 	int i;
1010 
1011 	if (sc->sc_nkeys == 0) {
1012 		device_printf(dev, "asmc_dumpall: key count not available\n");
1013 		return;
1014 	}
1015 
1016 	device_printf(dev, "asmc_dumpall: dumping %d keys\n", sc->sc_nkeys);
1017 	for (i = 0; i < sc->sc_nkeys; i++)
1018 		asmc_key_dump(dev, i);
1019 }
1020 #endif
1021 
1022 static int
1023 asmc_init(device_t dev)
1024 {
1025 	struct asmc_softc *sc = device_get_softc(dev);
1026 	struct sysctl_ctx_list *sysctlctx;
1027 	uint8_t buf[6];
1028 	int i, error = 1;
1029 
1030 	sysctlctx = device_get_sysctl_ctx(dev);
1031 
1032 	error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6);
1033 	if (error != 0)
1034 		goto out_err;
1035 	device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2],
1036 	    ntohs(*(uint16_t *)buf + 4));
1037 
1038 	if (sc->sc_model->smc_sms_x == NULL)
1039 		goto nosms;
1040 
1041 	/*
1042 	 * We are ready to receive interrupts from the SMS.
1043 	 */
1044 	buf[0] = 0x01;
1045 	ASMC_DPRINTF(("intok key\n"));
1046 	asmc_key_write(dev, ASMC_KEY_INTOK, buf, 1);
1047 	DELAY(50);
1048 
1049 	/*
1050 	 * Initiate the polling intervals.
1051 	 */
1052 	buf[0] = 20; /* msecs */
1053 	ASMC_DPRINTF(("low int key\n"));
1054 	asmc_key_write(dev, ASMC_KEY_SMS_LOW_INT, buf, 1);
1055 	DELAY(200);
1056 
1057 	buf[0] = 20; /* msecs */
1058 	ASMC_DPRINTF(("high int key\n"));
1059 	asmc_key_write(dev, ASMC_KEY_SMS_HIGH_INT, buf, 1);
1060 	DELAY(200);
1061 
1062 	buf[0] = 0x00;
1063 	buf[1] = 0x60;
1064 	ASMC_DPRINTF(("sms low key\n"));
1065 	asmc_key_write(dev, ASMC_KEY_SMS_LOW, buf, 2);
1066 	DELAY(200);
1067 
1068 	buf[0] = 0x01;
1069 	buf[1] = 0xc0;
1070 	ASMC_DPRINTF(("sms high key\n"));
1071 	asmc_key_write(dev, ASMC_KEY_SMS_HIGH, buf, 2);
1072 	DELAY(200);
1073 
1074 	/*
1075 	 * I'm not sure what this key does, but it seems to be
1076 	 * required.
1077 	 */
1078 	buf[0] = 0x01;
1079 	ASMC_DPRINTF(("sms flag key\n"));
1080 	asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1);
1081 	DELAY(100);
1082 
1083 	sc->sc_sms_intr_works = 0;
1084 
1085 	/*
1086 	 * Retry SMS initialization 1000 times
1087 	 * (takes approx. 2 seconds in worst case)
1088 	 */
1089 	for (i = 0; i < 1000; i++) {
1090 		if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 &&
1091 		    (buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) {
1092 			error = 0;
1093 			sc->sc_sms_intr_works = 1;
1094 			goto out;
1095 		}
1096 		buf[0] = ASMC_SMS_INIT1;
1097 		buf[1] = ASMC_SMS_INIT2;
1098 		ASMC_DPRINTF(("sms key\n"));
1099 		asmc_key_write(dev, ASMC_KEY_SMS, buf, 2);
1100 		DELAY(50);
1101 	}
1102 	device_printf(dev, "WARNING: Sudden Motion Sensor not initialized!\n");
1103 
1104 out:
1105 	asmc_sms_calibrate(dev);
1106 nosms:
1107 	/* Wake-on-LAN convenience sysctl */
1108 	if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) {
1109 		SYSCTL_ADD_PROC(sysctlctx,
1110 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1111 		    OID_AUTO, "wol",
1112 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1113 		    dev, 0, asmc_wol_sysctl, "I",
1114 		    "Wake-on-LAN enable (0=off, 1=on)");
1115 	}
1116 
1117 	sc->sc_nfan = asmc_fan_count(dev);
1118 	if (sc->sc_nfan > ASMC_MAXFANS) {
1119 		device_printf(dev,
1120 		    "more than %d fans were detected. Please report this.\n",
1121 		    ASMC_MAXFANS);
1122 		sc->sc_nfan = ASMC_MAXFANS;
1123 	}
1124 
1125 	/*
1126 	 * Read and cache the number of SMC keys (32 bit buffer)
1127 	 */
1128 	if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) {
1129 		sc->sc_nkeys = be32dec(buf);
1130 		if (bootverbose)
1131 			device_printf(dev, "number of keys: %d\n",
1132 			    sc->sc_nkeys);
1133 	} else {
1134 		sc->sc_nkeys = 0;
1135 	}
1136 
1137 out_err:
1138 #ifdef ASMC_DEBUG
1139 	asmc_dumpall(dev);
1140 #endif
1141 	return (error);
1142 }
1143 
1144 /*
1145  * We need to make sure that the SMC acks the byte sent.
1146  * Just wait up to (amount * 10)  ms.
1147  */
1148 static int
1149 asmc_wait_ack(device_t dev, uint8_t val, int amount)
1150 {
1151 	struct asmc_softc *sc = device_get_softc(dev);
1152 	u_int i;
1153 
1154 	val = val & ASMC_STATUS_MASK;
1155 
1156 	for (i = 0; i < amount; i++) {
1157 		if ((ASMC_CMDPORT_READ(sc) & ASMC_STATUS_MASK) == val)
1158 			return (0);
1159 		DELAY(10);
1160 	}
1161 
1162 	return (1);
1163 }
1164 
1165 /*
1166  * We need to make sure that the SMC acks the byte sent.
1167  * Just wait up to 100 ms.
1168  */
1169 static int
1170 asmc_wait(device_t dev, uint8_t val)
1171 {
1172 #ifdef ASMC_DEBUG
1173 	struct asmc_softc *sc;
1174 #endif
1175 
1176 	if (asmc_wait_ack(dev, val, 1000) == 0)
1177 		return (0);
1178 
1179 #ifdef ASMC_DEBUG
1180 	sc = device_get_softc(dev);
1181 
1182 	device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__,
1183 	    val & ASMC_STATUS_MASK, ASMC_CMDPORT_READ(sc));
1184 #endif
1185 	return (1);
1186 }
1187 
1188 /*
1189  * Send the given command, retrying up to 10 times if
1190  * the acknowledgement fails.
1191  */
1192 static int
1193 asmc_command(device_t dev, uint8_t command)
1194 {
1195 	int i;
1196 	struct asmc_softc *sc = device_get_softc(dev);
1197 
1198 	for (i = 0; i < 10; i++) {
1199 		ASMC_CMDPORT_WRITE(sc, command);
1200 		if (asmc_wait_ack(dev, 0x0c, 100) == 0) {
1201 			return (0);
1202 		}
1203 	}
1204 
1205 #ifdef ASMC_DEBUG
1206 	device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, command,
1207 	    ASMC_CMDPORT_READ(sc));
1208 #endif
1209 	return (1);
1210 }
1211 
1212 static int
1213 asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len)
1214 {
1215 	int i, error = 1, try = 0;
1216 	struct asmc_softc *sc = device_get_softc(dev);
1217 
1218 	mtx_lock_spin(&sc->sc_mtx);
1219 
1220 begin:
1221 	if (asmc_command(dev, ASMC_CMDREAD))
1222 		goto out;
1223 
1224 	for (i = 0; i < 4; i++) {
1225 		ASMC_DATAPORT_WRITE(sc, key[i]);
1226 		if (asmc_wait(dev, 0x04))
1227 			goto out;
1228 	}
1229 
1230 	ASMC_DATAPORT_WRITE(sc, len);
1231 
1232 	for (i = 0; i < len; i++) {
1233 		if (asmc_wait(dev, 0x05))
1234 			goto out;
1235 		buf[i] = ASMC_DATAPORT_READ(sc);
1236 	}
1237 
1238 	error = 0;
1239 out:
1240 	if (error) {
1241 		if (++try < 10)
1242 			goto begin;
1243 		device_printf(dev, "%s for key %s failed %d times, giving up\n",
1244 		    __func__, key, try);
1245 	}
1246 
1247 	mtx_unlock_spin(&sc->sc_mtx);
1248 
1249 	return (error);
1250 }
1251 
1252 #ifdef ASMC_DEBUG
1253 static int
1254 asmc_key_dump(device_t dev, int number)
1255 {
1256 	struct asmc_softc *sc = device_get_softc(dev);
1257 	char key[ASMC_KEYLEN + 1] = { 0 };
1258 	char type[ASMC_KEYINFO_RESPLEN + 1] = { 0 };
1259 	uint8_t index[4];
1260 	uint8_t v[ASMC_MAXVAL];
1261 	uint8_t maxlen;
1262 	int i, error = 1, try = 0;
1263 
1264 	mtx_lock_spin(&sc->sc_mtx);
1265 
1266 	index[0] = (number >> 24) & 0xff;
1267 	index[1] = (number >> 16) & 0xff;
1268 	index[2] = (number >> 8) & 0xff;
1269 	index[3] = number & 0xff;
1270 
1271 begin:
1272 	if (asmc_command(dev, ASMC_CMDGETBYINDEX))
1273 		goto out;
1274 
1275 	for (i = 0; i < ASMC_KEYLEN; i++) {
1276 		ASMC_DATAPORT_WRITE(sc, index[i]);
1277 		if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA))
1278 			goto out;
1279 	}
1280 
1281 	ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN);
1282 
1283 	for (i = 0; i < ASMC_KEYLEN; i++) {
1284 		if (asmc_wait(dev, ASMC_STATUS_DATA_READY))
1285 			goto out;
1286 		key[i] = ASMC_DATAPORT_READ(sc);
1287 	}
1288 
1289 	/* Get key info (length + type). */
1290 	if (asmc_command(dev, ASMC_CMDGETINFO))
1291 		goto out;
1292 
1293 	for (i = 0; i < ASMC_KEYLEN; i++) {
1294 		ASMC_DATAPORT_WRITE(sc, key[i]);
1295 		if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA))
1296 			goto out;
1297 	}
1298 
1299 	ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN);
1300 
1301 	for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) {
1302 		if (asmc_wait(dev, ASMC_STATUS_DATA_READY))
1303 			goto out;
1304 		type[i] = ASMC_DATAPORT_READ(sc);
1305 	}
1306 
1307 	error = 0;
1308 out:
1309 	if (error) {
1310 		if (++try < ASMC_MAXRETRIES)
1311 			goto begin;
1312 		device_printf(dev,
1313 		    "%s for key %d failed %d times, giving up\n",
1314 		    __func__, number, try);
1315 	}
1316 	mtx_unlock_spin(&sc->sc_mtx);
1317 
1318 	if (error)
1319 		return (error);
1320 
1321 	maxlen = type[0];
1322 	type[0] = ' ';
1323 	type[5] = '\0';
1324 	if (maxlen > sizeof(v))
1325 		maxlen = sizeof(v);
1326 
1327 	memset(v, 0, sizeof(v));
1328 	error = asmc_key_read(dev, key, v, maxlen);
1329 	if (error)
1330 		return (error);
1331 
1332 	device_printf(dev, "key %d: %s, type%s (len %d), data",
1333 	    number, key, type, maxlen);
1334 	for (i = 0; i < maxlen; i++)
1335 		printf(" %02x", v[i]);
1336 	printf("\n");
1337 
1338 	return (0);
1339 }
1340 
1341 /*
1342  * Get key info (length and type) from SMC using command 0x13.
1343  * Returns 0 on success, -1 on failure.
1344  * If len is non-NULL, stores the key's value length.
1345  * If type is non-NULL, stores the 4-char type string (must be at least 5 bytes).
1346  */
1347 static int
1348 asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type)
1349 {
1350 	struct asmc_softc *sc = device_get_softc(dev);
1351 	uint8_t info[ASMC_KEYINFO_RESPLEN];
1352 	int i, error = -1, try = 0;
1353 
1354 	mtx_lock_spin(&sc->sc_mtx);
1355 
1356 begin:
1357 	if (asmc_command(dev, ASMC_CMDGETINFO))
1358 		goto out;
1359 
1360 	for (i = 0; i < ASMC_KEYLEN; i++) {
1361 		ASMC_DATAPORT_WRITE(sc, key[i]);
1362 		if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA))
1363 			goto out;
1364 	}
1365 
1366 	ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN);
1367 
1368 	for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) {
1369 		if (asmc_wait(dev, ASMC_STATUS_DATA_READY))
1370 			goto out;
1371 		info[i] = ASMC_DATAPORT_READ(sc);
1372 	}
1373 
1374 	error = 0;
1375 out:
1376 	if (error && ++try < ASMC_MAXRETRIES)
1377 		goto begin;
1378 	mtx_unlock_spin(&sc->sc_mtx);
1379 
1380 	if (error == 0) {
1381 		if (len != NULL)
1382 			*len = info[0];
1383 		if (type != NULL) {
1384 			for (i = 0; i < ASMC_TYPELEN; i++)
1385 				type[i] = info[i + 1];
1386 			type[ASMC_TYPELEN] = '\0';
1387 		}
1388 	}
1389 	return (error);
1390 }
1391 
1392 /*
1393  * Raw SMC key access sysctls - enables reading/writing any SMC key by name
1394  * Usage:
1395  *   sysctl dev.asmc.0.raw.key=AUPO   # Set key, auto-detects length
1396  *   sysctl dev.asmc.0.raw.value      # Read current value (hex bytes)
1397  *   sysctl dev.asmc.0.raw.value=01   # Write new value
1398  */
1399 static int
1400 asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS)
1401 {
1402 	device_t dev = (device_t) arg1;
1403 	struct asmc_softc *sc = device_get_softc(dev);
1404 	char newkey[ASMC_KEYLEN + 1];
1405 	uint8_t keylen;
1406 	int error;
1407 
1408 	strlcpy(newkey, sc->sc_rawkey, sizeof(newkey));
1409 	error = sysctl_handle_string(oidp, newkey, sizeof(newkey), req);
1410 	if (error || req->newptr == NULL)
1411 		return (error);
1412 
1413 	if (strlen(newkey) != ASMC_KEYLEN)
1414 		return (EINVAL);
1415 
1416 	/* Get key info to auto-detect length and type */
1417 	if (asmc_key_getinfo(dev, newkey, &keylen, sc->sc_rawtype) != 0)
1418 		return (ENOENT);
1419 
1420 	if (keylen > ASMC_MAXVAL)
1421 		keylen = ASMC_MAXVAL;
1422 
1423 	strlcpy(sc->sc_rawkey, newkey, sizeof(sc->sc_rawkey));
1424 	sc->sc_rawlen = keylen;
1425 	memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval));
1426 
1427 	/* Read the key value */
1428 	asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen);
1429 
1430 	return (0);
1431 }
1432 
1433 static int
1434 asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS)
1435 {
1436 	device_t dev = (device_t) arg1;
1437 	struct asmc_softc *sc = device_get_softc(dev);
1438 	char hexbuf[ASMC_MAXVAL * 2 + 1];
1439 	int error, i;
1440 
1441 	/* Refresh from SMC if a key has been selected. */
1442 	if (sc->sc_rawkey[0] != '\0') {
1443 		asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval,
1444 		    sc->sc_rawlen > 0 ? sc->sc_rawlen : ASMC_MAXVAL);
1445 	}
1446 
1447 	/* Format as hex string */
1448 	for (i = 0; i < sc->sc_rawlen && i < ASMC_MAXVAL; i++)
1449 		snprintf(hexbuf + i * 2, 3, "%02x", sc->sc_rawval[i]);
1450 	hexbuf[i * 2] = '\0';
1451 
1452 	error = sysctl_handle_string(oidp, hexbuf, sizeof(hexbuf), req);
1453 	if (error || req->newptr == NULL)
1454 		return (error);
1455 
1456 	/* Reject writes until a key is selected via raw.key. */
1457 	if (sc->sc_rawkey[0] == '\0')
1458 		return (EINVAL);
1459 
1460 	memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval));
1461 	for (i = 0; i < sc->sc_rawlen && hexbuf[i*2] && hexbuf[i*2+1]; i++) {
1462 		unsigned int val;
1463 		char tmp[3] = { hexbuf[i*2], hexbuf[i*2+1], 0 };
1464 		if (sscanf(tmp, "%02x", &val) == 1)
1465 			sc->sc_rawval[i] = (uint8_t)val;
1466 	}
1467 
1468 	if (asmc_key_write(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen) != 0)
1469 		return (EIO);
1470 
1471 	return (0);
1472 }
1473 
1474 static int
1475 asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS)
1476 {
1477 	device_t dev = (device_t) arg1;
1478 	struct asmc_softc *sc = device_get_softc(dev);
1479 
1480 	return (sysctl_handle_8(oidp, &sc->sc_rawlen, 0, req));
1481 }
1482 
1483 static int
1484 asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS)
1485 {
1486 	device_t dev = (device_t) arg1;
1487 	struct asmc_softc *sc = device_get_softc(dev);
1488 
1489 	return (sysctl_handle_string(oidp, sc->sc_rawtype,
1490 	    sizeof(sc->sc_rawtype), req));
1491 }
1492 #endif
1493 
1494 static int
1495 asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
1496 {
1497 	int i, error = -1, try = 0;
1498 	struct asmc_softc *sc = device_get_softc(dev);
1499 
1500 	mtx_lock_spin(&sc->sc_mtx);
1501 
1502 begin:
1503 	ASMC_DPRINTF(("cmd port: cmd write\n"));
1504 	if (asmc_command(dev, ASMC_CMDWRITE))
1505 		goto out;
1506 
1507 	ASMC_DPRINTF(("data port: key\n"));
1508 	for (i = 0; i < 4; i++) {
1509 		ASMC_DATAPORT_WRITE(sc, key[i]);
1510 		if (asmc_wait(dev, 0x04))
1511 			goto out;
1512 	}
1513 	ASMC_DPRINTF(("data port: length\n"));
1514 	ASMC_DATAPORT_WRITE(sc, len);
1515 
1516 	ASMC_DPRINTF(("data port: buffer\n"));
1517 	for (i = 0; i < len; i++) {
1518 		if (asmc_wait(dev, 0x04))
1519 			goto out;
1520 		ASMC_DATAPORT_WRITE(sc, buf[i]);
1521 	}
1522 
1523 	error = 0;
1524 out:
1525 	if (error) {
1526 		if (++try < 10)
1527 			goto begin;
1528 		device_printf(dev, "%s for key %s failed %d times, giving up\n",
1529 		    __func__, key, try);
1530 	}
1531 
1532 	mtx_unlock_spin(&sc->sc_mtx);
1533 
1534 	return (error);
1535 }
1536 
1537 /*
1538  * Fan control functions.
1539  */
1540 static int
1541 asmc_fan_count(device_t dev)
1542 {
1543 	uint8_t buf[1];
1544 
1545 	if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof(buf)) != 0)
1546 		return (-1);
1547 
1548 	return (buf[0]);
1549 }
1550 
1551 static int
1552 asmc_fan_getvalue(device_t dev, const char *key, int fan)
1553 {
1554 	int speed;
1555 	uint8_t buf[2];
1556 	char fankey[5];
1557 
1558 	snprintf(fankey, sizeof(fankey), key, fan);
1559 	if (asmc_key_read(dev, fankey, buf, sizeof(buf)) != 0)
1560 		return (-1);
1561 	speed = (buf[0] << 6) | (buf[1] >> 2);
1562 
1563 	return (speed);
1564 }
1565 
1566 static char *
1567 asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf,
1568     uint8_t buflen)
1569 {
1570 	char fankey[5];
1571 	char *desc;
1572 
1573 	snprintf(fankey, sizeof(fankey), key, fan);
1574 	if (asmc_key_read(dev, fankey, buf, buflen) != 0)
1575 		return (NULL);
1576 	desc = buf + 4;
1577 
1578 	return (desc);
1579 }
1580 
1581 static int
1582 asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed)
1583 {
1584 	uint8_t buf[2];
1585 	char fankey[5];
1586 
1587 	speed *= 4;
1588 
1589 	buf[0] = speed >> 8;
1590 	buf[1] = speed;
1591 
1592 	snprintf(fankey, sizeof(fankey), key, fan);
1593 	if (asmc_key_write(dev, fankey, buf, sizeof(buf)) < 0)
1594 		return (-1);
1595 
1596 	return (0);
1597 }
1598 
1599 static int
1600 asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
1601 {
1602 	device_t dev = (device_t)arg1;
1603 	int fan = arg2;
1604 	int error;
1605 	int32_t v;
1606 
1607 	v = asmc_fan_getvalue(dev, ASMC_KEY_FANSPEED, fan);
1608 	error = sysctl_handle_int(oidp, &v, 0, req);
1609 
1610 	return (error);
1611 }
1612 
1613 static int
1614 asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS)
1615 {
1616 	uint8_t buf[16];
1617 	device_t dev = (device_t)arg1;
1618 	int fan = arg2;
1619 	int error = true;
1620 	char *desc;
1621 
1622 	desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf));
1623 
1624 	if (desc != NULL)
1625 		error = sysctl_handle_string(oidp, desc, 0, req);
1626 
1627 	return (error);
1628 }
1629 
1630 static int
1631 asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS)
1632 {
1633 	device_t dev = (device_t)arg1;
1634 	int fan = arg2;
1635 	int error;
1636 	int32_t v;
1637 
1638 	v = asmc_fan_getvalue(dev, ASMC_KEY_FANSAFESPEED, fan);
1639 	error = sysctl_handle_int(oidp, &v, 0, req);
1640 
1641 	return (error);
1642 }
1643 
1644 static int
1645 asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS)
1646 {
1647 	device_t dev = (device_t)arg1;
1648 	int fan = arg2;
1649 	int error;
1650 	int32_t v;
1651 
1652 	v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan);
1653 	error = sysctl_handle_int(oidp, &v, 0, req);
1654 
1655 	if (error == 0 && req->newptr != NULL) {
1656 		unsigned int newspeed = v;
1657 		asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed);
1658 	}
1659 
1660 	return (error);
1661 }
1662 
1663 static int
1664 asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS)
1665 {
1666 	device_t dev = (device_t)arg1;
1667 	int fan = arg2;
1668 	int error;
1669 	int32_t v;
1670 
1671 	v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan);
1672 	error = sysctl_handle_int(oidp, &v, 0, req);
1673 
1674 	if (error == 0 && req->newptr != NULL) {
1675 		unsigned int newspeed = v;
1676 		asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed);
1677 	}
1678 
1679 	return (error);
1680 }
1681 
1682 static int
1683 asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS)
1684 {
1685 	device_t dev = (device_t)arg1;
1686 	int fan = arg2;
1687 	int error;
1688 	int32_t v;
1689 
1690 	v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan);
1691 	error = sysctl_handle_int(oidp, &v, 0, req);
1692 
1693 	if (error == 0 && req->newptr != NULL) {
1694 		unsigned int newspeed = v;
1695 		asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed);
1696 	}
1697 
1698 	return (error);
1699 }
1700 
1701 static int
1702 asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS)
1703 {
1704 	device_t dev = (device_t)arg1;
1705 	int fan = arg2;
1706 	int error;
1707 	int32_t v;
1708 	uint8_t buf[2];
1709 	uint16_t val;
1710 
1711 	/* Read current FS! bitmask (asmc_key_read locks internally) */
1712 	error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf));
1713 	if (error != 0)
1714 		return (error);
1715 
1716 	/* Extract manual bit for this fan (big-endian) */
1717 	val = (buf[0] << 8) | buf[1];
1718 	v = (val >> fan) & 0x01;
1719 
1720 	/* Let sysctl handle the value */
1721 	error = sysctl_handle_int(oidp, &v, 0, req);
1722 
1723 	if (error == 0 && req->newptr != NULL) {
1724 		/* Validate input (0 = auto, 1 = manual) */
1725 		if (v != 0 && v != 1)
1726 			return (EINVAL);
1727 		/* Read-modify-write of FS! bitmask */
1728 		error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf,
1729 		    sizeof(buf));
1730 		if (error == 0) {
1731 			val = (buf[0] << 8) | buf[1];
1732 
1733 			/* Modify single bit */
1734 			if (v)
1735 				val |= (1 << fan);   /* Set to manual */
1736 			else
1737 				val &= ~(1 << fan);  /* Set to auto */
1738 
1739 			/* Write back */
1740 			buf[0] = val >> 8;
1741 			buf[1] = val & 0xff;
1742 			error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf,
1743 			    sizeof(buf));
1744 		}
1745 	}
1746 
1747 	return (error);
1748 }
1749 
1750 /*
1751  * Temperature functions.
1752  */
1753 static int
1754 asmc_temp_getvalue(device_t dev, const char *key)
1755 {
1756 	uint8_t buf[2];
1757 
1758 	/*
1759 	 * Check for invalid temperatures.
1760 	 */
1761 	if (asmc_key_read(dev, key, buf, sizeof(buf)) != 0)
1762 		return (-1);
1763 
1764 	return (buf[0]);
1765 }
1766 
1767 static int
1768 asmc_temp_sysctl(SYSCTL_HANDLER_ARGS)
1769 {
1770 	device_t dev = (device_t)arg1;
1771 	struct asmc_softc *sc = device_get_softc(dev);
1772 	int error, val;
1773 
1774 	val = asmc_temp_getvalue(dev, sc->sc_model->smc_temps[arg2]);
1775 	error = sysctl_handle_int(oidp, &val, 0, req);
1776 
1777 	return (error);
1778 }
1779 
1780 /*
1781  * Sudden Motion Sensor functions.
1782  */
1783 static int
1784 asmc_sms_read(device_t dev, const char *key, int16_t *val)
1785 {
1786 	uint8_t buf[2];
1787 	int error;
1788 
1789 	/* no need to do locking here as asmc_key_read() already does it */
1790 	switch (key[3]) {
1791 	case 'X':
1792 	case 'Y':
1793 	case 'Z':
1794 		error = asmc_key_read(dev, key, buf, sizeof(buf));
1795 		break;
1796 	default:
1797 		device_printf(dev, "%s called with invalid argument %s\n",
1798 		    __func__, key);
1799 		error = EINVAL;
1800 		goto out;
1801 	}
1802 	*val = ((int16_t)buf[0] << 8) | buf[1];
1803 out:
1804 	return (error);
1805 }
1806 
1807 static void
1808 asmc_sms_calibrate(device_t dev)
1809 {
1810 	struct asmc_softc *sc = device_get_softc(dev);
1811 
1812 	asmc_sms_read(dev, ASMC_KEY_SMS_X, &sc->sms_rest_x);
1813 	asmc_sms_read(dev, ASMC_KEY_SMS_Y, &sc->sms_rest_y);
1814 	asmc_sms_read(dev, ASMC_KEY_SMS_Z, &sc->sms_rest_z);
1815 }
1816 
1817 static int
1818 asmc_sms_intrfast(void *arg)
1819 {
1820 	uint8_t type;
1821 	device_t dev = (device_t)arg;
1822 	struct asmc_softc *sc = device_get_softc(dev);
1823 	if (!sc->sc_sms_intr_works)
1824 		return (FILTER_HANDLED);
1825 
1826 	mtx_lock_spin(&sc->sc_mtx);
1827 	type = ASMC_INTPORT_READ(sc);
1828 	mtx_unlock_spin(&sc->sc_mtx);
1829 
1830 	sc->sc_sms_intrtype = type;
1831 	asmc_sms_printintr(dev, type);
1832 
1833 	taskqueue_enqueue(sc->sc_sms_tq, &sc->sc_sms_task);
1834 	return (FILTER_HANDLED);
1835 }
1836 
1837 static void
1838 asmc_sms_printintr(device_t dev, uint8_t type)
1839 {
1840 	struct asmc_softc *sc = device_get_softc(dev);
1841 
1842 	switch (type) {
1843 	case ASMC_SMS_INTFF:
1844 		device_printf(dev, "WARNING: possible free fall!\n");
1845 		break;
1846 	case ASMC_SMS_INTHA:
1847 		device_printf(dev, "WARNING: high acceleration detected!\n");
1848 		break;
1849 	case ASMC_SMS_INTSH:
1850 		device_printf(dev, "WARNING: possible shock!\n");
1851 		break;
1852 	case ASMC_ALSL_INT2A:
1853 		/*
1854 		 * This suppresses console and log messages for the ambient
1855 		 * light sensor for models known to generate this interrupt.
1856 		 */
1857 		if (strcmp(sc->sc_model->smc_model, "MacBookPro5,5") == 0 ||
1858 		    strcmp(sc->sc_model->smc_model, "MacBookPro6,2") == 0)
1859 			break;
1860 		/* FALLTHROUGH */
1861 	default:
1862 		device_printf(dev, "unknown interrupt: 0x%x\n", type);
1863 	}
1864 }
1865 
1866 static void
1867 asmc_sms_task(void *arg, int pending)
1868 {
1869 	struct asmc_softc *sc = (struct asmc_softc *)arg;
1870 	char notify[16];
1871 	int type;
1872 
1873 	switch (sc->sc_sms_intrtype) {
1874 	case ASMC_SMS_INTFF:
1875 		type = 2;
1876 		break;
1877 	case ASMC_SMS_INTHA:
1878 		type = 1;
1879 		break;
1880 	case ASMC_SMS_INTSH:
1881 		type = 0;
1882 		break;
1883 	default:
1884 		type = 255;
1885 	}
1886 
1887 	snprintf(notify, sizeof(notify), " notify=0x%x", type);
1888 	devctl_notify("ACPI", "asmc", "SMS", notify);
1889 }
1890 
1891 static int
1892 asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS)
1893 {
1894 	device_t dev = (device_t)arg1;
1895 	int error;
1896 	int16_t val;
1897 	int32_t v;
1898 
1899 	asmc_sms_read(dev, ASMC_KEY_SMS_X, &val);
1900 	v = (int32_t)val;
1901 	error = sysctl_handle_int(oidp, &v, 0, req);
1902 
1903 	return (error);
1904 }
1905 
1906 static int
1907 asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS)
1908 {
1909 	device_t dev = (device_t)arg1;
1910 	int error;
1911 	int16_t val;
1912 	int32_t v;
1913 
1914 	asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val);
1915 	v = (int32_t)val;
1916 	error = sysctl_handle_int(oidp, &v, 0, req);
1917 
1918 	return (error);
1919 }
1920 
1921 static int
1922 asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS)
1923 {
1924 	device_t dev = (device_t)arg1;
1925 	int error;
1926 	int16_t val;
1927 	int32_t v;
1928 
1929 	asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val);
1930 	v = (int32_t)val;
1931 	error = sysctl_handle_int(oidp, &v, 0, req);
1932 
1933 	return (error);
1934 }
1935 
1936 static int
1937 asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS)
1938 {
1939 	device_t dev = (device_t)arg1;
1940 	uint8_t buf[6];
1941 	int error;
1942 	int32_t v;
1943 
1944 	asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf));
1945 	v = buf[2];
1946 	error = sysctl_handle_int(oidp, &v, 0, req);
1947 
1948 	return (error);
1949 }
1950 
1951 static int
1952 asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS)
1953 {
1954 	device_t dev = (device_t)arg1;
1955 	uint8_t buf[6];
1956 	int error;
1957 	int32_t v;
1958 
1959 	asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof(buf));
1960 	v = buf[2];
1961 	error = sysctl_handle_int(oidp, &v, 0, req);
1962 
1963 	return (error);
1964 }
1965 
1966 static int
1967 asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS)
1968 {
1969 	device_t dev = (device_t)arg1;
1970 	struct asmc_softc *sc = device_get_softc(dev);
1971 	uint8_t buf[2];
1972 	int error;
1973 	int v;
1974 
1975 	v = light_control;
1976 	error = sysctl_handle_int(oidp, &v, 0, req);
1977 
1978 	if (error == 0 && req->newptr != NULL) {
1979 		if (v < 0 || v > 255)
1980 			return (EINVAL);
1981 		light_control = v;
1982 		sc->sc_kbd_bkl_level = v * 100 / 255;
1983 		buf[0] = light_control;
1984 		buf[1] = 0x00;
1985 		asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf));
1986 	}
1987 	return (error);
1988 }
1989 
1990 static int
1991 asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS)
1992 {
1993 	device_t dev = (device_t)arg1;
1994 	uint8_t buf[10];
1995 	int error;
1996 	uint32_t v;
1997 
1998 	asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf));
1999 
2000 	/*
2001 	 * This seems to be a 32 bit big endian value from buf[6] -> buf[9].
2002 	 *
2003 	 * Extract it out manually here, then shift/clamp it.
2004 	 */
2005 	v = be32dec(&buf[6]);
2006 
2007 	/*
2008 	 * Shift out, clamp at 255; that way it looks like the
2009 	 * earlier SMC firmware version responses.
2010 	 */
2011 	v = v >> 8;
2012 	if (v > 255)
2013 		v = 255;
2014 
2015 	error = sysctl_handle_int(oidp, &v, 0, req);
2016 
2017 	return (error);
2018 }
2019 
2020 /*
2021  * Wake-on-LAN convenience sysctl.
2022  * Reading returns 1 if WoL is enabled, 0 if disabled.
2023  * Writing 1 enables WoL, 0 disables it.
2024  */
2025 static int
2026 asmc_wol_sysctl(SYSCTL_HANDLER_ARGS)
2027 {
2028 	device_t dev = (device_t)arg1;
2029 	uint8_t aupo;
2030 	int val, error;
2031 
2032 	/* Read current AUPO value */
2033 	if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0)
2034 		return (EIO);
2035 
2036 	val = (aupo != 0) ? 1 : 0;
2037 	error = sysctl_handle_int(oidp, &val, 0, req);
2038 	if (error != 0 || req->newptr == NULL)
2039 		return (error);
2040 
2041 	/* Clamp to 0 or 1 */
2042 	aupo = (val != 0) ? 1 : 0;
2043 
2044 	/* Write AUPO */
2045 	if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0)
2046 		return (EIO);
2047 
2048 	return (0);
2049 }
2050 
2051 static int
2052 asmc_backlight_update_status(device_t dev, struct backlight_props *props)
2053 {
2054 	struct asmc_softc *sc = device_get_softc(dev);
2055 	uint8_t buf[2];
2056 
2057 	sc->sc_kbd_bkl_level = props->brightness;
2058 	light_control = props->brightness * 255 / 100;
2059 	buf[0] = light_control;
2060 	buf[1] = 0x00;
2061 	asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf));
2062 
2063 	return (0);
2064 }
2065 
2066 static int
2067 asmc_backlight_get_status(device_t dev, struct backlight_props *props)
2068 {
2069 	struct asmc_softc *sc = device_get_softc(dev);
2070 
2071 	props->brightness = sc->sc_kbd_bkl_level;
2072 	props->nlevels = 0;
2073 
2074 	return (0);
2075 }
2076 
2077 static int
2078 asmc_backlight_get_info(device_t dev, struct backlight_info *info)
2079 {
2080 	info->type = BACKLIGHT_TYPE_KEYBOARD;
2081 	strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH);
2082 
2083 	return (0);
2084 }
2085