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