acpi.c revision 1.360
1/* $OpenBSD: acpi.c,v 1.360 2018/10/26 20:26:19 kettenis Exp $ */
2/*
3 * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
4 * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/systm.h>
21#include <sys/buf.h>
22#include <sys/device.h>
23#include <sys/malloc.h>
24#include <sys/fcntl.h>
25#include <sys/ioccom.h>
26#include <sys/event.h>
27#include <sys/signalvar.h>
28#include <sys/proc.h>
29#include <sys/kthread.h>
30#include <sys/sched.h>
31#include <sys/reboot.h>
32#include <sys/sysctl.h>
33#include <sys/mount.h>
34#include <sys/syscallargs.h>
35
36#ifdef HIBERNATE
37#include <sys/hibernate.h>
38#endif
39
40#include <machine/conf.h>
41#include <machine/cpufunc.h>
42#include <machine/bus.h>
43
44#include <dev/rndvar.h>
45#include <dev/pci/pcivar.h>
46#include <dev/acpi/acpireg.h>
47#include <dev/acpi/acpivar.h>
48#include <dev/acpi/amltypes.h>
49#include <dev/acpi/acpidev.h>
50#include <dev/acpi/dsdt.h>
51#include <dev/wscons/wsdisplayvar.h>
52
53#include <dev/pci/pcidevs.h>
54#include <dev/pci/ppbreg.h>
55
56#include <dev/pci/pciidevar.h>
57
58#include <machine/apmvar.h>
59#define APMUNIT(dev)	(minor(dev)&0xf0)
60#define APMDEV(dev)	(minor(dev)&0x0f)
61#define APMDEV_NORMAL	0
62#define APMDEV_CTL	8
63
64#include "wd.h"
65#include "wsdisplay.h"
66#include "softraid.h"
67
68#ifdef ACPI_DEBUG
69int	acpi_debug = 16;
70#endif
71
72int	acpi_poll_enabled;
73int	acpi_hasprocfvs;
74
75#define ACPIEN_RETRIES 15
76
77struct aml_node *acpi_pci_match(struct device *, struct pci_attach_args *);
78pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t);
79void	 acpi_pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int, int);
80int	acpi_pci_notify(struct aml_node *, int, void *);
81
82int	acpi_submatch(struct device *, void *, void *);
83int	acpi_print(void *, const char *);
84
85void	acpi_map_pmregs(struct acpi_softc *);
86void	acpi_unmap_pmregs(struct acpi_softc *);
87
88int	acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *);
89
90int	_acpi_matchhids(const char *, const char *[]);
91
92int	acpi_inidev(struct aml_node *, void *);
93int	acpi_foundprt(struct aml_node *, void *);
94
95int	acpi_enable(struct acpi_softc *);
96void	acpi_init_states(struct acpi_softc *);
97
98void 	acpi_gpe_task(void *, int);
99void	acpi_sbtn_task(void *, int);
100void	acpi_pbtn_task(void *, int);
101
102int	acpi_enabled;
103
104void	acpi_init_gpes(struct acpi_softc *);
105void	acpi_disable_allgpes(struct acpi_softc *);
106struct gpe_block *acpi_find_gpe(struct acpi_softc *, int);
107void	acpi_enable_onegpe(struct acpi_softc *, int);
108int	acpi_gpe(struct acpi_softc *, int, void *);
109
110void	acpi_enable_rungpes(struct acpi_softc *);
111void	acpi_enable_wakegpes(struct acpi_softc *, int);
112
113
114int	acpi_foundec(struct aml_node *, void *);
115int	acpi_foundsony(struct aml_node *node, void *arg);
116int	acpi_foundhid(struct aml_node *, void *);
117int	acpi_add_device(struct aml_node *node, void *arg);
118
119void	acpi_thread(void *);
120void	acpi_create_thread(void *);
121
122#ifndef SMALL_KERNEL
123
124void	acpi_indicator(struct acpi_softc *, int);
125
126void	acpi_init_pm(struct acpi_softc *);
127
128int	acpi_founddock(struct aml_node *, void *);
129int	acpi_foundpss(struct aml_node *, void *);
130int	acpi_foundtmp(struct aml_node *, void *);
131int	acpi_foundprw(struct aml_node *, void *);
132int	acpi_foundvideo(struct aml_node *, void *);
133int	acpi_foundsbs(struct aml_node *node, void *);
134
135int	acpi_foundide(struct aml_node *node, void *arg);
136int	acpiide_notify(struct aml_node *, int, void *);
137void	wdcattach(struct channel_softc *);
138int	wdcdetach(struct channel_softc *, int);
139int	is_ejectable_bay(struct aml_node *node);
140int	is_ata(struct aml_node *node);
141int	is_ejectable(struct aml_node *node);
142
143struct idechnl {
144	struct acpi_softc *sc;
145	int64_t		addr;
146	int64_t		chnl;
147	int64_t		sta;
148};
149
150/*
151 * This is a list of Synaptics devices with a 'top button area'
152 * based on the list in Linux supplied by Synaptics
153 * Synaptics clickpads with the following pnp ids will get a unique
154 * wscons mouse type that is used to define trackpad regions that will
155 * emulate mouse buttons
156 */
157static const char *sbtn_pnp[] = {
158	"LEN0017",
159	"LEN0018",
160	"LEN0019",
161	"LEN0023",
162	"LEN002A",
163	"LEN002B",
164	"LEN002C",
165	"LEN002D",
166	"LEN002E",
167	"LEN0033",
168	"LEN0034",
169	"LEN0035",
170	"LEN0036",
171	"LEN0037",
172	"LEN0038",
173	"LEN0039",
174	"LEN0041",
175	"LEN0042",
176	"LEN0045",
177	"LEN0047",
178	"LEN0049",
179	"LEN2000",
180	"LEN2001",
181	"LEN2002",
182	"LEN2003",
183	"LEN2004",
184	"LEN2005",
185	"LEN2006",
186	"LEN2007",
187	"LEN2008",
188	"LEN2009",
189	"LEN200A",
190	"LEN200B",
191};
192
193int	mouse_has_softbtn;
194#endif /* SMALL_KERNEL */
195
196struct acpi_softc *acpi_softc;
197
198/* XXX move this into dsdt softc at some point */
199extern struct aml_node aml_root;
200
201struct cfdriver acpi_cd = {
202	NULL, "acpi", DV_DULL
203};
204
205uint8_t
206acpi_pci_conf_read_1(pci_chipset_tag_t pc, pcitag_t tag, int reg)
207{
208	uint32_t val = pci_conf_read(pc, tag, reg & ~0x3);
209	return (val >> ((reg & 0x3) << 3));
210}
211
212uint16_t
213acpi_pci_conf_read_2(pci_chipset_tag_t pc, pcitag_t tag, int reg)
214{
215	uint32_t val = pci_conf_read(pc, tag, reg & ~0x2);
216	return (val >> ((reg & 0x2) << 3));
217}
218
219uint32_t
220acpi_pci_conf_read_4(pci_chipset_tag_t pc, pcitag_t tag, int reg)
221{
222	return pci_conf_read(pc, tag, reg);
223}
224
225void
226acpi_pci_conf_write_1(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val)
227{
228	uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x3);
229	tmp &= ~(0xff << ((reg & 0x3) << 3));
230	tmp |= (val << ((reg & 0x3) << 3));
231	pci_conf_write(pc, tag, reg & ~0x3, tmp);
232}
233
234void
235acpi_pci_conf_write_2(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint16_t val)
236{
237	uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x2);
238	tmp &= ~(0xffff << ((reg & 0x2) << 3));
239	tmp |= (val << ((reg & 0x2) << 3));
240	pci_conf_write(pc, tag, reg & ~0x2, tmp);
241}
242
243void
244acpi_pci_conf_write_4(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint32_t val)
245{
246	pci_conf_write(pc, tag, reg, val);
247}
248
249int
250acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
251    int access_size, int len, void *buffer)
252{
253	uint8_t *pb;
254	bus_space_tag_t iot;
255	bus_space_handle_t ioh;
256	pci_chipset_tag_t pc;
257	pcitag_t tag;
258	int reg, idx;
259
260	dnprintf(50, "gasio: %.2x 0x%.8llx %s\n",
261	    iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read");
262
263	KASSERT((len % access_size) == 0);
264
265	pb = (uint8_t *)buffer;
266	switch (iospace) {
267	case GAS_SYSTEM_MEMORY:
268	case GAS_SYSTEM_IOSPACE:
269		if (iospace == GAS_SYSTEM_MEMORY)
270			iot = sc->sc_memt;
271		else
272			iot = sc->sc_iot;
273
274		if (acpi_bus_space_map(iot, address, len, 0, &ioh) != 0) {
275			printf("%s: unable to map iospace\n", DEVNAME(sc));
276			return (-1);
277		}
278		for (reg = 0; reg < len; reg += access_size) {
279			if (iodir == ACPI_IOREAD) {
280				switch (access_size) {
281				case 1:
282					*(uint8_t *)(pb + reg) =
283					    bus_space_read_1(iot, ioh, reg);
284					dnprintf(80, "os_in8(%llx) = %x\n",
285					    reg+address, *(uint8_t *)(pb+reg));
286					break;
287				case 2:
288					*(uint16_t *)(pb + reg) =
289					    bus_space_read_2(iot, ioh, reg);
290					dnprintf(80, "os_in16(%llx) = %x\n",
291					    reg+address, *(uint16_t *)(pb+reg));
292					break;
293				case 4:
294					*(uint32_t *)(pb + reg) =
295					    bus_space_read_4(iot, ioh, reg);
296					break;
297				default:
298					printf("%s: rdio: invalid size %d\n",
299					    DEVNAME(sc), access_size);
300					return (-1);
301				}
302			} else {
303				switch (access_size) {
304				case 1:
305					bus_space_write_1(iot, ioh, reg,
306					    *(uint8_t *)(pb + reg));
307					dnprintf(80, "os_out8(%llx,%x)\n",
308					    reg+address, *(uint8_t *)(pb+reg));
309					break;
310				case 2:
311					bus_space_write_2(iot, ioh, reg,
312					    *(uint16_t *)(pb + reg));
313					dnprintf(80, "os_out16(%llx,%x)\n",
314					    reg+address, *(uint16_t *)(pb+reg));
315					break;
316				case 4:
317					bus_space_write_4(iot, ioh, reg,
318					    *(uint32_t *)(pb + reg));
319					break;
320				default:
321					printf("%s: wrio: invalid size %d\n",
322					    DEVNAME(sc), access_size);
323					return (-1);
324				}
325			}
326		}
327		acpi_bus_space_unmap(iot, ioh, len);
328		break;
329
330	case GAS_PCI_CFG_SPACE:
331		/*
332		 * The ACPI standard says that a function number of
333		 * FFFF can be used to refer to all functions on a
334		 * device.  This makes no sense though in the context
335		 * of accessing PCI config space.  Yet there is AML
336		 * out there that does this.  We simulate a read from
337		 * a nonexistent device here.  Writes will panic when
338		 * we try to construct the tag below.
339		 */
340		if (ACPI_PCI_FN(address) == 0xffff && iodir == ACPI_IOREAD) {
341			memset(buffer, 0xff, len);
342			return (0);
343		}
344
345		pc = pci_lookup_segment(ACPI_PCI_SEG(address));
346		tag = pci_make_tag(pc,
347		    ACPI_PCI_BUS(address), ACPI_PCI_DEV(address),
348		    ACPI_PCI_FN(address));
349
350		reg = ACPI_PCI_REG(address);
351		for (idx = 0; idx < len; idx += access_size) {
352			if (iodir == ACPI_IOREAD) {
353				switch (access_size) {
354				case 1:
355					*(uint8_t *)(pb + idx) =
356					    acpi_pci_conf_read_1(pc, tag, reg + idx);
357					break;
358				case 2:
359					*(uint16_t *)(pb + idx) =
360					    acpi_pci_conf_read_2(pc, tag, reg + idx);
361					break;
362				case 4:
363					*(uint32_t *)(pb + idx) =
364					    acpi_pci_conf_read_4(pc, tag, reg + idx);
365					break;
366				default:
367					printf("%s: rdcfg: invalid size %d\n",
368					    DEVNAME(sc), access_size);
369					return (-1);
370				}
371			} else {
372				switch (access_size) {
373				case 1:
374					acpi_pci_conf_write_1(pc, tag, reg + idx,
375					    *(uint8_t *)(pb + idx));
376					break;
377				case 2:
378					acpi_pci_conf_write_2(pc, tag, reg + idx,
379					    *(uint16_t *)(pb + idx));
380					break;
381				case 4:
382					acpi_pci_conf_write_4(pc, tag, reg + idx,
383					    *(uint32_t *)(pb + idx));
384					break;
385				default:
386					printf("%s: wrcfg: invalid size %d\n",
387					    DEVNAME(sc), access_size);
388					return (-1);
389				}
390			}
391		}
392		break;
393
394	case GAS_EMBEDDED:
395		if (sc->sc_ec == NULL) {
396			printf("%s: WARNING EC not initialized\n", DEVNAME(sc));
397			return (-1);
398		}
399		if (iodir == ACPI_IOREAD)
400			acpiec_read(sc->sc_ec, (uint8_t)address, len, buffer);
401		else
402			acpiec_write(sc->sc_ec, (uint8_t)address, len, buffer);
403		break;
404	}
405	return (0);
406}
407
408int
409acpi_inidev(struct aml_node *node, void *arg)
410{
411	struct acpi_softc	*sc = (struct acpi_softc *)arg;
412	int64_t st;
413
414	/*
415	 * Per the ACPI spec 6.5.1, only run _INI when device is there or
416	 * when there is no _STA.  We terminate the tree walk (with return 1)
417	 * early if necessary.
418	 */
419
420	/* Evaluate _STA to decide _INI fate and walk fate */
421	if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &st))
422		st = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
423
424	/* Evaluate _INI if we are present */
425	if (st & STA_PRESENT)
426		aml_evalnode(sc, node, 0, NULL, NULL);
427
428	/* If we are functioning, we walk/search our children */
429	if (st & STA_DEV_OK)
430		return 0;
431
432	/* If we are not enabled, or not present, terminate search */
433	if (!(st & (STA_PRESENT|STA_ENABLED)))
434		return 1;
435
436	/* Default just continue search */
437	return 0;
438}
439
440int
441acpi_foundprt(struct aml_node *node, void *arg)
442{
443	struct acpi_softc	*sc = (struct acpi_softc *)arg;
444	struct device		*self = (struct device *)arg;
445	struct acpi_attach_args	aaa;
446	int64_t st = 0;
447
448	dnprintf(10, "found prt entry: %s\n", node->parent->name);
449
450	/* Evaluate _STA to decide _PRT fate and walk fate */
451	if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &st))
452		st = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
453
454	if (st & STA_PRESENT) {
455		memset(&aaa, 0, sizeof(aaa));
456		aaa.aaa_iot = sc->sc_iot;
457		aaa.aaa_memt = sc->sc_memt;
458		aaa.aaa_node = node;
459		aaa.aaa_name = "acpiprt";
460
461		config_found(self, &aaa, acpi_print);
462	}
463
464	/* If we are functioning, we walk/search our children */
465	if (st & STA_DEV_OK)
466		return 0;
467
468	/* If we are not enabled, or not present, terminate search */
469	if (!(st & (STA_PRESENT|STA_ENABLED)))
470		return 1;
471
472	/* Default just continue search */
473	return 0;
474}
475
476TAILQ_HEAD(, acpi_pci) acpi_pcidevs =
477    TAILQ_HEAD_INITIALIZER(acpi_pcidevs);
478TAILQ_HEAD(, acpi_pci) acpi_pcirootdevs =
479    TAILQ_HEAD_INITIALIZER(acpi_pcirootdevs);
480
481int acpi_getpci(struct aml_node *node, void *arg);
482int acpi_getminbus(int crsidx, union acpi_resource *crs, void *arg);
483
484int
485acpi_getminbus(int crsidx, union acpi_resource *crs, void *arg)
486{
487	int *bbn = arg;
488	int typ = AML_CRSTYPE(crs);
489
490	/* Check for embedded bus number */
491	if (typ == LR_WORD && crs->lr_word.type == 2) {
492		/* If _MIN > _MAX, the resource is considered to be invalid. */
493		if (crs->lr_word._min > crs->lr_word._max)
494			return -1;
495		*bbn = crs->lr_word._min;
496	}
497	return 0;
498}
499
500int
501acpi_matchcls(struct acpi_attach_args *aaa, int class, int subclass,
502    int interface)
503{
504	struct acpi_softc *sc = acpi_softc;
505	struct aml_value res;
506
507	if (aaa->aaa_dev == NULL || aaa->aaa_node == NULL)
508		return (0);
509
510	if (aml_evalname(sc, aaa->aaa_node, "_CLS", 0, NULL, &res))
511		return (0);
512
513	if (res.type != AML_OBJTYPE_PACKAGE || res.length != 3 ||
514	    res.v_package[0]->type != AML_OBJTYPE_INTEGER ||
515	    res.v_package[1]->type != AML_OBJTYPE_INTEGER ||
516	    res.v_package[2]->type != AML_OBJTYPE_INTEGER)
517		return (0);
518
519	if (res.v_package[0]->v_integer == class &&
520	    res.v_package[1]->v_integer == subclass &&
521	    res.v_package[2]->v_integer == interface)
522		return (1);
523
524	return (0);
525}
526
527int
528_acpi_matchhids(const char *hid, const char *hids[])
529{
530	int i;
531
532	for (i = 0; hids[i]; i++)
533		if (!strcmp(hid, hids[i]))
534			return (1);
535	return (0);
536}
537
538int
539acpi_matchhids(struct acpi_attach_args *aa, const char *hids[],
540    const char *driver)
541{
542	if (aa->aaa_dev == NULL || aa->aaa_node == NULL)
543		return (0);
544
545	if (_acpi_matchhids(aa->aaa_dev, hids)) {
546		dnprintf(5, "driver %s matches at least one hid\n", driver);
547		return (2);
548	}
549	if (aa->aaa_cdev && _acpi_matchhids(aa->aaa_cdev, hids)) {
550		dnprintf(5, "driver %s matches at least one cid\n", driver);
551		return (1);
552	}
553
554	return (0);
555}
556
557/* Map ACPI device node to PCI */
558int
559acpi_getpci(struct aml_node *node, void *arg)
560{
561	const char *pcihid[] = { ACPI_DEV_PCIB, ACPI_DEV_PCIEB, "HWP0002", 0 };
562	struct acpi_pci *pci, *ppci;
563	struct aml_value res;
564	struct acpi_softc *sc = arg;
565	pci_chipset_tag_t pc;
566	pcitag_t tag;
567	uint64_t val;
568	uint32_t reg;
569
570	if (!node->value || node->value->type != AML_OBJTYPE_DEVICE)
571		return 0;
572	if (!aml_evalhid(node, &res)) {
573		/* Check if this is a PCI Root node */
574		if (_acpi_matchhids(res.v_string, pcihid)) {
575			aml_freevalue(&res);
576
577			pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
578
579			pci->bus = -1;
580			if (!aml_evalinteger(sc, node, "_SEG", 0, NULL, &val))
581				pci->seg = val;
582			if (!aml_evalname(sc, node, "_CRS", 0, NULL, &res)) {
583				aml_parse_resource(&res, acpi_getminbus,
584				    &pci->bus);
585				dnprintf(10, "%s post-crs: %d\n",
586				    aml_nodename(node), pci->bus);
587			}
588			if (!aml_evalinteger(sc, node, "_BBN", 0, NULL, &val)) {
589				dnprintf(10, "%s post-bbn: %d, %lld\n",
590				    aml_nodename(node), pci->bus, val);
591				if (pci->bus == -1)
592					pci->bus = val;
593			}
594			pci->sub = pci->bus;
595			node->pci = pci;
596			dnprintf(10, "found PCI root: %s %d\n",
597			    aml_nodename(node), pci->bus);
598			TAILQ_INSERT_TAIL(&acpi_pcirootdevs, pci, next);
599		}
600		aml_freevalue(&res);
601		return 0;
602	}
603
604	/* If parent is not PCI, or device does not have _ADR, return */
605	if (!node->parent || (ppci = node->parent->pci) == NULL)
606		return 0;
607	if (aml_evalinteger(sc, node, "_ADR", 0, NULL, &val))
608		return 0;
609
610	pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
611	pci->seg = ppci->seg;
612	pci->bus = ppci->sub;
613	pci->dev = ACPI_ADR_PCIDEV(val);
614	pci->fun = ACPI_ADR_PCIFUN(val);
615	pci->node = node;
616	pci->sub = -1;
617
618	dnprintf(10, "%.2x:%.2x.%x -> %s\n",
619		pci->bus, pci->dev, pci->fun,
620		aml_nodename(node));
621
622	/* Collect device power state information. */
623	if (aml_evalinteger(sc, node, "_S3D", 0, NULL, &val) == 0)
624		pci->_s3d = val;
625	else
626		pci->_s3d = -1;
627	if (aml_evalinteger(sc, node, "_S3W", 0, NULL, &val) == 0)
628		pci->_s3w = val;
629	else
630		pci->_s3w = -1;
631	if (aml_evalinteger(sc, node, "_S4D", 0, NULL, &val) == 0)
632		pci->_s4d = val;
633	else
634		pci->_s4d = -1;
635	if (aml_evalinteger(sc, node, "_S4W", 0, NULL, &val) == 0)
636		pci->_s4w = val;
637	else
638		pci->_s4w = -1;
639
640	/* Check if PCI device exists */
641	if (pci->dev > 0x1F || pci->fun > 7) {
642		free(pci, M_DEVBUF, sizeof(*pci));
643		return (1);
644	}
645	pc = pci_lookup_segment(pci->seg);
646	tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun);
647	reg = pci_conf_read(pc, tag, PCI_ID_REG);
648	if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) {
649		free(pci, M_DEVBUF, sizeof(*pci));
650		return (1);
651	}
652	node->pci = pci;
653
654	TAILQ_INSERT_TAIL(&acpi_pcidevs, pci, next);
655
656	/* Check if this is a PCI bridge */
657	reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
658	if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
659	    PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) {
660		reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
661		pci->sub = PPB_BUSINFO_SECONDARY(reg);
662
663		dnprintf(10, "found PCI bridge: %s %d\n",
664		    aml_nodename(node), pci->sub);
665
666		/* Continue scanning */
667		return (0);
668	}
669
670	/* Device does not have children, stop scanning */
671	return (1);
672}
673
674struct aml_node *
675acpi_find_pci(pci_chipset_tag_t pc, pcitag_t tag)
676{
677	struct acpi_pci *pdev;
678	int bus, dev, fun;
679
680	pci_decompose_tag(pc, tag, &bus, &dev, &fun);
681	TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
682		if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun)
683			return pdev->node;
684	}
685
686	return NULL;
687}
688
689struct aml_node *
690acpi_pci_match(struct device *dev, struct pci_attach_args *pa)
691{
692	struct acpi_pci *pdev;
693	int state;
694
695	TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
696		if (pdev->bus != pa->pa_bus ||
697		    pdev->dev != pa->pa_device ||
698		    pdev->fun != pa->pa_function)
699			continue;
700
701		dnprintf(10,"%s at acpi0 %s\n", dev->dv_xname,
702		    aml_nodename(pdev->node));
703
704		pdev->device = dev;
705
706		/*
707		 * If some Power Resources are dependent on this device
708		 * initialize them.
709		 */
710		state = pci_get_powerstate(pa->pa_pc, pa->pa_tag);
711		acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 1);
712		acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 0);
713
714		aml_register_notify(pdev->node, NULL, acpi_pci_notify, pdev, 0);
715
716		return pdev->node;
717	}
718
719	return NULL;
720}
721
722pcireg_t
723acpi_pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag)
724{
725	struct acpi_pci *pdev;
726	int bus, dev, fun;
727	int state = -1, defaultstate = pci_get_powerstate(pc, tag);
728
729	pci_decompose_tag(pc, tag, &bus, &dev, &fun);
730	TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
731		if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) {
732			switch (acpi_softc->sc_state) {
733			case ACPI_STATE_S3:
734				defaultstate = PCI_PMCSR_STATE_D3;
735				state = MAX(pdev->_s3d, pdev->_s3w);
736				break;
737			case ACPI_STATE_S4:
738				state = MAX(pdev->_s4d, pdev->_s4w);
739				break;
740			case ACPI_STATE_S5:
741			default:
742				break;
743			}
744
745			if (state >= PCI_PMCSR_STATE_D0 &&
746			    state <= PCI_PMCSR_STATE_D3)
747				return state;
748		}
749	}
750
751	return defaultstate;
752}
753
754void
755acpi_pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state, int pre)
756{
757#if NACPIPWRRES > 0
758	struct acpi_softc *sc = acpi_softc;
759	struct acpi_pwrres *pr;
760	struct acpi_pci *pdev;
761	int bus, dev, fun;
762	char name[5];
763
764	pci_decompose_tag(pc, tag, &bus, &dev, &fun);
765	TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
766		if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun)
767			break;
768	}
769
770	/* XXX Add a check to discard nodes without Power Resources? */
771	if (pdev == NULL)
772		return;
773
774	SIMPLEQ_FOREACH(pr, &sc->sc_pwrresdevs, p_next) {
775		if (pr->p_node != pdev->node)
776			continue;
777
778		/*
779		 * If the firmware is already aware that the device
780		 * is in the given state, there's nothing to do.
781		 */
782		if (pr->p_state == state)
783			continue;
784
785		if (pre) {
786			/*
787			 * If a Resource is dependent on this device for
788			 * the given state, make sure it is turned "_ON".
789			 */
790			if (pr->p_res_state == state)
791				acpipwrres_ref_incr(pr->p_res_sc, pr->p_node);
792		} else {
793			/*
794			 * If a Resource was referenced for the state we
795			 * left, drop a reference and turn it "_OFF" if
796			 * it was the last one.
797			 */
798			if (pr->p_res_state == pr->p_state)
799				acpipwrres_ref_decr(pr->p_res_sc, pr->p_node);
800
801			if (pr->p_res_state == state) {
802				snprintf(name, sizeof(name), "_PS%d", state);
803				aml_evalname(sc, pr->p_node, name, 0,
804				    NULL, NULL);
805			}
806
807			pr->p_state = state;
808		}
809
810	}
811#endif /* NACPIPWRRES > 0 */
812}
813
814int
815acpi_pci_notify(struct aml_node *node, int ntype, void *arg)
816{
817	struct acpi_pci *pdev = arg;
818	pci_chipset_tag_t pc;
819	pcitag_t tag;
820	pcireg_t reg;
821	int offset;
822
823	/* We're only interested in Device Wake notifications. */
824	if (ntype != 2)
825		return (0);
826
827	pc = pci_lookup_segment(pdev->seg);
828	tag = pci_make_tag(pc, pdev->bus, pdev->dev, pdev->fun);
829	if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) {
830		/* Clear the PME Status bit if it is set. */
831		reg = pci_conf_read(pc, tag, offset + PCI_PMCSR);
832		pci_conf_write(pc, tag, offset + PCI_PMCSR, reg);
833	}
834
835	return (0);
836}
837
838void
839acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr)
840{
841	struct acpi_pci			*pdev;
842	struct pcibus_attach_args	*pba = aux;
843
844	KASSERT(pba->pba_busex != NULL);
845
846	TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) {
847		if (extent_alloc_region(pba->pba_busex, pdev->bus,
848		    1, EX_NOWAIT) != 0)
849			continue;
850		pba->pba_bus = pdev->bus;
851		config_found(dev, pba, pr);
852	}
853}
854
855/* GPIO support */
856
857struct acpi_gpio_event {
858	struct aml_node *node;
859	uint16_t pin;
860};
861
862void
863acpi_gpio_event_task(void *arg0, int arg1)
864{
865	struct aml_node *node = arg0;
866	uint16_t pin = arg1;
867	char name[5];
868
869	snprintf(name, sizeof(name), "_E%.2X", pin);
870	aml_evalname(acpi_softc, node, name, 0, NULL, NULL);
871}
872
873int
874acpi_gpio_event(void *arg)
875{
876	struct acpi_gpio_event *ev = arg;
877
878	acpi_addtask(acpi_softc, acpi_gpio_event_task, ev->node, ev->pin);
879	acpi_wakeup(acpi_softc);
880	return 1;
881}
882
883int
884acpi_gpio_parse_events(int crsidx, union acpi_resource *crs, void *arg)
885{
886	struct aml_node *devnode = arg;
887	struct aml_node *node;
888	uint16_t pin;
889
890	switch (AML_CRSTYPE(crs)) {
891	case LR_GPIO:
892		node = aml_searchname(devnode,
893		    (char *)&crs->pad[crs->lr_gpio.res_off]);
894		pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
895		if (crs->lr_gpio.type == LR_GPIO_INT &&
896		    node && node->gpio && pin < 256) {
897			struct acpi_gpio *gpio = node->gpio;
898			struct acpi_gpio_event *ev;
899
900			ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK);
901			ev->node = devnode;
902			ev->pin = pin;
903			gpio->intr_establish(gpio->cookie, pin,
904			    crs->lr_gpio.tflags, acpi_gpio_event, ev);
905		}
906		break;
907	default:
908		printf("%s: unknown resource type %d\n", __func__,
909		    AML_CRSTYPE(crs));
910	}
911
912	return 0;
913}
914
915void
916acpi_register_gpio(struct acpi_softc *sc, struct aml_node *devnode)
917{
918	struct aml_value arg[2];
919	struct aml_node *node;
920	struct aml_value res;
921
922	/* Register GeneralPurposeIO address space. */
923	memset(&arg, 0, sizeof(arg));
924	arg[0].type = AML_OBJTYPE_INTEGER;
925	arg[0].v_integer = ACPI_OPREG_GPIO;
926	arg[1].type = AML_OBJTYPE_INTEGER;
927	arg[1].v_integer = 1;
928	node = aml_searchname(devnode, "_REG");
929	if (node && aml_evalnode(sc, node, 2, arg, NULL))
930		printf("%s: _REG failed\n", node->name);
931
932	/* Register GPIO signaled ACPI events. */
933	if (aml_evalname(sc, devnode, "_AEI", 0, NULL, &res))
934		return;
935	aml_parse_resource(&res, acpi_gpio_parse_events, devnode);
936}
937
938#ifndef SMALL_KERNEL
939
940void
941acpi_register_gsb(struct acpi_softc *sc, struct aml_node *devnode)
942{
943	struct aml_value arg[2];
944	struct aml_node *node;
945
946	/* Register GenericSerialBus address space. */
947	memset(&arg, 0, sizeof(arg));
948	arg[0].type = AML_OBJTYPE_INTEGER;
949	arg[0].v_integer = ACPI_OPREG_GSB;
950	arg[1].type = AML_OBJTYPE_INTEGER;
951	arg[1].v_integer = 1;
952	node = aml_searchname(devnode, "_REG");
953	if (node && aml_evalnode(sc, node, 2, arg, NULL))
954		printf("%s: _REG failed\n", node->name);
955}
956
957#endif
958
959void
960acpi_attach_common(struct acpi_softc *sc, paddr_t base)
961{
962	struct acpi_mem_map handle;
963	struct acpi_rsdp *rsdp;
964	struct acpi_q *entry;
965	struct acpi_dsdt *p_dsdt;
966#ifndef SMALL_KERNEL
967	int wakeup_dev_ct;
968	struct acpi_wakeq *wentry;
969	struct device *dev;
970#endif /* SMALL_KERNEL */
971	paddr_t facspa;
972	uint16_t pm1;
973	int s;
974
975	rw_init(&sc->sc_lck, "acpilk");
976
977	acpi_softc = sc;
978
979	if (acpi_map(base, sizeof(struct acpi_rsdp), &handle)) {
980		printf(": can't map memory\n");
981		return;
982	}
983
984	rsdp = (struct acpi_rsdp *)handle.va;
985	sc->sc_revision = (int)rsdp->rsdp_revision;
986	printf(": rev %d", sc->sc_revision);
987
988	SIMPLEQ_INIT(&sc->sc_tables);
989	SIMPLEQ_INIT(&sc->sc_wakedevs);
990#if NACPIPWRRES > 0
991	SIMPLEQ_INIT(&sc->sc_pwrresdevs);
992#endif /* NACPIPWRRES > 0 */
993
994
995#ifndef SMALL_KERNEL
996	sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT | M_ZERO);
997	if (sc->sc_note == NULL) {
998		printf(", can't allocate memory\n");
999		acpi_unmap(&handle);
1000		return;
1001	}
1002#endif /* SMALL_KERNEL */
1003
1004	if (acpi_loadtables(sc, rsdp)) {
1005		printf(", can't load tables\n");
1006		acpi_unmap(&handle);
1007		return;
1008	}
1009
1010	acpi_unmap(&handle);
1011
1012	/*
1013	 * Find the FADT
1014	 */
1015	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1016		if (memcmp(entry->q_table, FADT_SIG,
1017		    sizeof(FADT_SIG) - 1) == 0) {
1018			sc->sc_fadt = entry->q_table;
1019			break;
1020		}
1021	}
1022	if (sc->sc_fadt == NULL) {
1023		printf(", no FADT\n");
1024		return;
1025	}
1026
1027	/*
1028	 * A bunch of things need to be done differently for
1029	 * Hardware-reduced ACPI.
1030	 */
1031	if (sc->sc_fadt->hdr_revision >= 5 &&
1032	    sc->sc_fadt->flags & FADT_HW_REDUCED_ACPI)
1033		sc->sc_hw_reduced = 1;
1034
1035	/* Map Power Management registers */
1036	acpi_map_pmregs(sc);
1037
1038	/*
1039	 * Check if we can and need to enable ACPI control.
1040	 */
1041	pm1 = acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0);
1042	if ((pm1 & ACPI_PM1_SCI_EN) == 0 && sc->sc_fadt->smi_cmd &&
1043	    (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) {
1044		printf(", ACPI control unavailable\n");
1045		acpi_unmap_pmregs(sc);
1046		return;
1047	}
1048
1049	/*
1050	 * Set up a pointer to the firmware control structure
1051	 */
1052	if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0)
1053		facspa = sc->sc_fadt->firmware_ctl;
1054	else
1055		facspa = sc->sc_fadt->x_firmware_ctl;
1056
1057	if (acpi_map(facspa, sizeof(struct acpi_facs), &handle))
1058		printf(" !FACS");
1059	else
1060		sc->sc_facs = (struct acpi_facs *)handle.va;
1061
1062	/* Create opcode hashtable */
1063	aml_hashopcodes();
1064
1065	/* Create Default AML objects */
1066	aml_create_defaultobjects();
1067
1068	/*
1069	 * Load the DSDT from the FADT pointer -- use the
1070	 * extended (64-bit) pointer if it exists
1071	 */
1072	if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0)
1073		entry = acpi_maptable(sc, sc->sc_fadt->dsdt, NULL, NULL, NULL,
1074		    -1);
1075	else
1076		entry = acpi_maptable(sc, sc->sc_fadt->x_dsdt, NULL, NULL, NULL,
1077		    -1);
1078
1079	if (entry == NULL)
1080		printf(" !DSDT");
1081
1082	p_dsdt = entry->q_table;
1083	acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length -
1084	    sizeof(p_dsdt->hdr));
1085
1086	/* Load SSDT's */
1087	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1088		if (memcmp(entry->q_table, SSDT_SIG,
1089		    sizeof(SSDT_SIG) - 1) == 0) {
1090			p_dsdt = entry->q_table;
1091			acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length -
1092			    sizeof(p_dsdt->hdr));
1093		}
1094	}
1095
1096	/* Perform post-parsing fixups */
1097	aml_postparse();
1098
1099
1100#ifndef SMALL_KERNEL
1101	/* Find available sleeping states */
1102	acpi_init_states(sc);
1103
1104	/* Find available sleep/resume related methods. */
1105	acpi_init_pm(sc);
1106#endif /* SMALL_KERNEL */
1107
1108	/* Initialize GPE handlers */
1109	s = spltty();
1110	acpi_init_gpes(sc);
1111	splx(s);
1112
1113	/* some devices require periodic polling */
1114	timeout_set(&sc->sc_dev_timeout, acpi_poll, sc);
1115
1116	acpi_enabled = 1;
1117
1118	/*
1119	 * Take over ACPI control.  Note that once we do this, we
1120	 * effectively tell the system that we have ownership of
1121	 * the ACPI hardware registers, and that SMI should leave
1122	 * them alone
1123	 *
1124	 * This may prevent thermal control on some systems where
1125	 * that actually does work
1126	 */
1127	if ((pm1 & ACPI_PM1_SCI_EN) == 0 && sc->sc_fadt->smi_cmd) {
1128		if (acpi_enable(sc)) {
1129			printf(", can't enable ACPI\n");
1130			return;
1131		}
1132	}
1133
1134	printf("\n%s: tables", DEVNAME(sc));
1135	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1136		printf(" %.4s", (char *)entry->q_table);
1137	}
1138	printf("\n");
1139
1140#ifndef SMALL_KERNEL
1141	/* Display wakeup devices and lowest S-state */
1142	wakeup_dev_ct = 0;
1143	printf("%s: wakeup devices", DEVNAME(sc));
1144	SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) {
1145		if (wakeup_dev_ct < 16)
1146			printf(" %.4s(S%d)", wentry->q_node->name,
1147			    wentry->q_state);
1148		else if (wakeup_dev_ct == 16)
1149			printf(" [...]");
1150		wakeup_dev_ct ++;
1151	}
1152	printf("\n");
1153
1154	/*
1155	 * ACPI is enabled now -- attach timer
1156	 */
1157	if (!sc->sc_hw_reduced &&
1158	    (sc->sc_fadt->pm_tmr_blk || sc->sc_fadt->x_pm_tmr_blk.address)) {
1159		struct acpi_attach_args aaa;
1160
1161		memset(&aaa, 0, sizeof(aaa));
1162		aaa.aaa_name = "acpitimer";
1163		aaa.aaa_iot = sc->sc_iot;
1164		aaa.aaa_memt = sc->sc_memt;
1165		config_found(&sc->sc_dev, &aaa, acpi_print);
1166	}
1167#endif /* SMALL_KERNEL */
1168
1169	/*
1170	 * Attach table-defined devices
1171	 */
1172	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1173		struct acpi_attach_args aaa;
1174
1175		memset(&aaa, 0, sizeof(aaa));
1176		aaa.aaa_iot = sc->sc_iot;
1177		aaa.aaa_memt = sc->sc_memt;
1178		aaa.aaa_table = entry->q_table;
1179		config_found_sm(&sc->sc_dev, &aaa, acpi_print, acpi_submatch);
1180	}
1181
1182	/* initialize runtime environment */
1183	aml_find_node(&aml_root, "_INI", acpi_inidev, sc);
1184
1185	/* Get PCI mapping */
1186	aml_walknodes(&aml_root, AML_WALK_PRE, acpi_getpci, sc);
1187
1188#if defined (__amd64__) || defined(__i386__)
1189	/* attach pci interrupt routing tables */
1190	aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc);
1191#endif
1192
1193	aml_find_node(&aml_root, "_HID", acpi_foundec, sc);
1194
1195	/* check if we're running on a sony */
1196	aml_find_node(&aml_root, "GBRT", acpi_foundsony, sc);
1197
1198	aml_walknodes(&aml_root, AML_WALK_PRE, acpi_add_device, sc);
1199
1200#ifndef SMALL_KERNEL
1201	/* try to find smart battery first */
1202	aml_find_node(&aml_root, "_HID", acpi_foundsbs, sc);
1203#endif /* SMALL_KERNEL */
1204
1205	/* attach battery, power supply and button devices */
1206	aml_find_node(&aml_root, "_HID", acpi_foundhid, sc);
1207
1208#ifndef SMALL_KERNEL
1209#if NWD > 0
1210	/* Attach IDE bay */
1211	aml_walknodes(&aml_root, AML_WALK_PRE, acpi_foundide, sc);
1212#endif
1213
1214	/* attach docks */
1215	aml_find_node(&aml_root, "_DCK", acpi_founddock, sc);
1216
1217	/* attach video */
1218	aml_find_node(&aml_root, "_DOS", acpi_foundvideo, sc);
1219
1220	/* create list of devices we want to query when APM comes in */
1221	SLIST_INIT(&sc->sc_ac);
1222	SLIST_INIT(&sc->sc_bat);
1223	TAILQ_FOREACH(dev, &alldevs, dv_list) {
1224		if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpiac")) {
1225			struct acpi_ac *ac;
1226
1227			ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO);
1228			ac->aac_softc = (struct acpiac_softc *)dev;
1229			SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link);
1230		} else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpibat")) {
1231			struct acpi_bat *bat;
1232
1233			bat = malloc(sizeof(*bat), M_DEVBUF, M_WAITOK | M_ZERO);
1234			bat->aba_softc = (struct acpibat_softc *)dev;
1235			SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link);
1236		} else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpisbs")) {
1237			struct acpi_sbs *sbs;
1238
1239			sbs = malloc(sizeof(*sbs), M_DEVBUF, M_WAITOK | M_ZERO);
1240			sbs->asbs_softc = (struct acpisbs_softc *)dev;
1241			SLIST_INSERT_HEAD(&sc->sc_sbs, sbs, asbs_link);
1242		}
1243	}
1244
1245#endif /* SMALL_KERNEL */
1246
1247	/* Setup threads */
1248	sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK);
1249	sc->sc_thread->sc = sc;
1250	sc->sc_thread->running = 1;
1251
1252	/* Enable PCI Power Management. */
1253	pci_dopm = 1;
1254
1255	acpi_attach_machdep(sc);
1256
1257	kthread_create_deferred(acpi_create_thread, sc);
1258}
1259
1260int
1261acpi_submatch(struct device *parent, void *match, void *aux)
1262{
1263	struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux;
1264	struct cfdata *cf = match;
1265
1266	if (aaa->aaa_table == NULL)
1267		return (0);
1268	return ((*cf->cf_attach->ca_match)(parent, match, aux));
1269}
1270
1271int
1272acpi_print(void *aux, const char *pnp)
1273{
1274	struct acpi_attach_args *aa = aux;
1275
1276	if (pnp) {
1277		if (aa->aaa_name)
1278			printf("%s at %s", aa->aaa_name, pnp);
1279		else if (aa->aaa_dev)
1280			printf("\"%s\" at %s", aa->aaa_dev, pnp);
1281		else
1282			return (QUIET);
1283	}
1284
1285	return (UNCONF);
1286}
1287
1288struct acpi_q *
1289acpi_maptable(struct acpi_softc *sc, paddr_t addr, const char *sig,
1290    const char *oem, const char *tbl, int flag)
1291{
1292	static int tblid;
1293	struct acpi_mem_map handle;
1294	struct acpi_table_header *hdr;
1295	struct acpi_q *entry;
1296	size_t len;
1297
1298	/* Check if we can map address */
1299	if (addr == 0)
1300		return NULL;
1301	if (acpi_map(addr, sizeof(*hdr), &handle))
1302		return NULL;
1303	hdr = (struct acpi_table_header *)handle.va;
1304	len = hdr->length;
1305	acpi_unmap(&handle);
1306
1307	/* Validate length/checksum */
1308	if (acpi_map(addr, len, &handle))
1309		return NULL;
1310	hdr = (struct acpi_table_header *)handle.va;
1311	if (acpi_checksum(hdr, len))
1312		printf("\n%s: %.4s checksum error",
1313		    DEVNAME(sc), hdr->signature);
1314
1315	if ((sig && memcmp(sig, hdr->signature, 4)) ||
1316	    (oem && memcmp(oem, hdr->oemid, 6)) ||
1317	    (tbl && memcmp(tbl, hdr->oemtableid, 8))) {
1318		acpi_unmap(&handle);
1319		return NULL;
1320	}
1321
1322	/* Allocate copy */
1323	entry = malloc(sizeof(*entry) + len, M_DEVBUF, M_NOWAIT);
1324	if (entry != NULL) {
1325		memcpy(entry->q_data, handle.va, len);
1326		entry->q_table = entry->q_data;
1327		entry->q_id = ++tblid;
1328
1329		if (flag < 0)
1330			SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry,
1331			    q_next);
1332		else if (flag > 0)
1333			SIMPLEQ_INSERT_TAIL(&sc->sc_tables, entry,
1334			    q_next);
1335	}
1336	acpi_unmap(&handle);
1337	return entry;
1338}
1339
1340int
1341acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp)
1342{
1343	struct acpi_q *sdt;
1344	int i, ntables;
1345	size_t len;
1346
1347	if (rsdp->rsdp_revision == 2 && rsdp->rsdp_xsdt) {
1348		struct acpi_xsdt *xsdt;
1349
1350		sdt = acpi_maptable(sc, rsdp->rsdp_xsdt, NULL, NULL, NULL, 0);
1351		if (sdt == NULL) {
1352			printf("couldn't map rsdt\n");
1353			return (ENOMEM);
1354		}
1355
1356		xsdt = (struct acpi_xsdt *)sdt->q_data;
1357		len  = xsdt->hdr.length;
1358		ntables = (len - sizeof(struct acpi_table_header)) /
1359		    sizeof(xsdt->table_offsets[0]);
1360
1361		for (i = 0; i < ntables; i++)
1362			acpi_maptable(sc, xsdt->table_offsets[i], NULL, NULL,
1363			    NULL, 1);
1364
1365		free(sdt, M_DEVBUF, 0);
1366	} else {
1367		struct acpi_rsdt *rsdt;
1368
1369		sdt = acpi_maptable(sc, rsdp->rsdp_rsdt, NULL, NULL, NULL, 0);
1370		if (sdt == NULL) {
1371			printf("couldn't map rsdt\n");
1372			return (ENOMEM);
1373		}
1374
1375		rsdt = (struct acpi_rsdt *)sdt->q_data;
1376		len  = rsdt->hdr.length;
1377		ntables = (len - sizeof(struct acpi_table_header)) /
1378		    sizeof(rsdt->table_offsets[0]);
1379
1380		for (i = 0; i < ntables; i++)
1381			acpi_maptable(sc, rsdt->table_offsets[i], NULL, NULL,
1382			    NULL, 1);
1383
1384		free(sdt, M_DEVBUF, 0);
1385	}
1386
1387	return (0);
1388}
1389
1390/* Read from power management register */
1391int
1392acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset)
1393{
1394	bus_space_handle_t ioh;
1395	bus_size_t size;
1396	int regval;
1397
1398	/*
1399	 * For Hardware-reduced ACPI we emulate PM1B_CNT to reflect
1400	 * that the system is always in ACPI mode.
1401	 */
1402	if (sc->sc_hw_reduced && reg == ACPIREG_PM1B_CNT) {
1403		KASSERT(offset == 0);
1404		return ACPI_PM1_SCI_EN;
1405	}
1406
1407	/*
1408	 * For Hardware-reduced ACPI we also emulate PM1A_STS using
1409	 * SLEEP_STATUS_REG.
1410	 */
1411	if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_STS) {
1412		uint8_t value;
1413
1414		KASSERT(offset == 0);
1415		acpi_gasio(sc, ACPI_IOREAD,
1416		    sc->sc_fadt->sleep_status_reg.address_space_id,
1417		    sc->sc_fadt->sleep_status_reg.address,
1418		    sc->sc_fadt->sleep_status_reg.register_bit_width / 8,
1419		    sc->sc_fadt->sleep_status_reg.access_size, &value);
1420		return ((int)value << 8);
1421	}
1422
1423	/* Special cases: 1A/1B blocks can be OR'ed together */
1424	switch (reg) {
1425	case ACPIREG_PM1_EN:
1426		return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) |
1427		    acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset));
1428	case ACPIREG_PM1_STS:
1429		return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) |
1430		    acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset));
1431	case ACPIREG_PM1_CNT:
1432		return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) |
1433		    acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset));
1434	case ACPIREG_GPE_STS:
1435		dnprintf(50, "read GPE_STS  offset: %.2x %.2x %.2x\n", offset,
1436		    sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1);
1437		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1438			reg = ACPIREG_GPE0_STS;
1439		}
1440		break;
1441	case ACPIREG_GPE_EN:
1442		dnprintf(50, "read GPE_EN   offset: %.2x %.2x %.2x\n",
1443		    offset, sc->sc_fadt->gpe0_blk_len>>1,
1444		    sc->sc_fadt->gpe1_blk_len>>1);
1445		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1446			reg = ACPIREG_GPE0_EN;
1447		}
1448		break;
1449	}
1450
1451	if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0)
1452		return (0);
1453
1454	regval = 0;
1455	ioh = sc->sc_pmregs[reg].ioh;
1456	size = sc->sc_pmregs[reg].size;
1457	if (size > sc->sc_pmregs[reg].access)
1458		size = sc->sc_pmregs[reg].access;
1459
1460	switch (size) {
1461	case 1:
1462		regval = bus_space_read_1(sc->sc_iot, ioh, offset);
1463		break;
1464	case 2:
1465		regval = bus_space_read_2(sc->sc_iot, ioh, offset);
1466		break;
1467	case 4:
1468		regval = bus_space_read_4(sc->sc_iot, ioh, offset);
1469		break;
1470	}
1471
1472	dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n",
1473	    sc->sc_pmregs[reg].name,
1474	    sc->sc_pmregs[reg].addr, offset, regval);
1475	return (regval);
1476}
1477
1478/* Write to power management register */
1479void
1480acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval)
1481{
1482	bus_space_handle_t ioh;
1483	bus_size_t size;
1484
1485	/*
1486	 * For Hardware-reduced ACPI we also emulate PM1A_STS using
1487	 * SLEEP_STATUS_REG.
1488	 */
1489	if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_STS) {
1490		uint8_t value = (regval >> 8);
1491
1492		KASSERT(offset == 0);
1493		acpi_gasio(sc, ACPI_IOWRITE,
1494		    sc->sc_fadt->sleep_status_reg.address_space_id,
1495		    sc->sc_fadt->sleep_status_reg.address,
1496		    sc->sc_fadt->sleep_status_reg.register_bit_width / 8,
1497		    sc->sc_fadt->sleep_status_reg.access_size, &value);
1498		return;
1499	}
1500
1501	/*
1502	 * For Hardware-reduced ACPI we also emulate PM1A_CNT using
1503	 * SLEEP_CONTROL_REG.
1504	 */
1505	if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_CNT) {
1506		uint8_t value = (regval >> 8);
1507
1508		KASSERT(offset == 0);
1509		acpi_gasio(sc, ACPI_IOWRITE,
1510		    sc->sc_fadt->sleep_control_reg.address_space_id,
1511		    sc->sc_fadt->sleep_control_reg.address,
1512		    sc->sc_fadt->sleep_control_reg.register_bit_width / 8,
1513		    sc->sc_fadt->sleep_control_reg.access_size, &value);
1514		return;
1515	}
1516
1517	/* Special cases: 1A/1B blocks can be written with same value */
1518	switch (reg) {
1519	case ACPIREG_PM1_EN:
1520		acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval);
1521		acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval);
1522		break;
1523	case ACPIREG_PM1_STS:
1524		acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval);
1525		acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval);
1526		break;
1527	case ACPIREG_PM1_CNT:
1528		acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval);
1529		acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval);
1530		break;
1531	case ACPIREG_GPE_STS:
1532		dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n",
1533		    offset, sc->sc_fadt->gpe0_blk_len>>1,
1534		    sc->sc_fadt->gpe1_blk_len>>1, regval);
1535		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1536			reg = ACPIREG_GPE0_STS;
1537		}
1538		break;
1539	case ACPIREG_GPE_EN:
1540		dnprintf(50, "write GPE_EN  offset: %.2x %.2x %.2x %.2x\n",
1541		    offset, sc->sc_fadt->gpe0_blk_len>>1,
1542		    sc->sc_fadt->gpe1_blk_len>>1, regval);
1543		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1544			reg = ACPIREG_GPE0_EN;
1545		}
1546		break;
1547	}
1548
1549	/* All special case return here */
1550	if (reg >= ACPIREG_MAXREG)
1551		return;
1552
1553	ioh = sc->sc_pmregs[reg].ioh;
1554	size = sc->sc_pmregs[reg].size;
1555	if (size > sc->sc_pmregs[reg].access)
1556		size = sc->sc_pmregs[reg].access;
1557
1558	switch (size) {
1559	case 1:
1560		bus_space_write_1(sc->sc_iot, ioh, offset, regval);
1561		break;
1562	case 2:
1563		bus_space_write_2(sc->sc_iot, ioh, offset, regval);
1564		break;
1565	case 4:
1566		bus_space_write_4(sc->sc_iot, ioh, offset, regval);
1567		break;
1568	}
1569
1570	dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n",
1571	    sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval);
1572}
1573
1574/* Map Power Management registers */
1575void
1576acpi_map_pmregs(struct acpi_softc *sc)
1577{
1578	bus_addr_t addr;
1579	bus_size_t size, access;
1580	const char *name;
1581	int reg;
1582
1583	/* Registers don't exist on Hardware-reduced ACPI. */
1584	if (sc->sc_hw_reduced)
1585		return;
1586
1587	for (reg = 0; reg < ACPIREG_MAXREG; reg++) {
1588		size = 0;
1589		access = 0;
1590		switch (reg) {
1591		case ACPIREG_SMICMD:
1592			name = "smi";
1593			size = access = 1;
1594			addr = sc->sc_fadt->smi_cmd;
1595			break;
1596		case ACPIREG_PM1A_STS:
1597		case ACPIREG_PM1A_EN:
1598			name = "pm1a_sts";
1599			size = sc->sc_fadt->pm1_evt_len >> 1;
1600			addr = sc->sc_fadt->pm1a_evt_blk;
1601			access = 2;
1602			if (reg == ACPIREG_PM1A_EN && addr) {
1603				addr += size;
1604				name = "pm1a_en";
1605			}
1606			break;
1607		case ACPIREG_PM1A_CNT:
1608			name = "pm1a_cnt";
1609			size = sc->sc_fadt->pm1_cnt_len;
1610			addr = sc->sc_fadt->pm1a_cnt_blk;
1611			access = 2;
1612			break;
1613		case ACPIREG_PM1B_STS:
1614		case ACPIREG_PM1B_EN:
1615			name = "pm1b_sts";
1616			size = sc->sc_fadt->pm1_evt_len >> 1;
1617			addr = sc->sc_fadt->pm1b_evt_blk;
1618			access = 2;
1619			if (reg == ACPIREG_PM1B_EN && addr) {
1620				addr += size;
1621				name = "pm1b_en";
1622			}
1623			break;
1624		case ACPIREG_PM1B_CNT:
1625			name = "pm1b_cnt";
1626			size = sc->sc_fadt->pm1_cnt_len;
1627			addr = sc->sc_fadt->pm1b_cnt_blk;
1628			access = 2;
1629			break;
1630		case ACPIREG_PM2_CNT:
1631			name = "pm2_cnt";
1632			size = sc->sc_fadt->pm2_cnt_len;
1633			addr = sc->sc_fadt->pm2_cnt_blk;
1634			access = size;
1635			break;
1636#if 0
1637		case ACPIREG_PM_TMR:
1638			/* Allocated in acpitimer */
1639			name = "pm_tmr";
1640			size = sc->sc_fadt->pm_tmr_len;
1641			addr = sc->sc_fadt->pm_tmr_blk;
1642			access = 4;
1643			break;
1644#endif
1645		case ACPIREG_GPE0_STS:
1646		case ACPIREG_GPE0_EN:
1647			name = "gpe0_sts";
1648			size = sc->sc_fadt->gpe0_blk_len >> 1;
1649			addr = sc->sc_fadt->gpe0_blk;
1650			access = 1;
1651
1652			dnprintf(20, "gpe0 block len : %x\n",
1653			    sc->sc_fadt->gpe0_blk_len >> 1);
1654			dnprintf(20, "gpe0 block addr: %x\n",
1655			    sc->sc_fadt->gpe0_blk);
1656			if (reg == ACPIREG_GPE0_EN && addr) {
1657				addr += size;
1658				name = "gpe0_en";
1659			}
1660			break;
1661		case ACPIREG_GPE1_STS:
1662		case ACPIREG_GPE1_EN:
1663			name = "gpe1_sts";
1664			size = sc->sc_fadt->gpe1_blk_len >> 1;
1665			addr = sc->sc_fadt->gpe1_blk;
1666			access = 1;
1667
1668			dnprintf(20, "gpe1 block len : %x\n",
1669			    sc->sc_fadt->gpe1_blk_len >> 1);
1670			dnprintf(20, "gpe1 block addr: %x\n",
1671			    sc->sc_fadt->gpe1_blk);
1672			if (reg == ACPIREG_GPE1_EN && addr) {
1673				addr += size;
1674				name = "gpe1_en";
1675			}
1676			break;
1677		}
1678		if (size && addr) {
1679			dnprintf(50, "mapping: %.4lx %.4lx %s\n",
1680			    addr, size, name);
1681
1682			/* Size and address exist; map register space */
1683			bus_space_map(sc->sc_iot, addr, size, 0,
1684			    &sc->sc_pmregs[reg].ioh);
1685
1686			sc->sc_pmregs[reg].name = name;
1687			sc->sc_pmregs[reg].size = size;
1688			sc->sc_pmregs[reg].addr = addr;
1689			sc->sc_pmregs[reg].access = min(access, 4);
1690		}
1691	}
1692}
1693
1694void
1695acpi_unmap_pmregs(struct acpi_softc *sc)
1696{
1697	int reg;
1698
1699	for (reg = 0; reg < ACPIREG_MAXREG; reg++) {
1700		if (sc->sc_pmregs[reg].size && sc->sc_pmregs[reg].addr)
1701			bus_space_unmap(sc->sc_iot, sc->sc_pmregs[reg].ioh,
1702			    sc->sc_pmregs[reg].size);
1703	}
1704}
1705
1706int
1707acpi_enable(struct acpi_softc *sc)
1708{
1709	int idx;
1710
1711	acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable);
1712	idx = 0;
1713	do {
1714		if (idx++ > ACPIEN_RETRIES) {
1715			return ETIMEDOUT;
1716		}
1717	} while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN));
1718
1719	return 0;
1720}
1721
1722/* ACPI Workqueue support */
1723SIMPLEQ_HEAD(,acpi_taskq) acpi_taskq =
1724    SIMPLEQ_HEAD_INITIALIZER(acpi_taskq);
1725
1726void
1727acpi_addtask(struct acpi_softc *sc, void (*handler)(void *, int),
1728    void *arg0, int arg1)
1729{
1730	struct acpi_taskq *wq;
1731	int s;
1732
1733	wq = malloc(sizeof(*wq), M_DEVBUF, M_ZERO | M_NOWAIT);
1734	if (wq == NULL)
1735		return;
1736	wq->handler = handler;
1737	wq->arg0 = arg0;
1738	wq->arg1 = arg1;
1739
1740	s = spltty();
1741	SIMPLEQ_INSERT_TAIL(&acpi_taskq, wq, next);
1742	splx(s);
1743}
1744
1745int
1746acpi_dotask(struct acpi_softc *sc)
1747{
1748	struct acpi_taskq *wq;
1749	int s;
1750
1751	s = spltty();
1752	if (SIMPLEQ_EMPTY(&acpi_taskq)) {
1753		splx(s);
1754
1755		/* we don't have anything to do */
1756		return (0);
1757	}
1758	wq = SIMPLEQ_FIRST(&acpi_taskq);
1759	SIMPLEQ_REMOVE_HEAD(&acpi_taskq, next);
1760	splx(s);
1761
1762	wq->handler(wq->arg0, wq->arg1);
1763
1764	free(wq, M_DEVBUF, sizeof(*wq));
1765
1766	/* We did something */
1767	return (1);
1768}
1769
1770#ifndef SMALL_KERNEL
1771
1772int
1773is_ata(struct aml_node *node)
1774{
1775	return (aml_searchname(node, "_GTM") != NULL ||
1776	    aml_searchname(node, "_GTF") != NULL ||
1777	    aml_searchname(node, "_STM") != NULL ||
1778	    aml_searchname(node, "_SDD") != NULL);
1779}
1780
1781int
1782is_ejectable(struct aml_node *node)
1783{
1784	return (aml_searchname(node, "_EJ0") != NULL);
1785}
1786
1787int
1788is_ejectable_bay(struct aml_node *node)
1789{
1790	return ((is_ata(node) || is_ata(node->parent)) && is_ejectable(node));
1791}
1792
1793#if NWD > 0
1794int
1795acpiide_notify(struct aml_node *node, int ntype, void *arg)
1796{
1797	struct idechnl 		*ide = arg;
1798	struct acpi_softc 	*sc = ide->sc;
1799	struct pciide_softc 	*wsc;
1800	struct device 		*dev;
1801	int 			b,d,f;
1802	int64_t 		sta;
1803
1804	if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta) != 0)
1805		return (0);
1806
1807	dnprintf(10, "IDE notify! %s %d status:%llx\n", aml_nodename(node),
1808	    ntype, sta);
1809
1810	/* Walk device list looking for IDE device match */
1811	TAILQ_FOREACH(dev, &alldevs, dv_list) {
1812		if (strcmp(dev->dv_cfdata->cf_driver->cd_name, "pciide"))
1813			continue;
1814
1815		wsc = (struct pciide_softc *)dev;
1816		pci_decompose_tag(NULL, wsc->sc_tag, &b, &d, &f);
1817		if (b != ACPI_PCI_BUS(ide->addr) ||
1818		    d != ACPI_PCI_DEV(ide->addr) ||
1819		    f != ACPI_PCI_FN(ide->addr))
1820			continue;
1821		dnprintf(10, "Found pciide: %s %x.%x.%x channel:%llx\n",
1822		    dev->dv_xname, b,d,f, ide->chnl);
1823
1824		if (sta == 0 && ide->sta)
1825			wdcdetach(
1826			    &wsc->pciide_channels[ide->chnl].wdc_channel, 0);
1827		else if (sta && !ide->sta)
1828			wdcattach(
1829			    &wsc->pciide_channels[ide->chnl].wdc_channel);
1830		ide->sta = sta;
1831	}
1832	return (0);
1833}
1834
1835int
1836acpi_foundide(struct aml_node *node, void *arg)
1837{
1838	struct acpi_softc 	*sc = arg;
1839	struct aml_node 	*pp;
1840	struct idechnl 		*ide;
1841	union amlpci_t 		pi;
1842	int 			lvl;
1843
1844	/* Check if this is an ejectable bay */
1845	if (!is_ejectable_bay(node))
1846		return (0);
1847
1848	ide = malloc(sizeof(struct idechnl), M_DEVBUF, M_NOWAIT | M_ZERO);
1849	ide->sc = sc;
1850
1851	/* GTM/GTF can be at 2/3 levels:  pciX.ideX.channelX[.driveX] */
1852	lvl = 0;
1853	for (pp=node->parent; pp; pp=pp->parent) {
1854		lvl++;
1855		if (aml_searchname(pp, "_HID"))
1856			break;
1857	}
1858
1859	/* Get PCI address and channel */
1860	if (lvl == 3) {
1861		aml_evalinteger(sc, node->parent, "_ADR", 0, NULL,
1862		    &ide->chnl);
1863		aml_rdpciaddr(node->parent->parent, &pi);
1864		ide->addr = pi.addr;
1865	} else if (lvl == 4) {
1866		aml_evalinteger(sc, node->parent->parent, "_ADR", 0, NULL,
1867		    &ide->chnl);
1868		aml_rdpciaddr(node->parent->parent->parent, &pi);
1869		ide->addr = pi.addr;
1870	}
1871	dnprintf(10, "%s %llx channel:%llx\n",
1872	    aml_nodename(node), ide->addr, ide->chnl);
1873
1874	aml_evalinteger(sc, node, "_STA", 0, NULL, &ide->sta);
1875	dnprintf(10, "Got Initial STA: %llx\n", ide->sta);
1876
1877	aml_register_notify(node, "acpiide", acpiide_notify, ide, 0);
1878	return (0);
1879}
1880#endif /* NWD > 0 */
1881
1882void
1883acpi_sleep_task(void *arg0, int sleepmode)
1884{
1885	struct acpi_softc *sc = arg0;
1886	struct acpi_ac *ac;
1887	struct acpi_bat *bat;
1888	struct acpi_sbs *sbs;
1889
1890	/* System goes to sleep here.. */
1891	acpi_sleep_state(sc, sleepmode);
1892
1893	/* AC and battery information needs refreshing */
1894	SLIST_FOREACH(ac, &sc->sc_ac, aac_link)
1895		aml_notify(ac->aac_softc->sc_devnode, 0x80);
1896	SLIST_FOREACH(bat, &sc->sc_bat, aba_link)
1897		aml_notify(bat->aba_softc->sc_devnode, 0x80);
1898	SLIST_FOREACH(sbs, &sc->sc_sbs, asbs_link)
1899		aml_notify(sbs->asbs_softc->sc_devnode, 0x80);
1900}
1901
1902#endif /* SMALL_KERNEL */
1903
1904void
1905acpi_reset(void)
1906{
1907	uint32_t		 reset_as, reset_len;
1908	uint32_t		 value;
1909	struct acpi_softc	*sc = acpi_softc;
1910	struct acpi_fadt	*fadt = sc->sc_fadt;
1911
1912	if (acpi_enabled == 0)
1913		return;
1914
1915	/*
1916	 * RESET_REG_SUP is not properly set in some implementations,
1917	 * but not testing against it breaks more machines than it fixes
1918	 */
1919	if (fadt->hdr_revision <= 1 ||
1920	    !(fadt->flags & FADT_RESET_REG_SUP) || fadt->reset_reg.address == 0)
1921		return;
1922
1923	value = fadt->reset_value;
1924
1925	reset_as = fadt->reset_reg.register_bit_width / 8;
1926	if (reset_as == 0)
1927		reset_as = 1;
1928
1929	reset_len = fadt->reset_reg.access_size;
1930	if (reset_len == 0)
1931		reset_len = reset_as;
1932
1933	acpi_gasio(sc, ACPI_IOWRITE,
1934	    fadt->reset_reg.address_space_id,
1935	    fadt->reset_reg.address, reset_as, reset_len, &value);
1936
1937	delay(100000);
1938}
1939
1940void
1941acpi_gpe_task(void *arg0, int gpe)
1942{
1943	struct acpi_softc *sc = acpi_softc;
1944	struct gpe_block *pgpe = &sc->gpe_table[gpe];
1945
1946	dnprintf(10, "handle gpe: %x\n", gpe);
1947	if (pgpe->handler && pgpe->active) {
1948		pgpe->active = 0;
1949		pgpe->handler(sc, gpe, pgpe->arg);
1950	}
1951}
1952
1953void
1954acpi_pbtn_task(void *arg0, int dummy)
1955{
1956	struct acpi_softc *sc = arg0;
1957	uint16_t en;
1958	int s;
1959
1960	dnprintf(1,"power button pressed\n");
1961
1962	/* Reset the latch and re-enable the GPE */
1963	s = spltty();
1964	en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
1965	acpi_write_pmreg(sc, ACPIREG_PM1_EN,  0,
1966	    en | ACPI_PM1_PWRBTN_EN);
1967	splx(s);
1968
1969	acpi_addtask(sc, acpi_powerdown_task, sc, 0);
1970}
1971
1972void
1973acpi_sbtn_task(void *arg0, int dummy)
1974{
1975	struct acpi_softc *sc = arg0;
1976	uint16_t en;
1977	int s;
1978
1979	dnprintf(1,"sleep button pressed\n");
1980	aml_notify_dev(ACPI_DEV_SBD, 0x80);
1981
1982	/* Reset the latch and re-enable the GPE */
1983	s = spltty();
1984	en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
1985	acpi_write_pmreg(sc, ACPIREG_PM1_EN,  0,
1986	    en | ACPI_PM1_SLPBTN_EN);
1987	splx(s);
1988}
1989
1990void
1991acpi_powerdown_task(void *arg0, int dummy)
1992{
1993	extern int allowpowerdown;
1994
1995	if (allowpowerdown == 1) {
1996		allowpowerdown = 0;
1997		prsignal(initprocess, SIGUSR2);
1998	}
1999}
2000
2001int
2002acpi_interrupt(void *arg)
2003{
2004	struct acpi_softc *sc = (struct acpi_softc *)arg;
2005	uint32_t processed = 0, idx, jdx;
2006	uint16_t sts, en;
2007
2008	dnprintf(40, "ACPI Interrupt\n");
2009	for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
2010		sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3);
2011		en  = acpi_read_pmreg(sc, ACPIREG_GPE_EN,  idx>>3);
2012		if (en & sts) {
2013			dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts,
2014			    en);
2015			/* Mask the GPE until it is serviced */
2016			acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts);
2017			for (jdx = 0; jdx < 8; jdx++) {
2018				if (en & sts & (1L << jdx)) {
2019					/* Signal this GPE */
2020					sc->gpe_table[idx+jdx].active = 1;
2021					dnprintf(10, "queue gpe: %x\n",
2022					    idx+jdx);
2023					acpi_addtask(sc, acpi_gpe_task, NULL,
2024					    idx+jdx);
2025
2026					/*
2027					 * Edge interrupts need their STS bits
2028					 * cleared now.  Level interrupts will
2029					 * have their STS bits cleared just
2030					 * before they are re-enabled.
2031					 */
2032					if (sc->gpe_table[idx+jdx].edge)
2033						acpi_write_pmreg(sc,
2034						    ACPIREG_GPE_STS, idx>>3,
2035						    1L << jdx);
2036					processed = 1;
2037				}
2038			}
2039		}
2040	}
2041
2042	sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0);
2043	en  = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2044	if (sts & en) {
2045		dnprintf(10,"GEN interrupt: %.4x\n", sts & en);
2046		sts &= en;
2047		if (sts & ACPI_PM1_PWRBTN_STS) {
2048			/* Mask and acknowledge */
2049			en &= ~ACPI_PM1_PWRBTN_EN;
2050			acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2051			acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
2052			    ACPI_PM1_PWRBTN_STS);
2053			sts &= ~ACPI_PM1_PWRBTN_STS;
2054
2055			acpi_addtask(sc, acpi_pbtn_task, sc, 0);
2056		}
2057		if (sts & ACPI_PM1_SLPBTN_STS) {
2058			/* Mask and acknowledge */
2059			en &= ~ACPI_PM1_SLPBTN_EN;
2060			acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2061			acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
2062			    ACPI_PM1_SLPBTN_STS);
2063			sts &= ~ACPI_PM1_SLPBTN_STS;
2064
2065			acpi_addtask(sc, acpi_sbtn_task, sc, 0);
2066		}
2067		if (sts) {
2068			printf("%s: PM1 stuck (en 0x%x st 0x%x), clearing\n",
2069			    sc->sc_dev.dv_xname, en, sts);
2070			acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts);
2071			acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, sts);
2072		}
2073		processed = 1;
2074	}
2075
2076	if (processed) {
2077		acpi_wakeup(sc);
2078	}
2079
2080	return (processed);
2081}
2082
2083int
2084acpi_add_device(struct aml_node *node, void *arg)
2085{
2086	static int nacpicpus = 0;
2087	struct device *self = arg;
2088	struct acpi_softc *sc = arg;
2089	struct acpi_attach_args aaa;
2090	struct aml_value res;
2091	CPU_INFO_ITERATOR cii;
2092	struct cpu_info *ci;
2093	int proc_id = -1;
2094
2095	memset(&aaa, 0, sizeof(aaa));
2096	aaa.aaa_node = node;
2097	aaa.aaa_iot = sc->sc_iot;
2098	aaa.aaa_memt = sc->sc_memt;
2099	if (node == NULL || node->value == NULL)
2100		return 0;
2101
2102	switch (node->value->type) {
2103	case AML_OBJTYPE_PROCESSOR:
2104		if (nacpicpus >= ncpus)
2105			return 0;
2106		if (aml_evalnode(sc, aaa.aaa_node, 0, NULL, &res) == 0) {
2107			if (res.type == AML_OBJTYPE_PROCESSOR)
2108				proc_id = res.v_processor.proc_id;
2109			aml_freevalue(&res);
2110		}
2111		CPU_INFO_FOREACH(cii, ci) {
2112			if (ci->ci_acpi_proc_id == proc_id)
2113				break;
2114		}
2115		if (ci == NULL)
2116			return 0;
2117		nacpicpus++;
2118
2119		aaa.aaa_name = "acpicpu";
2120		break;
2121	case AML_OBJTYPE_THERMZONE:
2122		aaa.aaa_name = "acpitz";
2123		break;
2124	case AML_OBJTYPE_POWERRSRC:
2125		aaa.aaa_name = "acpipwrres";
2126		break;
2127	default:
2128		return 0;
2129	}
2130	config_found(self, &aaa, acpi_print);
2131	return 0;
2132}
2133
2134void
2135acpi_enable_onegpe(struct acpi_softc *sc, int gpe)
2136{
2137	uint8_t mask, en;
2138
2139	/* Read enabled register */
2140	mask = (1L << (gpe & 7));
2141	en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3);
2142	dnprintf(50, "enabling GPE %.2x (current: %sabled) %.2x\n",
2143	    gpe, (en & mask) ? "en" : "dis", en);
2144	acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask);
2145}
2146
2147/* Clear all GPEs */
2148void
2149acpi_disable_allgpes(struct acpi_softc *sc)
2150{
2151	int idx;
2152
2153	for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
2154		acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx >> 3, 0);
2155		acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx >> 3, -1);
2156	}
2157}
2158
2159/* Enable runtime GPEs */
2160void
2161acpi_enable_rungpes(struct acpi_softc *sc)
2162{
2163	int idx;
2164
2165	for (idx = 0; idx < sc->sc_lastgpe; idx++)
2166		if (sc->gpe_table[idx].handler)
2167			acpi_enable_onegpe(sc, idx);
2168}
2169
2170/* Enable wakeup GPEs */
2171void
2172acpi_enable_wakegpes(struct acpi_softc *sc, int state)
2173{
2174	struct acpi_wakeq *wentry;
2175
2176	SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) {
2177		dnprintf(10, "%.4s(S%d) gpe %.2x\n", wentry->q_node->name,
2178		    wentry->q_state,
2179		    wentry->q_gpe);
2180		if (state <= wentry->q_state)
2181			acpi_enable_onegpe(sc, wentry->q_gpe);
2182	}
2183}
2184
2185int
2186acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler)
2187    (struct acpi_softc *, int, void *), void *arg, int edge)
2188{
2189	struct gpe_block *ptbl;
2190
2191	ptbl = acpi_find_gpe(sc, gpe);
2192	if (ptbl == NULL || handler == NULL)
2193		return -EINVAL;
2194	if (ptbl->handler != NULL)
2195		printf("%s: GPE 0x%.2x already enabled\n", DEVNAME(sc), gpe);
2196
2197	dnprintf(50, "Adding GPE handler 0x%.2x (%s)\n", gpe,
2198	    edge ? "edge" : "level");
2199	ptbl->handler = handler;
2200	ptbl->arg = arg;
2201	ptbl->edge = edge;
2202
2203	return (0);
2204}
2205
2206int
2207acpi_gpe(struct acpi_softc *sc, int gpe, void *arg)
2208{
2209	struct aml_node *node = arg;
2210	uint8_t mask, en;
2211
2212	dnprintf(10, "handling GPE %.2x\n", gpe);
2213	aml_evalnode(sc, node, 0, NULL, NULL);
2214
2215	mask = (1L << (gpe & 7));
2216	if (!sc->gpe_table[gpe].edge)
2217		acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask);
2218	en = acpi_read_pmreg(sc, ACPIREG_GPE_EN,  gpe>>3);
2219	acpi_write_pmreg(sc, ACPIREG_GPE_EN,  gpe>>3, en | mask);
2220	return (0);
2221}
2222
2223/* Discover Devices that can wakeup the system
2224 * _PRW returns a package
2225 *  pkg[0] = integer (FADT gpe bit) or package (gpe block,gpe bit)
2226 *  pkg[1] = lowest sleep state
2227 *  pkg[2+] = power resource devices (optional)
2228 *
2229 * To enable wakeup devices:
2230 *    Evaluate _ON method in each power resource device
2231 *    Evaluate _PSW method
2232 */
2233int
2234acpi_foundprw(struct aml_node *node, void *arg)
2235{
2236	struct acpi_softc *sc = arg;
2237	struct acpi_wakeq *wq;
2238	int64_t sta;
2239
2240	if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &sta))
2241		sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
2242
2243	if ((sta & STA_PRESENT) == 0)
2244		return 0;
2245
2246	wq = malloc(sizeof(struct acpi_wakeq), M_DEVBUF, M_NOWAIT | M_ZERO);
2247	if (wq == NULL)
2248		return 0;
2249
2250	wq->q_wakepkg = malloc(sizeof(struct aml_value), M_DEVBUF,
2251	    M_NOWAIT | M_ZERO);
2252	if (wq->q_wakepkg == NULL) {
2253		free(wq, M_DEVBUF, sizeof(*wq));
2254		return 0;
2255	}
2256	dnprintf(10, "Found _PRW (%s)\n", node->parent->name);
2257	aml_evalnode(sc, node, 0, NULL, wq->q_wakepkg);
2258	wq->q_node = node->parent;
2259	wq->q_gpe = -1;
2260
2261	/* Get GPE of wakeup device, and lowest sleep level */
2262	if (wq->q_wakepkg->type == AML_OBJTYPE_PACKAGE &&
2263	    wq->q_wakepkg->length >= 2) {
2264		if (wq->q_wakepkg->v_package[0]->type == AML_OBJTYPE_INTEGER)
2265			wq->q_gpe = wq->q_wakepkg->v_package[0]->v_integer;
2266		if (wq->q_wakepkg->v_package[1]->type == AML_OBJTYPE_INTEGER)
2267			wq->q_state = wq->q_wakepkg->v_package[1]->v_integer;
2268	}
2269	SIMPLEQ_INSERT_TAIL(&sc->sc_wakedevs, wq, q_next);
2270	return 0;
2271}
2272
2273struct gpe_block *
2274acpi_find_gpe(struct acpi_softc *sc, int gpe)
2275{
2276	if (gpe >= sc->sc_lastgpe)
2277		return NULL;
2278	return &sc->gpe_table[gpe];
2279}
2280
2281void
2282acpi_init_gpes(struct acpi_softc *sc)
2283{
2284	struct aml_node *gpe;
2285	char name[12];
2286	int  idx, ngpe;
2287
2288	sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2;
2289	if (sc->sc_fadt->gpe1_blk_len) {
2290	}
2291	dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe);
2292
2293	/* Allocate GPE table */
2294	sc->gpe_table = mallocarray(sc->sc_lastgpe, sizeof(struct gpe_block),
2295	    M_DEVBUF, M_WAITOK | M_ZERO);
2296
2297	ngpe = 0;
2298
2299	/* Clear GPE status */
2300	acpi_disable_allgpes(sc);
2301	for (idx = 0; idx < sc->sc_lastgpe; idx++) {
2302		/* Search Level-sensitive GPES */
2303		snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx);
2304		gpe = aml_searchname(&aml_root, name);
2305		if (gpe != NULL)
2306			acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, 0);
2307		if (gpe == NULL) {
2308			/* Search Edge-sensitive GPES */
2309			snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx);
2310			gpe = aml_searchname(&aml_root, name);
2311			if (gpe != NULL)
2312				acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, 1);
2313		}
2314	}
2315	aml_find_node(&aml_root, "_PRW", acpi_foundprw, sc);
2316	sc->sc_maxgpe = ngpe;
2317}
2318
2319void
2320acpi_init_pm(struct acpi_softc *sc)
2321{
2322	sc->sc_tts = aml_searchname(&aml_root, "_TTS");
2323	sc->sc_pts = aml_searchname(&aml_root, "_PTS");
2324	sc->sc_wak = aml_searchname(&aml_root, "_WAK");
2325	sc->sc_bfs = aml_searchname(&aml_root, "_BFS");
2326	sc->sc_gts = aml_searchname(&aml_root, "_GTS");
2327	sc->sc_sst = aml_searchname(&aml_root, "_SI_._SST");
2328}
2329
2330#ifndef SMALL_KERNEL
2331
2332void
2333acpi_init_states(struct acpi_softc *sc)
2334{
2335	struct aml_value res;
2336	char name[8];
2337	int i;
2338
2339	printf("\n%s: sleep states", DEVNAME(sc));
2340	for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
2341		snprintf(name, sizeof(name), "_S%d_", i);
2342		sc->sc_sleeptype[i].slp_typa = -1;
2343		sc->sc_sleeptype[i].slp_typb = -1;
2344		if (aml_evalname(sc, &aml_root, name, 0, NULL, &res) == 0) {
2345			if (res.type == AML_OBJTYPE_PACKAGE) {
2346				sc->sc_sleeptype[i].slp_typa =
2347				    aml_val2int(res.v_package[0]);
2348				sc->sc_sleeptype[i].slp_typb =
2349				    aml_val2int(res.v_package[1]);
2350				printf(" S%d", i);
2351			}
2352			aml_freevalue(&res);
2353		}
2354	}
2355}
2356
2357void
2358acpi_sleep_pm(struct acpi_softc *sc, int state)
2359{
2360	uint16_t rega, regb, regra, regrb;
2361	int retry = 0;
2362
2363	intr_disable();
2364
2365	/* Clear WAK_STS bit */
2366	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS);
2367
2368	/* Disable BM arbitration at deep sleep and beyond */
2369	if (state >= ACPI_STATE_S3 &&
2370	    sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len)
2371		acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, ACPI_PM2_ARB_DIS);
2372
2373	/* Write SLP_TYPx values */
2374	rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0);
2375	regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0);
2376	rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2377	regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2378	rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa);
2379	regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb);
2380	acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
2381	acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
2382
2383	/* Loop on WAK_STS, setting the SLP_EN bits once in a while */
2384	rega |= ACPI_PM1_SLP_EN;
2385	regb |= ACPI_PM1_SLP_EN;
2386	while (1) {
2387		if (retry == 0) {
2388			acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
2389			acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
2390		}
2391		retry = (retry + 1) % 100000;
2392
2393		regra = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0);
2394		regrb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0);
2395		if ((regra & ACPI_PM1_WAK_STS) ||
2396		    (regrb & ACPI_PM1_WAK_STS))
2397			break;
2398	}
2399}
2400
2401uint32_t acpi_force_bm;
2402
2403void
2404acpi_resume_pm(struct acpi_softc *sc, int fromstate)
2405{
2406	uint16_t rega, regb, en;
2407
2408	/* Write SLP_TYPx values */
2409	rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0);
2410	regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0);
2411	rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2412	regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2413	rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typa);
2414	regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typb);
2415	acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
2416	acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
2417
2418	/* Force SCI_EN on resume to fix horribly broken machines */
2419	acpi_write_pmreg(sc, ACPIREG_PM1_CNT, 0,
2420	    ACPI_PM1_SCI_EN | acpi_force_bm);
2421
2422	/* Clear fixed event status */
2423	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
2424
2425	/* acpica-reference.pdf page 148 says do not call _BFS */
2426	/* 1st resume AML step: _BFS(fromstate) */
2427	aml_node_setval(sc, sc->sc_bfs, fromstate);
2428
2429	/* Enable runtime GPEs */
2430	acpi_disable_allgpes(sc);
2431	acpi_enable_rungpes(sc);
2432
2433	acpi_indicator(sc, ACPI_SST_WAKING);
2434
2435	/* 2nd resume AML step: _WAK(fromstate) */
2436	aml_node_setval(sc, sc->sc_wak, fromstate);
2437
2438	/* Clear WAK_STS bit */
2439	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS);
2440
2441	en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2442	if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON))
2443		en |= ACPI_PM1_PWRBTN_EN;
2444	if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON))
2445		en |= ACPI_PM1_SLPBTN_EN;
2446	acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2447
2448	/*
2449	 * If PM2 exists, re-enable BM arbitration (reportedly some
2450	 * BIOS forget to)
2451	 */
2452	if (sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) {
2453		rega = acpi_read_pmreg(sc, ACPIREG_PM2_CNT, 0);
2454		rega &= ~ACPI_PM2_ARB_DIS;
2455		acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, rega);
2456	}
2457}
2458
2459/* Set the indicator light to some state */
2460void
2461acpi_indicator(struct acpi_softc *sc, int led_state)
2462{
2463	static int save_led_state = -1;
2464
2465	if (save_led_state != led_state) {
2466		aml_node_setval(sc, sc->sc_sst, led_state);
2467		save_led_state = led_state;
2468	}
2469}
2470
2471
2472int
2473acpi_sleep_state(struct acpi_softc *sc, int sleepmode)
2474{
2475	extern int perflevel;
2476	extern int lid_action;
2477	int error = ENXIO;
2478	size_t rndbuflen = 0;
2479	char *rndbuf = NULL;
2480	int state, s;
2481#if NSOFTRAID > 0
2482	extern void sr_quiesce(void);
2483#endif
2484
2485	switch (sleepmode) {
2486	case ACPI_SLEEP_SUSPEND:
2487		state = ACPI_STATE_S3;
2488		break;
2489	case ACPI_SLEEP_HIBERNATE:
2490		state = ACPI_STATE_S4;
2491		break;
2492	default:
2493		return (EOPNOTSUPP);
2494	}
2495
2496	if (sc->sc_sleeptype[state].slp_typa == -1 ||
2497	    sc->sc_sleeptype[state].slp_typb == -1) {
2498		printf("%s: state S%d unavailable\n",
2499		    sc->sc_dev.dv_xname, state);
2500		return (EOPNOTSUPP);
2501	}
2502
2503	/* 1st suspend AML step: _TTS(tostate) */
2504	if (aml_node_setval(sc, sc->sc_tts, state) != 0)
2505		goto fail_tts;
2506	acpi_indicator(sc, ACPI_SST_WAKING);	/* blink */
2507
2508#if NWSDISPLAY > 0
2509	/*
2510	 * Temporarily release the lock to prevent the X server from
2511	 * blocking on setting the display brightness.
2512	 */
2513	rw_exit_write(&sc->sc_lck);
2514	wsdisplay_suspend();
2515	rw_enter_write(&sc->sc_lck);
2516#endif /* NWSDISPLAY > 0 */
2517
2518	stop_periodic_resettodr();
2519
2520#ifdef HIBERNATE
2521	if (sleepmode == ACPI_SLEEP_HIBERNATE) {
2522		/*
2523		 * Discard useless memory to reduce fragmentation,
2524		 * and attempt to create a hibernate work area
2525		 */
2526		hibernate_suspend_bufcache();
2527		uvmpd_hibernate();
2528		if (hibernate_alloc()) {
2529			printf("%s: failed to allocate hibernate memory\n",
2530			    sc->sc_dev.dv_xname);
2531			goto fail_alloc;
2532		}
2533	}
2534#endif /* HIBERNATE */
2535
2536	sensor_quiesce();
2537	if (config_suspend_all(DVACT_QUIESCE))
2538		goto fail_quiesce;
2539
2540	vfs_stall(curproc, 1);
2541#if NSOFTRAID > 0
2542	sr_quiesce();
2543#endif
2544	bufq_quiesce();
2545
2546#ifdef MULTIPROCESSOR
2547	acpi_sleep_mp();
2548#endif
2549
2550#ifdef HIBERNATE
2551	if (sleepmode == ACPI_SLEEP_HIBERNATE) {
2552		/*
2553		 * We've just done various forms of syncing to disk
2554		 * churned lots of memory dirty.  We don't need to
2555		 * save that dirty memory to hibernate, so release it.
2556		 */
2557		hibernate_suspend_bufcache();
2558		uvmpd_hibernate();
2559	}
2560#endif /* HIBERNATE */
2561
2562	resettodr();
2563
2564	s = splhigh();
2565	intr_disable();	/* PSL_I for resume; PIC/APIC broken until repair */
2566	cold = 2;	/* Force other code to delay() instead of tsleep() */
2567
2568	if (config_suspend_all(DVACT_SUSPEND) != 0)
2569		goto fail_suspend;
2570	acpi_sleep_clocks(sc, state);
2571
2572	suspend_randomness();
2573
2574	/* 2nd suspend AML step: _PTS(tostate) */
2575	if (aml_node_setval(sc, sc->sc_pts, state) != 0)
2576		goto fail_pts;
2577
2578	acpibtn_enable_psw();	/* enable _LID for wakeup */
2579	acpi_indicator(sc, ACPI_SST_SLEEPING);
2580
2581	/* 3rd suspend AML step: _GTS(tostate) */
2582	aml_node_setval(sc, sc->sc_gts, state);
2583
2584	/* Clear fixed event status */
2585	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
2586
2587	/* Enable wake GPEs */
2588	acpi_disable_allgpes(sc);
2589	acpi_enable_wakegpes(sc, state);
2590
2591	/* Sleep */
2592	sc->sc_state = state;
2593	error = acpi_sleep_cpu(sc, state);
2594	sc->sc_state = ACPI_STATE_S0;
2595	/* Resume */
2596
2597#ifdef HIBERNATE
2598	if (sleepmode == ACPI_SLEEP_HIBERNATE) {
2599		uvm_pmr_dirty_everything();
2600		hib_getentropy(&rndbuf, &rndbuflen);
2601	}
2602#endif /* HIBERNATE */
2603
2604	acpi_resume_clocks(sc);		/* AML may need clocks */
2605	acpi_resume_pm(sc, state);
2606	acpi_resume_cpu(sc);
2607
2608fail_pts:
2609	config_suspend_all(DVACT_RESUME);
2610
2611fail_suspend:
2612	cold = 0;
2613	intr_enable();
2614	splx(s);
2615
2616	acpibtn_disable_psw();		/* disable _LID for wakeup */
2617	inittodr(time_second);
2618
2619	/* 3rd resume AML step: _TTS(runstate) */
2620	aml_node_setval(sc, sc->sc_tts, sc->sc_state);
2621
2622	/* force RNG upper level reseed */
2623	resume_randomness(rndbuf, rndbuflen);
2624
2625#ifdef MULTIPROCESSOR
2626	acpi_resume_mp();
2627#endif
2628
2629	vfs_stall(curproc, 0);
2630	bufq_restart();
2631
2632fail_quiesce:
2633	config_suspend_all(DVACT_WAKEUP);
2634	sensor_restart();
2635
2636#ifdef HIBERNATE
2637	if (sleepmode == ACPI_SLEEP_HIBERNATE) {
2638		hibernate_free();
2639fail_alloc:
2640		hibernate_resume_bufcache();
2641	}
2642#endif /* HIBERNATE */
2643
2644	start_periodic_resettodr();
2645
2646#if NWSDISPLAY > 0
2647	rw_exit_write(&sc->sc_lck);
2648	wsdisplay_resume();
2649	rw_enter_write(&sc->sc_lck);
2650#endif /* NWSDISPLAY > 0 */
2651
2652	sys_sync(curproc, NULL, NULL);
2653
2654	/* Restore hw.setperf */
2655	if (cpu_setperf != NULL)
2656		cpu_setperf(perflevel);
2657
2658	acpi_record_event(sc, APM_NORMAL_RESUME);
2659	acpi_indicator(sc, ACPI_SST_WORKING);
2660
2661	/* If we woke up but all the lids are closed, go back to sleep */
2662	if (acpibtn_numopenlids() == 0 && lid_action != 0)
2663		acpi_addtask(sc, acpi_sleep_task, sc, sleepmode);
2664
2665fail_tts:
2666	return (error);
2667}
2668
2669/* XXX
2670 * We are going to do AML execution but are not in the acpi thread.
2671 * We do not know if the acpi thread is sleeping on acpiec in some
2672 * intermediate context.  Wish us luck.
2673 */
2674void
2675acpi_powerdown(void)
2676{
2677	int state = ACPI_STATE_S5, s;
2678	struct acpi_softc *sc = acpi_softc;
2679
2680	if (acpi_enabled == 0)
2681		return;
2682
2683	s = splhigh();
2684	intr_disable();
2685	cold = 1;
2686
2687	/* 1st powerdown AML step: _PTS(tostate) */
2688	aml_node_setval(sc, sc->sc_pts, state);
2689
2690	acpi_disable_allgpes(sc);
2691	acpi_enable_wakegpes(sc, state);
2692
2693	/* 2nd powerdown AML step: _GTS(tostate) */
2694	aml_node_setval(sc, sc->sc_gts, state);
2695
2696	acpi_sleep_pm(sc, state);
2697	panic("acpi S5 transition did not happen");
2698	while (1)
2699		;
2700}
2701
2702int
2703acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas, bus_addr_t base,
2704    bus_size_t size, bus_space_handle_t *pioh, bus_space_tag_t *piot)
2705{
2706	int iospace = GAS_SYSTEM_IOSPACE;
2707
2708	/* No GAS structure, default to I/O space */
2709	if (gas != NULL) {
2710		base += gas->address;
2711		iospace = gas->address_space_id;
2712	}
2713	switch (iospace) {
2714	case GAS_SYSTEM_MEMORY:
2715		*piot = sc->sc_memt;
2716		break;
2717	case GAS_SYSTEM_IOSPACE:
2718		*piot = sc->sc_iot;
2719		break;
2720	default:
2721		return -1;
2722	}
2723	if (bus_space_map(*piot, base, size, 0, pioh))
2724		return -1;
2725
2726	return 0;
2727}
2728
2729#endif /* SMALL_KERNEL */
2730
2731void
2732acpi_wakeup(void *arg)
2733{
2734	struct acpi_softc  *sc = (struct acpi_softc *)arg;
2735
2736	sc->sc_threadwaiting = 0;
2737	wakeup(sc);
2738}
2739
2740
2741void
2742acpi_thread(void *arg)
2743{
2744	struct acpi_thread *thread = arg;
2745	struct acpi_softc  *sc = thread->sc;
2746	extern int aml_busy;
2747	int s;
2748
2749	/* AML/SMI cannot be trusted -- only run on the BSP */
2750	sched_peg_curproc(&cpu_info_primary);
2751
2752	rw_enter_write(&sc->sc_lck);
2753
2754	/*
2755	 * If we have an interrupt handler, we can get notification
2756	 * when certain status bits changes in the ACPI registers,
2757	 * so let us enable some events we can forward to userland
2758	 */
2759	if (sc->sc_interrupt) {
2760		int16_t en;
2761
2762		dnprintf(1,"slpbtn:%c  pwrbtn:%c\n",
2763		    sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y',
2764		    sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y');
2765		dnprintf(10, "Enabling acpi interrupts...\n");
2766		sc->sc_threadwaiting = 1;
2767
2768		/* Enable Sleep/Power buttons if they exist */
2769		s = spltty();
2770		en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2771		if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON))
2772			en |= ACPI_PM1_PWRBTN_EN;
2773		if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON))
2774			en |= ACPI_PM1_SLPBTN_EN;
2775		acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2776
2777		/* Enable handled GPEs here */
2778		acpi_enable_rungpes(sc);
2779		splx(s);
2780	}
2781
2782	while (thread->running) {
2783		s = spltty();
2784		while (sc->sc_threadwaiting) {
2785			dnprintf(10, "acpi thread going to sleep...\n");
2786			rw_exit_write(&sc->sc_lck);
2787			tsleep(sc, PWAIT, "acpi0", 0);
2788			rw_enter_write(&sc->sc_lck);
2789		}
2790		sc->sc_threadwaiting = 1;
2791		splx(s);
2792		if (aml_busy) {
2793			panic("thread woke up to find aml was busy");
2794			continue;
2795		}
2796
2797		/* Run ACPI taskqueue */
2798		while(acpi_dotask(acpi_softc))
2799			;
2800	}
2801	free(thread, M_DEVBUF, sizeof(*thread));
2802
2803	kthread_exit(0);
2804}
2805
2806void
2807acpi_create_thread(void *arg)
2808{
2809	struct acpi_softc *sc = arg;
2810
2811	if (kthread_create(acpi_thread, sc->sc_thread, NULL, DEVNAME(sc))
2812	    != 0)
2813		printf("%s: unable to create isr thread, GPEs disabled\n",
2814		    DEVNAME(sc));
2815}
2816
2817int
2818acpi_foundec(struct aml_node *node, void *arg)
2819{
2820	struct acpi_softc	*sc = (struct acpi_softc *)arg;
2821	struct device		*self = (struct device *)arg;
2822	const char		*dev;
2823	struct aml_value	 res;
2824	struct acpi_attach_args	aaa;
2825
2826	if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
2827		return 0;
2828
2829	switch (res.type) {
2830	case AML_OBJTYPE_STRING:
2831		dev = res.v_string;
2832		break;
2833	case AML_OBJTYPE_INTEGER:
2834		dev = aml_eisaid(aml_val2int(&res));
2835		break;
2836	default:
2837		dev = "unknown";
2838		break;
2839	}
2840
2841	if (strcmp(dev, ACPI_DEV_ECD))
2842		return 0;
2843
2844	/* Check if we're already attached */
2845	if (sc->sc_ec && sc->sc_ec->sc_devnode == node->parent)
2846		return 0;
2847
2848	memset(&aaa, 0, sizeof(aaa));
2849	aaa.aaa_iot = sc->sc_iot;
2850	aaa.aaa_memt = sc->sc_memt;
2851	aaa.aaa_node = node->parent;
2852	aaa.aaa_dev = dev;
2853	aaa.aaa_name = "acpiec";
2854	config_found(self, &aaa, acpi_print);
2855	aml_freevalue(&res);
2856
2857	return 0;
2858}
2859
2860int
2861acpi_foundsony(struct aml_node *node, void *arg)
2862{
2863	struct acpi_softc *sc = (struct acpi_softc *)arg;
2864	struct device *self = (struct device *)arg;
2865	struct acpi_attach_args aaa;
2866
2867	memset(&aaa, 0, sizeof(aaa));
2868	aaa.aaa_iot = sc->sc_iot;
2869	aaa.aaa_memt = sc->sc_memt;
2870	aaa.aaa_node = node->parent;
2871	aaa.aaa_name = "acpisony";
2872
2873	config_found(self, &aaa, acpi_print);
2874
2875	return 0;
2876}
2877
2878/* Support for _DSD Device Properties. */
2879
2880uint32_t
2881acpi_getpropint(struct aml_node *node, const char *prop, uint32_t defval)
2882{
2883	struct aml_value dsd;
2884	int i;
2885
2886	/* daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
2887	static uint8_t prop_guid[] = {
2888		0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
2889		0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01,
2890	};
2891
2892	if (aml_evalname(acpi_softc, node, "_DSD", 0, NULL, &dsd))
2893		return defval;
2894
2895	if (dsd.type != AML_OBJTYPE_PACKAGE || dsd.length != 2 ||
2896	    dsd.v_package[0]->type != AML_OBJTYPE_BUFFER ||
2897	    dsd.v_package[1]->type != AML_OBJTYPE_PACKAGE)
2898		return defval;
2899
2900	/* Check UUID. */
2901	if (dsd.v_package[0]->length != sizeof(prop_guid) ||
2902	    memcmp(dsd.v_package[0]->v_buffer, prop_guid,
2903	    sizeof(prop_guid)) != 0)
2904		return defval;
2905
2906	/* Check properties. */
2907	for (i = 0; i < dsd.v_package[1]->length; i++) {
2908		struct aml_value *res = dsd.v_package[1]->v_package[i];
2909
2910		if (res->type != AML_OBJTYPE_PACKAGE || res->length != 2 ||
2911		    res->v_package[0]->type != AML_OBJTYPE_STRING ||
2912		    res->v_package[1]->type != AML_OBJTYPE_INTEGER)
2913			continue;
2914
2915		if (strcmp(res->v_package[0]->v_string, prop) == 0)
2916			return res->v_package[1]->v_integer;
2917	}
2918
2919	return defval;
2920}
2921
2922int
2923acpi_parsehid(struct aml_node *node, void *arg, char *outcdev, char *outdev,
2924    size_t devlen)
2925{
2926	struct acpi_softc	*sc = (struct acpi_softc *)arg;
2927	struct aml_value	 res;
2928	const char		*dev;
2929
2930	/* NB aml_eisaid returns a static buffer, this must come first */
2931	if (aml_evalname(acpi_softc, node->parent, "_CID", 0, NULL, &res) == 0) {
2932		switch (res.type) {
2933		case AML_OBJTYPE_STRING:
2934			dev = res.v_string;
2935			break;
2936		case AML_OBJTYPE_INTEGER:
2937			dev = aml_eisaid(aml_val2int(&res));
2938			break;
2939		default:
2940			dev = "unknown";
2941			break;
2942		}
2943		strlcpy(outcdev, dev, devlen);
2944		aml_freevalue(&res);
2945
2946		dnprintf(10, "compatible with device: %s\n", outcdev);
2947	} else {
2948		outcdev[0] = '\0';
2949	}
2950
2951	dnprintf(10, "found hid device: %s ", node->parent->name);
2952	if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
2953		return (1);
2954
2955	switch (res.type) {
2956	case AML_OBJTYPE_STRING:
2957		dev = res.v_string;
2958		break;
2959	case AML_OBJTYPE_INTEGER:
2960		dev = aml_eisaid(aml_val2int(&res));
2961		break;
2962	default:
2963		dev = "unknown";
2964		break;
2965	}
2966	dnprintf(10, "	device: %s\n", dev);
2967
2968	strlcpy(outdev, dev, devlen);
2969
2970	aml_freevalue(&res);
2971
2972	return (0);
2973}
2974
2975/* Devices for which we don't want to attach a driver */
2976const char *acpi_skip_hids[] = {
2977	"INT0800",	/* Intel 82802Firmware Hub Device */
2978	"PNP0000",	/* 8259-compatible Programmable Interrupt Controller */
2979	"PNP0001",	/* EISA Interrupt Controller */
2980	"PNP0100",	/* PC-class System Timer */
2981	"PNP0103",	/* HPET System Timer */
2982	"PNP0200",	/* PC-class DMA Controller */
2983	"PNP0201",	/* EISA DMA Controller */
2984	"PNP0800",	/* Microsoft Sound System Compatible Device */
2985	"PNP0C01",	/* System Board */
2986	"PNP0C02",	/* PNP Motherboard Resources */
2987	"PNP0C04",	/* x87-compatible Floating Point Processing Unit */
2988	"PNP0C09",	/* Embedded Controller Device */
2989	"PNP0C0F",	/* PCI Interrupt Link Device */
2990	NULL
2991};
2992
2993/* ISA devices for which we attach a driver later */
2994const char *acpi_isa_hids[] = {
2995	"PNP0303",	/* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */
2996	"PNP0400",	/* Standard LPT Parallel Port */
2997	"PNP0401",	/* ECP Parallel Port */
2998	"PNP0501",	/* 16550A-compatible COM Serial Port */
2999	"PNP0700",	/* PC-class Floppy Disk Controller */
3000	"PNP0F03",	/* Microsoft PS/2-style Mouse */
3001	"PNP0F13",	/* PS/2 Mouse */
3002	NULL
3003};
3004
3005void
3006acpi_attach_deps(struct acpi_softc *sc, struct aml_node *node)
3007{
3008	struct aml_value res;
3009	struct aml_node *dep;
3010	int i;
3011
3012	if (aml_evalname(sc, node, "_DEP", 0, NULL, &res))
3013		return;
3014
3015	if (res.type != AML_OBJTYPE_PACKAGE)
3016		return;
3017
3018	for (i = 0; i < res.length; i++) {
3019		if (res.v_package[i]->type != AML_OBJTYPE_STRING)
3020			continue;
3021		dep = aml_searchrel(node, res.v_package[i]->v_string);
3022		if (dep == NULL || dep->attached)
3023			continue;
3024		dep = aml_searchname(dep, "_HID");
3025		if (dep)
3026			acpi_foundhid(dep, sc);
3027	}
3028
3029	aml_freevalue(&res);
3030}
3031
3032int
3033acpi_foundhid(struct aml_node *node, void *arg)
3034{
3035	struct acpi_softc	*sc = (struct acpi_softc *)arg;
3036	struct device		*self = (struct device *)arg;
3037	char		 	 cdev[32];
3038	char		 	 dev[32];
3039	struct acpi_attach_args	 aaa;
3040	int64_t			 sta;
3041#ifndef SMALL_KERNEL
3042	int			 i;
3043#endif
3044
3045	if (acpi_parsehid(node, arg, cdev, dev, sizeof(dev)) != 0)
3046		return (0);
3047
3048	if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &sta))
3049		sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
3050
3051	if ((sta & STA_PRESENT) == 0)
3052		return (0);
3053
3054	acpi_attach_deps(sc, node->parent);
3055
3056	memset(&aaa, 0, sizeof(aaa));
3057	aaa.aaa_iot = sc->sc_iot;
3058	aaa.aaa_memt = sc->sc_memt;
3059	aaa.aaa_dmat = sc->sc_dmat;
3060	aaa.aaa_node = node->parent;
3061	aaa.aaa_dev = dev;
3062	aaa.aaa_cdev = cdev;
3063
3064#ifndef SMALL_KERNEL
3065	if (!strcmp(cdev, ACPI_DEV_MOUSE)) {
3066		for (i = 0; i < nitems(sbtn_pnp); i++) {
3067			if (!strcmp(dev, sbtn_pnp[i])) {
3068				mouse_has_softbtn = 1;
3069				break;
3070			}
3071		}
3072	}
3073#endif
3074
3075	if (acpi_matchhids(&aaa, acpi_skip_hids, "none") ||
3076	    acpi_matchhids(&aaa, acpi_isa_hids, "none"))
3077		return (0);
3078
3079	if (!node->parent->attached) {
3080		node->parent->attached = 1;
3081		config_found(self, &aaa, acpi_print);
3082	}
3083
3084	return (0);
3085}
3086
3087#ifndef SMALL_KERNEL
3088int
3089acpi_founddock(struct aml_node *node, void *arg)
3090{
3091	struct acpi_softc	*sc = (struct acpi_softc *)arg;
3092	struct device		*self = (struct device *)arg;
3093	struct acpi_attach_args	aaa;
3094
3095	dnprintf(10, "found dock entry: %s\n", node->parent->name);
3096
3097	memset(&aaa, 0, sizeof(aaa));
3098	aaa.aaa_iot = sc->sc_iot;
3099	aaa.aaa_memt = sc->sc_memt;
3100	aaa.aaa_node = node->parent;
3101	aaa.aaa_name = "acpidock";
3102
3103	config_found(self, &aaa, acpi_print);
3104
3105	return 0;
3106}
3107
3108int
3109acpi_foundvideo(struct aml_node *node, void *arg)
3110{
3111	struct acpi_softc *sc = (struct acpi_softc *)arg;
3112	struct device *self = (struct device *)arg;
3113	struct acpi_attach_args	aaa;
3114
3115	memset(&aaa, 0, sizeof(aaa));
3116	aaa.aaa_iot = sc->sc_iot;
3117	aaa.aaa_memt = sc->sc_memt;
3118	aaa.aaa_node = node->parent;
3119	aaa.aaa_name = "acpivideo";
3120
3121	config_found(self, &aaa, acpi_print);
3122
3123	return (0);
3124}
3125
3126int
3127acpi_foundsbs(struct aml_node *node, void *arg)
3128{
3129	struct acpi_softc	*sc = (struct acpi_softc *)arg;
3130	struct device		*self = (struct device *)arg;
3131	char		 	 cdev[32], dev[32];
3132	struct acpi_attach_args	 aaa;
3133	int64_t			 sta;
3134
3135	if (acpi_parsehid(node, arg, cdev, dev, sizeof(dev)) != 0)
3136		return (0);
3137
3138	if (aml_evalinteger(sc, node->parent, "_STA", 0, NULL, &sta))
3139		sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
3140
3141	if ((sta & STA_PRESENT) == 0)
3142		return (0);
3143
3144	acpi_attach_deps(sc, node->parent);
3145
3146	if (strcmp(dev, ACPI_DEV_SBS) != 0)
3147		return (0);
3148
3149	if (node->parent->attached)
3150		return (0);
3151
3152	memset(&aaa, 0, sizeof(aaa));
3153	aaa.aaa_iot = sc->sc_iot;
3154	aaa.aaa_memt = sc->sc_memt;
3155	aaa.aaa_node = node->parent;
3156	aaa.aaa_dev = dev;
3157	aaa.aaa_cdev = cdev;
3158
3159	config_found(self, &aaa, acpi_print);
3160	node->parent->attached = 1;
3161
3162	return (0);
3163}
3164
3165int
3166acpiopen(dev_t dev, int flag, int mode, struct proc *p)
3167{
3168	int error = 0;
3169	struct acpi_softc *sc;
3170	int s;
3171
3172	if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 ||
3173	    !(sc = acpi_cd.cd_devs[APMUNIT(dev)]))
3174		return (ENXIO);
3175
3176	s = spltty();
3177	switch (APMDEV(dev)) {
3178	case APMDEV_CTL:
3179		if (!(flag & FWRITE)) {
3180			error = EINVAL;
3181			break;
3182		}
3183		if (sc->sc_flags & SCFLAG_OWRITE) {
3184			error = EBUSY;
3185			break;
3186		}
3187		sc->sc_flags |= SCFLAG_OWRITE;
3188		break;
3189	case APMDEV_NORMAL:
3190		if (!(flag & FREAD) || (flag & FWRITE)) {
3191			error = EINVAL;
3192			break;
3193		}
3194		sc->sc_flags |= SCFLAG_OREAD;
3195		break;
3196	default:
3197		error = ENXIO;
3198		break;
3199	}
3200	splx(s);
3201	return (error);
3202}
3203
3204int
3205acpiclose(dev_t dev, int flag, int mode, struct proc *p)
3206{
3207	int error = 0;
3208	struct acpi_softc *sc;
3209	int s;
3210
3211	if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 ||
3212	    !(sc = acpi_cd.cd_devs[APMUNIT(dev)]))
3213		return (ENXIO);
3214
3215	s = spltty();
3216	switch (APMDEV(dev)) {
3217	case APMDEV_CTL:
3218		sc->sc_flags &= ~SCFLAG_OWRITE;
3219		break;
3220	case APMDEV_NORMAL:
3221		sc->sc_flags &= ~SCFLAG_OREAD;
3222		break;
3223	default:
3224		error = ENXIO;
3225		break;
3226	}
3227	splx(s);
3228	return (error);
3229}
3230
3231int
3232acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
3233{
3234	int error = 0;
3235	struct acpi_softc *sc;
3236	struct acpi_ac *ac;
3237	struct acpi_bat *bat;
3238	struct acpi_sbs *sbs;
3239	struct apm_power_info *pi = (struct apm_power_info *)data;
3240	int bats;
3241	unsigned int remaining, rem, minutes, rate;
3242	int s;
3243
3244	if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 ||
3245	    !(sc = acpi_cd.cd_devs[APMUNIT(dev)]))
3246		return (ENXIO);
3247
3248	s = spltty();
3249	/* fake APM */
3250	switch (cmd) {
3251	case APM_IOC_SUSPEND:
3252	case APM_IOC_STANDBY:
3253		if ((flag & FWRITE) == 0) {
3254			error = EBADF;
3255			break;
3256		}
3257		acpi_addtask(sc, acpi_sleep_task, sc, ACPI_SLEEP_SUSPEND);
3258		acpi_wakeup(sc);
3259		break;
3260#ifdef HIBERNATE
3261	case APM_IOC_HIBERNATE:
3262		if ((error = suser(p)) != 0)
3263			break;
3264		if ((flag & FWRITE) == 0) {
3265			error = EBADF;
3266			break;
3267		}
3268		if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL) {
3269			error = EOPNOTSUPP;
3270			break;
3271		}
3272		acpi_addtask(sc, acpi_sleep_task, sc, ACPI_SLEEP_HIBERNATE);
3273		acpi_wakeup(sc);
3274		break;
3275#endif
3276	case APM_IOC_GETPOWER:
3277		/* A/C */
3278		pi->ac_state = APM_AC_UNKNOWN;
3279		SLIST_FOREACH(ac, &sc->sc_ac, aac_link) {
3280			if (ac->aac_softc->sc_ac_stat == PSR_ONLINE)
3281				pi->ac_state = APM_AC_ON;
3282			else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE)
3283				if (pi->ac_state == APM_AC_UNKNOWN)
3284					pi->ac_state = APM_AC_OFF;
3285		}
3286
3287		/* battery */
3288		pi->battery_state = APM_BATT_UNKNOWN;
3289		pi->battery_life = 0;
3290		pi->minutes_left = 0;
3291		bats = 0;
3292		remaining = rem = 0;
3293		minutes = 0;
3294		rate = 0;
3295		SLIST_FOREACH(bat, &sc->sc_bat, aba_link) {
3296			if (bat->aba_softc->sc_bat_present == 0)
3297				continue;
3298
3299			if (bat->aba_softc->sc_bix.bix_last_capacity == 0)
3300				continue;
3301
3302			bats++;
3303			rem = (bat->aba_softc->sc_bst.bst_capacity * 100) /
3304			    bat->aba_softc->sc_bix.bix_last_capacity;
3305			if (rem > 100)
3306				rem = 100;
3307			remaining += rem;
3308
3309			if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN)
3310				continue;
3311			else if (bat->aba_softc->sc_bst.bst_rate > 1)
3312				rate = bat->aba_softc->sc_bst.bst_rate;
3313
3314			minutes += bat->aba_softc->sc_bst.bst_capacity;
3315		}
3316
3317		SLIST_FOREACH(sbs, &sc->sc_sbs, asbs_link) {
3318			if (sbs->asbs_softc->sc_batteries_present == 0)
3319				continue;
3320
3321			if (sbs->asbs_softc->sc_battery.rel_charge == 0)
3322				continue;
3323
3324			bats++;
3325			rem = sbs->asbs_softc->sc_battery.rel_charge;
3326			if (rem > 100)
3327				rem = 100;
3328			remaining += rem;
3329
3330			if (sbs->asbs_softc->sc_battery.run_time ==
3331			    ACPISBS_VALUE_UNKNOWN)
3332				continue;
3333
3334			rate = 60; /* XXX */
3335			minutes += sbs->asbs_softc->sc_battery.run_time;
3336		}
3337
3338		if (bats == 0) {
3339			pi->battery_state = APM_BATTERY_ABSENT;
3340			pi->battery_life = 0;
3341			pi->minutes_left = (unsigned int)-1;
3342			break;
3343		}
3344
3345		if (pi->ac_state == APM_AC_ON || rate == 0)
3346			pi->minutes_left = (unsigned int)-1;
3347		else
3348			pi->minutes_left = 60 * minutes / rate;
3349
3350		/* running on battery */
3351		pi->battery_life = remaining / bats;
3352		if (pi->battery_life > 50)
3353			pi->battery_state = APM_BATT_HIGH;
3354		else if (pi->battery_life > 25)
3355			pi->battery_state = APM_BATT_LOW;
3356		else
3357			pi->battery_state = APM_BATT_CRITICAL;
3358
3359		break;
3360
3361	default:
3362		error = ENOTTY;
3363	}
3364
3365	splx(s);
3366	return (error);
3367}
3368
3369void	acpi_filtdetach(struct knote *);
3370int	acpi_filtread(struct knote *, long);
3371
3372struct filterops acpiread_filtops = {
3373	1, NULL, acpi_filtdetach, acpi_filtread
3374};
3375
3376int acpi_evindex;
3377
3378int
3379acpi_record_event(struct acpi_softc *sc, u_int type)
3380{
3381	if ((sc->sc_flags & SCFLAG_OPEN) == 0)
3382		return (1);
3383
3384	acpi_evindex++;
3385	KNOTE(sc->sc_note, APM_EVENT_COMPOSE(type, acpi_evindex));
3386	return (0);
3387}
3388
3389void
3390acpi_filtdetach(struct knote *kn)
3391{
3392	struct acpi_softc *sc = kn->kn_hook;
3393	int s;
3394
3395	s = spltty();
3396	SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext);
3397	splx(s);
3398}
3399
3400int
3401acpi_filtread(struct knote *kn, long hint)
3402{
3403	/* XXX weird kqueue_scan() semantics */
3404	if (hint && !kn->kn_data)
3405		kn->kn_data = hint;
3406	return (1);
3407}
3408
3409int
3410acpikqfilter(dev_t dev, struct knote *kn)
3411{
3412	struct acpi_softc *sc;
3413	int s;
3414
3415	if (!acpi_cd.cd_ndevs || APMUNIT(dev) != 0 ||
3416	    !(sc = acpi_cd.cd_devs[APMUNIT(dev)]))
3417		return (ENXIO);
3418
3419	switch (kn->kn_filter) {
3420	case EVFILT_READ:
3421		kn->kn_fop = &acpiread_filtops;
3422		break;
3423	default:
3424		return (EINVAL);
3425	}
3426
3427	kn->kn_hook = sc;
3428
3429	s = spltty();
3430	SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext);
3431	splx(s);
3432
3433	return (0);
3434}
3435
3436#else /* SMALL_KERNEL */
3437
3438int
3439acpiopen(dev_t dev, int flag, int mode, struct proc *p)
3440{
3441	return (ENXIO);
3442}
3443
3444int
3445acpiclose(dev_t dev, int flag, int mode, struct proc *p)
3446{
3447	return (ENXIO);
3448}
3449
3450int
3451acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
3452{
3453	return (ENXIO);
3454}
3455
3456int
3457acpikqfilter(dev_t dev, struct knote *kn)
3458{
3459	return (ENXIO);
3460}
3461
3462#endif /* SMALL_KERNEL */
3463