acpi_button.c revision 1.7
1#define ACPI_BUT_DEBUG 2/* $NetBSD: acpi_button.c,v 1.7 2003/04/17 01:22:21 thorpej Exp $ */ 3 4/* 5 * Copyright 2001, 2003 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * ACPI Button driver. 41 */ 42 43#include <sys/cdefs.h> 44__KERNEL_RCSID(0, "$NetBSD: acpi_button.c,v 1.7 2003/04/17 01:22:21 thorpej Exp $"); 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/device.h> 49 50#include <dev/acpi/acpica.h> 51#include <dev/acpi/acpireg.h> 52#include <dev/acpi/acpivar.h> 53 54#include <dev/sysmon/sysmonvar.h> 55 56struct acpibut_softc { 57 struct device sc_dev; /* base device glue */ 58 struct acpi_devnode *sc_node; /* our ACPI devnode */ 59 struct sysmon_pswitch sc_smpsw; /* our sysmon glue */ 60 int sc_flags; /* see below */ 61}; 62 63#define ACPIBUT_F_VERBOSE 0x01 /* verbose events */ 64 65int acpibut_match(struct device *, struct cfdata *, void *); 66void acpibut_attach(struct device *, struct device *, void *); 67 68CFATTACH_DECL(acpibut, sizeof(struct acpibut_softc), 69 acpibut_match, acpibut_attach, NULL, NULL); 70 71void acpibut_pressed_event(void *); 72void acpibut_notify_handler(ACPI_HANDLE, UINT32, void *context); 73 74/* 75 * acpibut_match: 76 * 77 * Autoconfiguration `match' routine. 78 */ 79int 80acpibut_match(struct device *parent, struct cfdata *match, void *aux) 81{ 82 struct acpi_attach_args *aa = aux; 83 84 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 85 return (0); 86 87 if (strcmp(aa->aa_node->ad_devinfo.HardwareId, "PNP0C0C") == 0 || 88 strcmp(aa->aa_node->ad_devinfo.HardwareId, "PNP0C0E") == 0) 89 return (1); 90 91 return (0); 92} 93 94/* 95 * acpibut_attach: 96 * 97 * Autoconfiguration `attach' routine. 98 */ 99void 100acpibut_attach(struct device *parent, struct device *self, void *aux) 101{ 102 struct acpibut_softc *sc = (void *) self; 103 struct acpi_attach_args *aa = aux; 104 const char *desc; 105 ACPI_STATUS rv; 106 107 sc->sc_smpsw.smpsw_name = sc->sc_dev.dv_xname; 108 109 if (strcmp(aa->aa_node->ad_devinfo.HardwareId, "PNP0C0C") == 0) { 110 sc->sc_smpsw.smpsw_type = SMPSW_TYPE_POWER; 111 desc = "Power"; 112 } else if (strcmp(aa->aa_node->ad_devinfo.HardwareId, "PNP0C0E") == 0) { 113 sc->sc_smpsw.smpsw_type = SMPSW_TYPE_SLEEP; 114 desc = "Sleep"; 115 } else { 116 printf("\n"); 117 panic("acpibut_attach: impossible"); 118 } 119 120 printf(": ACPI %s Button\n", desc); 121 122 sc->sc_node = aa->aa_node; 123 124 if (sysmon_pswitch_register(&sc->sc_smpsw) != 0) { 125 printf("%s: unable to register with sysmon\n", 126 sc->sc_dev.dv_xname); 127 return; 128 } 129 130 rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, 131 ACPI_DEVICE_NOTIFY, acpibut_notify_handler, sc); 132 if (rv != AE_OK) { 133 printf("%s: unable to register device notify handler: %d\n", 134 sc->sc_dev.dv_xname, rv); 135 return; 136 } 137 138#ifdef ACPI_BUT_DEBUG 139 /* Display the current state when it changes. */ 140 sc->sc_flags = ACPIBUT_F_VERBOSE; 141#endif 142} 143 144/* 145 * acpibut_pressed_event: 146 * 147 * Deal with a button being pressed. 148 */ 149void 150acpibut_pressed_event(void *arg) 151{ 152 struct acpibut_softc *sc = arg; 153 154 if (sc->sc_flags & ACPIBUT_F_VERBOSE) 155 printf("%s: button pressed\n", sc->sc_dev.dv_xname); 156 157 sysmon_pswitch_event(&sc->sc_smpsw, SMPSW_EVENT_PRESSED); 158} 159 160/* 161 * acpibut_notify_handler: 162 * 163 * Callback from ACPI interrupt handler to notify us of an event. 164 */ 165void 166acpibut_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context) 167{ 168 struct acpibut_softc *sc = context; 169 int rv; 170 171 switch (notify) { 172 case ACPI_NOTIFY_S0PowerButtonPressed: 173#if 0 174 case ACPI_NOTIFY_S0SleepButtonPressed: /* same as above */ 175#endif 176#ifdef ACPI_BUT_DEBUG 177 printf("%s: received ButtonPressed message\n", 178 sc->sc_dev.dv_xname); 179#endif 180 rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO, 181 acpibut_pressed_event, sc); 182 if (rv != AE_OK) 183 printf("%s: WARNING: unable to queue button pressed " 184 "callback: %d\n", sc->sc_dev.dv_xname, rv); 185 break; 186 187 /* XXX ACPI_NOTIFY_DeviceWake?? */ 188 189 default: 190 printf("%s: received unknown notify message: 0x%x\n", 191 sc->sc_dev.dv_xname, notify); 192 } 193} 194