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