acpi_button.c revision 118783
167761Smsmith/*- 267761Smsmith * Copyright (c) 2000 Mitsaru IWASAKI <iwasaki@jp.freebsd.org> 367761Smsmith * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 467761Smsmith * Copyright (c) 2000 BSDi 567761Smsmith * All rights reserved. 667761Smsmith * 767761Smsmith * Redistribution and use in source and binary forms, with or without 867761Smsmith * modification, are permitted provided that the following conditions 967761Smsmith * are met: 1067761Smsmith * 1. Redistributions of source code must retain the above copyright 1167761Smsmith * notice, this list of conditions and the following disclaimer. 1267761Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1367761Smsmith * notice, this list of conditions and the following disclaimer in the 1467761Smsmith * documentation and/or other materials provided with the distribution. 1567761Smsmith * 1667761Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1767761Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1867761Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1967761Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2067761Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2167761Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2267761Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2367761Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2467761Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2567761Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2667761Smsmith * SUCH DAMAGE. 2767761Smsmith * 2867761Smsmith * $FreeBSD: head/sys/dev/acpica/acpi_button.c 118783 2003-08-11 15:34:43Z njl $ 2967761Smsmith */ 3067761Smsmith 3167761Smsmith#include "opt_acpi.h" 3267761Smsmith#include <sys/param.h> 3367761Smsmith#include <sys/kernel.h> 3467761Smsmith#include <sys/bus.h> 3567761Smsmith 3667761Smsmith#include "acpi.h" 3767761Smsmith#include <dev/acpica/acpivar.h> 3867761Smsmith 39118783Snjl/* Hooks for the ACPI CA debugging infrastructure */ 4077432Smsmith#define _COMPONENT ACPI_BUTTON 4191123SmsmithACPI_MODULE_NAME("BUTTON") 4269744Smsmith 4367761Smsmithstruct acpi_button_softc { 4467761Smsmith device_t button_dev; 4567761Smsmith ACPI_HANDLE button_handle; 4667761Smsmith boolean_t button_type; /* Power or Sleep Button */ 47118783Snjl#define ACPI_POWER_BUTTON 0 48118783Snjl#define ACPI_SLEEP_BUTTON 1 4967761Smsmith}; 5067761Smsmith 51118783Snjl#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 52118783Snjl#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 53118783Snjl 5467761Smsmithstatic int acpi_button_probe(device_t dev); 5567761Smsmithstatic int acpi_button_attach(device_t dev); 56100497Siwasakistatic int acpi_button_suspend(device_t dev); 57100497Siwasakistatic int acpi_button_resume(device_t dev); 58118783Snjlstatic void acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, 59118783Snjl void *context); 6067761Smsmithstatic void acpi_button_notify_pressed_for_sleep(void *arg); 6167761Smsmithstatic void acpi_button_notify_pressed_for_wakeup(void *arg); 6267761Smsmith 6367761Smsmithstatic device_method_t acpi_button_methods[] = { 6467761Smsmith /* Device interface */ 6567761Smsmith DEVMETHOD(device_probe, acpi_button_probe), 6667761Smsmith DEVMETHOD(device_attach, acpi_button_attach), 67100497Siwasaki DEVMETHOD(device_suspend, acpi_button_suspend), 68118049Stakawata DEVMETHOD(device_shutdown, acpi_button_suspend), 69100497Siwasaki DEVMETHOD(device_resume, acpi_button_resume), 7067761Smsmith 7167761Smsmith {0, 0} 7267761Smsmith}; 7367761Smsmith 7467761Smsmithstatic driver_t acpi_button_driver = { 7567761Smsmith "acpi_button", 7667761Smsmith acpi_button_methods, 7767761Smsmith sizeof(struct acpi_button_softc), 7867761Smsmith}; 7967761Smsmith 8089054Smsmithstatic devclass_t acpi_button_devclass; 81118783SnjlDRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 82118783Snjl 0, 0); 8367761Smsmith 8467761Smsmithstatic int 8567761Smsmithacpi_button_probe(device_t dev) 8667761Smsmith{ 8767761Smsmith struct acpi_button_softc *sc; 8867761Smsmith 8967761Smsmith sc = device_get_softc(dev); 9067761Smsmith if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) { 9169744Smsmith if (!acpi_disabled("button")) { 9269744Smsmith if (acpi_MatchHid(dev, "PNP0C0C")) { 9380067Smsmith device_set_desc(dev, "Power Button"); 9469744Smsmith sc->button_type = ACPI_POWER_BUTTON; 95118783Snjl return (0); 9669744Smsmith } 9769744Smsmith if (acpi_MatchHid(dev, "PNP0C0E")) { 9880067Smsmith device_set_desc(dev, "Sleep Button"); 9969744Smsmith sc->button_type = ACPI_SLEEP_BUTTON; 100118783Snjl return (0); 10169744Smsmith } 10267761Smsmith } 10367761Smsmith } 104118783Snjl return (ENXIO); 10567761Smsmith} 10667761Smsmith 10767761Smsmithstatic int 10867761Smsmithacpi_button_attach(device_t dev) 10967761Smsmith{ 11067761Smsmith struct acpi_button_softc *sc; 11167761Smsmith ACPI_STATUS status; 11267761Smsmith 11396926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 11469744Smsmith 11567761Smsmith sc = device_get_softc(dev); 11667761Smsmith sc->button_dev = dev; 11767761Smsmith sc->button_handle = acpi_get_handle(dev); 11867761Smsmith 119118783Snjl status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY, 120118783Snjl acpi_button_notify_handler, sc); 121118783Snjl if (ACPI_FAILURE(status)) { 122118783Snjl device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", 123118783Snjl AcpiFormatException(status)); 124118783Snjl return_VALUE (ENXIO); 12567761Smsmith } 126100497Siwasaki acpi_device_enable_wake_capability(sc->button_handle, 1); 127118783Snjl return_VALUE (0); 12867761Smsmith} 12967761Smsmith 130100497Siwasakistatic int 131100497Siwasakiacpi_button_suspend(device_t dev) 132100497Siwasaki{ 133100497Siwasaki struct acpi_button_softc *sc; 134100497Siwasaki 135100497Siwasaki sc = device_get_softc(dev); 136100497Siwasaki acpi_device_enable_wake_event(sc->button_handle); 137100497Siwasaki return (0); 138100497Siwasaki} 139100497Siwasaki 140100497Siwasakistatic int 141100497Siwasakiacpi_button_resume(device_t dev) 142100497Siwasaki{ 143100497Siwasaki return (0); 144100497Siwasaki} 145100497Siwasaki 14667761Smsmithstatic void 14767761Smsmithacpi_button_notify_pressed_for_sleep(void *arg) 14867761Smsmith{ 14967761Smsmith struct acpi_button_softc *sc; 15067761Smsmith struct acpi_softc *acpi_sc; 15167761Smsmith 15296926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 15369744Smsmith 15467761Smsmith sc = (struct acpi_button_softc *)arg; 15567761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 156118783Snjl if (acpi_sc == NULL) 15769744Smsmith return_VOID; 15867761Smsmith 15967761Smsmith switch (sc->button_type) { 16067761Smsmith case ACPI_POWER_BUTTON: 16197274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n"); 16267761Smsmith acpi_eventhandler_power_button_for_sleep((void *)acpi_sc); 16367761Smsmith break; 16467761Smsmith case ACPI_SLEEP_BUTTON: 16597274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "sleep button pressed\n"); 16667761Smsmith acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc); 16767761Smsmith break; 16867761Smsmith default: 16969744Smsmith break; /* unknown button type */ 17067761Smsmith } 17167761Smsmith} 17267761Smsmith 17367761Smsmithstatic void 17467761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg) 17567761Smsmith{ 17667761Smsmith struct acpi_button_softc *sc; 17767761Smsmith struct acpi_softc *acpi_sc; 17867761Smsmith 17996926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 18069744Smsmith 18167761Smsmith sc = (struct acpi_button_softc *)arg; 18267761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 183118783Snjl if (acpi_sc == NULL) 18469744Smsmith return_VOID; 18567761Smsmith 18667761Smsmith switch (sc->button_type) { 18767761Smsmith case ACPI_POWER_BUTTON: 18897274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n"); 18967761Smsmith acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc); 19067761Smsmith break; 19167761Smsmith case ACPI_SLEEP_BUTTON: 19297274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n"); 19367761Smsmith acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc); 19467761Smsmith break; 19567761Smsmith default: 19669744Smsmith break; /* unknown button type */ 19767761Smsmith } 19867761Smsmith} 19967761Smsmith 20067761Smsmithstatic void 20167761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 20267761Smsmith{ 20367761Smsmith struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 20467761Smsmith 20596926Speter ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 20669744Smsmith 20767761Smsmith switch (notify) { 20867761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 209118783Snjl AcpiOsQueueForExecution(OSD_PRIORITY_LO, 210118783Snjl acpi_button_notify_pressed_for_sleep, sc); 21167761Smsmith break; 21267761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 213118783Snjl AcpiOsQueueForExecution(OSD_PRIORITY_LO, 214118783Snjl acpi_button_notify_pressed_for_wakeup, sc); 21567761Smsmith break; 21667761Smsmith default: 21769744Smsmith break; /* unknown notification value */ 21867761Smsmith } 21967761Smsmith} 220