This is an initial driver for the Apple System Management Controller
found in Intel based Apple computers.

The driver is currently missing support for the Sudden Motion Sensor
(SMS), light sensor, and keyboard backlight since I don't have that
hardware available to develop on.

On my iMac11,2 it can deliver fan and temperatures values:

        hw.sensors.acpiapplesmc0.temp0=24.00 degC (Airflow 1)
        hw.sensors.acpiapplesmc0.temp1=33.00 degC (CPU Core 0)
        hw.sensors.acpiapplesmc0.temp2=36.00 degC (CPU Heatsink)
        hw.sensors.acpiapplesmc0.temp3=40.00 degC (CPU Core 1)
        hw.sensors.acpiapplesmc0.temp4=47.00 degC (GPU)
        hw.sensors.acpiapplesmc0.temp5=45.00 degC (GPU Heatsink)
        hw.sensors.acpiapplesmc0.temp6=59.00 degC (PCH)
        hw.sensors.acpiapplesmc0.temp7=42.00 degC (Memory)
        hw.sensors.acpiapplesmc0.temp8=45.00 degC (Mainboard Proximity)
        hw.sensors.acpiapplesmc0.fan0=998 RPM
        hw.sensors.acpiapplesmc0.fan1=1132 RPM
        hw.sensors.acpiapplesmc0.fan2=1198 RPM

Feedback, testers, OKs?


Index: share/man/man4/Makefile
===================================================================
RCS file: /cvs/src/share/man/man4/Makefile,v
retrieving revision 1.782
diff -u -p -u -p -r1.782 Makefile
--- share/man/man4/Makefile     25 Jun 2020 12:26:31 -0000      1.782
+++ share/man/man4/Makefile     7 Sep 2020 04:54:57 -0000
@@ -1,7 +1,7 @@
 #      $OpenBSD: Makefile,v 1.782 2020/06/25 12:26:31 patrick Exp $
 
 MAN=   aac.4 abcrtc.4 ac97.4 acphy.4 acrtc.4 \
-       acpi.4 acpiac.4 acpials.4 acpiasus.4 acpibat.4 \
+       acpi.4 acpiac.4 acpials.4 acpiapplesmc.4 acpiasus.4 acpibat.4 \
        acpibtn.4 acpicbkbd.4 acpicpu.4 acpidock.4 acpihve.4 acpiec.4 \
        acpihid.4 \
        acpihpet.4 acpimadt.4 acpimcfg.4 acpipci.4 acpiprt.4 acpipwrres.4 \
