115e32d5dSMike Smith /*- 215e32d5dSMike Smith * Copyright (c) 2000 Mitsaru IWASAKI <iwasaki@jp.freebsd.org> 315e32d5dSMike Smith * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 415e32d5dSMike Smith * Copyright (c) 2000 BSDi 515e32d5dSMike Smith * All rights reserved. 615e32d5dSMike Smith * 715e32d5dSMike Smith * Redistribution and use in source and binary forms, with or without 815e32d5dSMike Smith * modification, are permitted provided that the following conditions 915e32d5dSMike Smith * are met: 1015e32d5dSMike Smith * 1. Redistributions of source code must retain the above copyright 1115e32d5dSMike Smith * notice, this list of conditions and the following disclaimer. 1215e32d5dSMike Smith * 2. Redistributions in binary form must reproduce the above copyright 1315e32d5dSMike Smith * notice, this list of conditions and the following disclaimer in the 1415e32d5dSMike Smith * documentation and/or other materials provided with the distribution. 1515e32d5dSMike Smith * 1615e32d5dSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1715e32d5dSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1815e32d5dSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1915e32d5dSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2015e32d5dSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2115e32d5dSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2215e32d5dSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2315e32d5dSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2415e32d5dSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2515e32d5dSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2615e32d5dSMike Smith * SUCH DAMAGE. 2715e32d5dSMike Smith * 2815e32d5dSMike Smith * $FreeBSD$ 2915e32d5dSMike Smith */ 3015e32d5dSMike Smith 3115e32d5dSMike Smith #include "opt_acpi.h" 3215e32d5dSMike Smith #include <sys/param.h> 3315e32d5dSMike Smith #include <sys/kernel.h> 3415e32d5dSMike Smith #include <sys/bus.h> 3515e32d5dSMike Smith 3615e32d5dSMike Smith #include "acpi.h" 3715e32d5dSMike Smith 3815e32d5dSMike Smith #include <dev/acpica/acpivar.h> 3915e32d5dSMike Smith 400ae55423SMike Smith /* 410ae55423SMike Smith * Hooks for the ACPI CA debugging infrastructure 420ae55423SMike Smith */ 432a4ac806SMike Smith #define _COMPONENT ACPI_BUTTON 440ae55423SMike Smith MODULE_NAME("BUTTON") 450ae55423SMike Smith 4615e32d5dSMike Smith struct acpi_button_softc { 4715e32d5dSMike Smith device_t button_dev; 4815e32d5dSMike Smith ACPI_HANDLE button_handle; 4915e32d5dSMike Smith #define ACPI_POWER_BUTTON 0 5015e32d5dSMike Smith #define ACPI_SLEEP_BUTTON 1 5115e32d5dSMike Smith boolean_t button_type; /* Power or Sleep Button */ 5215e32d5dSMike Smith }; 5315e32d5dSMike Smith 5415e32d5dSMike Smith static int acpi_button_probe(device_t dev); 5515e32d5dSMike Smith static int acpi_button_attach(device_t dev); 5615e32d5dSMike Smith static void acpi_button_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context); 5715e32d5dSMike Smith static void acpi_button_notify_pressed_for_sleep(void *arg); 5815e32d5dSMike Smith static void acpi_button_notify_pressed_for_wakeup(void *arg); 5915e32d5dSMike Smith 6015e32d5dSMike Smith static device_method_t acpi_button_methods[] = { 6115e32d5dSMike Smith /* Device interface */ 6215e32d5dSMike Smith DEVMETHOD(device_probe, acpi_button_probe), 6315e32d5dSMike Smith DEVMETHOD(device_attach, acpi_button_attach), 6415e32d5dSMike Smith 6515e32d5dSMike Smith {0, 0} 6615e32d5dSMike Smith }; 6715e32d5dSMike Smith 6815e32d5dSMike Smith static driver_t acpi_button_driver = { 6915e32d5dSMike Smith "acpi_button", 7015e32d5dSMike Smith acpi_button_methods, 7115e32d5dSMike Smith sizeof(struct acpi_button_softc), 7215e32d5dSMike Smith }; 7315e32d5dSMike Smith 7415e32d5dSMike Smith devclass_t acpi_button_devclass; 7515e32d5dSMike Smith DRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 0, 0); 7615e32d5dSMike Smith 7715e32d5dSMike Smith static int 7815e32d5dSMike Smith acpi_button_probe(device_t dev) 7915e32d5dSMike Smith { 8015e32d5dSMike Smith struct acpi_button_softc *sc; 8115e32d5dSMike Smith 8215e32d5dSMike Smith sc = device_get_softc(dev); 8315e32d5dSMike Smith if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) { 840ae55423SMike Smith if (!acpi_disabled("button")) { 8515e32d5dSMike Smith if (acpi_MatchHid(dev, "PNP0C0C")) { 8667ce1673SMike Smith device_set_desc(dev, "Power Button"); 8715e32d5dSMike Smith sc->button_type = ACPI_POWER_BUTTON; 8815e32d5dSMike Smith return(0); 8915e32d5dSMike Smith } 9015e32d5dSMike Smith if (acpi_MatchHid(dev, "PNP0C0E")) { 9167ce1673SMike Smith device_set_desc(dev, "Sleep Button"); 9215e32d5dSMike Smith sc->button_type = ACPI_SLEEP_BUTTON; 9315e32d5dSMike Smith return(0); 9415e32d5dSMike Smith } 950ae55423SMike Smith } 9615e32d5dSMike Smith } 9715e32d5dSMike Smith return(ENXIO); 9815e32d5dSMike Smith } 9915e32d5dSMike Smith 10015e32d5dSMike Smith static int 10115e32d5dSMike Smith acpi_button_attach(device_t dev) 10215e32d5dSMike Smith { 10315e32d5dSMike Smith struct acpi_button_softc *sc; 10415e32d5dSMike Smith ACPI_STATUS status; 10515e32d5dSMike Smith 1062a4ac806SMike Smith FUNCTION_TRACE(__func__); 1070ae55423SMike Smith 10815e32d5dSMike Smith sc = device_get_softc(dev); 10915e32d5dSMike Smith sc->button_dev = dev; 11015e32d5dSMike Smith sc->button_handle = acpi_get_handle(dev); 11115e32d5dSMike Smith 11215e32d5dSMike Smith if ((status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY, 11315e32d5dSMike Smith acpi_button_notify_handler, sc)) != AE_OK) { 11415e32d5dSMike Smith device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", acpi_strerror(status)); 1150ae55423SMike Smith return_VALUE(ENXIO); 11615e32d5dSMike Smith } 1170ae55423SMike Smith return_VALUE(0); 11815e32d5dSMike Smith } 11915e32d5dSMike Smith 12015e32d5dSMike Smith static void 12115e32d5dSMike Smith acpi_button_notify_pressed_for_sleep(void *arg) 12215e32d5dSMike Smith { 12315e32d5dSMike Smith struct acpi_button_softc *sc; 12415e32d5dSMike Smith struct acpi_softc *acpi_sc; 12515e32d5dSMike Smith 1262a4ac806SMike Smith FUNCTION_TRACE(__func__); 1270ae55423SMike Smith 12815e32d5dSMike Smith sc = (struct acpi_button_softc *)arg; 12915e32d5dSMike Smith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 13015e32d5dSMike Smith if (acpi_sc == NULL) { 1310ae55423SMike Smith return_VOID; 13215e32d5dSMike Smith } 13315e32d5dSMike Smith 13415e32d5dSMike Smith switch (sc->button_type) { 13515e32d5dSMike Smith case ACPI_POWER_BUTTON: 13667ce1673SMike Smith device_printf(sc->button_dev, "power button pressed\n", sc->button_type); 13715e32d5dSMike Smith acpi_eventhandler_power_button_for_sleep((void *)acpi_sc); 13815e32d5dSMike Smith break; 13915e32d5dSMike Smith case ACPI_SLEEP_BUTTON: 14067ce1673SMike Smith device_printf(sc->button_dev, "sleep button pressed\n", sc->button_type); 14115e32d5dSMike Smith acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc); 14215e32d5dSMike Smith break; 14315e32d5dSMike Smith default: 1440ae55423SMike Smith break; /* unknown button type */ 14515e32d5dSMike Smith } 1460ae55423SMike Smith return_VOID; 14715e32d5dSMike Smith } 14815e32d5dSMike Smith 14915e32d5dSMike Smith static void 15015e32d5dSMike Smith acpi_button_notify_pressed_for_wakeup(void *arg) 15115e32d5dSMike Smith { 15215e32d5dSMike Smith struct acpi_button_softc *sc; 15315e32d5dSMike Smith struct acpi_softc *acpi_sc; 15415e32d5dSMike Smith 1552a4ac806SMike Smith FUNCTION_TRACE(__func__); 1560ae55423SMike Smith 15715e32d5dSMike Smith sc = (struct acpi_button_softc *)arg; 15815e32d5dSMike Smith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 15915e32d5dSMike Smith if (acpi_sc == NULL) { 1600ae55423SMike Smith return_VOID; 16115e32d5dSMike Smith } 16215e32d5dSMike Smith 16315e32d5dSMike Smith switch (sc->button_type) { 16415e32d5dSMike Smith case ACPI_POWER_BUTTON: 16567ce1673SMike Smith device_printf(sc->button_dev, "wakeup by power button\n", sc->button_type); 16615e32d5dSMike Smith acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc); 16715e32d5dSMike Smith break; 16815e32d5dSMike Smith case ACPI_SLEEP_BUTTON: 16967ce1673SMike Smith device_printf(sc->button_dev, "wakeup by sleep button\n", sc->button_type); 17015e32d5dSMike Smith acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc); 17115e32d5dSMike Smith break; 17215e32d5dSMike Smith default: 1730ae55423SMike Smith break; /* unknown button type */ 17415e32d5dSMike Smith } 1750ae55423SMike Smith return_VOID; 17615e32d5dSMike Smith } 17715e32d5dSMike Smith 17815e32d5dSMike Smith /* XXX maybe not here */ 17915e32d5dSMike Smith #define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 18015e32d5dSMike Smith #define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 18115e32d5dSMike Smith 18215e32d5dSMike Smith static void 18315e32d5dSMike Smith acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 18415e32d5dSMike Smith { 18515e32d5dSMike Smith struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 18615e32d5dSMike Smith 1872a4ac806SMike Smith FUNCTION_TRACE_U32(__func__, notify); 1880ae55423SMike Smith 18915e32d5dSMike Smith switch (notify) { 19015e32d5dSMike Smith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 19115e32d5dSMike Smith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc); 19215e32d5dSMike Smith break; 19315e32d5dSMike Smith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 19415e32d5dSMike Smith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc); 19515e32d5dSMike Smith break; 19615e32d5dSMike Smith default: 1970ae55423SMike Smith break; /* unknown notification value */ 19815e32d5dSMike Smith } 1990ae55423SMike Smith return_VOID; 20015e32d5dSMike Smith } 20115e32d5dSMike Smith 20215e32d5dSMike Smith 203