xref: /openbsd-src/sys/dev/acpi/acpi_apm.c (revision a74a190b711f8f8a2cc69e9cc1c5bec1009a1cb1)
1*a74a190bSjsg /* $OpenBSD: acpi_apm.c,v 1.4 2024/10/30 06:16:27 jsg Exp $ */
2c7569092Stobhe /*
3c7569092Stobhe  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
4c7569092Stobhe  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
5c7569092Stobhe  *
6c7569092Stobhe  * Permission to use, copy, modify, and distribute this software for any
7c7569092Stobhe  * purpose with or without fee is hereby granted, provided that the above
8c7569092Stobhe  * copyright notice and this permission notice appear in all copies.
9c7569092Stobhe  *
10c7569092Stobhe  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11c7569092Stobhe  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12c7569092Stobhe  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13c7569092Stobhe  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14c7569092Stobhe  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15c7569092Stobhe  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16c7569092Stobhe  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17c7569092Stobhe  */
18c7569092Stobhe 
19c7569092Stobhe #include <sys/param.h>
20c7569092Stobhe #include <sys/systm.h>
21c7569092Stobhe #include <sys/fcntl.h>
22c7569092Stobhe 
23c7569092Stobhe #include <dev/acpi/acpireg.h>
24c7569092Stobhe #include <dev/acpi/acpivar.h>
25c7569092Stobhe #include <dev/acpi/acpidev.h>
26c7569092Stobhe #include <dev/acpi/dsdt.h>
27c7569092Stobhe 
28c7569092Stobhe #include <machine/conf.h>
29c7569092Stobhe #include <machine/cpufunc.h>
30c7569092Stobhe 
31c7569092Stobhe #ifdef HIBERNATE
32c7569092Stobhe #include <sys/hibernate.h>
33c7569092Stobhe #endif
34c7569092Stobhe 
35c7569092Stobhe #include <machine/apmvar.h>
36c7569092Stobhe #define APMUNIT(dev)	(minor(dev)&0xf0)
37c7569092Stobhe #define APMDEV(dev)	(minor(dev)&0x0f)
38c7569092Stobhe #define APMDEV_NORMAL	0
39c7569092Stobhe #define APMDEV_CTL	8
40c7569092Stobhe 
41c7569092Stobhe #ifndef SMALL_KERNEL
42c7569092Stobhe 
43c7569092Stobhe int
44c7569092Stobhe acpiopen(dev_t dev, int flag, int mode, struct proc *p)
45c7569092Stobhe {
46c7569092Stobhe 	int error = 0;
47c7569092Stobhe 	struct acpi_softc *sc = acpi_softc;
48c7569092Stobhe 	int s;
49c7569092Stobhe 
50a3c01fdfStobhe 	if (sc == NULL)
51a3c01fdfStobhe 		return (ENXIO);
52a3c01fdfStobhe 
53c7569092Stobhe 	s = splbio();
54c7569092Stobhe 	switch (APMDEV(dev)) {
55c7569092Stobhe 	case APMDEV_CTL:
56c7569092Stobhe 		if (!(flag & FWRITE)) {
57c7569092Stobhe 			error = EINVAL;
58c7569092Stobhe 			break;
59c7569092Stobhe 		}
60c7569092Stobhe 		if (sc->sc_flags & SCFLAG_OWRITE) {
61c7569092Stobhe 			error = EBUSY;
62c7569092Stobhe 			break;
63c7569092Stobhe 		}
64c7569092Stobhe 		sc->sc_flags |= SCFLAG_OWRITE;
65c7569092Stobhe 		break;
66c7569092Stobhe 	case APMDEV_NORMAL:
67c7569092Stobhe 		if (!(flag & FREAD) || (flag & FWRITE)) {
68c7569092Stobhe 			error = EINVAL;
69c7569092Stobhe 			break;
70c7569092Stobhe 		}
71c7569092Stobhe 		sc->sc_flags |= SCFLAG_OREAD;
72c7569092Stobhe 		break;
73c7569092Stobhe 	default:
74c7569092Stobhe 		error = ENXIO;
75c7569092Stobhe 		break;
76c7569092Stobhe 	}
77c7569092Stobhe 	splx(s);
78c7569092Stobhe 	return (error);
79c7569092Stobhe }
80c7569092Stobhe 
81c7569092Stobhe int
82c7569092Stobhe acpiclose(dev_t dev, int flag, int mode, struct proc *p)
83c7569092Stobhe {
84c7569092Stobhe 	int error = 0;
85c7569092Stobhe 	struct acpi_softc *sc = acpi_softc;
86c7569092Stobhe 	int s;
87c7569092Stobhe 
88a3c01fdfStobhe 	if (sc == NULL)
89a3c01fdfStobhe 		return (ENXIO);
90a3c01fdfStobhe 
91c7569092Stobhe 	s = splbio();
92c7569092Stobhe 	switch (APMDEV(dev)) {
93c7569092Stobhe 	case APMDEV_CTL:
94c7569092Stobhe 		sc->sc_flags &= ~SCFLAG_OWRITE;
95c7569092Stobhe 		break;
96c7569092Stobhe 	case APMDEV_NORMAL:
97c7569092Stobhe 		sc->sc_flags &= ~SCFLAG_OREAD;
98c7569092Stobhe 		break;
99c7569092Stobhe 	default:
100c7569092Stobhe 		error = ENXIO;
101c7569092Stobhe 		break;
102c7569092Stobhe 	}
103c7569092Stobhe 	splx(s);
104c7569092Stobhe 	return (error);
105c7569092Stobhe }
106c7569092Stobhe 
107c7569092Stobhe int
108c7569092Stobhe acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
109c7569092Stobhe {
110c7569092Stobhe 	int error = 0;
111c7569092Stobhe 	struct acpi_softc *sc = acpi_softc;
112c7569092Stobhe 	struct apm_power_info *pi = (struct apm_power_info *)data;
113c7569092Stobhe 	int s;
114c7569092Stobhe 
115a3c01fdfStobhe 	if (sc == NULL)
116a3c01fdfStobhe 		return (ENXIO);
117a3c01fdfStobhe 
118c7569092Stobhe 	s = splbio();
119c7569092Stobhe 	/* fake APM */
120c7569092Stobhe 	switch (cmd) {
1218cae9a59Stobhe #ifdef SUSPEND
122c7569092Stobhe 	case APM_IOC_SUSPEND:
123c7569092Stobhe 	case APM_IOC_STANDBY:
124c7569092Stobhe 		if ((flag & FWRITE) == 0) {
125c7569092Stobhe 			error = EBADF;
126c7569092Stobhe 			break;
127c7569092Stobhe 		}
1288cae9a59Stobhe 		error = request_sleep(SLEEP_SUSPEND);
1298cae9a59Stobhe 		if (error)
1308cae9a59Stobhe 			break;
131c7569092Stobhe 		acpi_wakeup(sc);
132c7569092Stobhe 		break;
133c7569092Stobhe #ifdef HIBERNATE
134c7569092Stobhe 	case APM_IOC_HIBERNATE:
135c7569092Stobhe 		if ((error = suser(p)) != 0)
136c7569092Stobhe 			break;
137c7569092Stobhe 		if ((flag & FWRITE) == 0) {
138c7569092Stobhe 			error = EBADF;
139c7569092Stobhe 			break;
140c7569092Stobhe 		}
141*a74a190bSjsg 		if (get_hibernate_io_function(swdevt[0]) == NULL) {
142c7569092Stobhe 			error = EOPNOTSUPP;
143c7569092Stobhe 			break;
144c7569092Stobhe 		}
1458cae9a59Stobhe 		error = request_sleep(SLEEP_HIBERNATE);
1468cae9a59Stobhe 		if (error)
1478cae9a59Stobhe 			break;
148c7569092Stobhe 		acpi_wakeup(sc);
149c7569092Stobhe 		break;
150c7569092Stobhe #endif
1518cae9a59Stobhe #endif
152c7569092Stobhe 	case APM_IOC_GETPOWER:
153c7569092Stobhe 		error = acpi_apminfo(pi);
154c7569092Stobhe 		break;
155c7569092Stobhe 
156c7569092Stobhe 	default:
157c7569092Stobhe 		error = ENOTTY;
158c7569092Stobhe 	}
159c7569092Stobhe 
160c7569092Stobhe 	splx(s);
161c7569092Stobhe 	return (error);
162c7569092Stobhe }
163c7569092Stobhe 
164c7569092Stobhe void	acpi_filtdetach(struct knote *);
165c7569092Stobhe int	acpi_filtread(struct knote *, long);
166c7569092Stobhe 
167c7569092Stobhe const struct filterops acpiread_filtops = {
168c7569092Stobhe 	.f_flags	= FILTEROP_ISFD,
169c7569092Stobhe 	.f_attach	= NULL,
170c7569092Stobhe 	.f_detach	= acpi_filtdetach,
171c7569092Stobhe 	.f_event	= acpi_filtread,
172c7569092Stobhe };
173c7569092Stobhe 
174c7569092Stobhe int
175c7569092Stobhe acpikqfilter(dev_t dev, struct knote *kn)
176c7569092Stobhe {
177c7569092Stobhe 	struct acpi_softc *sc = acpi_softc;
178c7569092Stobhe 	int s;
179c7569092Stobhe 
180a3c01fdfStobhe 	if (sc == NULL)
181a3c01fdfStobhe 		return (ENXIO);
182a3c01fdfStobhe 
183c7569092Stobhe 	switch (kn->kn_filter) {
184c7569092Stobhe 	case EVFILT_READ:
185c7569092Stobhe 		kn->kn_fop = &acpiread_filtops;
186c7569092Stobhe 		break;
187c7569092Stobhe 	default:
188c7569092Stobhe 		return (EINVAL);
189c7569092Stobhe 	}
190c7569092Stobhe 
191c7569092Stobhe 	kn->kn_hook = sc;
192c7569092Stobhe 
193c7569092Stobhe 	s = splbio();
194c7569092Stobhe 	klist_insert_locked(&sc->sc_note, kn);
195c7569092Stobhe 	splx(s);
196c7569092Stobhe 
197c7569092Stobhe 	return (0);
198c7569092Stobhe }
199c7569092Stobhe 
200c7569092Stobhe void
201c7569092Stobhe acpi_filtdetach(struct knote *kn)
202c7569092Stobhe {
203c7569092Stobhe 	struct acpi_softc *sc = kn->kn_hook;
204c7569092Stobhe 	int s;
205c7569092Stobhe 
206c7569092Stobhe 	s = splbio();
207c7569092Stobhe 	klist_remove_locked(&sc->sc_note, kn);
208c7569092Stobhe 	splx(s);
209c7569092Stobhe }
210c7569092Stobhe 
211c7569092Stobhe int
212c7569092Stobhe acpi_filtread(struct knote *kn, long hint)
213c7569092Stobhe {
214c7569092Stobhe 	/* XXX weird kqueue_scan() semantics */
215c7569092Stobhe 	if (hint && !kn->kn_data)
216c7569092Stobhe 		kn->kn_data = hint;
217c7569092Stobhe 	return (1);
218c7569092Stobhe }
219c7569092Stobhe 
2208cae9a59Stobhe #ifdef SUSPEND
2218cae9a59Stobhe int
2228cae9a59Stobhe request_sleep(int sleepmode)
2238cae9a59Stobhe {
2248cae9a59Stobhe 	struct acpi_softc *sc = acpi_softc;
2258cae9a59Stobhe 
2268cae9a59Stobhe #ifdef HIBERNATE
2278cae9a59Stobhe 	if (sleepmode == SLEEP_HIBERNATE) {
228*a74a190bSjsg 		if (get_hibernate_io_function(swdevt[0]) == NULL)
2298cae9a59Stobhe 			return EOPNOTSUPP;
2308cae9a59Stobhe 	}
2318cae9a59Stobhe #endif
2328cae9a59Stobhe 	acpi_addtask(sc, acpi_sleep_task, sc, sleepmode);
2338cae9a59Stobhe 	return 0;
2348cae9a59Stobhe }
2358cae9a59Stobhe #endif /* SUSPEND */
2368cae9a59Stobhe 
237c7569092Stobhe #else /* SMALL_KERNEL */
238c7569092Stobhe 
239c7569092Stobhe int
240c7569092Stobhe acpiopen(dev_t dev, int flag, int mode, struct proc *p)
241c7569092Stobhe {
242c7569092Stobhe 	return (ENXIO);
243c7569092Stobhe }
244c7569092Stobhe 
245c7569092Stobhe int
246c7569092Stobhe acpiclose(dev_t dev, int flag, int mode, struct proc *p)
247c7569092Stobhe {
248c7569092Stobhe 	return (ENXIO);
249c7569092Stobhe }
250c7569092Stobhe 
251c7569092Stobhe int
252c7569092Stobhe acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
253c7569092Stobhe {
254c7569092Stobhe 	return (ENXIO);
255c7569092Stobhe }
256c7569092Stobhe 
257c7569092Stobhe int
258c7569092Stobhe acpikqfilter(dev_t dev, struct knote *kn)
259c7569092Stobhe {
260c7569092Stobhe 	return (EOPNOTSUPP);
261c7569092Stobhe }
262c7569092Stobhe 
263c7569092Stobhe #endif /* SMALL_KERNEL */
264