acpi_acad.c revision 71872
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 71872 2001-01-31 09:30:57Z 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#define ACPI_DEVICE_CHECK_PNP		0x00
47#define ACPI_DEVICE_CHECK_EXISTENCE	0x01
48#define ACPI_POWERSOURCE_STAT_CHANGE	0x80
49
50static void acpi_acad_get_status(void * );
51static void acpi_acad_notify_handler(ACPI_HANDLE , UINT32 ,void *);
52static int acpi_acad_probe(device_t);
53static int acpi_acad_attach(device_t);
54static int acpi_acad_ioctl(u_long, caddr_t, void *);
55
56struct  acpi_acad_softc {
57	int status;
58};
59
60static void
61acpi_acad_get_status(void *context)
62{
63	device_t dev = context;
64	struct acpi_acad_softc *sc = device_get_softc(dev);
65	ACPI_HANDLE h = acpi_get_handle(dev);
66
67	if (acpi_EvaluateInteger(h, "_PSR", &sc->status) != AE_OK)
68		return;
69	device_printf(dev,"%s\n",(sc->status) ? "On Line" : "Off Line");
70}
71
72static void
73acpi_acad_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
74{
75	device_t dev = context;
76
77	device_printf(dev, "Notify %d\n", notify);
78	switch (notify) {
79	case ACPI_DEVICE_CHECK_PNP:
80	case ACPI_DEVICE_CHECK_EXISTENCE:
81	case ACPI_POWERSOURCE_STAT_CHANGE:
82		/*Temporally. It is better to notify policy manager*/
83		AcpiOsQueueForExecution(OSD_PRIORITY_LO,
84		    acpi_acad_get_status,context);
85		break;
86	default:
87		break;
88	}
89}
90
91static int
92acpi_acad_probe(device_t dev)
93{
94
95    if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) &&
96	acpi_MatchHid(dev, "ACPI0003")) {
97
98      /*
99       * Set device description
100       */
101	device_set_desc(dev, "AC adapter");
102	return(0);
103    }
104    return(ENXIO);
105}
106
107static int
108acpi_acad_attach(device_t dev)
109{
110	int	 error;
111
112	ACPI_HANDLE handle = acpi_get_handle(dev);
113	AcpiInstallNotifyHandler(handle,
114				 ACPI_DEVICE_NOTIFY,
115				 acpi_acad_notify_handler, dev);
116	/*Installing system notify is not so good*/
117	AcpiInstallNotifyHandler(handle,
118				 ACPI_SYSTEM_NOTIFY,
119				 acpi_acad_notify_handler, dev);
120
121	acpi_acad_get_status((void *)dev);
122
123	error = acpi_register_ioctl(ACPIIO_ACAD_GET_STATUS, acpi_acad_ioctl,
124	    device_get_softc(dev));
125	if (error)
126		return (error);
127
128	return(0);
129}
130
131static device_method_t acpi_acad_methods[] = {
132    /* Device interface */
133    DEVMETHOD(device_probe,	acpi_acad_probe),
134    DEVMETHOD(device_attach,	acpi_acad_attach),
135
136    {0, 0}
137};
138
139static driver_t acpi_acad_driver = {
140    "acpi_acad",
141    acpi_acad_methods,
142    sizeof(struct acpi_acad_softc),
143};
144
145static devclass_t acpi_acad_devclass;
146DRIVER_MODULE(acpi_acad,acpi,acpi_acad_driver,acpi_acad_devclass,0,0);
147
148static int
149acpi_acad_ioctl(u_long cmd, caddr_t addr, void *arg)
150{
151	struct	 acpi_acad_softc *sc;
152
153	sc = (struct acpi_acad_softc *)arg;
154	if (sc == NULL) {
155		return(ENXIO);
156	}
157
158	switch (cmd) {
159	case ACPIIO_ACAD_GET_STATUS:
160		*(int *)addr = sc->status;
161		break;
162	}
163
164	return(0);
165}
166