Module Name: src Committed By: nonaka Date: Mon Sep 21 12:32:06 UTC 2015
Modified Files: src/sys/arch/amd64/conf: GENERIC src/sys/arch/i386/conf: GENERIC src/sys/dev/acpi: files.acpi Added Files: src/sys/dev/acpi: valz_acpi.c Log Message: PR/50261: Added newer Toshiba hotkeys support. To generate a diff of this commit: cvs rdiff -u -r1.416 -r1.417 src/sys/arch/amd64/conf/GENERIC cvs rdiff -u -r1.1126 -r1.1127 src/sys/arch/i386/conf/GENERIC cvs rdiff -u -r1.95 -r1.96 src/sys/dev/acpi/files.acpi cvs rdiff -u -r0 -r1.5 src/sys/dev/acpi/valz_acpi.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/amd64/conf/GENERIC diff -u src/sys/arch/amd64/conf/GENERIC:1.416 src/sys/arch/amd64/conf/GENERIC:1.417 --- src/sys/arch/amd64/conf/GENERIC:1.416 Thu Aug 27 14:04:07 2015 +++ src/sys/arch/amd64/conf/GENERIC Mon Sep 21 12:32:06 2015 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.416 2015/08/27 14:04:07 nonaka Exp $ +# $NetBSD: GENERIC,v 1.417 2015/09/21 12:32:06 nonaka Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.416 $" +#ident "GENERIC-$Revision: 1.417 $" maxusers 64 # estimated number of users @@ -325,6 +325,7 @@ wsmouse* at spic? # mouse thinkpad* at acpi? # IBM/Lenovo Thinkpad hotkeys #tpm* at acpi? # ACPI TPM (Experimental) ug* at acpi? # Abit uGuru Hardware monitor +valz* at acpi? # Toshiba Dynabook hotkeys wb* at acpi? # Winbond W83L518D SD/MMC reader sdmmc* at wb? # SD/MMC bus wmidell* at acpiwmibus? # Dell WMI mappings Index: src/sys/arch/i386/conf/GENERIC diff -u src/sys/arch/i386/conf/GENERIC:1.1126 src/sys/arch/i386/conf/GENERIC:1.1127 --- src/sys/arch/i386/conf/GENERIC:1.1126 Thu Aug 27 14:04:07 2015 +++ src/sys/arch/i386/conf/GENERIC Mon Sep 21 12:32:06 2015 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.1126 2015/08/27 14:04:07 nonaka Exp $ +# $NetBSD: GENERIC,v 1.1127 2015/09/21 12:32:06 nonaka Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.1126 $" +#ident "GENERIC-$Revision: 1.1127 $" maxusers 64 # estimated number of users @@ -375,6 +375,7 @@ thinkpad* at acpi? # IBM/Lenovo Thinkpa #tpm* at acpi? # ACPI TPM (Experimental) ug* at acpi? # Abit uGuru Hardware monitor vald* at acpi? # Toshiba Libretto hotkeys +valz* at acpi? # Toshiba Dynabook hotkeys wb* at acpi? # Winbond W83L518D SD/MMC reader sdmmc* at wb? # SD/MMC bus wmidell* at acpiwmibus? # Dell WMI mappings Index: src/sys/dev/acpi/files.acpi diff -u src/sys/dev/acpi/files.acpi:1.95 src/sys/dev/acpi/files.acpi:1.96 --- src/sys/dev/acpi/files.acpi:1.95 Sun Sep 14 19:54:05 2014 +++ src/sys/dev/acpi/files.acpi Mon Sep 21 12:32:06 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.acpi,v 1.95 2014/09/14 19:54:05 mrg Exp $ +# $NetBSD: files.acpi,v 1.96 2015/09/21 12:32:06 nonaka Exp $ include "dev/acpi/acpica/files.acpica" @@ -169,6 +169,11 @@ device vald attach vald at acpinodebus with vald_acpi file dev/acpi/vald_acpi.c vald_acpi +# Toshiba Dynabook hotkeys +device valz +attach valz at acpinodebus with valz_acpi +file dev/acpi/valz_acpi.c valz_acpi + # Sony SPIC (jog dial etc.) attach spic at acpinodebus with spic_acpi file dev/acpi/spic_acpi.c spic_acpi Added files: Index: src/sys/dev/acpi/valz_acpi.c diff -u /dev/null src/sys/dev/acpi/valz_acpi.c:1.5 --- /dev/null Mon Sep 21 12:32:06 2015 +++ src/sys/dev/acpi/valz_acpi.c Mon Sep 21 12:32:06 2015 @@ -0,0 +1,643 @@ +/* $NetBSD: valz_acpi.c,v 1.5 2015/09/21 12:32:06 nonaka Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Masanori Kanaoka. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright 2001 Bill Sommerfeld. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* + * ACPI VALZ Driver for Toshiba dynabook R63/PS + * This driver is based on vald_acpi.c + */ + +/* + * Obtain information of Toshiba "GHCI" Method from next URL. + * http://www.buzzard.me.uk/toshiba/docs.html + * http://memebeam.org/toys/ToshibaAcpiDriver + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: valz_acpi.c,v 1.5 2015/09/21 12:32:06 nonaka Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <dev/acpi/acpica.h> +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> + +#define _COMPONENT ACPI_RESOURCE_COMPONENT +ACPI_MODULE_NAME ("valz_acpi") + +#define METHOD_HCI "GHCI" +#define METHOD_HCI_ENABLE "ENAB" + +/* Operations */ +/* Get */ +#define HCI_GET 0xfe00 +#define SCI_CHECK 0xf000 +#define SCI_GET 0xf300 + +/* Set */ +#define HCI_SET 0xff00 +#define SCI_OPEN 0xf100 +#define SCI_CLOSE 0xf200 +#define SCI_SET 0xf400 + +/* Return codes */ +#define HCI_SUCCESS 0x0000 +#define HCI_FAILURE 0x1000 +#define HCI_NOT_SUPPORTED 0x8000 +#define HCI_INPUT_ERROR 0x8300 +#define HCI_FIFO_EMPTY 0x8c00 + +#define SCI_OPENCLOSE_OK 0x0044 +#define SCI_NOT_SUPPORTED 0x8000 +#define SCI_ALREADY_OPEN 0x8100 +#define SCI_NOT_OPEN 0x8200 +#define SCI_NOT_PRESENT 0x8600 + +/* Functions */ +#define HCI_LCD_BACKLIGHT 0x0002 +#define HCI_ACADAPTOR 0x0003 +#define HCI_SYSTEM_EVENT_FIFO 0x0016 +#define HCI_KBD_BACKLIGHT 0x0017 +#define HCI_DISPLAY_DEV 0x001c +#define HCI_HOTKEY_EVENT 0x001e +#define HCI_LCD_BRIGHTNESS 0x002a +#define HCI_CPU_SPEED 0x0032 + +#define SCI_USB_OFF_CHARGE 0x0150 +#define SCI_TOUCHPAD 0x050e +#define SCI_KBD_BACKLIGHT_STS 0x015c +#define SCI_KBD_BACKLIGHT 0x0095 + +#define SCI_KBD_BL_TIME_SHIFT 0x10 + +/* Field definitions */ +#define HCI_LCD_BRIGHTNESS_BITS 3 +#define HCI_LCD_BRIGHTNESS_SFT (16 - HCI_LCD_BRIGHTNESS_BITS) +#define HCI_LCD_BRIGHTNESS_MIN 0 +#define HCI_LCD_BRIGHTNESS_MAX 7 +#define HCI_VIDEO_DEVICE_FLG 0x0100 +#define HCI_CPU_SPEED_BITS 3 +#define HCI_CPU_SPEED_SFT (16 - HCI_CPU_SPEED_BITS) +#define HCI_CPU_SPEED_MAX ((1 << HCI_CPU_SPEED_BITS) - 1) + +/* Key press/release events */ + +/* Key press/release events */ +#define FN_RELEASE_OFFSET 0x80 +# if 0 +/* Not used */ +#define FN_PRESS 0x01ff +#define FN_RELEASE 0x0100 +# endif +#define FN_ESC_PRESS 0x0101 +#define FN_ESC_RELEASE (FN_ESC_PRESS + FN_RELEASE_OFFSET) +#define FN_F1_PRESS 0x013b +#define FN_F1_RELEASE (FN_F1_PRESS + FN_RELEASE_OFFSET) +#define FN_F2_PRESS 0x013c +#define FN_F2_RELEASE (FN_F2_PRESS + FN_RELEASE_OFFSET) +#define FN_F3_PRESS 0x013d +#define FN_F3_RELEASE (FN_F3_PRESS + FN_RELEASE_OFFSET) +#define FN_F4_PRESS 0x013e +#define FN_F4_RELEASE (FN_F4_PRESS + FN_RELEASE_OFFSET) +#define FN_F5_PRESS 0x013f +#define FN_F5_RELEASE (FN_F5_PRESS + FN_RELEASE_OFFSET) +#define FN_F6_PRESS 0x0140 +#define FN_F6_RELEASE (FN_F6_PRESS + FN_RELEASE_OFFSET) +#define FN_F7_PRESS 0x0141 +#define FN_F7_RELEASE (FN_F7_PRESS + FN_RELEASE_OFFSET) +#define FN_F8_PRESS 0x0142 +#define FN_F8_RELEASE (FN_F8_PRESS + FN_RELEASE_OFFSET) +#define FN_F9_PRESS 0x0143 +#define FN_F9_RELEASE (FN_F9_PRESS + FN_RELEASE_OFFSET) +/* Toggle, they are controlled by hardware */ +#define FN_F10_ON 0x1bb0 +#define FN_F10_OFF 0x1bb1 +#define FN_F11_ON 0x1bb2 +#define FN_F11_OFF 0x1bb3 +/* Fn+F12 does not emit keycode */ +/* dynabook R63/PS does not have KANJI keytop print */ +#define FN_KNJ_PRESS 0x0129 +#define FN_KNJ_RELEASE (FN_KNJ_PRESS + FN_RELEASE_OFFSET) +#define FN_1_PRESS 0x0102 +#define FN_1_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) +#define FN_2_PRESS 0x0103 +#define FN_2_RELEASE (FN_2_PRESS + FN_RELEASE_OFFSET) +/* Fn+3 and Fn+4 do not emit keybode */ +#define FN_Z_PRESS 0x012c +#define FN_Z_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) +#define FN_SPACE_PRESS 0x0139 +#define FN_SPACE_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) +#define FN_TAB_PRESS 0x010f +#define FN_TAB_RELEASE (FN_TAB_PRESS + FN_RELEASE_OFFSET) +#define FN_CAPS_PRESS 0x013a +#define FN_CAPS_RELEASE (FN_CAPS_PRESS + FN_RELEASE_OFFSET) +#define FN_BACKSPACE_PRESS 0x010e +#define FN_BACKSPACE_RELEASE (FN_BACKSPACE_PRESS + FN_RELEASE_OFFSET) +#define FN_INS_PRESS 0x0152 +#define FN_INS_RELEASE (FN_INS_PRESS + FN_RELEASE_OFFSET) +#define FN_DEL_PRESS 0x0153 +#define FN_DEL_RELEASE (FN_DEL_PRESS + FN_RELEASE_OFFSET) +#define FN_PRTSC_PRESS 0x0137 +#define FN_PRTSC_RELEASE (FN_PRTSC_PRESS + FN_RELEASE_OFFSET) + +/* HCI register definitions */ +#define HCI_WORDS 6 /* number of registers */ +#define HCI_REG_AX 0 /* Operation -> return value */ +#define HCI_REG_BX 1 /* Function */ +#define HCI_REG_CX 2 /* Argument (in or out) */ +#define HCI_REG_DX 3 /* unused */ +#define HCI_REG_SI 4 /* unused */ +#define HCI_REG_DI 5 /* unused */ + +#define HCI_ON 0x0001 +#define HCI_OFF 0x0000 +#define HCI_ENABLE 0x0001 +#define HCI_DISABLE 0x0000 + +#define HCI_LCD 0x1 +#define HCI_CRT 0x2 +#define HCI_TV 0x4 + +#define SCI_KBD_BL_MODE_MASK 0x1f +#define SCI_KBD_BL_TIMO_SFT 0x10 +#define SCI_KBD_BL_MODE_AUTO 0x2 +#define SCI_KBD_BL_MODE_ON 0x8 +#define SCI_KBD_BL_MODE_OFF 0x10 + +struct valz_acpi_softc { + device_t sc_dev; /* base device glue */ + struct acpi_devnode *sc_node; /* our ACPI devnode */ +}; + +static const char * const valz_acpi_hids[] = { + "TOS6208", + NULL +}; + +static int valz_acpi_match(device_t, cfdata_t, void *); +static void valz_acpi_attach(device_t, device_t, void *); + +static void valz_acpi_event(void *); +static void valz_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); + +#define ACPI_NOTIFY_ValzHotkeyPressed 0x80 +#define ACPI_NOTIFY_ValzLidClosed 0x8f +#define ACPI_NOTIFY_ValzKbdBLChanges 0x92 + +/* HCI manipulation */ +static ACPI_STATUS hci_op(struct valz_acpi_softc *, + uint32_t *, uint32_t *); +static ACPI_STATUS valz_acpi_hci_get(struct valz_acpi_softc *, uint32_t, + uint32_t, uint32_t *, uint32_t *); +static ACPI_STATUS valz_acpi_hci_set(struct valz_acpi_softc *, uint32_t, + uint32_t, uint32_t, uint32_t *); + +static ACPI_STATUS sci_open(struct valz_acpi_softc *); +static ACPI_STATUS sci_close(struct valz_acpi_softc *); + +static ACPI_STATUS valz_acpi_touchpad_toggle(struct valz_acpi_softc *); +static ACPI_STATUS valz_acpi_lcd_backlight_toggle( + struct valz_acpi_softc *sc); + +CFATTACH_DECL_NEW(valz_acpi, sizeof(struct valz_acpi_softc), + valz_acpi_match, valz_acpi_attach, NULL, NULL); + +/* + * valz_acpi_match: + * + * Autoconfiguration `match' routine. + */ +static int +valz_acpi_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, valz_acpi_hids)); +} + +/* + * valz_acpi_attach: + * + * Autoconfiguration `attach' routine. + */ +static void +valz_acpi_attach(device_t parent, device_t self, void *aux) +{ + struct valz_acpi_softc *sc = device_private(self); + struct acpi_attach_args *aa = aux; + ACPI_STATUS rv; + + aprint_naive(": Toshiba VALZ\n"); + aprint_normal(": Toshiba VALZ\n"); + + sc->sc_node = aa->aa_node; + sc->sc_dev = self; + + /* enable valz notify */ + rv = AcpiEvaluateObject(sc->sc_node->ad_handle, METHOD_HCI_ENABLE, + NULL, NULL); + if (ACPI_FAILURE(rv)) { + aprint_error("Cannot enable VALZ.\n"); + } else { + (void)acpi_register_notify(sc->sc_node, + valz_acpi_notify_handler); + } +} + +/* + * valz_acpi_notify_handler: + * + * Notify handler. + */ +static void +valz_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) +{ + struct valz_acpi_softc *sc; + device_t self = context; + + sc = device_private(self); + + switch (notify) { + case ACPI_NOTIFY_ValzHotkeyPressed: + (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, valz_acpi_event, sc); + break; + + case ACPI_NOTIFY_ValzLidClosed: + /* Lid closed */ + break; + + case ACPI_NOTIFY_ValzKbdBLChanges: + /* Keyboard backlight mode changed */ + break; + + default: + aprint_error_dev(sc->sc_dev, + "unknown notify 0x%02X\n", notify); + break; + } +} + +/* + * valz_acpi_event: + * + * Check hotkey event and do it, if event occur. + */ +static void +valz_acpi_event(void *arg) +{ + struct valz_acpi_softc *sc = arg; + ACPI_STATUS rv; + uint32_t value, result; + + for (;;) { + rv = valz_acpi_hci_get(sc, HCI_GET, HCI_SYSTEM_EVENT_FIFO, + &value, &result); + if (ACPI_SUCCESS(rv) && result == 0) { + switch (value) { + case FN_F9_PRESS: + valz_acpi_touchpad_toggle(sc); + break; + case FN_TAB_PRESS: + valz_acpi_lcd_backlight_toggle(sc); + break; + + default: + /* Many unused buttons */ + aprint_debug("Pressed: 0x%x\n", value); + break; + } + } + if (ACPI_FAILURE(rv) || result == HCI_NOT_SUPPORTED || + result == HCI_FIFO_EMPTY) + break; + } +} + +/* + * HCI/SCI operation + */ +static ACPI_STATUS +hci_op(struct valz_acpi_softc *sc, uint32_t *input, uint32_t *output) +{ + ACPI_STATUS rv; + ACPI_OBJECT Arg[HCI_WORDS]; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT *param, *PrtElement; + ACPI_BUFFER buf; + int i; + + for (i = 0; i < HCI_WORDS; i++) { + Arg[i].Type = ACPI_TYPE_INTEGER; + Arg[i].Integer.Value = 0; + } + + for (i = 0; i < HCI_WORDS; i++) { + Arg[i].Integer.Value = input[i]; + } + + ArgList.Count = HCI_WORDS; + ArgList.Pointer = Arg; + + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + + rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, + METHOD_HCI, &ArgList, &buf, ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(rv)) { + aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", + AcpiFormatException(rv)); + return rv; + } + + for (i = 0; i < HCI_WORDS; i++) { + output[i] = 0; + } + param = (ACPI_OBJECT *)buf.Pointer; + PrtElement = param->Package.Elements; + for (i = 0; i < HCI_WORDS; i++) { + if (PrtElement->Type == ACPI_TYPE_INTEGER) + output[i] = PrtElement->Integer.Value; + PrtElement++; + } + + if (buf.Pointer) + ACPI_FREE(buf.Pointer); + + return rv; +} + +/* + * valz_acpi_hci_get: + * + * Get value via "GHCI" Method. + */ +static ACPI_STATUS +valz_acpi_hci_get(struct valz_acpi_softc *sc, uint32_t function, + uint32_t reg, uint32_t *value, uint32_t *result) +{ + ACPI_STATUS rv; + + uint32_t input[HCI_WORDS]; + uint32_t output[HCI_WORDS]; + + input[HCI_REG_AX] = function; + input[HCI_REG_BX] = reg; + input[HCI_REG_CX] = 0; + input[HCI_REG_DX] = 0; + input[HCI_REG_SI] = 0; + input[HCI_REG_DI] = 0; + + rv = hci_op(sc, input, output); + + *result = output[HCI_REG_AX]; + *value = output[HCI_REG_CX]; + + return rv; +} + +/* + * valz_acpi_hci_set: + * + * Set value via "GHCI" Method. + */ +static ACPI_STATUS +valz_acpi_hci_set(struct valz_acpi_softc *sc, uint32_t function, + uint32_t reg, uint32_t value, uint32_t *result) +{ + ACPI_STATUS rv; + + uint32_t input[HCI_WORDS]; + uint32_t output[HCI_WORDS]; + + input[HCI_REG_AX] = function; + input[HCI_REG_BX] = reg; + input[HCI_REG_CX] = value; + input[HCI_REG_DX] = 0; + input[HCI_REG_SI] = 0; + input[HCI_REG_DI] = 0; + + rv = hci_op(sc, input, output); + + *result = output[HCI_REG_AX]; + + return rv; +} + +/* + * Open SCI + */ +static ACPI_STATUS +sci_open(struct valz_acpi_softc *sc) +{ + ACPI_STATUS rv; + uint32_t result; + + rv = valz_acpi_hci_set(sc, SCI_OPEN, 0, 0, &result); + if (ACPI_FAILURE(rv)) { + aprint_error("SCI: ACPI set error\n"); + } else { + switch (result) { + case SCI_OPENCLOSE_OK: + aprint_debug("Opening SCI\n"); + break; + case SCI_ALREADY_OPEN: + aprint_error("SCI already open\n"); + break; + case SCI_NOT_SUPPORTED: + aprint_error("SCI is not supported\n"); + break; + case SCI_NOT_PRESENT: + aprint_error("SCI is not present\n"); + break; + default: + aprint_error("SCI: undefined behavior\n"); + break; + } + } + + return rv; +} + +/* + * Close SCI + */ +static ACPI_STATUS +sci_close(struct valz_acpi_softc *sc) +{ + ACPI_STATUS rv; + uint32_t result; + + rv = valz_acpi_hci_set(sc, SCI_CLOSE, 0, 0, &result); + if (ACPI_FAILURE(rv)) { + aprint_error("SCI: ACPI set error\n"); + } else { + switch (result) { + case SCI_OPENCLOSE_OK: + aprint_debug("Closing SCI\n"); + break; + case SCI_NOT_OPEN: + aprint_error("SCI is not opened\n"); + break; + case SCI_NOT_SUPPORTED: + aprint_error("SCI is not supported\n"); + break; + case SCI_NOT_PRESENT: + aprint_error("SCI is not present\n"); + break; + default: + aprint_error("SCI: undefined behavior\n"); + break; + } + } + + return rv; +} + +/* + * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE + */ +static ACPI_STATUS +valz_acpi_touchpad_toggle(struct valz_acpi_softc *sc) +{ + ACPI_STATUS rv; + uint32_t result, status, value; + + rv = sci_open(sc); + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, + "Cannot open SCI: %s\n", + AcpiFormatException(rv)); + + rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result); + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, + "Cannot get SCI touchpad status: %s\n", + AcpiFormatException(rv)); + + switch (value) { + case HCI_ENABLE: + status = HCI_DISABLE; + break; + case HCI_DISABLE: + status = HCI_ENABLE; + break; + default: + status = HCI_ENABLE; + break; + } + + rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result); + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, + "Cannot set SCI touchpad status: %s\n", + AcpiFormatException(rv)); + + rv = sci_close(sc); + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, + "Cannot close SCI: %s\n", + AcpiFormatException(rv)); + + return rv; +} + +/* + * Enable/disable LCD backlight with HCI_ENABLE/HCI_DISABLE + */ +static ACPI_STATUS +valz_acpi_lcd_backlight_toggle(struct valz_acpi_softc *sc) +{ + ACPI_STATUS rv; + uint32_t result, status, value; + + rv = valz_acpi_hci_get(sc, HCI_GET, HCI_LCD_BACKLIGHT, &value, &result); + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, + "Cannot get HCI LCD backlight status: %s\n", + AcpiFormatException(rv)); + + switch (value) { + case HCI_ON: + status = HCI_OFF; + break; + case HCI_OFF: + status = HCI_ON; + break; + default: + status = HCI_ON; + break; + } + + rv = valz_acpi_hci_set(sc, HCI_SET, HCI_LCD_BACKLIGHT, status, &result); + if (ACPI_FAILURE(rv)) + aprint_error_dev(sc->sc_dev, + "Cannot set HCI LCD backlight status: %s\n", + AcpiFormatException(rv)); + + return rv; +}