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