Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys PR# kern/42139: ACPI WMI: new driver



details:   https://anonhg.NetBSD.org/src/rev/d26cc2120315
branches:  trunk
changeset: 747798:d26cc2120315
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Oct 02 16:47:52 2009 +0000

description:
PR# kern/42139: ACPI WMI: new driver

Import acpiwmi(4) from Jukka Ruohonen. From the PR:

Attached is a driver that implements ACPI WMI API:

http://www.microsoft.com/whdc/system/pnppwr/wmi/wmi-acpi.mspx

The WMI is used to provide a generic interface for OEMs to use certain
platform/laptop-specific additions to the standard ACPI in a somewhat
portable way. These can be hotkeys for additional buttons, different event
handlers (wireless kill switch, lid switch, etc.), and so on. At least HP
and Acer use it by default nowadays.

The benefit of this interface would be portability. For an example, instead
of hpqlb(4) that works only with certain HP models, we could have a generic
HP WMI-driver that should work in theory across all HP laptops. On many new
laptops WMI may also be the only way to access laptop/manufacturer-specific
features.

diffstat:

 sys/arch/amd64/conf/GENERIC |    5 +-
 sys/arch/i386/conf/ALL      |    5 +-
 sys/arch/i386/conf/GENERIC  |    5 +-
 sys/dev/acpi/files.acpi     |    7 +-
 sys/dev/acpi/wmi_acpi.c     |  695 ++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/acpi/wmi_acpivar.h  |   43 ++
 6 files changed, 753 insertions(+), 7 deletions(-)

diffs (truncated from 842 to 300 lines):

diff -r b184d6b44df4 -r d26cc2120315 sys/arch/amd64/conf/GENERIC
--- a/sys/arch/amd64/conf/GENERIC       Fri Oct 02 16:19:19 2009 +0000
+++ b/sys/arch/amd64/conf/GENERIC       Fri Oct 02 16:47:52 2009 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.256 2009/09/30 22:19:27 jmcneill Exp $
+# $NetBSD: GENERIC,v 1.257 2009/10/02 16:47:52 jmcneill Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options        INCLUDE_CONFIG_FILE     # embed config file in kernel binary
 
-#ident                 "GENERIC-$Revision: 1.256 $"
+#ident                 "GENERIC-$Revision: 1.257 $"
 
 maxusers       64              # estimated number of users
 
@@ -279,6 +279,7 @@
 acpiecdt*      at acpi?                # ACPI Embedded Controller (early binding)
 acpilid*       at acpi?                # ACPI Lid Switch
 acpitz*        at acpi?                # ACPI Thermal Zone
+acpiwmi*       at acpi?                # ACPI WMI Mapper
 
 # Mainboard devices
 aiboost*       at acpi?                # ASUS AI Booster Hardware monitor
diff -r b184d6b44df4 -r d26cc2120315 sys/arch/i386/conf/ALL
--- a/sys/arch/i386/conf/ALL    Fri Oct 02 16:19:19 2009 +0000
+++ b/sys/arch/i386/conf/ALL    Fri Oct 02 16:47:52 2009 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.216 2009/09/30 22:19:00 jmcneill Exp $
+# $NetBSD: ALL,v 1.217 2009/10/02 16:47:52 jmcneill Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@
 
 options        INCLUDE_CONFIG_FILE     # embed config file in kernel binary
 
-#ident                 "ALL-$Revision: 1.216 $"
+#ident                 "ALL-$Revision: 1.217 $"
 
 maxusers       32              # estimated number of users
 
@@ -351,6 +351,7 @@
 acpiecdt*      at acpi?                # ACPI Embedded Controller (early binding)
 acpilid*       at acpi?                # ACPI Lid Switch
 acpitz*        at acpi?                # ACPI Thermal Zone
+acpiwmi*       at acpi?                # ACPI WMI Mapper
 
 # Mainboard devices
 aiboost*       at acpi?                # ASUS AI Booster Hardware monitor
diff -r b184d6b44df4 -r d26cc2120315 sys/arch/i386/conf/GENERIC
--- a/sys/arch/i386/conf/GENERIC        Fri Oct 02 16:19:19 2009 +0000
+++ b/sys/arch/i386/conf/GENERIC        Fri Oct 02 16:47:52 2009 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.947 2009/09/30 22:19:00 jmcneill Exp $
+# $NetBSD: GENERIC,v 1.948 2009/10/02 16:47:52 jmcneill Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options        INCLUDE_CONFIG_FILE     # embed config file in kernel binary
 
