acpi_button.c revision 100497
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 100497 2002-07-22 12:52:54Z iwasaki $ 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 3867761Smsmith#include <dev/acpica/acpivar.h> 3967761Smsmith 4069744Smsmith/* 4169744Smsmith * Hooks for the ACPI CA debugging infrastructure 4269744Smsmith */ 4377432Smsmith#define _COMPONENT ACPI_BUTTON 4491123SmsmithACPI_MODULE_NAME("BUTTON") 4569744Smsmith 4667761Smsmithstruct acpi_button_softc { 4767761Smsmith device_t button_dev; 4867761Smsmith ACPI_HANDLE button_handle; 4967761Smsmith#define ACPI_POWER_BUTTON 0 5067761Smsmith#define ACPI_SLEEP_BUTTON 1 5167761Smsmith boolean_t button_type; /* Power or Sleep Button */ 5267761Smsmith}; 5367761Smsmith 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); 5867761Smsmithstatic void acpi_button_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context); 5967761Smsmithstatic void acpi_button_notify_pressed_for_sleep(void *arg); 6067761Smsmithstatic void acpi_button_notify_pressed_for_wakeup(void *arg); 6167761Smsmith 6267761Smsmithstatic device_method_t acpi_button_methods[] = { 6367761Smsmith /* Device interface */ 6467761Smsmith DEVMETHOD(device_probe, acpi_button_probe), 6567761Smsmith DEVMETHOD(device_attach, acpi_button_attach), 66100497Siwasaki DEVMETHOD(device_suspend, acpi_button_suspend), 67100497Siwasaki DEVMETHOD(device_resume, acpi_button_resume), 6867761Smsmith 6967761Smsmith {0, 0} 7067761Smsmith}; 7167761Smsmith 7267761Smsmithstatic driver_t acpi_button_driver = { 7367761Smsmith "acpi_button", 7467761Smsmith acpi_button_methods, 7567761Smsmith sizeof(struct acpi_button_softc), 7667761Smsmith}; 7767761Smsmith 7889054Smsmithstatic devclass_t acpi_button_devclass; 7967761SmsmithDRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 0, 0); 8067761Smsmith 8167761Smsmithstatic int 8267761Smsmithacpi_button_probe(device_t dev) 8367761Smsmith{ 8467761Smsmith struct acpi_button_softc *sc; 8567761Smsmith 8667761Smsmith sc = device_get_softc(dev); 8767761Smsmith if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) { 8869744Smsmith if (!acpi_disabled("button")) { 8969744Smsmith if (acpi_MatchHid(dev, "PNP0C0C")) { 9080067Smsmith device_set_desc(dev, "Power Button"); 9169744Smsmith sc->button_type = ACPI_POWER_BUTTON; 9269744Smsmith return(0); 9369744Smsmith } 9469744Smsmith if (acpi_MatchHid(dev, "PNP0C0E")) { 9580067Smsmith device_set_desc(dev, "Sleep Button"); 9669744Smsmith sc->button_type = ACPI_SLEEP_BUTTON; 9769744Smsmith return(0); 9869744Smsmith } 9967761Smsmith } 10067761Smsmith } 10167761Smsmith return(ENXIO); 10267761Smsmith} 10367761Smsmith 10467761Smsmithstatic int 10567761Smsmithacpi_button_attach(device_t dev) 10667761Smsmith{ 10767761Smsmith struct acpi_button_softc *sc; 10867761Smsmith ACPI_STATUS status; 10967761Smsmith 11096926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 11169744Smsmith 11267761Smsmith sc = device_get_softc(dev); 11367761Smsmith sc->button_dev = dev; 11467761Smsmith sc->button_handle = acpi_get_handle(dev); 11567761Smsmith 11691123Smsmith if (ACPI_FAILURE(status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY, 11791123Smsmith acpi_button_notify_handler, sc))) { 11880078Smsmith device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", AcpiFormatException(status)); 11969744Smsmith return_VALUE(ENXIO); 12067761Smsmith } 121100497Siwasaki acpi_device_enable_wake_capability(sc->button_handle, 1); 12269744Smsmith return_VALUE(0); 12367761Smsmith} 12467761Smsmith 125100497Siwasakistatic int 126100497Siwasakiacpi_button_suspend(device_t dev) 127100497Siwasaki{ 128100497Siwasaki struct acpi_button_softc *sc; 129100497Siwasaki 130100497Siwasaki sc = device_get_softc(dev); 131100497Siwasaki acpi_device_enable_wake_event(sc->button_handle); 132100497Siwasaki return (0); 133100497Siwasaki} 134100497Siwasaki 135100497Siwasakistatic int 136100497Siwasakiacpi_button_resume(device_t dev) 137100497Siwasaki{ 138100497Siwasaki 139100497Siwasaki return (0); 140100497Siwasaki} 141100497Siwasaki 14267761Smsmithstatic void 14367761Smsmithacpi_button_notify_pressed_for_sleep(void *arg) 14467761Smsmith{ 14567761Smsmith struct acpi_button_softc *sc; 14667761Smsmith struct acpi_softc *acpi_sc; 14767761Smsmith 14896926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 14969744Smsmith 15067761Smsmith sc = (struct acpi_button_softc *)arg; 15167761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 15267761Smsmith if (acpi_sc == NULL) { 15369744Smsmith return_VOID; 15467761Smsmith } 15567761Smsmith 15667761Smsmith switch (sc->button_type) { 15767761Smsmith case ACPI_POWER_BUTTON: 15897274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n"); 15967761Smsmith acpi_eventhandler_power_button_for_sleep((void *)acpi_sc); 16067761Smsmith break; 16167761Smsmith case ACPI_SLEEP_BUTTON: 16297274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "sleep button pressed\n"); 16367761Smsmith acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc); 16467761Smsmith break; 16567761Smsmith default: 16669744Smsmith break; /* unknown button type */ 16767761Smsmith } 16869744Smsmith return_VOID; 16967761Smsmith} 17067761Smsmith 17167761Smsmithstatic void 17267761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg) 17367761Smsmith{ 17467761Smsmith struct acpi_button_softc *sc; 17567761Smsmith struct acpi_softc *acpi_sc; 17667761Smsmith 17796926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 17869744Smsmith 17967761Smsmith sc = (struct acpi_button_softc *)arg; 18067761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 18167761Smsmith if (acpi_sc == NULL) { 18269744Smsmith return_VOID; 18367761Smsmith } 18467761Smsmith 18567761Smsmith switch (sc->button_type) { 18667761Smsmith case ACPI_POWER_BUTTON: 18797274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n"); 18867761Smsmith acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc); 18967761Smsmith break; 19067761Smsmith case ACPI_SLEEP_BUTTON: 19197274Sbde ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n"); 19267761Smsmith acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc); 19367761Smsmith break; 19467761Smsmith default: 19569744Smsmith break; /* unknown button type */ 19667761Smsmith } 19769744Smsmith return_VOID; 19867761Smsmith} 19967761Smsmith 20067761Smsmith/* XXX maybe not here */ 20167761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 20267761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 20367761Smsmith 20467761Smsmithstatic void 20567761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 20667761Smsmith{ 20767761Smsmith struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 20867761Smsmith 20996926Speter ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 21069744Smsmith 21167761Smsmith switch (notify) { 21267761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 21367761Smsmith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc); 21467761Smsmith break; 21567761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 21667761Smsmith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc); 21767761Smsmith break; 21867761Smsmith default: 21969744Smsmith break; /* unknown notification value */ 22067761Smsmith } 22169744Smsmith return_VOID; 22267761Smsmith} 22367761Smsmith 22467761Smsmith 225