Index: share/man/man4/acpiapplesmc.4
===================================================================
RCS file: share/man/man4/acpiapplesmc.4
diff -N share/man/man4/acpiapplesmc.4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ share/man/man4/acpiapplesmc.4       7 Sep 2020 04:54:57 -0000
@@ -0,0 +1,63 @@
+.\"    $OpenBSD$
+.\"
+.\" Copyright (c) 2020 Marcus Glocker <[email protected]>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: September 07 2020 $
+.Dt APPLESMC 4
+.Os
+.Sh NAME
+.Nm acpiapplesmc
+.Nd Apple System Management Controller
+.Sh SYNOPSIS
+.Cd "acpiapplesmc* at acpi?"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Apple System Management Controller chipsets
+found in Intel based Apple computers.  The sensors are exposed through the
+.Xr sysctl 8
+interface.
+.Pp
+The currently supported sensors are:
+.Bl -column "CPU power cons." "Units" "Typical Use" -offset indent
+.It Sy "Sensor" Ta Sy "Units" Ta Sy "Typical Use"
+.It Li "F?Ac" Ta "RPM" Ta "Fan"
+.It Li "TA0P" Ta "degC" Ta "Airflow 1"
+.It Li "TC0C" Ta "degC" Ta "CPU Core 0"
+.It Li "TC0H" Ta "degC" Ta "CPU Heatsink"
+.It Li "TC1C" Ta "degC" Ta "CPU Core 1"
+.It Li "TG0D" Ta "degC" Ta "GPU"
+.It Li "TG0H" Ta "degC" Ta "GPU Heatsink"
+.It Li "TPCD" Ta "degC" Ta "PCH"
+.It Li "Tm0P" Ta "degC" Ta "Memory"
+.It Li "Tm1P" Ta "degC" Ta "Mainboard Proximity"
+.El
+.Sh SEE ALSO
+.Xr acpi 4 ,
+.Xr sensorsd 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 6.8 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Marcus Glocker Aq Mt [email protected] .
+.Sh CAVEATS
+The driver is currently missing support for the Sudden Motion Sensor (SMS),
+light sensor, and keyboard backlight.
Index: sys/dev/acpi/acpiapplesmc.c
===================================================================
RCS file: sys/dev/acpi/acpiapplesmc.c
diff -N sys/dev/acpi/acpiapplesmc.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/dev/acpi/acpiapplesmc.c 7 Sep 2020 04:54:57 -0000
@@ -0,0 +1,661 @@
+/*     $OpenBSD$ */
+
+/*
+ * Copyright (c) 2020 Marcus Glocker <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for the System Management Controller (SMC).
+ *
+ * The documentation to write this driver was found in the FreeBSD asmc and
+ * Linux applesmc driver.
+ *
+ * TODO:
+ *     - Add support for Sudden Motion Sensor (SMS).
+ *     - Add support for light sensor.
+ *     - Add support for keyboard backlight.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpidev.h>
+#include <dev/acpi/amltypes.h>
+#include <dev/acpi/dsdt.h>
+
+#define ACPIAPPLESMC_DEBUG
+#ifdef ACPIAPPLESMC_DEBUG
+#define DPRINTF(x) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+#define APPLESMC_PORT_DATA             0x00
+#define APPLESMC_PORT_CMD              0x04
+
+#define APLLESMC_WAITACK_WRITE         0x04
+#define APLLESMC_WAITACK_READ          0x05
+#define APPLESMC_WAITACK_CMD           0x0C
+#define APPLESMC_WAITACK_RETRY         1600
+
+#define APPLESMC_CMD_KEY_READ          0x10
+#define APPLESMC_CMD_KEY_WRITE         0x11
+#define APPLESMC_CMD_KEY_GET_BY_INDEX  0x12
+#define APPLESMC_CMD_KEY_GET_TYPE      0x13
+#define APPLESMC_CMD_RETRY             10
+
+#define APPLESMC_KEY_LEN               4
+#define APPLESMC_KEY_TYPE_LEN          6
+#define APPLESMC_KEY_COUNT             "#KEY"
+#define APPLESMC_KEY_FANCOUNT          "FNum"
+#define APPLESMC_KEY_FANSPEED          "F%dAc"
+
+#define APPLESMC_MAX_KEY               1024
+#define APPLESMC_MAX_FAN               8
+#define APPLESMC_MAX_TEMP              16
+
+/* List of known temperature sensors. */
+const struct {
+       char *key;
+       char *desc;
+} acpiapplesmc_temp_desc[] = {
+       { "TA0P", "Airflow 1" },
+       { "TC0C", "CPU Core 0" },
+       { "TC0H", "CPU Heatsink" },
+       { "TC1C", "CPU Core 1" },
+       { "TG0D", "GPU" },
+       { "TG0H", "GPU Heatsink" },
+       { "TPCD", "PCH" },
+       { "Tm0P", "Memory" },
+       { "Tm1P", "Mainboard Proximity" },
+       { NULL, NULL }
+};
+
+/* Key entry. */
+struct acpiapplesmc_key {
+       char    key[5];
+       char    type[5];
+       uint8_t len;
+       uint8_t flags;
+       uint8_t temp_use;
+};
+
+struct acpiapplesmc_softc {
+       struct device            sc_dev;
+
+       struct acpi_softc       *sc_acpi;
+       struct aml_node         *sc_devnode;
+
+       bus_space_tag_t          sc_bt;
+       bus_space_handle_t       sc_bh;
+
+       struct ksensor           sc_sens[APPLESMC_MAX_FAN + APPLESMC_MAX_TEMP];
+       struct ksensordev        sc_sensdev;
+
+       uint32_t                 sc_key_count;
+       uint8_t                  sc_fan_count;
+       uint8_t                  sc_temp_count;
+       uint8_t                  sc_temp_count_total;
+       int                      sc_keys_init;
+       struct acpiapplesmc_key  sc_keys[APPLESMC_MAX_KEY];
+};
+
+int    acpiapplesmc_match(struct device *, void *, void *);
+void   acpiapplesmc_attach(struct device *, struct device *, void *);
+int    acpiapplesmc_notify(struct aml_node *, int, void *);
+int    acpiapplesmc_activate(struct device *, int);
+
+int    acpiapplesmc_waitack(struct acpiapplesmc_softc *,
+           const uint8_t);
+int    acpiapplesmc_cmd(struct acpiapplesmc_softc *,
+           const uint8_t);
+int    acpiapplesmc_key_read(struct acpiapplesmc_softc *,
+           const char *, char *, const uint8_t);
+int    acpiapplesmc_key_write(struct acpiapplesmc_softc *,
+           const char *, const char *, const uint8_t);
+int    acpiapplesmc_key_get_byindex(struct acpiapplesmc_softc *,
+           const uint32_t, char *);
+int    acpiapplesmc_key_get_type(struct acpiapplesmc_softc *,
+           const char *, char *);
+int    acpiapplesmc_key_count(struct acpiapplesmc_softc *,
+           uint32_t *);
+int    acpiapplesmc_key_get_entry(struct acpiapplesmc_softc *,
+           const int, struct acpiapplesmc_key *);
+int    acpiapplesmc_key_init(struct acpiapplesmc_softc *,
+           const int);
+int    acpiapplesmc_fan_count(struct acpiapplesmc_softc *,
+           uint8_t *);
+int    acpiapplesmc_fan_get_value(struct acpiapplesmc_softc *,
+           const char *, const uint8_t, uint16_t *);
+int    acpiapplesmc_temp_count_total(struct acpiapplesmc_softc *,
+           uint8_t *);
+int    acpiapplesmc_temp_init(struct acpiapplesmc_softc *,
+           uint8_t *);
+int    acpiapplesmc_temp_get_value(struct acpiapplesmc_softc *,
+           const char *, uint8_t *);
+int    acpiapplesmc_temp_get_desc(struct acpiapplesmc_softc *,
+           const char *, const int, char *);
+int    acpiapplesmc_init(struct acpiapplesmc_softc *);
+
+struct cfattach acpiapplesmc_ca = {
+       sizeof(struct acpiapplesmc_softc), acpiapplesmc_match,
+           acpiapplesmc_attach, NULL, acpiapplesmc_activate
+};
+
+struct cfdriver acpiapplesmc_cd = {
+       NULL, "acpiapplesmc", DV_DULL
+};
+
+const char *acpiapplesmc_hids[] = {
+       "APP0001", NULL
+};
+
+int
+acpiapplesmc_match(struct device *parent, void *match, void *aux)
+{
+       struct acpi_attach_args *aa = aux;
+       struct cfdata *cf = match;
+       
+       return acpi_matchhids(aa, acpiapplesmc_hids, cf->cf_driver->cd_name);
+}
+
+void
+acpiapplesmc_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct acpiapplesmc_softc *sc = (struct acpiapplesmc_softc *)self;
+       struct acpi_attach_args *aaa = aux;
+       int64_t sta;
+       struct aml_value res;
+       int i, sens_index;
+
+       sc->sc_acpi = (struct acpi_softc *)parent;
+       sc->sc_devnode = aaa->aaa_node;
+
+       printf(": %s", sc->sc_devnode->name);
+
+        sta = acpi_getsta(sc->sc_acpi, sc->sc_devnode);
+       if ((sta & (STA_PRESENT | STA_ENABLED | STA_DEV_OK)) !=
+           (STA_PRESENT | STA_ENABLED | STA_DEV_OK)) {
+               printf(": not enabled\n");
+               return;
+       }
+
+       if (!(aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CID", 0, NULL, &res)))
+               printf(" (%s)", res.v_string);
+
+       if (aaa->aaa_naddr < 1) {
+               printf(": no registers\n");
+               return;
+       }
+
+       printf (" addr 0x%llx/0x%llx\n", aaa->aaa_addr[0], aaa->aaa_size[0]);
+
+       sc->sc_bt = aaa->aaa_bst[0];
+       if (bus_space_map(sc->sc_bt, aaa->aaa_addr[0], aaa->aaa_size[0], 0,
+           &sc->sc_bh)) {
+               printf(": can't map registers\n");
+               return;
+       }
+
+       if (acpiapplesmc_init(sc) == -1) {
+               printf("%s: SMC init failed!\n", DEVNAME(sc));
+               return;
+       }
+
+       strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
+           sizeof(sc->sc_sensdev.xname));
+
+       /* Add fans to sensor framework. */
+       for (i = 0; i < sc->sc_fan_count; i++) {
+               sc->sc_sens[i].type = SENSOR_FANRPM;
+               sensor_attach(&sc->sc_sensdev, &sc->sc_sens[i]);
+       }
+       sens_index = i;
+
+       /* Add temperature sensors to sensor framework. */
+       for (i = 0; sc->sc_temp_count != 0 && i < sc->sc_key_count; i++) {
+               if (sc->sc_keys[i].temp_use == 0)
+                       continue;
+               sc->sc_sens[sens_index].type = SENSOR_TEMP;
+               (void)acpiapplesmc_temp_get_desc(sc,
+                   sc->sc_keys[i].key,
+                   sizeof(sc->sc_sens[sens_index].desc),
+                   sc->sc_sens[sens_index].desc);
+               sensor_attach(&sc->sc_sensdev, &sc->sc_sens[sens_index]);
+               sens_index++;
+       }
+
+       sensordev_install(&sc->sc_sensdev);
+
+       aml_register_notify(sc->sc_devnode, NULL, acpiapplesmc_notify, sc,
+           ACPIDEV_POLL);
+}
+
+int
+acpiapplesmc_notify(struct aml_node *node, int notify_type, void *arg)
+{
+       struct acpiapplesmc_softc *sc = arg;
+       uint8_t temp;
+       uint16_t rpm;
+       int i, sens_index;
+
+       /* Get current fan speed. */
+       for (i = 0; i < sc->sc_fan_count; i++) {
+               if (acpiapplesmc_fan_get_value(sc, APPLESMC_KEY_FANSPEED, i,
+                   &rpm) == -1) {
+                       printf("%s: can't get fan #%d speed!\n",
+                           DEVNAME(sc), i);
+               } else
+                       sc->sc_sens[i].value = rpm;
+       }
+       sens_index = i;
+
+       /* Get current sensor temperature. */
+       for (i = 0; sc->sc_temp_count != 0 && i < sc->sc_key_count; i++) {
+               if (sc->sc_keys[i].temp_use == 0)
+                       continue;
+               if (acpiapplesmc_temp_get_value(sc, sc->sc_keys[i].key, &temp)
+                   == -1) {
+                       printf("%s: can't get sensor #%d temperature!\n",
+                           DEVNAME(sc), i);
+               } else {
+                       sc->sc_sens[sens_index].value =
+                           (temp * 1000000) + 273150000;
+                       sens_index++;
+               }
+       }
+
+       return 0;
+}
+
+int
+acpiapplesmc_activate(struct device *self, int act)
+{
+#if 0
+       struct acpiapplesmc_softc *sc = (struct acpiapplesmc_softc *)self;
+
+       DPRINTF(("%s: %s\n", DEVNAME(sc), __func__));
+#endif
+       return 0;
+}
+
+/* ************************************************************************** 
*/
+
+int
+acpiapplesmc_waitack(struct acpiapplesmc_softc *sc, const uint8_t status_wait)
+{
+       int i;
+       uint8_t status;
+
+       for (i = 0; i < APPLESMC_WAITACK_RETRY; i++) {
+               status = bus_space_read_1(sc->sc_bt, sc->sc_bh,
+                   APPLESMC_PORT_CMD);
+               if ((status & 0xf) == (status_wait & 0xf))
+                       return 0;
+               delay(1);
+       }
+
+       return -1;
+}
+
+int
+acpiapplesmc_cmd(struct acpiapplesmc_softc *sc, const uint8_t cmd)
+{
+       int i;
+
+       for (i = 0; i < APPLESMC_CMD_RETRY; i++) {
+               bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_CMD, cmd);
+
+               if (acpiapplesmc_waitack(sc, APPLESMC_WAITACK_CMD) == 0)
+                       return 0;
+       }
+
+       DPRINTF(("%s: %s: command did fail after %d retries!\n",
+           DEVNAME(sc), __func__, APPLESMC_CMD_RETRY));
+
+       return -1;
+}
+
+int
+acpiapplesmc_key_read(struct acpiapplesmc_softc *sc, const char *key,
+    char *value, const uint8_t len)
+{
+       int i;
+
+       if (acpiapplesmc_cmd(sc, APPLESMC_CMD_KEY_READ) == -1)
+               return -1;
+
+       for (i = 0; i < APPLESMC_KEY_LEN; i++) {
+               bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+                   key[i]);
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_WRITE) == -1)
+                       return -1;
+       }
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA, len);
+
+       for (i = 0; i < len; i++) {
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_READ) == -1)
+                       return -1;
+               value[i] = bus_space_read_1(sc->sc_bt, sc->sc_bh,
+                   APPLESMC_PORT_DATA);
+       }
+
+       return 0;
+}
+
+int
+acpiapplesmc_key_write(struct acpiapplesmc_softc *sc, const char *key,
+    const char *value, const uint8_t len)
+{
+       int i;
+
+       if (acpiapplesmc_cmd(sc, APPLESMC_CMD_KEY_WRITE) == -1)
+               return -1;
+
+       for (i = 0; i < APPLESMC_KEY_LEN; i++) {
+               bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+                   key[i]);
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_WRITE) == -1)
+                       return -1;
+       }
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA, len);
+
+       for (i = 0; i < len; i++) {
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_WRITE) == -1)
+                       return -1;
+               bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+                   value[i]);
+       }
+
+       return 0;
+}
+
+int
+acpiapplesmc_key_get_byindex(struct acpiapplesmc_softc *sc,
+    const uint32_t index, char *key)
+{
+       int i;
+       uint32_t indexbe;
+       char index_send[4];
+
+       indexbe = htobe32(index);
+       index_send[0] = indexbe & 0xff;
+       index_send[1] = (indexbe >> 8) & 0xff;
+       index_send[2] = (indexbe >> 16) & 0xff;
+       index_send[3] = (indexbe >> 24) & 0xff;
+
+       if (acpiapplesmc_cmd(sc, APPLESMC_CMD_KEY_GET_BY_INDEX) == -1)
+               return -1;
+
+       for (i = 0; i < APPLESMC_KEY_LEN; i++) {
+               bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+                   index_send[i]);
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_WRITE) == -1)
+                       return -1;
+       }
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+           APPLESMC_KEY_LEN);
+
+       for (i = 0; i < APPLESMC_KEY_LEN; i++) {
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_READ) == -1)
+                       return -1;
+               key[i] = bus_space_read_1(sc->sc_bt, sc->sc_bh,
+                   APPLESMC_PORT_DATA);
+       }
+
+       return 0;
+}
+
+int
+acpiapplesmc_key_get_type(struct acpiapplesmc_softc *sc, const char *key,
+    char *key_type)
+{
+       int i;
+
+       if (acpiapplesmc_cmd(sc, APPLESMC_CMD_KEY_GET_TYPE) == -1)
+               return -1;
+
+       for (i = 0; i < APPLESMC_KEY_LEN; i++) {
+               bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+                   key[i]);
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_WRITE) == -1)
+                       return -1;
+       }
+       bus_space_write_1(sc->sc_bt, sc->sc_bh, APPLESMC_PORT_DATA,
+           APPLESMC_KEY_LEN);
+
+       for (i = 0; i < APPLESMC_KEY_TYPE_LEN; i++) {
+               if (acpiapplesmc_waitack(sc, APLLESMC_WAITACK_READ) == -1)
+                       return -1;
+               key_type[i] = bus_space_read_1(sc->sc_bt, sc->sc_bh,
+                   APPLESMC_PORT_DATA);
+       }
+
+       return 0;
+}
+
+int
+acpiapplesmc_key_count(struct acpiapplesmc_softc *sc, uint32_t *key_count)
+{
+       uint32_t buf;
+
+       if (acpiapplesmc_key_read(sc, APPLESMC_KEY_COUNT, (uint8_t *)&buf,
+           sizeof(buf)) == -1)
+               return -1;
+
+       *key_count = be32toh(buf);
+
+       return 0;
+}
+
+int
+acpiapplesmc_key_get_entry(struct acpiapplesmc_softc *sc, const int index,
+    struct acpiapplesmc_key *k)
+{
+       char key[4];
+       char key_info[6];
+
+       if (acpiapplesmc_key_get_byindex(sc, index, key) == -1)
+               return -1;
+       if (acpiapplesmc_key_get_type(sc, key, key_info) == -1)
+               return -1;
+
+       memcpy(k->key, key, sizeof(key));
+       memcpy(k->type, (key_info + 1), 4);
+       k->len = key_info[0];
+       k->flags = key_info[5];
+
+       return 0;
+}
+
+int
+acpiapplesmc_key_init(struct acpiapplesmc_softc *sc, const int key_count)
+{
+       int i;
+
+       memset(sc->sc_keys, 0, sizeof(struct acpiapplesmc_key));
+
+       for (i = 0; i < sc->sc_key_count; i++) {
+               if (acpiapplesmc_key_get_entry(sc, i, &sc->sc_keys[i]) == -1)
+                       return -1;
+               DPRINTF(("%d: key=%s, type_len=%d, type=%s, type_flags=0x%x\n",
+                   i,
+                   sc->sc_keys[i].key,
+                   sc->sc_keys[i].len,
+                   sc->sc_keys[i].type,
+                   sc->sc_keys[i].flags));
+       }
+       sc->sc_keys_init = 1;
+
+       return 0;
+}
+
+int
+acpiapplesmc_fan_count(struct acpiapplesmc_softc *sc, uint8_t *fan_count)
+{
+       uint8_t buf[1];
+
+       if (acpiapplesmc_key_read(sc, APPLESMC_KEY_FANCOUNT, buf, sizeof(buf))
+           == -1)
+               return -1;
+
+       *fan_count = buf[0];
+
+       return 0;
+}
+
+int
+acpiapplesmc_fan_get_value(struct acpiapplesmc_softc *sc,
+    const char *key, const uint8_t fan, uint16_t *fan_speed)
+{
+       uint8_t buf[2];
+       char fankey[5];
+
+       snprintf(fankey, sizeof(fankey), key, fan);
+
+       if (acpiapplesmc_key_read(sc, fankey, buf, sizeof(buf)) == -1)
+               return -1;
+
+       *fan_speed = (buf[0] << 6) | (buf[1] >> 2);
+
+       return 0;
+}
+
+int
+acpiapplesmc_temp_count(struct acpiapplesmc_softc *sc, uint8_t *temp_count)
+{
+       int i;
+       uint8_t tc = 0;
+
+       if (sc->sc_keys_init != 1)
+               return -1;
+
+       for (i = 0; i < sc->sc_key_count; i++) {
+               if (sc->sc_keys[i].key[0] == 'T')
+                       tc++;
+       }
+
+       *temp_count = tc;
+
+       return 0;
+}
+
+int
+acpiapplesmc_temp_init(struct acpiapplesmc_softc *sc, uint8_t *temp_count)
+{
+       int i;
+       uint8_t tc;
+
+       if (sc->sc_keys_init != 1)
+               return -1;
+
+       for (tc = 0, i = 0; i < sc->sc_key_count; i++) {
+               if (sc->sc_keys[i].key[0] == 'T' &&
+                   acpiapplesmc_temp_get_desc(sc, sc->sc_keys[i].key, 0,
+                   NULL)) {
+                       sc->sc_keys[i].temp_use = 1;
+                       tc++;
+               }
+       }
+
+       *temp_count = tc;
+
+       return 0;
+}
+
+int
+acpiapplesmc_temp_get_value(struct acpiapplesmc_softc *sc, const char *key,
+    uint8_t *temp)
+{
+       uint8_t buf[2];
+
+       if (acpiapplesmc_key_read(sc, key, buf, sizeof(buf)) == -1)
+               return -1;
+
+       *temp = buf[0];
+
+       return 0;
+}
+
+int
+acpiapplesmc_temp_get_desc(struct acpiapplesmc_softc *sc, const char *key,
+    const int len, char *desc)
+{
+       int i;
+
+       for (i = 0; acpiapplesmc_temp_desc[i].key != NULL; i++) {
+               if (strcmp(key, acpiapplesmc_temp_desc[i].key) == 0) {
+                       if (len != 0 && key != NULL) {
+                               strlcpy(desc, acpiapplesmc_temp_desc[i].desc,
+                                   len);
+                       }
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int
+acpiapplesmc_init(struct acpiapplesmc_softc *sc)
+{
+       /* Count all available keys. */
+       if (acpiapplesmc_key_count(sc, &sc->sc_key_count) == -1) {
+               printf("%s: acpiapplesmc_key_count failed!\n", DEVNAME(sc));
+               return -1;
+       }
+       if (sc->sc_key_count > APPLESMC_MAX_KEY) {
+               printf("%s: key count exceeded!\n", DEVNAME(sc));
+               return -1;
+       }
+       /* Store all available keys in to an internal array. */
+       if (acpiapplesmc_key_init(sc, sc->sc_key_count) == -1) {
+               printf("%s: acpiapplesmc_key_init failed!\n", DEVNAME(sc));
+               return -1;
+       }
+
+       /* Count all available fans. */
+       if (acpiapplesmc_fan_count(sc, &sc->sc_fan_count) == -1) {
+               printf("%s: acpiapplesmc_fan_count failed!\n", DEVNAME(sc));
+               return -1;
+       }
+       if (sc->sc_fan_count > APPLESMC_MAX_FAN) {
+               printf("%s: fan count exceeded!\n", DEVNAME(sc));
+               return -1;
+       }
+
+       /* Count all available temperature sensors. */
+       if (acpiapplesmc_temp_count(sc, &sc->sc_temp_count_total) == -1) {
+               printf("%s: acpiapplesmc_temp_count failed!\n", DEVNAME(sc));
+               return -1;
+       }
+
+       /* Select which temperature sensors to use. */
+       if (acpiapplesmc_temp_init(sc, &sc->sc_temp_count)  == -1) {
+               printf("%s: acpiapplesmc_temp_init failed!\n", DEVNAME(sc));
+               return -1;
+       }
+       if (sc->sc_temp_count > APPLESMC_MAX_TEMP) {
+               printf("%s: temp count exceeded!\n", DEVNAME(sc));
+               return -1;
+       }
+
+       DPRINTF(("# keys = %d\n", sc->sc_key_count));
+       DPRINTF(("# fans = %d\n", sc->sc_fan_count));
+       DPRINTF(("# temp total = %d\n", sc->sc_temp_count_total));
+       DPRINTF(("# temp use = %d\n", sc->sc_temp_count));
+
+       return 0;
+}
Index: sys/dev/acpi/files.acpi
===================================================================
RCS file: /cvs/src/sys/dev/acpi/files.acpi,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 files.acpi
--- sys/dev/acpi/files.acpi     2 Jun 2020 16:24:24 -0000       1.55
+++ sys/dev/acpi/files.acpi     7 Sep 2020 04:54:57 -0000
@@ -75,6 +75,11 @@ device       acpidock
 attach acpidock at acpi
 file   dev/acpi/acpidock.c             acpidock
 
+# Apple SMC support
+device acpiapplesmc
+attach acpiapplesmc at acpi
+file   dev/acpi/acpiapplesmc.c         acpiapplesmc
+
 # ASUS ACPI Hotkeys
 device acpiasus
 attach acpiasus at acpi

Reply via email to