1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
|
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#define ASMC_MAXFANS 6
#define ASMC_MAXVAL 32 /* Maximum SMC value size */
#define ASMC_KEYLEN 4 /* SMC key name length */
#define ASMC_TYPELEN 4 /* SMC type string length */
#define ASMC_MAX_SENSORS 64 /* Max sensors per type */
/* Maximum number of auto-detected temperature sensors */
#define ASMC_TEMP_MAX 80
struct asmc_softc {
device_t sc_dev;
struct mtx sc_mtx;
int sc_nfan;
int sc_nkeys;
int16_t sms_rest_x;
int16_t sms_rest_y;
int16_t sms_rest_z;
struct sysctl_oid *sc_fan_tree[ASMC_MAXFANS+1];
struct sysctl_oid *sc_temp_tree;
struct sysctl_oid *sc_sms_tree;
struct sysctl_oid *sc_light_tree;
int sc_rid_port;
int sc_rid_irq;
struct resource *sc_ioport;
struct resource *sc_irq;
void *sc_cookie;
/* MMIO backend (T2 Macs) */
int sc_rid_mem;
struct resource *sc_iomem;
bool sc_is_mmio;
int sc_is_t2; /* T2 fan float + per-fan manual */
int sc_sms_intrtype;
struct taskqueue *sc_sms_tq;
struct task sc_sms_task;
uint8_t sc_sms_intr_works;
struct cdev *sc_kbd_bkl;
uint32_t sc_kbd_bkl_level;
#ifdef ASMC_DEBUG
/* Raw key access */
struct sysctl_oid *sc_raw_tree;
char sc_rawkey[ASMC_KEYLEN + 1];
uint8_t sc_rawval[ASMC_MAXVAL];
uint8_t sc_rawlen;
char sc_rawtype[ASMC_TYPELEN + 1];
#endif
/* Voltage/Current/Power/Light sensors */
char *sc_voltage_sensors[ASMC_MAX_SENSORS];
int sc_voltage_count;
char *sc_current_sensors[ASMC_MAX_SENSORS];
int sc_current_count;
char *sc_power_sensors[ASMC_MAX_SENSORS];
int sc_power_count;
char *sc_light_sensors[ASMC_MAX_SENSORS];
int sc_light_count;
/* Auto-detected temperature sensors */
char *sc_temp_sensors[ASMC_TEMP_MAX];
int sc_temp_count;
/* Auto-detected capabilities */
int sc_has_sms;
int sc_has_light;
int sc_light_len; /* ASMC_LIGHT_{SHORT,LONG}LEN */
int sc_has_safespeed;
int sc_has_alsl; /* ALSL interrupt source */
};
/*
* Data port.
*/
#define ASMC_DATAPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x00)
#define ASMC_DATAPORT_WRITE(sc, val) \
bus_write_1(sc->sc_ioport, 0x00, val)
#define ASMC_STATUS_MASK 0x0f
/*
* Command port.
*/
#define ASMC_CMDPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x04)
#define ASMC_CMDPORT_WRITE(sc, val) \
bus_write_1(sc->sc_ioport, 0x04, val)
#define ASMC_CMDREAD 0x10
#define ASMC_CMDWRITE 0x11
#define ASMC_CMDGETBYINDEX 0x12
#define ASMC_CMDGETINFO 0x13
#define ASMC_STATUS_AWAIT_DATA 0x04
#define ASMC_STATUS_DATA_READY 0x05
#define ASMC_KEYINFO_RESPLEN 6 /* getinfo: 1 len + 4 type + 1 attr */
#define ASMC_MAXRETRIES 10
/*
* Interrupt port.
*/
#define ASMC_INTPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x1f)
/* Number of keys */
#define ASMC_NKEYS "#KEY" /* RO; 4 bytes */
/* Query the ASMC revision */
#define ASMC_KEY_REV "REV " /* RO: 6 bytes */
/*
* Fan control via SMC.
*/
#define ASMC_KEY_FANCOUNT "FNum" /* RO; 1 byte */
#define ASMC_KEY_FANMANUAL "FS! " /* RW; 2 bytes */
#define ASMC_KEY_FANID "F%dID" /* RO; 16 bytes */
#define ASMC_KEY_FANSPEED "F%dAc" /* RO; 2 bytes */
#define ASMC_KEY_FANMINSPEED "F%dMn" /* RW; 2 bytes */
#define ASMC_KEY_FANMAXSPEED "F%dMx" /* RO; 2 bytes */
#define ASMC_KEY_FANSAFESPEED "F%dSf" /* RO; 2 bytes */
#define ASMC_KEY_FANTARGETSPEED "F%dTg" /* RW; 2 bytes */
/*
* Sudden Motion Sensor (SMS).
*/
#define ASMC_SMS_INIT1 0xe0
#define ASMC_SMS_INIT2 0xf8
#define ASMC_KEY_SMS "MOCN" /* RW; 2 bytes */
#define ASMC_KEY_SMS_X "MO_X" /* RO; 2 bytes */
#define ASMC_KEY_SMS_Y "MO_Y" /* RO; 2 bytes */
#define ASMC_KEY_SMS_Z "MO_Z" /* RO; 2 bytes */
#define ASMC_KEY_SMS_LOW "MOLT" /* RW; 2 bytes */
#define ASMC_KEY_SMS_HIGH "MOHT" /* RW; 2 bytes */
#define ASMC_KEY_SMS_LOW_INT "MOLD" /* RW; 1 byte */
#define ASMC_KEY_SMS_HIGH_INT "MOHD" /* RW; 1 byte */
#define ASMC_KEY_SMS_FLAG "MSDW" /* RW; 1 byte */
#define ASMC_SMS_INTFF 0x60 /* Free fall Interrupt */
#define ASMC_SMS_INTHA 0x6f /* High Acceleration Interrupt */
#define ASMC_SMS_INTSH 0x80 /* Shock Interrupt */
/*
* Light Sensor.
*/
#define ASMC_ALSL_INT2A 0x2a /* Ambient Light related Interrupt */
/*
* Keyboard backlight.
*/
#define ASMC_LIGHT_SHORTLEN 6 /* ALV0 short format */
#define ASMC_LIGHT_LONGLEN 10 /* ALV0 long format (10-byte) */
#define ASMC_KEY_LIGHTLEFT "ALV0" /* RO; 6 or 10 bytes */
#define ASMC_KEY_LIGHTRIGHT "ALV1" /* RO; 6 bytes */
#define ASMC_KEY_LIGHTVALUE "LKSB" /* WO; 2 bytes */
#define ASMC_KEY_LIGHTSRC "ALSL" /* RO; ambient light source */
#define ASMC_KEY_FANSAFESPEED0 "F0Sf" /* RO; 2 bytes */
/*
* Sleep Indicator LED (SIL).
*
* MSLD controls the duty cycle of the front-panel sleep indicator LED.
* 0x00 = LED at idle brightness, 0xff = LED fully off.
* MSLS is the SIL state latch — must be written to 0x01 before MSLD
* can re-enable the LED after it has been turned off.
*
* Protocol: OFF = write MSLD 0xff
* ON = write MSLS 0x01, then write MSLD 0x01
*
* Present on all Intel Macs with a sleep indicator (laptops + Mac Mini).
*/
#define ASMC_KEY_MSLD "MSLD" /* RW; 1 byte, SIL duty */
#define ASMC_KEY_MSLS "MSLS" /* RW; 1 byte, SIL state latch */
/*
* Auto power-on after AC power loss (AUPO).
* When set, the machine boots automatically when AC power is restored
* after an unclean power loss. This is NOT Wake-on-LAN.
*/
#define ASMC_KEY_AUPO "AUPO" /* RW; 1 byte */
/*
* Interrupt keys.
*/
#define ASMC_KEY_INTOK "NTOK" /* WO; 1 byte */
/*
* System State Machine / diagnostics keys.
*
* MSSD - Mac System Shutdown cause (last shutdown reason code)
* MSSP - Mac System SleeP cause (last sleep reason code)
* MSAL - Mac System ALarm (thermal subsystem status bitmap)
* MSPS - Mac System Power State (current power state index)
* CLKT - CLocK Time (seconds since midnight, SMC RTC)
* MSTS - Mac System sTate/Status (SSM state; 0 = S0 awake)
*/
#define ASMC_KEY_CLKT "CLKT" /* RO; 4 bytes ui32 BE */
#define ASMC_KEY_MSSD "MSSD" /* RO; 1 byte si8 */
#define ASMC_KEY_MSSP "MSSP" /* RO; 1 byte si8 */
#define ASMC_KEY_MSAL "MSAL" /* RO; 1 byte hex_ */
#define ASMC_KEY_MSPS "MSPS" /* RO; 1 or 2 bytes hex_ */
#define ASMC_KEY_MSTS "MSTS" /* RO; 1 byte ui8 */
#define ASMC_MSAL_TSS 0x01 /* TSS running */
#define ASMC_MSAL_THERM_VALID 0x02 /* thermal calibration valid */
#define ASMC_MSAL_CALIB_VALID 0x08 /* I/P calibration valid */
#define ASMC_MSAL_PROCHOT 0x40 /* Prochot enabled */
#define ASMC_MSAL_PLIMITS 0x80 /* plimits enabled */
/*
* Board identity keys.
*
* RPlt - board platform identifier (e.g. "Mac-XXXX")
* RGEN - security chip generation (3 = T2)
*/
#define ASMC_KEY_RPLT "RPlt" /* RO; 8 bytes ch8* */
#define ASMC_KEY_RGEN "RGEN" /* RO; 1 byte ui8 */
#define ASMC_RPLT_MAXLEN 8 /* RPlt key data length */
/*
* Shutdown/sleep cause codes (MSSD/MSSP values).
*
* Positive values indicate normal operation; negative values indicate
* fault conditions.
* Sources: Apple SMC firmware, VirtualSMC docs, macOS
* pmset/powermetrics output.
*/
struct asmc_cause {
int8_t code;
const char *desc; /* shutdown description */
const char *sleep_desc; /* sleep description, or NULL if same */
};
#define ASMC_CAUSE_BUFLEN 48 /* "-128 (temperature-overlimit-timeout)\0" */
static const struct asmc_cause asmc_cause_table[] = {
{ 5, "good-shutdown", "good-sleep" },
{ 3, "power-button", NULL },
{ 2, "low-battery-sleep", NULL },
{ 1, "overtemp-sleep", NULL },
{ 0, "initial", NULL },
{ -1, "health-check", NULL },
{ -2, "power-supply", NULL },
{ -3, "temperature-multisleep", NULL },
{ -4, "sensor-fan", NULL },
{ -30, "temperature-overlimit-timeout",NULL },
{ -40, "pswr-smrst", NULL }, /* power supply watchdog reset */
{ -50, "unmapped", NULL },
{ -60, "low-battery", NULL },
{ -61, "ninja-shutdown", NULL }, /* sudden unexpected power loss */
{ -62, "ninja-restart", NULL },
{ -70, "palm-rest-temperature", NULL },
{ -71, "sodimm-temperature", NULL },
{ -72, "heatpipe-temperature", NULL },
{ -74, "battery-temperature", NULL },
{ -75, "adapter-timeout", NULL },
{ -77, "manual-temperature", NULL },
{ -78, "adapter-current", NULL },
{ -79, "battery-current", NULL },
{ -82, "skin-temperature", NULL },
{ -83, "skin-temperature-sensors", NULL },
{ -84, "backup-temperature", NULL },
{ -86, "cpu-proximity-temperature", NULL },
{ -95, "cpu-temperature", NULL },
{ -100, "power-supply-temperature", NULL },
{ -101, "lcd-temperature", NULL },
{ -102, "rsm-power-fail", NULL },
{ -103, "battery-cuv", NULL }, /* cell under-voltage */
{ -127, "pmu-forced-shutdown", NULL },
{ -128, "unknown", NULL },
};
|