acpi_button.c revision 67761
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 67761 2000-10-28 06:59:48Z 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 4067761Smsmithstruct acpi_button_softc { 4167761Smsmith device_t button_dev; 4267761Smsmith ACPI_HANDLE button_handle; 4367761Smsmith#define ACPI_POWER_BUTTON 0 4467761Smsmith#define ACPI_SLEEP_BUTTON 1 4567761Smsmith boolean_t button_type; /* Power or Sleep Button */ 4667761Smsmith}; 4767761Smsmith 4867761Smsmithstatic int acpi_button_probe(device_t dev); 4967761Smsmithstatic int acpi_button_attach(device_t dev); 5067761Smsmithstatic void acpi_button_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context); 5167761Smsmithstatic void acpi_button_notify_pressed_for_sleep(void *arg); 5267761Smsmithstatic void acpi_button_notify_pressed_for_wakeup(void *arg); 5367761Smsmith 5467761Smsmithstatic device_method_t acpi_button_methods[] = { 5567761Smsmith /* Device interface */ 5667761Smsmith DEVMETHOD(device_probe, acpi_button_probe), 5767761Smsmith DEVMETHOD(device_attach, acpi_button_attach), 5867761Smsmith 5967761Smsmith {0, 0} 6067761Smsmith}; 6167761Smsmith 6267761Smsmithstatic driver_t acpi_button_driver = { 6367761Smsmith "acpi_button", 6467761Smsmith acpi_button_methods, 6567761Smsmith sizeof(struct acpi_button_softc), 6667761Smsmith}; 6767761Smsmith 6867761Smsmithdevclass_t acpi_button_devclass; 6967761SmsmithDRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 0, 0); 7067761Smsmith 7167761Smsmithstatic int 7267761Smsmithacpi_button_probe(device_t dev) 7367761Smsmith{ 7467761Smsmith struct acpi_button_softc *sc; 7567761Smsmith 7667761Smsmith sc = device_get_softc(dev); 7767761Smsmith if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) { 7867761Smsmith if (acpi_MatchHid(dev, "PNP0C0C")) { 7967761Smsmith device_set_desc(dev, "Control Method Power Button Device"); 8067761Smsmith sc->button_type = ACPI_POWER_BUTTON; 8167761Smsmith return(0); 8267761Smsmith } 8367761Smsmith if (acpi_MatchHid(dev, "PNP0C0E")) { 8467761Smsmith device_set_desc(dev, "Control Method Sleep Button Device"); 8567761Smsmith sc->button_type = ACPI_SLEEP_BUTTON; 8667761Smsmith return(0); 8767761Smsmith } 8867761Smsmith return(ENXIO); 8967761Smsmith } 9067761Smsmith return(ENXIO); 9167761Smsmith} 9267761Smsmith 9367761Smsmithstatic int 9467761Smsmithacpi_button_attach(device_t dev) 9567761Smsmith{ 9667761Smsmith struct acpi_button_softc *sc; 9767761Smsmith ACPI_STATUS status; 9867761Smsmith 9967761Smsmith sc = device_get_softc(dev); 10067761Smsmith sc->button_dev = dev; 10167761Smsmith sc->button_handle = acpi_get_handle(dev); 10267761Smsmith 10367761Smsmith if ((status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY, 10467761Smsmith acpi_button_notify_handler, sc)) != AE_OK) { 10567761Smsmith device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", acpi_strerror(status)); 10667761Smsmith return(ENXIO); 10767761Smsmith } 10867761Smsmith return(0); 10967761Smsmith} 11067761Smsmith 11167761Smsmithstatic void 11267761Smsmithacpi_button_notify_pressed_for_sleep(void *arg) 11367761Smsmith{ 11467761Smsmith struct acpi_button_softc *sc; 11567761Smsmith struct acpi_softc *acpi_sc; 11667761Smsmith 11767761Smsmith sc = (struct acpi_button_softc *)arg; 11867761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 11967761Smsmith if (acpi_sc == NULL) { 12067761Smsmith return; 12167761Smsmith } 12267761Smsmith 12367761Smsmith switch (sc->button_type) { 12467761Smsmith case ACPI_POWER_BUTTON: 12567761Smsmith acpi_eventhandler_power_button_for_sleep((void *)acpi_sc); 12667761Smsmith break; 12767761Smsmith case ACPI_SLEEP_BUTTON: 12867761Smsmith acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc); 12967761Smsmith break; 13067761Smsmith default: 13167761Smsmith return; /* unknown button type */ 13267761Smsmith } 13367761Smsmith} 13467761Smsmith 13567761Smsmithstatic void 13667761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg) 13767761Smsmith{ 13867761Smsmith struct acpi_button_softc *sc; 13967761Smsmith struct acpi_softc *acpi_sc; 14067761Smsmith 14167761Smsmith sc = (struct acpi_button_softc *)arg; 14267761Smsmith acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 14367761Smsmith if (acpi_sc == NULL) { 14467761Smsmith return; 14567761Smsmith } 14667761Smsmith 14767761Smsmith switch (sc->button_type) { 14867761Smsmith case ACPI_POWER_BUTTON: 14967761Smsmith acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc); 15067761Smsmith break; 15167761Smsmith case ACPI_SLEEP_BUTTON: 15267761Smsmith acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc); 15367761Smsmith break; 15467761Smsmith default: 15567761Smsmith return; /* unknown button type */ 15667761Smsmith } 15767761Smsmith} 15867761Smsmith 15967761Smsmith/* XXX maybe not here */ 16067761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 16167761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 16267761Smsmith 16367761Smsmithstatic void 16467761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 16567761Smsmith{ 16667761Smsmith struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 16767761Smsmith 16867761Smsmith switch (notify) { 16967761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 17067761Smsmith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc); 17167761Smsmith device_printf(sc->button_dev, "pressed for sleep, button type: %d\n", sc->button_type); 17267761Smsmith break; 17367761Smsmith case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 17467761Smsmith AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc); 17567761Smsmith device_printf(sc->button_dev, "pressed for wakeup, button type: %d\n", sc->button_type); 17667761Smsmith break; 17767761Smsmith default: 17867761Smsmith return; /* unknown notification value */ 17967761Smsmith } 18067761Smsmith} 18167761Smsmith 18267761Smsmith 183