acpi_button.c revision 80067
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 80067 2001-07-21 04:05:08Z msmith $ 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 4469744SmsmithMODULE_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); 5667761Smsmithstatic void acpi_button_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context); 5767761Smsmithstatic void acpi_button_notify_pressed_for_sleep(void *arg); 5867761Smsmithstatic void acpi_button_notify_pressed_for_wakeup(void *arg); 5967761Smsmith 6067761Smsmithstatic device_method_t acpi_button_methods[] = { 6167761Smsmith /* Device interface */ 6267761Smsmith DEVMETHOD(device_probe, acpi_button_probe), 6367761Smsmith DEVMETHOD(device_attach, acpi_button_attach), 6467761Smsmith 6567761Smsmith {0, 0} 6667761Smsmith}; 6767761Smsmith 6867761Smsmithstatic driver_t acpi_button_driver = { 6967761Smsmith "acpi_button", 7067761Smsmith acpi_button_methods, 7167761Smsmith sizeof(struct acpi_button_softc), 7267761Smsmith}; 7367761Smsmith 7467761Smsmithdevclass_t acpi_button_devclass; 7567761SmsmithDRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 0, 0); 7667761Smsmith 7767761Smsmithstatic int 7867761Smsmithacpi_button_probe(device_t dev) 7967761Smsmith{ 8067761Smsmith struct acpi_button_softc *sc; 8167761Smsmith 8267761Smsmith sc = device_get_softc(dev); 8367761Smsmith if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) { 8469744Smsmith if (!acpi_disabled("button")) { 8569744Smsmith if (acpi_MatchHid(dev, "PNP0C0C")) { 8680067Smsmith device_set_desc(dev, "Power Button"); 8769744Smsmith sc->button_type = ACPI_POWER_BUTTON; 8869744Smsmith return(0); 8969744Smsmith } 9069744Smsmith if (acpi_MatchHid(dev, "PNP0C0E")) { 9180067Smsmith device_set_desc(dev, "Sleep Button"); 9269744Smsmith sc->button_type = ACPI_SLEEP_BUTTON; 9369744Smsmith return(0); 9469744Smsmith } 9567761Smsmith } 9667761Smsmith } 9767761Smsmith return(ENXIO); 9867761Smsmith} 9967761Smsmith 10067761Smsmithstatic int 10167761Smsmithacpi_button_attach(device_t dev) 10267761Smsmith{ 10367761Smsmith struct acpi_button_softc *sc; 10467761Smsmith ACPI_STATUS status; 10567761Smsmith 10677432Smsmith FUNCTION_TRACE(__func__); 10769744Smsmith 10867761Smsmith sc = device_get_softc(dev); 10967761Smsmith sc->button_dev = dev; 11067761Smsmith sc->button_handle = acpi_get_handle(dev); 11167761Smsmith 11267761Smsmith if ((status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY, 11367761Smsmith acpi_button_notify_handler, sc)) != AE_OK) { 11467761Smsmith device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", acpi_strerror(status)); 11569744Smsmith return_VALUE(ENXIO); 11667761Smsmith } 11769744Smsmith return_VALUE(0); 11867761Smsmith} 11967761Smsmith 12067761Smsmithstatic void 12167761Smsmithacpi_button_notify_pressed_for_sleep(void *arg) 12267761Smsmith{ 12367761Smsmith struct acpi_button_softc *sc; 12467761Smsmith struct acpi_softc *acpi_sc; 12567761Smsmith 12677432Smsmith FUNCTION_TRACE(__func__); 12769744Smsmith 12867761Smsmith sc = (struct acpi_button_softc *)arg; 12967761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 13067761Smsmith if (acpi_sc == NULL) { 13169744Smsmith return_VOID; 13267761Smsmith } 13367761Smsmith 13467761Smsmith switch (sc->button_type) { 13567761Smsmith case ACPI_POWER_BUTTON: 13680067Smsmith device_printf(sc->button_dev, "power button pressed\n", sc->button_type); 13767761Smsmith acpi_eventhandler_power_button_for_sleep((void *)acpi_sc); 13867761Smsmith break; 13967761Smsmith case ACPI_SLEEP_BUTTON: 14080067Smsmith device_printf(sc->button_dev, "sleep button pressed\n", sc->button_type); 14167761Smsmith acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc); 14267761Smsmith break; 14367761Smsmith default: 14469744Smsmith break; /* unknown button type */ 14567761Smsmith } 14669744Smsmith return_VOID; 14767761Smsmith} 14867761Smsmith 14967761Smsmithstatic void 15067761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg) 15167761Smsmith{ 15267761Smsmith struct acpi_button_softc *sc; 15367761Smsmith struct acpi_softc *acpi_sc; 15467761Smsmith 15577432Smsmith FUNCTION_TRACE(__func__); 15669744Smsmith 15767761Smsmith sc = (struct acpi_button_softc *)arg; 15867761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 15967761Smsmith if (acpi_sc == NULL) { 16069744Smsmith return_VOID; 16167761Smsmith } 16267761Smsmith 16367761Smsmith switch (sc->button_type) { 16467761Smsmith case ACPI_POWER_BUTTON: 16580067Smsmith device_printf(sc->button_dev, "wakeup by power button\n", sc->button_type); 16667761Smsmith acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc); 16767761Smsmith break; 16867761Smsmith case ACPI_SLEEP_BUTTON: 16980067Smsmith device_printf(sc->button_dev, "wakeup by sleep button\n", sc->button_type); 17067761Smsmith acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc); 17167761Smsmith break; 17267761Smsmith default: 17369744Smsmith break; /* unknown button type */ 17467761Smsmith } 17569744Smsmith return_VOID; 17667761Smsmith} 17767761Smsmith 17867761Smsmith/* XXX maybe not here */ 17967761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 18067761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 18167761Smsmith 18267761Smsmithstatic void 18367761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 18467761Smsmith{ 18567761Smsmith struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 18667761Smsmith 18777432Smsmith FUNCTION_TRACE_U32(__func__, notify); 18869744Smsmith 18967761Smsmith switch (notify) { 19067761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 19167761Smsmith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc); 19267761Smsmith break; 19367761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 19467761Smsmith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc); 19567761Smsmith break; 19667761Smsmith default: 19769744Smsmith break; /* unknown notification value */ 19867761Smsmith } 19969744Smsmith return_VOID; 20067761Smsmith} 20167761Smsmith 20267761Smsmith 203