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