1/*- 2 * Copyright (c) 2000 Mitsaru IWASAKI <iwasaki@jp.freebsd.org> 3 * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000 BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 *
| 1/*- 2 * Copyright (c) 2000 Mitsaru IWASAKI <iwasaki@jp.freebsd.org> 3 * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000 BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 *
|
28 * $FreeBSD: head/sys/dev/acpica/acpi_button.c 121493 2003-10-25 05:03:25Z njl $
| 28 * $FreeBSD: head/sys/dev/acpica/acpi_button.c 125679 2004-02-11 02:57:33Z njl $
|
29 */ 30 31#include "opt_acpi.h" 32#include <sys/param.h> 33#include <sys/kernel.h> 34#include <sys/bus.h> 35 36#include "acpi.h" 37#include <dev/acpica/acpivar.h> 38 39/* Hooks for the ACPI CA debugging infrastructure */ 40#define _COMPONENT ACPI_BUTTON 41ACPI_MODULE_NAME("BUTTON") 42 43struct acpi_button_softc { 44 device_t button_dev; 45 ACPI_HANDLE button_handle; 46 boolean_t button_type; 47#define ACPI_POWER_BUTTON 0 48#define ACPI_SLEEP_BUTTON 1 49 boolean_t fixed; 50}; 51 52#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 53#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 54 55static int acpi_button_probe(device_t dev); 56static int acpi_button_attach(device_t dev); 57static int acpi_button_suspend(device_t dev); 58static int acpi_button_resume(device_t dev); 59static void acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, 60 void *context); 61static ACPI_STATUS 62 acpi_button_fixed_handler(void *context);
| 29 */ 30 31#include "opt_acpi.h" 32#include <sys/param.h> 33#include <sys/kernel.h> 34#include <sys/bus.h> 35 36#include "acpi.h" 37#include <dev/acpica/acpivar.h> 38 39/* Hooks for the ACPI CA debugging infrastructure */ 40#define _COMPONENT ACPI_BUTTON 41ACPI_MODULE_NAME("BUTTON") 42 43struct acpi_button_softc { 44 device_t button_dev; 45 ACPI_HANDLE button_handle; 46 boolean_t button_type; 47#define ACPI_POWER_BUTTON 0 48#define ACPI_SLEEP_BUTTON 1 49 boolean_t fixed; 50}; 51 52#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP 0x80 53#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP 0x02 54 55static int acpi_button_probe(device_t dev); 56static int acpi_button_attach(device_t dev); 57static int acpi_button_suspend(device_t dev); 58static int acpi_button_resume(device_t dev); 59static void acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, 60 void *context); 61static ACPI_STATUS 62 acpi_button_fixed_handler(void *context);
|
63static void acpi_button_notify_pressed_for_sleep(void *arg); 64static void acpi_button_notify_pressed_for_wakeup(void *arg);
| 63static void acpi_button_notify_sleep(void *arg); 64static void acpi_button_notify_wakeup(void *arg);
|
65 66static device_method_t acpi_button_methods[] = { 67 /* Device interface */ 68 DEVMETHOD(device_probe, acpi_button_probe), 69 DEVMETHOD(device_attach, acpi_button_attach), 70 DEVMETHOD(device_suspend, acpi_button_suspend), 71 DEVMETHOD(device_shutdown, acpi_button_suspend), 72 DEVMETHOD(device_resume, acpi_button_resume), 73 74 {0, 0} 75}; 76 77static driver_t acpi_button_driver = { 78 "acpi_button", 79 acpi_button_methods, 80 sizeof(struct acpi_button_softc), 81}; 82 83static devclass_t acpi_button_devclass; 84DRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 85 0, 0); 86 87static int 88acpi_button_probe(device_t dev) 89{ 90 struct acpi_button_softc *sc; 91 int ret = ENXIO; 92 93 sc = device_get_softc(dev); 94 if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("button")) { 95 if (acpi_MatchHid(dev, "PNP0C0C")) { 96 device_set_desc(dev, "Power Button"); 97 sc->button_type = ACPI_POWER_BUTTON; 98 ret = 0; 99 } else if (acpi_MatchHid(dev, "ACPI_FPB")) { 100 device_set_desc(dev, "Power Button (fixed)"); 101 sc->button_type = ACPI_POWER_BUTTON; 102 sc->fixed = 1; 103 ret = 0; 104 } else if (acpi_MatchHid(dev, "PNP0C0E")) { 105 device_set_desc(dev, "Sleep Button"); 106 sc->button_type = ACPI_SLEEP_BUTTON; 107 ret = 0; 108 } else if (acpi_MatchHid(dev, "ACPI_FSB")) { 109 device_set_desc(dev, "Sleep Button (fixed)"); 110 sc->button_type = ACPI_SLEEP_BUTTON; 111 sc->fixed = 1; 112 ret = 0; 113 } 114 } 115 return (ret); 116} 117 118static int 119acpi_button_attach(device_t dev) 120{ 121 struct acpi_button_softc *sc; 122 ACPI_STATUS status; 123 int event; 124 125 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 126 127 sc = device_get_softc(dev); 128 sc->button_dev = dev; 129 sc->button_handle = acpi_get_handle(dev);
| 65 66static device_method_t acpi_button_methods[] = { 67 /* Device interface */ 68 DEVMETHOD(device_probe, acpi_button_probe), 69 DEVMETHOD(device_attach, acpi_button_attach), 70 DEVMETHOD(device_suspend, acpi_button_suspend), 71 DEVMETHOD(device_shutdown, acpi_button_suspend), 72 DEVMETHOD(device_resume, acpi_button_resume), 73 74 {0, 0} 75}; 76 77static driver_t acpi_button_driver = { 78 "acpi_button", 79 acpi_button_methods, 80 sizeof(struct acpi_button_softc), 81}; 82 83static devclass_t acpi_button_devclass; 84DRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 85 0, 0); 86 87static int 88acpi_button_probe(device_t dev) 89{ 90 struct acpi_button_softc *sc; 91 int ret = ENXIO; 92 93 sc = device_get_softc(dev); 94 if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("button")) { 95 if (acpi_MatchHid(dev, "PNP0C0C")) { 96 device_set_desc(dev, "Power Button"); 97 sc->button_type = ACPI_POWER_BUTTON; 98 ret = 0; 99 } else if (acpi_MatchHid(dev, "ACPI_FPB")) { 100 device_set_desc(dev, "Power Button (fixed)"); 101 sc->button_type = ACPI_POWER_BUTTON; 102 sc->fixed = 1; 103 ret = 0; 104 } else if (acpi_MatchHid(dev, "PNP0C0E")) { 105 device_set_desc(dev, "Sleep Button"); 106 sc->button_type = ACPI_SLEEP_BUTTON; 107 ret = 0; 108 } else if (acpi_MatchHid(dev, "ACPI_FSB")) { 109 device_set_desc(dev, "Sleep Button (fixed)"); 110 sc->button_type = ACPI_SLEEP_BUTTON; 111 sc->fixed = 1; 112 ret = 0; 113 } 114 } 115 return (ret); 116} 117 118static int 119acpi_button_attach(device_t dev) 120{ 121 struct acpi_button_softc *sc; 122 ACPI_STATUS status; 123 int event; 124 125 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 126 127 sc = device_get_softc(dev); 128 sc->button_dev = dev; 129 sc->button_handle = acpi_get_handle(dev);
|
| 130 event = (sc->button_type == ACPI_SLEEP_BUTTON) ? 131 ACPI_EVENT_SLEEP_BUTTON : ACPI_EVENT_POWER_BUTTON;
|
130
| 132
|
| 133 /* Install the appropriate new handler. */
|
131 if (sc->fixed) {
| 134 if (sc->fixed) {
|
132 event = (sc->button_type == ACPI_SLEEP_BUTTON) ? 133 ACPI_EVENT_SLEEP_BUTTON : ACPI_EVENT_POWER_BUTTON;
| 135 AcpiEnableEvent(event, 0); 136 AcpiClearEvent(event);
|
134 status = AcpiInstallFixedEventHandler(event, 135 acpi_button_fixed_handler, sc); 136 } else { 137 status = AcpiInstallNotifyHandler(sc->button_handle, 138 ACPI_DEVICE_NOTIFY, acpi_button_notify_handler, sc); 139 } 140 if (ACPI_FAILURE(status)) { 141 device_printf(sc->button_dev, "couldn't install notify handler - %s\n", 142 AcpiFormatException(status)); 143 return_VALUE (ENXIO); 144 } 145 acpi_device_enable_wake_capability(sc->button_handle, 1);
| 137 status = AcpiInstallFixedEventHandler(event, 138 acpi_button_fixed_handler, sc); 139 } else { 140 status = AcpiInstallNotifyHandler(sc->button_handle, 141 ACPI_DEVICE_NOTIFY, acpi_button_notify_handler, sc); 142 } 143 if (ACPI_FAILURE(status)) { 144 device_printf(sc->button_dev, "couldn't install notify handler - %s\n", 145 AcpiFormatException(status)); 146 return_VALUE (ENXIO); 147 } 148 acpi_device_enable_wake_capability(sc->button_handle, 1);
|
| 149 150 /* 151 * If we have fixed buttons defined in the FADT, remove them now that 152 * we have found one in the AML. Some systems define buttons both ways 153 * but only deliver events to the AML object. 154 */ 155 if (event == ACPI_EVENT_POWER_BUTTON && AcpiGbl_FADT->PwrButton == 0) { 156 AcpiDisableEvent(event, 0); 157 AcpiClearEvent(event); 158 AcpiRemoveFixedEventHandler(event, acpi_event_power_button_sleep); 159 } 160 if (event == ACPI_EVENT_SLEEP_BUTTON && AcpiGbl_FADT->SleepButton == 0) { 161 AcpiDisableEvent(event, 0); 162 AcpiClearEvent(event); 163 AcpiRemoveFixedEventHandler(event, acpi_event_sleep_button_sleep); 164 } 165
|
146 return_VALUE (0); 147} 148 149static int 150acpi_button_suspend(device_t dev) 151{ 152 struct acpi_button_softc *sc; 153 154 sc = device_get_softc(dev); 155 acpi_device_enable_wake_event(sc->button_handle); 156 return (0); 157} 158 159static int 160acpi_button_resume(device_t dev) 161{ 162 return (0); 163} 164 165static void
| 166 return_VALUE (0); 167} 168 169static int 170acpi_button_suspend(device_t dev) 171{ 172 struct acpi_button_softc *sc; 173 174 sc = device_get_softc(dev); 175 acpi_device_enable_wake_event(sc->button_handle); 176 return (0); 177} 178 179static int 180acpi_button_resume(device_t dev) 181{ 182 return (0); 183} 184 185static void
|
166acpi_button_notify_pressed_for_sleep(void *arg)
| 186acpi_button_notify_sleep(void *arg)
|
167{ 168 struct acpi_button_softc *sc; 169 struct acpi_softc *acpi_sc; 170 171 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 172 173 sc = (struct acpi_button_softc *)arg; 174 acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 175 if (acpi_sc == NULL) 176 return_VOID; 177 178 acpi_UserNotify("Button", sc->button_handle, sc->button_type); 179 180 switch (sc->button_type) { 181 case ACPI_POWER_BUTTON: 182 ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n");
| 187{ 188 struct acpi_button_softc *sc; 189 struct acpi_softc *acpi_sc; 190 191 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 192 193 sc = (struct acpi_button_softc *)arg; 194 acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 195 if (acpi_sc == NULL) 196 return_VOID; 197 198 acpi_UserNotify("Button", sc->button_handle, sc->button_type); 199 200 switch (sc->button_type) { 201 case ACPI_POWER_BUTTON: 202 ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n");
|
183 acpi_eventhandler_power_button_for_sleep((void *)acpi_sc);
| 203 acpi_event_power_button_sleep(acpi_sc);
|
184 break; 185 case ACPI_SLEEP_BUTTON: 186 ACPI_VPRINT(sc->button_dev, acpi_sc, "sleep button pressed\n");
| 204 break; 205 case ACPI_SLEEP_BUTTON: 206 ACPI_VPRINT(sc->button_dev, acpi_sc, "sleep button pressed\n");
|
187 acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc);
| 207 acpi_event_sleep_button_sleep(acpi_sc);
|
188 break; 189 default: 190 break; /* unknown button type */ 191 } 192} 193 194static void
| 208 break; 209 default: 210 break; /* unknown button type */ 211 } 212} 213 214static void
|
195acpi_button_notify_pressed_for_wakeup(void *arg)
| 215acpi_button_notify_wakeup(void *arg)
|
196{ 197 struct acpi_button_softc *sc; 198 struct acpi_softc *acpi_sc; 199 200 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 201 202 sc = (struct acpi_button_softc *)arg; 203 acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 204 if (acpi_sc == NULL) 205 return_VOID; 206 207 acpi_UserNotify("Button", sc->button_handle, sc->button_type); 208 209 switch (sc->button_type) { 210 case ACPI_POWER_BUTTON: 211 ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n");
| 216{ 217 struct acpi_button_softc *sc; 218 struct acpi_softc *acpi_sc; 219 220 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 221 222 sc = (struct acpi_button_softc *)arg; 223 acpi_sc = acpi_device_get_parent_softc(sc->button_dev); 224 if (acpi_sc == NULL) 225 return_VOID; 226 227 acpi_UserNotify("Button", sc->button_handle, sc->button_type); 228 229 switch (sc->button_type) { 230 case ACPI_POWER_BUTTON: 231 ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n");
|
212 acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc);
| 232 acpi_event_power_button_wake(acpi_sc);
|
213 break; 214 case ACPI_SLEEP_BUTTON: 215 ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n");
| 233 break; 234 case ACPI_SLEEP_BUTTON: 235 ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n");
|
216 acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc);
| 236 acpi_event_sleep_button_wake(acpi_sc);
|
217 break; 218 default: 219 break; /* unknown button type */ 220 } 221} 222 223static void 224acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 225{ 226 struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 227 228 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 229 230 switch (notify) { 231 case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 232 AcpiOsQueueForExecution(OSD_PRIORITY_LO,
| 237 break; 238 default: 239 break; /* unknown button type */ 240 } 241} 242 243static void 244acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 245{ 246 struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 247 248 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 249 250 switch (notify) { 251 case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP: 252 AcpiOsQueueForExecution(OSD_PRIORITY_LO,
|
233 acpi_button_notify_pressed_for_sleep, sc);
| 253 acpi_button_notify_sleep, sc);
|
234 break; 235 case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 236 AcpiOsQueueForExecution(OSD_PRIORITY_LO,
| 254 break; 255 case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP: 256 AcpiOsQueueForExecution(OSD_PRIORITY_LO,
|
237 acpi_button_notify_pressed_for_wakeup, sc);
| 257 acpi_button_notify_wakeup, sc);
|
238 break; 239 default: 240 break; /* unknown notification value */ 241 } 242} 243 244static ACPI_STATUS 245acpi_button_fixed_handler(void *context) 246{ 247 struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 248 249 ACPI_FUNCTION_TRACE_PTR((char *)(uintptr_t)__func__, context); 250 251 if (context == NULL) 252 return_ACPI_STATUS (AE_BAD_PARAMETER); 253 254 acpi_button_notify_handler(sc->button_handle, 255 ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP, sc); 256 return_ACPI_STATUS (AE_OK); 257}
| 258 break; 259 default: 260 break; /* unknown notification value */ 261 } 262} 263 264static ACPI_STATUS 265acpi_button_fixed_handler(void *context) 266{ 267 struct acpi_button_softc *sc = (struct acpi_button_softc *)context; 268 269 ACPI_FUNCTION_TRACE_PTR((char *)(uintptr_t)__func__, context); 270 271 if (context == NULL) 272 return_ACPI_STATUS (AE_BAD_PARAMETER); 273 274 acpi_button_notify_handler(sc->button_handle, 275 ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP, sc); 276 return_ACPI_STATUS (AE_OK); 277}
|