acpi_button.c revision 89054
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 89054 2002-01-08 06:46:01Z 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
7489054Smsmithstatic devclass_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) {
11480078Smsmith	device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", AcpiFormatException(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:
13686552Siwasaki	ACPI_VPRINT(sc->button_dev, acpi_sc,
13786552Siwasaki	    "power button pressed\n", sc->button_type);
13867761Smsmith	acpi_eventhandler_power_button_for_sleep((void *)acpi_sc);
13967761Smsmith	break;
14067761Smsmith    case ACPI_SLEEP_BUTTON:
14186552Siwasaki	ACPI_VPRINT(sc->button_dev, acpi_sc,
14286552Siwasaki	    "sleep button pressed\n", sc->button_type);
14367761Smsmith	acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc);
14467761Smsmith	break;
14567761Smsmith    default:
14669744Smsmith	break;		/* unknown button type */
14767761Smsmith    }
14869744Smsmith    return_VOID;
14967761Smsmith}
15067761Smsmith
15167761Smsmithstatic void
15267761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg)
15367761Smsmith{
15467761Smsmith    struct acpi_button_softc	*sc;
15567761Smsmith    struct acpi_softc		*acpi_sc;
15667761Smsmith
15777432Smsmith    FUNCTION_TRACE(__func__);
15869744Smsmith
15967761Smsmith    sc = (struct acpi_button_softc *)arg;
16067761Smsmith    acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
16167761Smsmith    if (acpi_sc == NULL) {
16269744Smsmith	return_VOID;
16367761Smsmith    }
16467761Smsmith
16567761Smsmith    switch (sc->button_type) {
16667761Smsmith    case ACPI_POWER_BUTTON:
16786552Siwasaki	ACPI_VPRINT(sc->button_dev, acpi_sc,
16886552Siwasaki	    "wakeup by power button\n", sc->button_type);
16967761Smsmith	acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc);
17067761Smsmith	break;
17167761Smsmith    case ACPI_SLEEP_BUTTON:
17286552Siwasaki	ACPI_VPRINT(sc->button_dev, acpi_sc,
17386552Siwasaki	    "wakeup by sleep button\n", sc->button_type);
17467761Smsmith	acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc);
17567761Smsmith	break;
17667761Smsmith    default:
17769744Smsmith	break;		/* unknown button type */
17867761Smsmith    }
17969744Smsmith    return_VOID;
18067761Smsmith}
18167761Smsmith
18267761Smsmith/* XXX maybe not here */
18367761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP	0x80
18467761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP	0x02
18567761Smsmith
18667761Smsmithstatic void
18767761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
18867761Smsmith{
18967761Smsmith    struct acpi_button_softc	*sc = (struct acpi_button_softc *)context;
19067761Smsmith
19177432Smsmith    FUNCTION_TRACE_U32(__func__, notify);
19269744Smsmith
19367761Smsmith    switch (notify) {
19467761Smsmith    case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP:
19567761Smsmith	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc);
19667761Smsmith	break;
19767761Smsmith    case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP:
19867761Smsmith	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc);
19967761Smsmith	break;
20067761Smsmith    default:
20169744Smsmith	break;		/* unknown notification value */
20267761Smsmith    }
20369744Smsmith    return_VOID;
20467761Smsmith}
20567761Smsmith
20667761Smsmith
207