acpi_acad.c revision 77432
1/*-
2 * Copyright (c) 2000 Takanori Watanabe
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/acpica/acpi_acad.c 77432 2001-05-29 20:13:42Z msmith $
27 */
28
29#include "opt_acpi.h"
30#include <sys/param.h>
31#include <sys/kernel.h>
32#include <sys/bus.h>
33
34#include <machine/bus.h>
35#include <machine/resource.h>
36#include <sys/rman.h>
37#include <sys/ioccom.h>
38#include <sys/malloc.h>
39#include <sys/conf.h>
40
41#include  "acpi.h"
42#include <dev/acpica/acpivar.h>
43#include <dev/acpica/acpiio.h>
44
45/*
46 * Hooks for the ACPI CA debugging infrastructure
47 */
48#define _COMPONENT	ACPI_AC_ADAPTER
49MODULE_NAME("AC_ADAPTER")
50
51#define ACPI_DEVICE_CHECK_PNP		0x00
52#define ACPI_DEVICE_CHECK_EXISTENCE	0x01
53#define ACPI_POWERSOURCE_STAT_CHANGE	0x80
54
55static void acpi_acad_get_status(void * );
56static void acpi_acad_notify_handler(ACPI_HANDLE , UINT32 ,void *);
57static int acpi_acad_probe(device_t);
58static int acpi_acad_attach(device_t);
59static int acpi_acad_ioctl(u_long, caddr_t, void *);
60
61struct  acpi_acad_softc {
62	int status;
63};
64
65static void
66acpi_acad_get_status(void *context)
67{
68	device_t dev = context;
69	struct acpi_acad_softc *sc = device_get_softc(dev);
70	ACPI_HANDLE h = acpi_get_handle(dev);
71
72	if (acpi_EvaluateInteger(h, "_PSR", &sc->status) != AE_OK)
73		return;
74	device_printf(dev,"%s\n",(sc->status) ? "On Line" : "Off Line");
75}
76
77static void
78acpi_acad_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
79{
80	device_t dev = context;
81
82	device_printf(dev, "Notify %d\n", notify);
83	switch (notify) {
84	case ACPI_DEVICE_CHECK_PNP:
85	case ACPI_DEVICE_CHECK_EXISTENCE:
86	case ACPI_POWERSOURCE_STAT_CHANGE:
87		/*Temporally. It is better to notify policy manager*/
88		AcpiOsQueueForExecution(OSD_PRIORITY_LO,
89		    acpi_acad_get_status,context);
90		break;
91	default:
92		break;
93	}
94}
95
96static int
97acpi_acad_probe(device_t dev)
98{
99
100    if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) &&
101	acpi_MatchHid(dev, "ACPI0003")) {
102
103      /*
104       * Set device description
105       */
106	device_set_desc(dev, "AC adapter");
107	return(0);
108    }
109    return(ENXIO);
110}
111
112static int
113acpi_acad_attach(device_t dev)
114{
115	int	 error;
116
117	ACPI_HANDLE handle = acpi_get_handle(dev);
118	AcpiInstallNotifyHandler(handle,
119				 ACPI_DEVICE_NOTIFY,
120				 acpi_acad_notify_handler, dev);
121	/*Installing system notify is not so good*/
122	AcpiInstallNotifyHandler(handle,
123				 ACPI_SYSTEM_NOTIFY,
124				 acpi_acad_notify_handler, dev);
125
126	acpi_acad_get_status((void *)dev);
127
128	error = acpi_register_ioctl(ACPIIO_ACAD_GET_STATUS, acpi_acad_ioctl,
129	    device_get_softc(dev));
130	if (error)
131		return (error);
132
133	return(0);
134}
135
136static device_method_t acpi_acad_methods[] = {
137    /* Device interface */
138    DEVMETHOD(device_probe,	acpi_acad_probe),
139    DEVMETHOD(device_attach,	acpi_acad_attach),
140
141    {0, 0}
142};
143
144static driver_t acpi_acad_driver = {
145    "acpi_acad",
146    acpi_acad_methods,
147    sizeof(struct acpi_acad_softc),
148};
149
150static devclass_t acpi_acad_devclass;
151DRIVER_MODULE(acpi_acad,acpi,acpi_acad_driver,acpi_acad_devclass,0,0);
152
153static int
154acpi_acad_ioctl(u_long cmd, caddr_t addr, void *arg)
155{
156	struct	 acpi_acad_softc *sc;
157
158	sc = (struct acpi_acad_softc *)arg;
159	if (sc == NULL) {
160		return(ENXIO);
161	}
162
163	switch (cmd) {
164	case ACPIIO_ACAD_GET_STATUS:
165		*(int *)addr = sc->status;
166		break;
167	}
168
169	return(0);
170}
171