acpi_apm.c revision 225177
185556Siwasaki/*-
285556Siwasaki * Copyright (c) 2001 Mitsuru IWASAKI
385556Siwasaki * All rights reserved.
485556Siwasaki *
585556Siwasaki * Redistribution and use in source and binary forms, with or without
685556Siwasaki * modification, are permitted provided that the following conditions
785556Siwasaki * are met:
885556Siwasaki * 1. Redistributions of source code must retain the above copyright
985556Siwasaki *    notice, this list of conditions and the following disclaimer.
1085556Siwasaki * 2. Redistributions in binary form must reproduce the above copyright
1185556Siwasaki *    notice, this list of conditions and the following disclaimer in the
1285556Siwasaki *    documentation and/or other materials provided with the distribution.
1385556Siwasaki *
1485556Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1585556Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1685556Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1785556Siwasaki * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1885556Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1985556Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2085556Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2185556Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2285556Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2385556Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2485556Siwasaki * SUCH DAMAGE.
2585556Siwasaki */
2685556Siwasaki
27115681Sobrien#include <sys/cdefs.h>
28115681Sobrien__FBSDID("$FreeBSD: head/sys/x86/acpica/acpi_apm.c 225177 2011-08-25 15:51:54Z attilio $");
29115681Sobrien
3085556Siwasaki#include <sys/param.h>
3185556Siwasaki#include <sys/bus.h>
32168191Sjhb#include <sys/condvar.h>
3385556Siwasaki#include <sys/conf.h>
3485556Siwasaki#include <sys/fcntl.h>
35215097Sjkim#include <sys/kernel.h>
36170976Snjl#include <sys/malloc.h>
37170976Snjl#include <sys/poll.h>
3885556Siwasaki#include <sys/uio.h>
3985556Siwasaki
40193530Sjkim#include <contrib/dev/acpica/include/acpi.h>
41193530Sjkim
4285556Siwasaki#include <dev/acpica/acpivar.h>
4385556Siwasaki#include <dev/acpica/acpiio.h>
4485556Siwasaki
45215072Sjkim#include <machine/apm_bios.h>
46177157Sjhb
4785556Siwasaki/*
4885556Siwasaki * APM driver emulation
4985556Siwasaki */
5085556Siwasaki
51215072Sjkim#define	APM_UNKNOWN	0xff
5285556Siwasaki
53132619Snjlstatic int apm_active;
54170976Snjlstatic struct clonedevs *apm_clones;
5585556Siwasaki
56170976SnjlMALLOC_DEFINE(M_APMDEV, "apmdev", "APM device emulation");
5785556Siwasaki
58170976Snjlstatic d_open_t		apmopen;
59170976Snjlstatic d_close_t	apmclose;
60170976Snjlstatic d_write_t	apmwrite;
61170976Snjlstatic d_ioctl_t	apmioctl;
62170976Snjlstatic d_poll_t		apmpoll;
63170976Snjlstatic d_kqfilter_t	apmkqfilter;
64170976Snjlstatic void		apmreadfiltdetach(struct knote *kn);
65170976Snjlstatic int		apmreadfilt(struct knote *kn, long hint);
66197134Srwatsonstatic struct filterops	apm_readfiltops = {
67197134Srwatson	.f_isfd = 1,
68197134Srwatson	.f_detach = apmreadfiltdetach,
69197134Srwatson	.f_event = apmreadfilt,
70197134Srwatson};
71170976Snjl
7285556Siwasakistatic struct cdevsw apm_cdevsw = {
73126080Sphk	.d_version =	D_VERSION,
74179726Sed	.d_flags =	D_TRACKCLOSE | D_NEEDMINOR,
75111815Sphk	.d_open =	apmopen,
76111815Sphk	.d_close =	apmclose,
77111815Sphk	.d_write =	apmwrite,
78111815Sphk	.d_ioctl =	apmioctl,
79111815Sphk	.d_poll =	apmpoll,
80111815Sphk	.d_name =	"apm",
81170976Snjl	.d_kqfilter =	apmkqfilter
8285556Siwasaki};
8385556Siwasaki
8485556Siwasakistatic int
8585556Siwasakiacpi_capm_convert_battstate(struct  acpi_battinfo *battp)
8685556Siwasaki{
8785556Siwasaki	int	state;
8885556Siwasaki
89131218Simp	state = APM_UNKNOWN;
9085556Siwasaki
9185556Siwasaki	if (battp->state & ACPI_BATT_STAT_DISCHARG) {
92119530Snjl		if (battp->cap >= 50)
9385556Siwasaki			state = 0;	/* high */
94119530Snjl		else
9585556Siwasaki			state = 1;	/* low */
9685556Siwasaki	}
97119530Snjl	if (battp->state & ACPI_BATT_STAT_CRITICAL)
9885556Siwasaki		state = 2;		/* critical */
99119530Snjl	if (battp->state & ACPI_BATT_STAT_CHARGING)
10085556Siwasaki		state = 3;		/* charging */
101119530Snjl
102120156Siwasaki	/* If still unknown, determine it based on the battery capacity. */
103131218Simp	if (state == APM_UNKNOWN) {
104128975Snjl		if (battp->cap >= 50)
105120156Siwasaki			state = 0;	/* high */
106128975Snjl		else
107120156Siwasaki			state = 1;	/* low */
108120156Siwasaki	}
109120156Siwasaki
11085556Siwasaki	return (state);
11185556Siwasaki}
11285556Siwasaki
11385556Siwasakistatic int
11485556Siwasakiacpi_capm_convert_battflags(struct  acpi_battinfo *battp)
11585556Siwasaki{
11685556Siwasaki	int	flags;
11785556Siwasaki
11885556Siwasaki	flags = 0;
11985556Siwasaki
120128975Snjl	if (battp->cap >= 50)
12185556Siwasaki		flags |= APM_BATT_HIGH;
122128975Snjl	else {
123119530Snjl		if (battp->state & ACPI_BATT_STAT_CRITICAL)
12485556Siwasaki			flags |= APM_BATT_CRITICAL;
125119530Snjl		else
12685556Siwasaki			flags |= APM_BATT_LOW;
12785556Siwasaki	}
128119530Snjl	if (battp->state & ACPI_BATT_STAT_CHARGING)
12985556Siwasaki		flags |= APM_BATT_CHARGING;
130119530Snjl	if (battp->state == ACPI_BATT_STAT_NOT_PRESENT)
13185556Siwasaki		flags = APM_BATT_NOT_PRESENT;
13285556Siwasaki
13385556Siwasaki	return (flags);
13485556Siwasaki}
13585556Siwasaki
13685556Siwasakistatic int
13785556Siwasakiacpi_capm_get_info(apm_info_t aip)
13885556Siwasaki{
13985556Siwasaki	int	acline;
14085556Siwasaki	struct	acpi_battinfo batt;
14185556Siwasaki
14285556Siwasaki	aip->ai_infoversion = 1;
14385556Siwasaki	aip->ai_major       = 1;
14485556Siwasaki	aip->ai_minor       = 2;
145132619Snjl	aip->ai_status      = apm_active;
146131218Simp	aip->ai_capabilities= 0xff00;	/* unknown */
14785556Siwasaki
148119530Snjl	if (acpi_acad_get_acline(&acline))
149131218Simp		aip->ai_acline = APM_UNKNOWN;	/* unknown */
150119530Snjl	else
15185556Siwasaki		aip->ai_acline = acline;	/* on/off */
15285556Siwasaki
153148352Snjl	if (acpi_battery_get_battinfo(NULL, &batt) != 0) {
154131218Simp		aip->ai_batt_stat = APM_UNKNOWN;
155131218Simp		aip->ai_batt_life = APM_UNKNOWN;
156131218Simp		aip->ai_batt_time = -1;		 /* unknown */
157131218Simp		aip->ai_batteries = ~0U;	 /* unknown */
15885556Siwasaki	} else {
15985556Siwasaki		aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
16085556Siwasaki		aip->ai_batt_life = batt.cap;
16185556Siwasaki		aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
16285556Siwasaki		aip->ai_batteries = acpi_battery_get_units();
16385556Siwasaki	}
16485556Siwasaki
16585556Siwasaki	return (0);
16685556Siwasaki}
16785556Siwasaki
16885556Siwasakistatic int
16985556Siwasakiacpi_capm_get_pwstatus(apm_pwstatus_t app)
17085556Siwasaki{
171148352Snjl	device_t dev;
172148352Snjl	int	acline, unit, error;
17385556Siwasaki	struct	acpi_battinfo batt;
17485556Siwasaki
17585556Siwasaki	if (app->ap_device != PMDV_ALLDEV &&
176128975Snjl	    (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL))
17785556Siwasaki		return (1);
17885556Siwasaki
179119530Snjl	if (app->ap_device == PMDV_ALLDEV)
180148352Snjl		error = acpi_battery_get_battinfo(NULL, &batt);
181148352Snjl	else {
182148352Snjl		unit = app->ap_device - PMDV_BATT0;
183148352Snjl		dev = devclass_get_device(devclass_find("battery"), unit);
184148352Snjl		if (dev != NULL)
185148352Snjl			error = acpi_battery_get_battinfo(dev, &batt);
186148352Snjl		else
187148352Snjl			error = ENXIO;
188148352Snjl	}
189148352Snjl	if (error)
19085556Siwasaki		return (1);
19185556Siwasaki
19285556Siwasaki	app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
19385556Siwasaki	app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
19485556Siwasaki	app->ap_batt_life = batt.cap;
19585556Siwasaki	app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
19685556Siwasaki
197119530Snjl	if (acpi_acad_get_acline(&acline))
198131218Simp		app->ap_acline = APM_UNKNOWN;
199119530Snjl	else
20085556Siwasaki		app->ap_acline = acline;	/* on/off */
20185556Siwasaki
20285556Siwasaki	return (0);
20385556Siwasaki}
20485556Siwasaki
205170976Snjl/* Create single-use devices for /dev/apm and /dev/apmctl. */
206170976Snjlstatic void
207170976Snjlapm_clone(void *arg, struct ucred *cred, char *name, int namelen,
208170976Snjl    struct cdev **dev)
209170976Snjl{
210170976Snjl	int ctl_dev, unit;
211170976Snjl
212170976Snjl	if (*dev != NULL)
213170976Snjl		return;
214170976Snjl	if (strcmp(name, "apmctl") == 0)
215170976Snjl		ctl_dev = TRUE;
216170976Snjl	else if (strcmp(name, "apm") == 0)
217170976Snjl		ctl_dev = FALSE;
218170976Snjl	else
219170976Snjl		return;
220170976Snjl
221170976Snjl	/* Always create a new device and unit number. */
222170976Snjl	unit = -1;
223170976Snjl	if (clone_create(&apm_clones, &apm_cdevsw, &unit, dev, 0)) {
224170976Snjl		if (ctl_dev) {
225183381Sed			*dev = make_dev(&apm_cdevsw, unit,
226170976Snjl			    UID_ROOT, GID_OPERATOR, 0660, "apmctl%d", unit);
227170976Snjl		} else {
228183381Sed			*dev = make_dev(&apm_cdevsw, unit,
229170976Snjl			    UID_ROOT, GID_OPERATOR, 0664, "apm%d", unit);
230170976Snjl		}
231170976Snjl		if (*dev != NULL) {
232170976Snjl			dev_ref(*dev);
233170976Snjl			(*dev)->si_flags |= SI_CHEAPCLONE;
234170976Snjl		}
235170976Snjl	}
236170976Snjl}
237170976Snjl
238170976Snjl/* Create a struct for tracking per-device suspend notification. */
239170976Snjlstatic struct apm_clone_data *
240170976Snjlapm_create_clone(struct cdev *dev, struct acpi_softc *acpi_sc)
241170976Snjl{
242170976Snjl	struct apm_clone_data *clone;
243170976Snjl
244170976Snjl	clone = malloc(sizeof(*clone), M_APMDEV, M_WAITOK);
245170976Snjl	clone->cdev = dev;
246170976Snjl	clone->acpi_sc = acpi_sc;
247170976Snjl	clone->notify_status = APM_EV_NONE;
248170976Snjl	bzero(&clone->sel_read, sizeof(clone->sel_read));
249193951Skib	knlist_init_mtx(&clone->sel_read.si_note, &acpi_mutex);
250170976Snjl
251170976Snjl	/*
252170976Snjl	 * The acpi device is always managed by devd(8) and is considered
253170976Snjl	 * writable (i.e., ack is required to allow suspend to proceed.)
254170976Snjl	 */
255170976Snjl	if (strcmp("acpi", devtoname(dev)) == 0)
256170976Snjl		clone->flags = ACPI_EVF_DEVD | ACPI_EVF_WRITE;
257170976Snjl	else
258170976Snjl		clone->flags = ACPI_EVF_NONE;
259170976Snjl
260170976Snjl	ACPI_LOCK(acpi);
261170976Snjl	STAILQ_INSERT_TAIL(&acpi_sc->apm_cdevs, clone, entries);
262170976Snjl	ACPI_UNLOCK(acpi);
263170976Snjl	return (clone);
264170976Snjl}
265170976Snjl
26685556Siwasakistatic int
267192442Simpapmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
26885556Siwasaki{
269170976Snjl	struct	acpi_softc *acpi_sc;
270170976Snjl	struct 	apm_clone_data *clone;
271170976Snjl
272170976Snjl	acpi_sc = devclass_get_softc(devclass_find("acpi"), 0);
273170976Snjl	clone = apm_create_clone(dev, acpi_sc);
274170976Snjl	dev->si_drv1 = clone;
275170976Snjl
276170976Snjl	/* If the device is opened for write, record that. */
277170976Snjl	if ((flag & FWRITE) != 0)
278170976Snjl		clone->flags |= ACPI_EVF_WRITE;
279170976Snjl
28085556Siwasaki	return (0);
28185556Siwasaki}
28285556Siwasaki
28385556Siwasakistatic int
284192442Simpapmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
28585556Siwasaki{
286170976Snjl	struct	apm_clone_data *clone;
287170976Snjl	struct	acpi_softc *acpi_sc;
288170976Snjl
289170976Snjl	clone = dev->si_drv1;
290170976Snjl	acpi_sc = clone->acpi_sc;
291170976Snjl
292170976Snjl	/* We are about to lose a reference so check if suspend should occur */
293170976Snjl	if (acpi_sc->acpi_next_sstate != 0 &&
294170976Snjl	    clone->notify_status != APM_EV_ACKED)
295170976Snjl		acpi_AckSleepState(clone, 0);
296170976Snjl
297170976Snjl	/* Remove this clone's data from the list and free it. */
298170976Snjl	ACPI_LOCK(acpi);
299170976Snjl	STAILQ_REMOVE(&acpi_sc->apm_cdevs, clone, apm_clone_data, entries);
300225177Sattilio	seldrain(&clone->sel_read);
301170976Snjl	knlist_destroy(&clone->sel_read.si_note);
302170976Snjl	ACPI_UNLOCK(acpi);
303170976Snjl	free(clone, M_APMDEV);
304171297Snjl	destroy_dev_sched(dev);
30585556Siwasaki	return (0);
30685556Siwasaki}
30785556Siwasaki
30885556Siwasakistatic int
309192442Simpapmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
31085556Siwasaki{
311170976Snjl	int	error;
312170976Snjl	struct	apm_clone_data *clone;
31385556Siwasaki	struct	acpi_softc *acpi_sc;
314170976Snjl	struct	apm_info info;
315170976Snjl	struct 	apm_event_info *ev_info;
31685556Siwasaki	apm_info_old_t aiop;
31785556Siwasaki
318170976Snjl	error = 0;
319170976Snjl	clone = dev->si_drv1;
320170976Snjl	acpi_sc = clone->acpi_sc;
32185556Siwasaki
32285556Siwasaki	switch (cmd) {
32385556Siwasaki	case APMIO_SUSPEND:
324119530Snjl		if ((flag & FWRITE) == 0)
32585556Siwasaki			return (EPERM);
326170976Snjl		if (acpi_sc->acpi_next_sstate == 0) {
327170976Snjl			if (acpi_sc->acpi_suspend_sx != ACPI_STATE_S5) {
328170976Snjl				error = acpi_ReqSleepState(acpi_sc,
329170976Snjl				    acpi_sc->acpi_suspend_sx);
330170976Snjl			} else {
331170976Snjl				printf(
332170976Snjl			"power off via apm suspend not supported\n");
333170976Snjl				error = ENXIO;
334170976Snjl			}
335170976Snjl		} else
336170976Snjl			error = acpi_AckSleepState(clone, 0);
33785556Siwasaki		break;
33885556Siwasaki	case APMIO_STANDBY:
339119530Snjl		if ((flag & FWRITE) == 0)
34085556Siwasaki			return (EPERM);
341170976Snjl		if (acpi_sc->acpi_next_sstate == 0) {
342170976Snjl			if (acpi_sc->acpi_standby_sx != ACPI_STATE_S5) {
343170976Snjl				error = acpi_ReqSleepState(acpi_sc,
344170976Snjl				    acpi_sc->acpi_standby_sx);
345170976Snjl			} else {
346170976Snjl				printf(
347170976Snjl			"power off via apm standby not supported\n");
348170976Snjl				error = ENXIO;
349170976Snjl			}
350170976Snjl		} else
351170976Snjl			error = acpi_AckSleepState(clone, 0);
35285556Siwasaki		break;
353170976Snjl	case APMIO_NEXTEVENT:
354170976Snjl		printf("apm nextevent start\n");
355170976Snjl		ACPI_LOCK(acpi);
356170976Snjl		if (acpi_sc->acpi_next_sstate != 0 && clone->notify_status ==
357170976Snjl		    APM_EV_NONE) {
358170976Snjl			ev_info = (struct apm_event_info *)addr;
359170976Snjl			if (acpi_sc->acpi_next_sstate <= ACPI_STATE_S3)
360170976Snjl				ev_info->type = PMEV_STANDBYREQ;
361170976Snjl			else
362170976Snjl				ev_info->type = PMEV_SUSPENDREQ;
363170976Snjl			ev_info->index = 0;
364170976Snjl			clone->notify_status = APM_EV_NOTIFIED;
365170976Snjl			printf("apm event returning %d\n", ev_info->type);
366170976Snjl		} else
367170976Snjl			error = EAGAIN;
368170976Snjl		ACPI_UNLOCK(acpi);
369170976Snjl		break;
37085556Siwasaki	case APMIO_GETINFO_OLD:
37185556Siwasaki		if (acpi_capm_get_info(&info))
37285556Siwasaki			error = ENXIO;
37385556Siwasaki		aiop = (apm_info_old_t)addr;
37485556Siwasaki		aiop->ai_major = info.ai_major;
37585556Siwasaki		aiop->ai_minor = info.ai_minor;
37685556Siwasaki		aiop->ai_acline = info.ai_acline;
37785556Siwasaki		aiop->ai_batt_stat = info.ai_batt_stat;
37885556Siwasaki		aiop->ai_batt_life = info.ai_batt_life;
37985556Siwasaki		aiop->ai_status = info.ai_status;
38085556Siwasaki		break;
38185556Siwasaki	case APMIO_GETINFO:
38285556Siwasaki		if (acpi_capm_get_info((apm_info_t)addr))
38385556Siwasaki			error = ENXIO;
38485556Siwasaki		break;
38585556Siwasaki	case APMIO_GETPWSTATUS:
38685556Siwasaki		if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
38785556Siwasaki			error = ENXIO;
38885556Siwasaki		break;
38985556Siwasaki	case APMIO_ENABLE:
390119530Snjl		if ((flag & FWRITE) == 0)
39185556Siwasaki			return (EPERM);
392132619Snjl		apm_active = 1;
39385556Siwasaki		break;
39485556Siwasaki	case APMIO_DISABLE:
395119530Snjl		if ((flag & FWRITE) == 0)
39685556Siwasaki			return (EPERM);
397132619Snjl		apm_active = 0;
39885556Siwasaki		break;
39985556Siwasaki	case APMIO_HALTCPU:
40085556Siwasaki		break;
40185556Siwasaki	case APMIO_NOTHALTCPU:
40285556Siwasaki		break;
40385556Siwasaki	case APMIO_DISPLAY:
404119530Snjl		if ((flag & FWRITE) == 0)
40585556Siwasaki			return (EPERM);
40685556Siwasaki		break;
40785556Siwasaki	case APMIO_BIOS:
408119530Snjl		if ((flag & FWRITE) == 0)
40985556Siwasaki			return (EPERM);
41085556Siwasaki		bzero(addr, sizeof(struct apm_bios_arg));
41185556Siwasaki		break;
41285556Siwasaki	default:
41385556Siwasaki		error = EINVAL;
41485556Siwasaki		break;
41585556Siwasaki	}
41685556Siwasaki
41785556Siwasaki	return (error);
41885556Siwasaki}
41985556Siwasaki
42085556Siwasakistatic int
421130585Sphkapmwrite(struct cdev *dev, struct uio *uio, int ioflag)
42285556Siwasaki{
42385556Siwasaki	return (uio->uio_resid);
42485556Siwasaki}
42585556Siwasaki
42685556Siwasakistatic int
427192442Simpapmpoll(struct cdev *dev, int events, struct thread *td)
42885556Siwasaki{
429170976Snjl	struct	apm_clone_data *clone;
430170976Snjl	int revents;
431170976Snjl
432170976Snjl	revents = 0;
433170976Snjl	ACPI_LOCK(acpi);
434170976Snjl	clone = dev->si_drv1;
435170976Snjl	if (clone->acpi_sc->acpi_next_sstate)
436170976Snjl		revents |= events & (POLLIN | POLLRDNORM);
437170976Snjl	else
438170976Snjl		selrecord(td, &clone->sel_read);
439170976Snjl	ACPI_UNLOCK(acpi);
440170976Snjl	return (revents);
441170976Snjl}
442170976Snjl
443170976Snjlstatic int
444170976Snjlapmkqfilter(struct cdev *dev, struct knote *kn)
445170976Snjl{
446170976Snjl	struct	apm_clone_data *clone;
447170976Snjl
448170976Snjl	ACPI_LOCK(acpi);
449170976Snjl	clone = dev->si_drv1;
450170976Snjl	kn->kn_hook = clone;
451170976Snjl	kn->kn_fop = &apm_readfiltops;
452170976Snjl	knlist_add(&clone->sel_read.si_note, kn, 0);
453170976Snjl	ACPI_UNLOCK(acpi);
45485556Siwasaki	return (0);
45585556Siwasaki}
45685556Siwasaki
45785556Siwasakistatic void
458170976Snjlapmreadfiltdetach(struct knote *kn)
45985556Siwasaki{
460170976Snjl	struct	apm_clone_data *clone;
461170976Snjl
462170976Snjl	ACPI_LOCK(acpi);
463170976Snjl	clone = kn->kn_hook;
464170976Snjl	knlist_remove(&clone->sel_read.si_note, kn, 0);
465170976Snjl	ACPI_UNLOCK(acpi);
46685556Siwasaki}
46785556Siwasaki
468170976Snjlstatic int
469170976Snjlapmreadfilt(struct knote *kn, long hint)
470170976Snjl{
471170976Snjl	struct	apm_clone_data *clone;
472170976Snjl	int	sleeping;
473170976Snjl
474170976Snjl	ACPI_LOCK(acpi);
475170976Snjl	clone = kn->kn_hook;
476170976Snjl	sleeping = clone->acpi_sc->acpi_next_sstate ? 1 : 0;
477170976Snjl	ACPI_UNLOCK(acpi);
478170976Snjl	return (sleeping);
479170976Snjl}
480170976Snjl
481215097Sjkimvoid
482215097Sjkimacpi_apm_init(struct acpi_softc *sc)
48385556Siwasaki{
48485556Siwasaki
485215097Sjkim	/* Create a clone for /dev/acpi also. */
486215097Sjkim	STAILQ_INIT(&sc->apm_cdevs);
487215097Sjkim	sc->acpi_clone = apm_create_clone(sc->acpi_dev_t, sc);
488170976Snjl	clone_setup(&apm_clones);
489170976Snjl	EVENTHANDLER_REGISTER(dev_clone, apm_clone, 0, 1000);
49085556Siwasaki}
491