xref: /freebsd/sys/dev/acpica/acpi_acad.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
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$
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
49 MODULE_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 
55 static void acpi_acad_get_status(void * );
56 static void acpi_acad_notify_handler(ACPI_HANDLE , UINT32 ,void *);
57 static int acpi_acad_probe(device_t);
58 static int acpi_acad_attach(device_t);
59 static int acpi_acad_ioctl(u_long, caddr_t, void *);
60 static int acpi_acad_sysctl(SYSCTL_HANDLER_ARGS);
61 
62 struct  acpi_acad_softc {
63 	int status;
64 };
65 
66 static void
67 acpi_acad_get_status(void *context)
68 {
69 	device_t dev = context;
70 	struct acpi_acad_softc *sc = device_get_softc(dev);
71 	ACPI_HANDLE h = acpi_get_handle(dev);
72 
73 	if (acpi_EvaluateInteger(h, "_PSR", &sc->status) != AE_OK) {
74 		sc->status = -1;
75 		return;
76 	}
77 
78 	if (bootverbose) {
79 		device_printf(dev,"%s\n",(sc->status) ? "On Line" : "Off Line");
80 	}
81 }
82 
83 static void
84 acpi_acad_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
85 {
86 	device_t dev = context;
87 
88 	if (bootverbose) {
89 		device_printf(dev, "Notify %d\n", notify);
90 	}
91 
92 	switch (notify) {
93 	case ACPI_DEVICE_CHECK_PNP:
94 	case ACPI_DEVICE_CHECK_EXISTENCE:
95 	case ACPI_POWERSOURCE_STAT_CHANGE:
96 		/*Temporally. It is better to notify policy manager*/
97 		AcpiOsQueueForExecution(OSD_PRIORITY_LO,
98 		    acpi_acad_get_status,context);
99 		break;
100 	default:
101 		break;
102 	}
103 }
104 
105 static int
106 acpi_acad_probe(device_t dev)
107 {
108 
109     if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) &&
110 	acpi_MatchHid(dev, "ACPI0003")) {
111 
112       /*
113        * Set device description
114        */
115 	device_set_desc(dev, "AC adapter");
116 	return(0);
117     }
118     return(ENXIO);
119 }
120 
121 static int
122 acpi_acad_attach(device_t dev)
123 {
124 	int	 error;
125 	struct acpi_acad_softc	*sc;
126 	struct acpi_softc	*acpi_sc;
127 
128 	ACPI_HANDLE handle = acpi_get_handle(dev);
129 	AcpiInstallNotifyHandler(handle,
130 				 ACPI_DEVICE_NOTIFY,
131 				 acpi_acad_notify_handler, dev);
132 	/*Installing system notify is not so good*/
133 	AcpiInstallNotifyHandler(handle,
134 				 ACPI_SYSTEM_NOTIFY,
135 				 acpi_acad_notify_handler, dev);
136 
137 	if ((sc = device_get_softc(dev)) == NULL) {
138 		return (ENXIO);
139 	}
140 	if ((error = acpi_register_ioctl(ACPIIO_ACAD_GET_STATUS,
141 			acpi_acad_ioctl, dev)) != 0) {
142 		return (error);
143 	}
144 
145 	if (device_get_unit(dev) == 0) {
146 		acpi_sc = acpi_device_get_parent_softc(dev);
147 		SYSCTL_ADD_PROC(&acpi_sc->acpi_sysctl_ctx,
148 			SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
149 			OID_AUTO, "acline", CTLTYPE_INT | CTLFLAG_RD,
150 			&sc->status, 0, acpi_acad_sysctl, "I", "");
151 	}
152 
153 	return(0);
154 }
155 
156 static device_method_t acpi_acad_methods[] = {
157     /* Device interface */
158     DEVMETHOD(device_probe,	acpi_acad_probe),
159     DEVMETHOD(device_attach,	acpi_acad_attach),
160 
161     {0, 0}
162 };
163 
164 static driver_t acpi_acad_driver = {
165     "acpi_acad",
166     acpi_acad_methods,
167     sizeof(struct acpi_acad_softc),
168 };
169 
170 static devclass_t acpi_acad_devclass;
171 DRIVER_MODULE(acpi_acad,acpi,acpi_acad_driver,acpi_acad_devclass,0,0);
172 
173 static int
174 acpi_acad_ioctl(u_long cmd, caddr_t addr, void *arg)
175 {
176 	device_t		 dev;
177 	struct acpi_acad_softc	*sc;
178 
179 	dev = (device_t)arg;
180 	if ((sc = device_get_softc(dev)) == NULL) {
181 		return(ENXIO);
182 	}
183 
184 	switch (cmd) {
185 	case ACPIIO_ACAD_GET_STATUS:
186 		acpi_acad_get_status(dev);
187 		*(int *)addr = sc->status;
188 		break;
189 	}
190 
191 	return(0);
192 }
193 
194 static int
195 acpi_acad_sysctl(SYSCTL_HANDLER_ARGS)
196 {
197 	int     val;
198 	int     error;
199 	device_t	dev;
200 	struct acpi_acad_softc	*sc;
201 
202 	if ((dev = devclass_get_device(acpi_acad_devclass, 0)) == NULL) {
203 		return (ENXIO);
204 	}
205 	if ((sc = device_get_softc(dev)) == NULL) {
206 		return (ENXIO);
207 	}
208 	acpi_acad_get_status(dev);
209 	val = *(u_int *)oidp->oid_arg1;
210 	error = sysctl_handle_int(oidp, &val, 0, req);
211 	return (error);
212 }
213 
214