-#ident                 "GENERIC-$Revision: 1.947 $"
+#ident                 "GENERIC-$Revision: 1.948 $"
 
 maxusers       64              # estimated number of users
 
@@ -361,6 +361,7 @@
 acpiecdt*      at acpi?                # ACPI Embedded Controller (early binding)
 acpilid*       at acpi?                # ACPI Lid Switch
 acpitz*        at acpi?                # ACPI Thermal Zone
+acpiwmi*       at acpi?                # ACPI WMI Mapper
 
 # Mainboard devices
 aiboost*       at acpi?                # ASUS AI Booster Hardware Monitor
diff -r b184d6b44df4 -r d26cc2120315 sys/dev/acpi/files.acpi
--- a/sys/dev/acpi/files.acpi   Fri Oct 02 16:19:19 2009 +0000
+++ b/sys/dev/acpi/files.acpi   Fri Oct 02 16:47:52 2009 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.acpi,v 1.59 2009/09/30 20:44:50 jmcneill Exp $
+#      $NetBSD: files.acpi,v 1.60 2009/10/02 16:47:52 jmcneill Exp $
 
 include "dev/acpi/acpica/files.acpica"
 
@@ -145,3 +145,8 @@
 # Winbond Integrated Media Reader
 attach wb at acpinodebus with wb_acpi
 file   dev/acpi/wb_acpi.c              wb_acpi
