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