Device layer rollup commit.
[dragonfly.git] / sys / platform / pc32 / acpica / acpi_machdep.c
CommitLineData
bf3e6b54
DR
1/*-
2 * Copyright (c) 2001 Mitsuru IWASAKI
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.
e4c9c0c8 25 * $DragonFly: src/sys/platform/pc32/acpica/Attic/acpi_machdep.c,v 1.3 2004/05/19 22:52:56 dillon Exp $
bf3e6b54
DR
26 */
27
28#include <sys/cdefs.h>
29
30#include <sys/param.h>
31#include <sys/bus.h>
32#include <sys/conf.h>
33#include <sys/fcntl.h>
34#include <sys/uio.h>
35
36#include "acpi.h"
37
38#include <dev/acpica/acpivar.h>
39#include <dev/acpica/acpiio.h>
40
41static device_t acpi_dev;
42
43/*
44 * APM driver emulation
45 */
46
3c4d4a21 47#if defined(__DragonFly__) || __FreeBSD_version < 500000
bf3e6b54
DR
48#include <sys/select.h>
49#else
50#include <sys/selinfo.h>
51#endif
52
53#include <machine/apm_bios.h>
54#include <machine/pc/bios.h>
55
3c4d4a21 56#if defined(__DragonFly__) || __FreeBSD_version < 500000
bf3e6b54
DR
57#include <i386/apm/apm.h>
58#else
59#include <i386/bios/apm.h>
60#endif
61
62static struct apm_softc apm_softc;
63
64static d_open_t apmopen;
65static d_close_t apmclose;
66static d_write_t apmwrite;
67static d_ioctl_t apmioctl;
68static d_poll_t apmpoll;
69
70#define CDEV_MAJOR 39
71static struct cdevsw apm_cdevsw = {
72
73/**
74 .d_open = apmopen,
75 .d_close = apmclose,
76 .d_write = apmwrite,
77 .d_ioctl = apmioctl,
78
79 .d_poll = apmpoll,
80*/
81 .d_name = "apm",
82 .d_maj = CDEV_MAJOR,
83
84};
85
86static int
87acpi_capm_convert_battstate(struct acpi_battinfo *battp)
88{
89 int state;
90
91 state = 0xff; /* XXX unknown */
92
93 if (battp->state & ACPI_BATT_STAT_DISCHARG) {
94 if (battp->cap >= 50) {
95 state = 0; /* high */
96 } else {
97 state = 1; /* low */
98 }
99 }
100 if (battp->state & ACPI_BATT_STAT_CRITICAL) {
101 state = 2; /* critical */
102 }
103 if (battp->state & ACPI_BATT_STAT_CHARGING) {
104 state = 3; /* charging */
105 }
106 return (state);
107}
108
109static int
110acpi_capm_convert_battflags(struct acpi_battinfo *battp)
111{
112 int flags;
113
114 flags = 0;
115
116 if (battp->cap >= 50) {
117 flags |= APM_BATT_HIGH;
118 } else {
119 if (battp->state & ACPI_BATT_STAT_CRITICAL) {
120 flags |= APM_BATT_CRITICAL;
121 } else {
122 flags |= APM_BATT_LOW;
123 }
124 }
125 if (battp->state & ACPI_BATT_STAT_CHARGING) {
126 flags |= APM_BATT_CHARGING;
127 }
128 if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) {
129 flags = APM_BATT_NOT_PRESENT;
130 }
131
132 return (flags);
133}
134
135static int
136acpi_capm_get_info(apm_info_t aip)
137{
138 int acline;
139 struct acpi_battinfo batt;
140
141 aip->ai_infoversion = 1;
142 aip->ai_major = 1;
143 aip->ai_minor = 2;
144 aip->ai_status = apm_softc.active;
145 aip->ai_capabilities= 0xff00; /* XXX unknown */
146
147 if (acpi_acad_get_acline(&acline)) {
148 aip->ai_acline = 0xff; /* unknown */
149 } else {
150 aip->ai_acline = acline; /* on/off */
151 }
152
153 if (acpi_battery_get_battinfo(-1, &batt)) {
154 aip->ai_batt_stat = 0xff; /* unknown */
155 aip->ai_batt_life = 0xff; /* unknown */
156 aip->ai_batt_time = -1; /* unknown */
157 aip->ai_batteries = 0;
158 } else {
159 aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
160 aip->ai_batt_life = batt.cap;
161 aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
162 aip->ai_batteries = acpi_battery_get_units();
163 }
164
165 return (0);
166}
167
168static int
169acpi_capm_get_pwstatus(apm_pwstatus_t app)
170{
171 int batt_unit;
172 int acline;
173 struct acpi_battinfo batt;
174
175 if (app->ap_device != PMDV_ALLDEV &&
176 (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) {
177 return (1);
178 }
179
180 if (app->ap_device == PMDV_ALLDEV) {
181 batt_unit = -1; /* all units */
182 } else {
183 batt_unit = app->ap_device - PMDV_BATT0;
184 }
185
186 if (acpi_battery_get_battinfo(batt_unit, &batt)) {
187 return (1);
188 }
189
190 app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
191 app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
192 app->ap_batt_life = batt.cap;
193 app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
194
195 if (acpi_acad_get_acline(&acline)) {
196 app->ap_acline = 0xff; /* unknown */
197 } else {
198 app->ap_acline = acline; /* on/off */
199 }
200
201 return (0);
202}
203
204static int
205apmopen(dev_t dev, int flag, int fmt, d_thread_t *td)
206{
207 return (0);
208}
209
210static int
211apmclose(dev_t dev, int flag, int fmt, d_thread_t *td)
212{
213 return (0);
214}
215
216static int
217apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
218{
219 int error = 0;
220 struct acpi_softc *acpi_sc;
221 struct apm_info info;
222 apm_info_old_t aiop;
223
224 if ((acpi_sc = device_get_softc(acpi_dev)) == NULL) {
225 return (ENXIO);
226 }
227
228 switch (cmd) {
229 case APMIO_SUSPEND:
230 if (!(flag & FWRITE))
231 return (EPERM);
232 if (apm_softc.active)
233 acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
234 else
235 error = EINVAL;
236 break;
237
238 case APMIO_STANDBY:
239 if (!(flag & FWRITE))
240 return (EPERM);
241 if (apm_softc.active)
242 acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
243 else
244 error = EINVAL;
245 break;
246
247 case APMIO_GETINFO_OLD:
248 if (acpi_capm_get_info(&info))
249 error = ENXIO;
250 aiop = (apm_info_old_t)addr;
251 aiop->ai_major = info.ai_major;
252 aiop->ai_minor = info.ai_minor;
253 aiop->ai_acline = info.ai_acline;
254 aiop->ai_batt_stat = info.ai_batt_stat;
255 aiop->ai_batt_life = info.ai_batt_life;
256 aiop->ai_status = info.ai_status;
257 break;
258
259 case APMIO_GETINFO:
260 if (acpi_capm_get_info((apm_info_t)addr))
261 error = ENXIO;
262
263 break;
264
265 case APMIO_GETPWSTATUS:
266 if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
267 error = ENXIO;
268 break;
269
270 case APMIO_ENABLE:
271 if (!(flag & FWRITE))
272 return (EPERM);
273 apm_softc.active = 1;
274 break;
275
276 case APMIO_DISABLE:
277 if (!(flag & FWRITE))
278 return (EPERM);
279 apm_softc.active = 0;
280 break;
281
282 case APMIO_HALTCPU:
283 break;
284
285 case APMIO_NOTHALTCPU:
286 break;
287
288 case APMIO_DISPLAY:
289 if (!(flag & FWRITE))
290 return (EPERM);
291 break;
292
293 case APMIO_BIOS:
294 if (!(flag & FWRITE))
295 return (EPERM);
296 bzero(addr, sizeof(struct apm_bios_arg));
297 break;
298
299 default:
300 error = EINVAL;
301 break;
302 }
303
304 return (error);
305}
306
307static int
308apmwrite(dev_t dev, struct uio *uio, int ioflag)
309{
310
311 return (uio->uio_resid);
312}
313
314static int
315apmpoll(dev_t dev, int events, d_thread_t *td)
316{
317 return (0);
318}
319
320static void
321acpi_capm_init(struct acpi_softc *sc)
322{
e4c9c0c8 323 cdevsw_add(&apm_cdevsw, 0, 0);
bf3e6b54
DR
324 make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
325}
326
327int
328acpi_machdep_init(device_t dev)
329{
330 struct acpi_softc *sc;
331
332 acpi_dev = dev;
333 if ((sc = device_get_softc(acpi_dev)) == NULL) {
334 return (ENXIO);
335 }
336
337 /*
338 * XXX: Prevent the PnP BIOS code from interfering with
339 * our own scan of ISA devices.
340 */
341 PnPBIOStable = NULL;
342
343 acpi_capm_init(sc);
344
345 acpi_install_wakeup_handler(sc);
346
347#ifdef SMP
348 acpi_SetIntrModel(ACPI_INTR_APIC);
349#endif
350 return (0);
351}
352