+
+# ACPI-WMI Mapper
+device acpiwmi
+attach acpiwmi at acpinodebus
+file   dev/acpi/wmi_acpi.c             acpiwmi
diff -r b184d6b44df4 -r d26cc2120315 sys/dev/acpi/wmi_acpi.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/acpi/wmi_acpi.c   Fri Oct 02 16:47:52 2009 +0000
@@ -0,0 +1,695 @@
+/*     $NetBSD: wmi_acpi.c,v 1.1 2009/10/02 16:47:52 jmcneill Exp $    */
+
+/*-
+ * Copyright (c) 2009 Jukka Ruohonen <jruohonen%iki.fi@localhost>
+ * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: wmi_acpi.c,v 1.1 2009/10/02 16:47:52 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/endian.h>
+#include <sys/kmem.h>
+
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/wmi_acpivar.h>
+/*
+ * This implements something called "Microsoft Windows Management
+ * Instrumentation" (WMI). This subset of ACPI is desribed in:
+ *
+ * http://www.microsoft.com/whdc/system/pnppwr/wmi/wmi-acpi.mspx
+ *
+ * (Obtained on Thu Feb 12 18:21:44 EET 2009.)
+ */
+struct guid_t {
+       /*
+        * The GUID itself. The used format is the usual 32-16-16-64-bit
+        * representation. All except the fourth field are in native byte
+        * order. A 32-16-16-16-48-bit hexadecimal notation with hyphens
+        * is used for human-readable GUIDs.
+        */
+       struct {
+               uint32_t data1;
+               uint16_t data2;
+               uint16_t data3;
+               uint8_t  data4[8];
+       } __packed;
+
+       union {
+               char oid[2];            /* ACPI object ID. */
+
+               struct {
+                       uint8_t nid;    /* Notification value. */
+                       uint8_t res;    /* Reserved. */
+               } __packed;
+       } __packed;
+
+       uint8_t count;                  /* Number of instances. */
+       uint8_t flags;                  /* Additional flags. */
+
+} __packed;
+
+struct wmi_t {
+       struct guid_t       guid;
+       ACPI_HANDLE         handle;
+       bool                eevent;
+
+       SIMPLEQ_ENTRY(wmi_t) wmi_link;
+};
+
+struct acpi_wmi_softc {
+       device_t              sc_dev;
+       struct acpi_devnode  *sc_node;
+       struct wmi_t         *sc_wmi;
+       bool                  sc_event;
+};
+
+static SIMPLEQ_HEAD(, wmi_t) wmi_head =
+       SIMPLEQ_HEAD_INITIALIZER(wmi_head);
+
+#define ACPI_WMI_FLAG_EXPENSIVE 0x01
+#define ACPI_WMI_FLAG_METHOD    0x02
+#define ACPI_WMI_FLAG_STRING    0x04
+#define ACPI_WMI_FLAG_EVENT     0x08
+#define ACPI_WMI_FLAG_DATA      (ACPI_WMI_FLAG_EXPENSIVE |             \
+                                ACPI_WMI_FLAG_STRING)
+
+#define UGET16(x)   (*(u_int16_t *)(x))
+#define UGET64(x)   (*(u_int64_t *)(x))
+
+#define HEXCHAR(x)  (((x) >= '0' && (x) <= '9') ||                     \
+                    ((x) >= 'a' && (x) <= 'f') ||                      \
+                    ((x) >= 'A' && (x) <= 'F'))
+
+#define GUIDCMP(a, b)                                                  \
+       ((a)->data1 == (b)->data1 &&                                    \
+        (a)->data2 == (b)->data2 &&                                    \
+        (a)->data3 == (b)->data3 &&                                    \
+        UGET64((a)->data4) == UGET64((b)->data4))
+
+static int         acpi_wmi_match(device_t, cfdata_t, void *);
+static void        acpi_wmi_attach(device_t, device_t, void *);
+static bool        acpi_wmi_init(ACPI_HANDLE, const char * const);
+static bool        acpi_wmi_add(ACPI_OBJECT *, ACPI_HANDLE);
+static void        acpi_wmi_del(void);
+
+#ifdef ACPIVERBOSE
+static void        acpi_wmi_dump(const char * const);
+#endif
+
+static ACPI_STATUS acpi_wmi_guid_get(const u_char * const, struct wmi_t **);
+static bool        acpi_wmi_event_add(struct acpi_wmi_softc *);
+static bool        acpi_wmi_event_del(struct acpi_wmi_softc *);
+static void        acpi_wmi_event_handler(ACPI_HANDLE, uint32_t, void *);
+static bool        acpi_wmi_suspend(device_t PMF_FN_PROTO);
+static bool        acpi_wmi_resume(device_t PMF_FN_PROTO);
+static ACPI_STATUS acpi_wmi_enable(const ACPI_HANDLE, const char * const,
+                                   const bool, const bool);
+
+static ACPI_NOTIFY_HANDLER wmi_handler;
+
+const char * const acpi_wmi_ids[] = {
+       "PNP0C14",
+       NULL
+};
+
+CFATTACH_DECL_NEW(acpiwmi, sizeof(struct acpi_wmi_softc),
+    acpi_wmi_match, acpi_wmi_attach, NULL, NULL);
+
+static int
+acpi_wmi_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct acpi_attach_args *aa = aux;
+
+       if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
+               return 0;
+
+       return acpi_match_hid(aa->aa_node->ad_devinfo, acpi_wmi_ids);
+}
+
+static void
+acpi_wmi_attach(device_t parent, device_t self, void *aux)
+{
+       struct acpi_wmi_softc *sc = device_private(self);
+       struct acpi_attach_args *aa = aux;
+       const char *xname;
+
+       sc->sc_dev = self;
+       sc->sc_node = aa->aa_node;
+
+       aprint_naive("\n");
+       aprint_normal(": ACPI WMI Interface\n");
+
+       wmi_handler = NULL;
+       xname = device_xname(sc->sc_dev);
+
+       if (acpi_wmi_init(sc->sc_node->ad_handle, xname) != true)
+               return;
+
+#ifdef ACPIVERBOSE
+       acpi_wmi_dump(xname);
+#endif
+       /*
+        * Add internal event handler. If the user-driver
+        * registers an external event handler with us, we
+        * will forward events through this.
+        */
+       sc->sc_event = acpi_wmi_event_add(sc);
+
+       if (pmf_device_register(sc->sc_dev,
+               acpi_wmi_suspend, acpi_wmi_resume) != true)
+               aprint_error_dev(self, "failed to register power handler\n");
+}
+
+static bool
+acpi_wmi_init(ACPI_HANDLE hdl, const char * const xname)
+{
+       ACPI_OBJECT *obj;
+       ACPI_BUFFER buf;
+       ACPI_STATUS rv;
+       uint32_t len;
+
+       rv = acpi_eval_struct(hdl, "_WDG", &buf);
+
+       if (ACPI_FAILURE(rv))
+               goto fail;
+
+       obj = buf.Pointer;



Home | Main Index | Thread Index | Old Index