acpi.c revision 1.72
1/*	$OpenBSD: acpi.c,v 1.72 2006/12/21 05:57:17 marco 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
30#include <machine/conf.h>
31#include <machine/cpufunc.h>
32#include <machine/bus.h>
33
34#include <dev/pci/pcivar.h>
35#include <dev/acpi/acpireg.h>
36#include <dev/acpi/acpivar.h>
37#include <dev/acpi/amltypes.h>
38#include <dev/acpi/acpidev.h>
39#include <dev/acpi/dsdt.h>
40
41#include "ioapic.h"
42
43#include <machine/apmvar.h>
44
45#ifdef ACPI_DEBUG
46int acpi_debug = 16;
47#endif
48int acpi_enabled = 0;
49
50#define ACPIEN_RETRIES 15
51
52void	acpi_isr_thread(void *);
53void	acpi_create_thread(void *);
54
55int	acpi_match(struct device *, void *, void *);
56void	acpi_attach(struct device *, struct device *, void *);
57int	acpi_submatch(struct device *, void *, void *);
58int	acpi_print(void *, const char *);
59
60void	acpi_map_pmregs(struct acpi_softc *);
61
62void	acpi_foundpss(struct aml_node *, void *);
63void	acpi_foundhid(struct aml_node *, void *);
64void	acpi_foundtmp(struct aml_node *, void *);
65void	acpi_inidev(struct aml_node *, void *);
66
67int	acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *);
68void	acpi_load_table(paddr_t, size_t, acpi_qhead_t *);
69void	acpi_load_dsdt(paddr_t, struct acpi_q **);
70
71void	acpi_init_states(struct acpi_softc *);
72void	acpi_init_gpes(struct acpi_softc *);
73void	acpi_init_pm(struct acpi_softc *);
74
75void	acpi_init_pic(struct acpi_softc *);
76void	acpi_foundprt(struct aml_node *, void *);
77
78void	acpi_filtdetach(struct knote *);
79int	acpi_filtread(struct knote *, long);
80
81void	acpi_enable_onegpe(struct acpi_softc *, int, int);
82int	acpi_gpe_level(struct acpi_softc *, int, void *);
83int	acpi_gpe_edge(struct acpi_softc *, int, void *);
84
85#define	ACPI_LOCK(sc)
86#define	ACPI_UNLOCK(sc)
87
88/* XXX move this into dsdt softc at some point */
89extern struct aml_node aml_root;
90
91struct filterops acpiread_filtops = {
92	1, NULL, acpi_filtdetach, acpi_filtread
93};
94
95struct cfattach acpi_ca = {
96	sizeof(struct acpi_softc), acpi_match, acpi_attach
97};
98
99struct cfdriver acpi_cd = {
100	NULL, "acpi", DV_DULL
101};
102
103struct acpi_softc *acpi_softc;
104int acpi_s5, acpi_evindex;
105
106#ifdef __i386__
107#define acpi_bus_space_map	_bus_space_map
108#define acpi_bus_space_unmap	_bus_space_unmap
109#elif defined(__amd64__)
110#define acpi_bus_space_map	_x86_memio_map
111#define acpi_bus_space_unmap	_x86_memio_unmap
112#else
113#error ACPI supported on i386/amd64 only
114#endif
115
116#define pch(x) (((x)>=' ' && (x)<='z') ? (x) : ' ')
117
118void
119acpi_delay(struct acpi_softc *sc, int64_t uSecs)
120{
121	/* XXX this needs to become a tsleep later */
122	delay(uSecs);
123}
124
125int
126acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
127    int access_size, int len, void *buffer)
128{
129	u_int8_t *pb;
130	bus_space_handle_t ioh;
131	struct acpi_mem_map mh;
132	pci_chipset_tag_t pc;
133	pcitag_t tag;
134	bus_addr_t ioaddr;
135	int reg, idx, ival, sval;
136
137	dnprintf(50, "gasio: %.2x 0x%.8llx %s\n",
138	    iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read");
139
140	pb = (u_int8_t *)buffer;
141	switch (iospace) {
142	case GAS_SYSTEM_MEMORY:
143		/* copy to/from system memory */
144		acpi_map(address, len, &mh);
145		if (iodir == ACPI_IOREAD)
146			memcpy(buffer, mh.va, len);
147		else
148			memcpy(mh.va, buffer, len);
149		acpi_unmap(&mh);
150		break;
151
152	case GAS_SYSTEM_IOSPACE:
153		/* read/write from I/O registers */
154		ioaddr = address;
155		if (acpi_bus_space_map(sc->sc_iot, ioaddr, len, 0, &ioh) != 0) {
156			printf("Unable to map iospace!\n");
157			return (-1);
158		}
159		for (reg=0; reg < len; reg += access_size) {
160			if (iodir == ACPI_IOREAD) {
161				switch (access_size) {
162				case 1:
163					*(uint8_t *)(pb+reg) = bus_space_read_1(
164					    sc->sc_iot, ioh, reg);
165					dnprintf(80, "os_in8(%llx) = %x\n",
166					    reg+address, *(uint8_t *)(pb+reg));
167					break;
168				case 2:
169					*(uint16_t *)(pb+reg) = bus_space_read_2(
170					    sc->sc_iot, ioh, reg);
171					dnprintf(80, "os_in16(%llx) = %x\n",
172					    reg+address, *(uint16_t *)(pb+reg));
173					break;
174				case 4:
175					*(uint32_t *)(pb+reg) = bus_space_read_4(
176					    sc->sc_iot, ioh, reg);
177					break;
178				}
179			} else {
180				switch (access_size) {
181				case 1:
182					bus_space_write_1(sc->sc_iot, ioh, reg,
183					    *(uint8_t *)(pb+reg));
184					dnprintf(80, "os_out8(%llx,%x)\n",
185					    reg+address, *(uint8_t *)(pb+reg));
186					break;
187				case 2:
188					bus_space_write_2(sc->sc_iot, ioh, reg,
189					    *(uint16_t *)(pb+reg));
190					dnprintf(80, "os_out16(%llx,%x)\n",
191					    reg+address, *(uint16_t *)(pb+reg));
192					break;
193				case 4:
194					bus_space_write_4(sc->sc_iot, ioh, reg,
195					    *(uint32_t *)(pb+reg));
196					break;
197				}
198			}
199
200			/* During autoconf some devices are still gathering
201			 * information.  Delay here to give them an opportunity
202			 * to finish.  During runtime we simply need to ignore
203			 * transient values.
204			 */
205			if (cold)
206				delay(10000);
207		}
208		acpi_bus_space_unmap(sc->sc_iot, ioh, len, &ioaddr);
209		break;
210
211	case GAS_PCI_CFG_SPACE:
212		/* format of address:
213		 *    bits 00..15 = register
214		 *    bits 16..31 = function
215		 *    bits 32..47 = device
216		 *    bits 48..63 = bus
217		 */
218		pc = NULL;
219		tag = pci_make_tag(pc,
220		    ACPI_PCI_BUS(address), ACPI_PCI_DEV(address),
221		    ACPI_PCI_FN(address));
222
223		/* XXX: This is ugly. read-modify-write does a byte at a time */
224		reg = ACPI_PCI_REG(address);
225		for (idx=reg; idx<reg+len; idx++) {
226			ival = pci_conf_read(pc, tag, idx & ~0x3);
227			if (iodir == ACPI_IOREAD) {
228				*pb = ival >> (8 * (idx & 0x3));
229			} else {
230				sval = *pb;
231				ival &= ~(0xFF << (8* (idx & 0x3)));
232				ival |= sval << (8* (idx & 0x3));
233				pci_conf_write(pc, tag, idx & ~0x3, ival);
234			}
235			pb++;
236		}
237		break;
238	case GAS_EMBEDDED:
239		if (sc->sc_ec == NULL)
240			break;
241		if (iodir == ACPI_IOREAD)
242			acpiec_read(sc->sc_ec, (u_int8_t)address, len, buffer);
243		else
244			acpiec_write(sc->sc_ec, (u_int8_t)address, len, buffer);
245		break;
246	}
247	return (0);
248}
249
250/* Map Power Management registers */
251void
252acpi_map_pmregs(struct acpi_softc *sc)
253{
254	bus_addr_t addr;
255	bus_size_t size;
256	const char *name;
257	int reg;
258
259	for (reg = 0; reg < ACPIREG_MAXREG; reg++) {
260		size = 0;
261		switch (reg) {
262		case ACPIREG_SMICMD:
263			name = "smi";
264			size = 1;
265			addr = sc->sc_fadt->smi_cmd;
266			break;
267		case ACPIREG_PM1A_STS:
268		case ACPIREG_PM1A_EN:
269			name = "pm1a_sts";
270			size = sc->sc_fadt->pm1_evt_len >> 1;
271			addr = sc->sc_fadt->pm1a_evt_blk;
272			if (reg == ACPIREG_PM1A_EN && addr) {
273				addr += size;
274				name = "pm1a_en";
275			}
276			break;
277		case ACPIREG_PM1A_CNT:
278			name = "pm1a_cnt";
279			size = sc->sc_fadt->pm1_cnt_len;
280			addr = sc->sc_fadt->pm1a_cnt_blk;
281			break;
282		case ACPIREG_PM1B_STS:
283		case ACPIREG_PM1B_EN:
284			name = "pm1b_sts";
285			size = sc->sc_fadt->pm1_evt_len >> 1;
286			addr = sc->sc_fadt->pm1b_evt_blk;
287			if (reg == ACPIREG_PM1B_EN && addr) {
288				addr += size;
289				name = "pm1b_en";
290			}
291			break;
292		case ACPIREG_PM1B_CNT:
293			name = "pm1b_cnt";
294			size = sc->sc_fadt->pm1_cnt_len;
295			addr = sc->sc_fadt->pm1b_cnt_blk;
296			break;
297		case ACPIREG_PM2_CNT:
298			name = "pm2_cnt";
299			size = sc->sc_fadt->pm2_cnt_len;
300			addr = sc->sc_fadt->pm2_cnt_blk;
301			break;
302#if 0
303		case ACPIREG_PM_TMR:
304			/* Allocated in acpitimer */
305			name = "pm_tmr";
306			size = sc->sc_fadt->pm_tmr_len;
307			addr = sc->sc_fadt->pm_tmr_blk;
308			break;
309#endif
310		case ACPIREG_GPE0_STS:
311		case ACPIREG_GPE0_EN:
312			name = "gpe0_sts";
313			size = sc->sc_fadt->gpe0_blk_len >> 1;
314			addr = sc->sc_fadt->gpe0_blk;
315
316			dnprintf(20, "gpe0 block len : %x\n",
317			    sc->sc_fadt->gpe0_blk_len >> 1);
318			dnprintf(20, "gpe0 block addr: %x\n",
319			    sc->sc_fadt->gpe0_blk);
320			if (reg == ACPIREG_GPE0_EN && addr) {
321				addr += size;
322				name = "gpe0_en";
323			}
324			break;
325		case ACPIREG_GPE1_STS:
326		case ACPIREG_GPE1_EN:
327			name = "gpe1_sts";
328			size = sc->sc_fadt->gpe1_blk_len >> 1;
329			addr = sc->sc_fadt->gpe1_blk;
330
331			dnprintf(20, "gpe1 block len : %x\n",
332			    sc->sc_fadt->gpe1_blk_len >> 1);
333			dnprintf(20, "gpe1 block addr: %x\n",
334			    sc->sc_fadt->gpe1_blk);
335			if (reg == ACPIREG_GPE1_EN && addr) {
336				addr += size;
337				name = "gpe1_en";
338			}
339			break;
340		}
341		if (size && addr) {
342			dnprintf(50, "mapping: %.4x %.4x %s\n",
343			    addr, size, name);
344
345			/* Size and address exist; map register space */
346			bus_space_map(sc->sc_iot, addr, size, 0,
347			    &sc->sc_pmregs[reg].ioh);
348
349			sc->sc_pmregs[reg].name = name;
350			sc->sc_pmregs[reg].size = size;
351			sc->sc_pmregs[reg].addr = addr;
352		}
353	}
354}
355
356/* Read from power management register */
357int
358acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset)
359{
360	bus_space_handle_t ioh;
361	bus_size_t size, __size;
362	int regval;
363
364	__size = 0;
365	/* Special cases: 1A/1B blocks can be OR'ed together */
366	switch (reg) {
367	case ACPIREG_PM1_EN:
368		return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) |
369		    acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset));
370	case ACPIREG_PM1_STS:
371		return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) |
372		    acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset));
373	case ACPIREG_PM1_CNT:
374		return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) |
375		    acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset));
376	case ACPIREG_GPE_STS:
377		__size = 1;
378		dnprintf(50, "read GPE_STS  offset: %.2x %.2x %.2x\n", offset,
379		    sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1);
380		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
381			reg = ACPIREG_GPE0_STS;
382		}
383		break;
384	case ACPIREG_GPE_EN:
385		__size = 1;
386		dnprintf(50, "read GPE_EN   offset: %.2x %.2x %.2x\n",
387		    offset, sc->sc_fadt->gpe0_blk_len>>1,
388		    sc->sc_fadt->gpe1_blk_len>>1);
389		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
390			reg = ACPIREG_GPE0_EN;
391		}
392		break;
393	}
394
395	if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0)
396		return (0);
397
398	regval = 0;
399	ioh = sc->sc_pmregs[reg].ioh;
400	size = sc->sc_pmregs[reg].size;
401	if (__size)
402		size = __size;
403	if (size > 4)
404		size = 4;
405
406	switch (size) {
407	case 1:
408		regval = bus_space_read_1(sc->sc_iot, ioh, offset);
409		break;
410	case 2:
411		regval = bus_space_read_2(sc->sc_iot, ioh, offset);
412		break;
413	case 4:
414		regval = bus_space_read_4(sc->sc_iot, ioh, offset);
415		break;
416	}
417
418	dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n",
419	    sc->sc_pmregs[reg].name,
420	    sc->sc_pmregs[reg].addr, offset, regval);
421	return (regval);
422}
423
424/* Write to power management register */
425void
426acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval)
427{
428	bus_space_handle_t ioh;
429	bus_size_t size, __size;
430
431	__size = 0;
432	/* Special cases: 1A/1B blocks can be written with same value */
433	switch (reg) {
434	case ACPIREG_PM1_EN:
435		acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval);
436		acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval);
437		break;
438	case ACPIREG_PM1_STS:
439		acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval);
440		acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval);
441		break;
442	case ACPIREG_PM1_CNT:
443		acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval);
444		acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval);
445		break;
446	case ACPIREG_GPE_STS:
447		__size = 1;
448		dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n",
449		    offset, sc->sc_fadt->gpe0_blk_len>>1,
450		    sc->sc_fadt->gpe1_blk_len>>1, regval);
451		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
452			reg = ACPIREG_GPE0_STS;
453		}
454		break;
455	case ACPIREG_GPE_EN:
456		__size = 1;
457		dnprintf(50, "write GPE_EN  offset: %.2x %.2x %.2x %.2x\n",
458		    offset, sc->sc_fadt->gpe0_blk_len>>1,
459		    sc->sc_fadt->gpe1_blk_len>>1, regval);
460		if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
461			reg = ACPIREG_GPE0_EN;
462		}
463		break;
464	}
465
466	/* All special case return here */
467	if (reg >= ACPIREG_MAXREG)
468		return;
469
470	ioh = sc->sc_pmregs[reg].ioh;
471	size = sc->sc_pmregs[reg].size;
472	if (__size)
473		size = __size;
474	if (size > 4)
475		size = 4;
476	switch (size) {
477	case 1:
478		bus_space_write_1(sc->sc_iot, ioh, offset, regval);
479		break;
480	case 2:
481		bus_space_write_2(sc->sc_iot, ioh, offset, regval);
482		break;
483	case 4:
484		bus_space_write_4(sc->sc_iot, ioh, offset, regval);
485		break;
486	}
487
488	dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n",
489	    sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval);
490}
491
492void
493acpi_inidev(struct aml_node *node, void *arg)
494{
495	struct acpi_softc	*sc = (struct acpi_softc *)arg;
496
497	aml_evalnode(sc, node, 0, NULL, NULL);
498}
499
500void
501acpi_foundtmp(struct aml_node *node, void *arg)
502{
503	struct acpi_softc	*sc = (struct acpi_softc *)arg;
504	struct device		*self = (struct device *)arg;
505	const char		*dev;
506	struct acpi_attach_args	aaa;
507
508	dnprintf(10, "found thermal zone entry: %s\n", node->parent->name);
509
510	memset(&aaa, 0, sizeof(aaa));
511	aaa.aaa_iot = sc->sc_iot;
512	aaa.aaa_memt = sc->sc_memt;
513	aaa.aaa_node = node->parent;
514	aaa.aaa_dev = dev;
515	aaa.aaa_name = "acpitz";
516
517	config_found(self, &aaa, acpi_print);
518}
519
520void
521acpi_foundpss(struct aml_node *node, void *arg)
522{
523	struct acpi_softc	*sc = (struct acpi_softc *)arg;
524	struct device		*self = (struct device *)arg;
525	const char		*dev;
526	struct acpi_attach_args	aaa;
527
528	dnprintf(10, "found pss entry: %s\n", node->parent->name);
529
530	memset(&aaa, 0, sizeof(aaa));
531	aaa.aaa_iot = sc->sc_iot;
532	aaa.aaa_memt = sc->sc_memt;
533	aaa.aaa_node = node->parent;
534	aaa.aaa_dev = dev;
535	aaa.aaa_name = "acpicpu";
536
537	config_found(self, &aaa, acpi_print);
538}
539
540void
541acpi_foundhid(struct aml_node *node, void *arg)
542{
543	struct acpi_softc	*sc = (struct acpi_softc *)arg;
544	struct device		*self = (struct device *)arg;
545	const char		*dev;
546	struct aml_value	 res;
547	struct acpi_attach_args	aaa;
548
549	dnprintf(10, "found hid device: %s ", node->parent->name);
550	if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
551		return;
552
553	switch (res.type) {
554	case AML_OBJTYPE_STRING:
555		dev = res.v_string;
556		break;
557	case AML_OBJTYPE_INTEGER:
558		dev = aml_eisaid(aml_val2int(&res));
559		break;
560	default:
561		dev = "unknown";
562		break;
563	}
564	dnprintf(10, "	device: %s\n", dev);
565
566	memset(&aaa, 0, sizeof(aaa));
567	aaa.aaa_iot = sc->sc_iot;
568	aaa.aaa_memt = sc->sc_memt;
569	aaa.aaa_node = node->parent;
570	aaa.aaa_dev = dev;
571
572	if (!strcmp(dev, ACPI_DEV_AC))
573		aaa.aaa_name = "acpiac";
574	else if (!strcmp(dev, ACPI_DEV_CMB))
575		aaa.aaa_name = "acpibat";
576	else if (!strcmp(dev, ACPI_DEV_LD) ||
577	    !strcmp(dev, ACPI_DEV_PBD) ||
578	    !strcmp(dev, ACPI_DEV_SBD))
579		aaa.aaa_name = "acpibtn";
580	else if (!strcmp(dev, ACPI_DEV_ECD))
581		aaa.aaa_name = "acpiec";
582
583	if (aaa.aaa_name)
584		config_found(self, &aaa, acpi_print);
585	aml_freevalue(&res);
586}
587
588void
589acpi_init_pic(struct acpi_softc *sc)
590{
591	struct aml_node		*node;
592	struct aml_value	arg;
593
594	node = aml_searchname(&aml_root, "\\_PIC");
595	if (node == 0)
596		return;
597
598	memset(&arg, 0, sizeof(arg));
599	arg.type = AML_OBJTYPE_INTEGER;
600#if NIOAPIC > 0
601	arg.v_integer = 1;
602#else
603	arg.v_integer = 0;
604#endif
605	aml_evalnode(sc, node, 1, &arg, NULL);
606}
607
608void
609acpi_foundprt(struct aml_node *node, void *arg)
610{
611	struct acpi_softc	*sc = (struct acpi_softc *)arg;
612	struct device		*self = (struct device *)arg;
613	const char		*dev;
614	struct acpi_attach_args	aaa;
615
616	dnprintf(10, "found prt entry: %s\n", node->parent->name);
617
618	memset(&aaa, 0, sizeof(aaa));
619	aaa.aaa_iot = sc->sc_iot;
620	aaa.aaa_memt = sc->sc_memt;
621	aaa.aaa_node = node;
622	aaa.aaa_dev = dev;
623	aaa.aaa_name = "acpiprt";
624
625	config_found(self, &aaa, acpi_print);
626}
627
628int
629acpi_match(struct device *parent, void *match, void *aux)
630{
631	struct acpi_attach_args	*aaa = aux;
632	struct cfdata		*cf = match;
633
634	/* sanity */
635	if (strcmp(aaa->aaa_name, cf->cf_driver->cd_name))
636		return (0);
637
638	if (!acpi_probe(parent, cf, aaa))
639		return (0);
640
641	return (1);
642}
643
644void
645acpi_attach(struct device *parent, struct device *self, void *aux)
646{
647	struct acpi_attach_args *aaa = aux;
648	struct acpi_softc *sc = (struct acpi_softc *)self;
649	struct acpi_mem_map handle;
650	struct acpi_rsdp *rsdp;
651	struct acpi_q *entry;
652	struct acpi_dsdt *p_dsdt;
653	struct device *dev;
654	struct acpi_ac *ac;
655	struct acpi_bat *bat;
656	paddr_t facspa;
657
658	sc->sc_iot = aaa->aaa_iot;
659	sc->sc_memt = aaa->aaa_memt;
660
661	if (acpi_map(aaa->aaa_pbase, sizeof(struct acpi_rsdp), &handle)) {
662		printf(": can't map memory\n");
663		return;
664	}
665
666	rsdp = (struct acpi_rsdp *)handle.va;
667	printf(": rev %d", (int)rsdp->rsdp_revision);
668
669	SIMPLEQ_INIT(&sc->sc_tables);
670
671	sc->sc_fadt = NULL;
672	sc->sc_facs = NULL;
673	sc->sc_powerbtn = 0;
674	sc->sc_sleepbtn = 0;
675
676	sc->sc_note = malloc(sizeof(struct klist), M_DEVBUF, M_NOWAIT);
677	if (sc->sc_note == NULL) {
678		printf(": can't allocate memory\n");
679		acpi_unmap(&handle);
680		return;
681	}
682	memset(sc->sc_note, 0, sizeof(struct klist));
683
684	if (acpi_loadtables(sc, rsdp)) {
685		printf(": can't load tables\n");
686		acpi_unmap(&handle);
687		return;
688	}
689
690	acpi_unmap(&handle);
691
692	/*
693	 * Find the FADT
694	 */
695	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
696		if (memcmp(entry->q_table, FADT_SIG,
697		    sizeof(FADT_SIG) - 1) == 0) {
698			sc->sc_fadt = entry->q_table;
699			break;
700		}
701	}
702	if (sc->sc_fadt == NULL) {
703		printf(": no FADT\n");
704		return;
705	}
706
707#ifdef ACPI_ENABLE
708	/*
709	 * Check if we are able to enable ACPI control
710	 */
711	if (!sc->sc_fadt->smi_cmd ||
712	    (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) {
713		printf(": ACPI control unavailable\n");
714		return;
715	}
716#endif
717
718	acpi_enabled=1;
719
720	/* Create Default AML objects */
721	aml_create_defaultobjects();
722
723	/*
724	 * Load the DSDT from the FADT pointer -- use the
725	 * extended (64-bit) pointer if it exists
726	 */
727	if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0)
728		acpi_load_dsdt(sc->sc_fadt->dsdt, &entry);
729	else
730		acpi_load_dsdt(sc->sc_fadt->x_dsdt, &entry);
731
732	if (entry == NULL)
733		printf(" !DSDT");
734	SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry, q_next);
735
736	p_dsdt = entry->q_table;
737	acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length -
738	    sizeof(p_dsdt->hdr));
739
740	/* Load SSDT's */
741	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
742		if (memcmp(entry->q_table, SSDT_SIG,
743		    sizeof(SSDT_SIG) - 1) == 0) {
744			p_dsdt = entry->q_table;
745			acpi_parse_aml(sc, p_dsdt->aml, p_dsdt->hdr_length -
746			    sizeof(p_dsdt->hdr));
747		}
748	}
749
750	/* Perform post-parsing fixups */
751	aml_postparse();
752
753	/* Walk AML Tree */
754	//aml_walkroot();
755
756	/* Find available sleeping states */
757	acpi_init_states(sc);
758
759	/* Find available sleep/resume related methods. */
760	acpi_init_pm(sc);
761
762	/*
763	 * Set up a pointer to the firmware control structure
764	 */
765	if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0)
766		facspa = sc->sc_fadt->firmware_ctl;
767	else
768		facspa = sc->sc_fadt->x_firmware_ctl;
769
770	if (acpi_map(facspa, sizeof(struct acpi_facs), &handle))
771		printf(" !FACS");
772	else
773		sc->sc_facs = (struct acpi_facs *)handle.va;
774
775	/* Map Power Management registers */
776	acpi_map_pmregs(sc);
777
778	/* Initialize GPE handlers */
779	acpi_init_gpes(sc);
780
781	/*
782	 * Take over ACPI control.  Note that once we do this, we
783	 * effectively tell the system that we have ownership of
784	 * the ACPI hardware registers, and that SMI should leave
785	 * them alone
786	 *
787	 * This may prevent thermal control on some systems where
788	 * that actually does work
789	 */
790#ifdef ACPI_ENABLE
791	int idx;
792
793	acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable);
794	idx = 0;
795	do {
796		if (idx++ > ACPIEN_RETRIES) {
797			printf(": can't enable ACPI\n");
798			return;
799		}
800	} while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN));
801#endif
802
803	acpi_init_pic(sc);
804
805	acpi_attach_machdep(sc);
806
807	printf("\n");
808
809	printf("%s: tables ", DEVNAME(sc));
810	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
811		printf("%.4s ", entry->q_table);
812	}
813	printf("\n");
814
815	/*
816	 * ACPI is enabled now -- attach timer
817	 */
818	{
819		struct acpi_attach_args aaa;
820
821		memset(&aaa, 0, sizeof(aaa));
822		aaa.aaa_name = "acpitimer";
823		aaa.aaa_iot = sc->sc_iot;
824		aaa.aaa_memt = sc->sc_memt;
825#if 0
826		aaa.aaa_pcit = sc->sc_pcit;
827		aaa.aaa_smbust = sc->sc_smbust;
828#endif
829		config_found(self, &aaa, acpi_print);
830	}
831
832	/*
833	 * Attach table-defined devices
834	 */
835	SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
836		struct acpi_attach_args aaa;
837
838		memset(&aaa, 0, sizeof(aaa));
839		aaa.aaa_iot = sc->sc_iot;
840		aaa.aaa_memt = sc->sc_memt;
841	#if 0
842		aaa.aaa_pcit = sc->sc_pcit;
843		aaa.aaa_smbust = sc->sc_smbust;
844	#endif
845		aaa.aaa_table = entry->q_table;
846		config_found_sm(self, &aaa, acpi_print, acpi_submatch);
847	}
848
849	acpi_softc = sc;
850
851	/* initialize runtime environment */
852	aml_find_node(aml_root.child, "_INI", acpi_inidev, sc);
853
854	/* attach pci interrupt routing tables */
855	aml_find_node(aml_root.child, "_PRT", acpi_foundprt, sc);
856
857	/*
858	 * attach embedded controller, battery, power supply and button
859	 * devices
860	 */
861	aml_find_node(aml_root.child, "_HID", acpi_foundhid, sc);
862
863	/* attach cpu devices */
864	aml_find_node(aml_root.child, "_PSS", acpi_foundpss, sc);
865
866	/* attach thermal zone devices, XXX MUST be last entry */
867	aml_find_node(aml_root.child, "_TMP", acpi_foundtmp, sc);
868
869	/* create list of devices we want to query when APM come in */
870	SLIST_INIT(&sc->sc_ac);
871	SLIST_INIT(&sc->sc_bat);
872	TAILQ_FOREACH(dev, &alldevs, dv_list) {
873		if (!strncmp(dev->dv_xname, "acpiac", strlen("acpiac"))) {
874			ac = malloc(sizeof(struct acpi_ac), M_DEVBUF, M_WAITOK);
875			memset(ac, 0, sizeof(struct acpi_ac));
876			ac->aac_softc = (struct acpiac_softc *)dev;
877			SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link);
878		}
879		if (!strncmp(dev->dv_xname, "acpibat", strlen("acpibat"))) {
880			bat = malloc(sizeof(struct acpi_bat), M_DEVBUF,
881			    M_WAITOK);
882			memset(bat, 0, sizeof(struct acpi_bat));
883			bat->aba_softc = (struct acpibat_softc *)dev;
884			SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link);
885		}
886	}
887
888	/* Setup threads */
889	sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK);
890	sc->sc_thread->sc = sc;
891	sc->sc_thread->running = 1;
892
893	kthread_create_deferred(acpi_create_thread, sc);
894}
895
896int
897acpi_submatch(struct device *parent, void *match, void *aux)
898{
899	struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux;
900	struct cfdata *cf = match;
901
902	if (aaa->aaa_table == NULL)
903		return (0);
904	return ((*cf->cf_attach->ca_match)(parent, match, aux));
905}
906
907int
908acpi_print(void *aux, const char *pnp)
909{
910	/* XXX ACPIVERBOSE should be replaced with dnprintf */
911	struct acpi_attach_args *aa = aux;
912#ifdef ACPIVERBOSE
913	struct acpi_table_header *hdr =
914		(struct acpi_table_header *)aa->aaa_table;
915#endif
916
917	if (pnp) {
918		if (aa->aaa_name)
919			printf("%s at %s", aa->aaa_name, pnp);
920#ifdef ACPIVERBOSE
921		else
922			printf("acpi device at %s from", pnp);
923#else
924		else
925			return (QUIET);
926#endif
927	}
928#ifdef ACPIVERBOSE
929	if (hdr)
930		printf(" table %c%c%c%c",
931		    hdr->signature[0], hdr->signature[1],
932		    hdr->signature[2], hdr->signature[3]);
933#endif
934
935	return (UNCONF);
936}
937
938int
939acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp)
940{
941	struct acpi_mem_map hrsdt, handle;
942	struct acpi_table_header *hdr;
943	int i, ntables;
944	size_t len;
945
946	if (rsdp->rsdp_revision == 2) {
947		struct acpi_xsdt *xsdt;
948
949		if (acpi_map(rsdp->rsdp_xsdt, sizeof(*hdr), &handle)) {
950			printf("couldn't map rsdt\n");
951			return (ENOMEM);
952		}
953
954		hdr = (struct acpi_table_header *)handle.va;
955		len = hdr->length;
956		acpi_unmap(&handle);
957		hdr = NULL;
958
959		acpi_map(rsdp->rsdp_xsdt, len, &hrsdt);
960		xsdt = (struct acpi_xsdt *)hrsdt.va;
961
962		ntables = (len - sizeof(struct acpi_table_header)) /
963		    sizeof(xsdt->table_offsets[0]);
964
965		for (i = 0; i < ntables; i++) {
966			acpi_map(xsdt->table_offsets[i], sizeof(*hdr), &handle);
967			hdr = (struct acpi_table_header *)handle.va;
968			acpi_load_table(xsdt->table_offsets[i], hdr->length,
969			    &sc->sc_tables);
970			acpi_unmap(&handle);
971		}
972		acpi_unmap(&hrsdt);
973	} else {
974		struct acpi_rsdt *rsdt;
975
976		if (acpi_map(rsdp->rsdp_rsdt, sizeof(*hdr), &handle)) {
977			printf("couldn't map rsdt\n");
978			return (ENOMEM);
979		}
980
981		hdr = (struct acpi_table_header *)handle.va;
982		len = hdr->length;
983		acpi_unmap(&handle);
984		hdr = NULL;
985
986		acpi_map(rsdp->rsdp_rsdt, len, &hrsdt);
987		rsdt = (struct acpi_rsdt *)hrsdt.va;
988
989		ntables = (len - sizeof(struct acpi_table_header)) /
990		    sizeof(rsdt->table_offsets[0]);
991
992		for (i = 0; i < ntables; i++) {
993			acpi_map(rsdt->table_offsets[i], sizeof(*hdr), &handle);
994			hdr = (struct acpi_table_header *)handle.va;
995			acpi_load_table(rsdt->table_offsets[i], hdr->length,
996			    &sc->sc_tables);
997			acpi_unmap(&handle);
998		}
999		acpi_unmap(&hrsdt);
1000	}
1001
1002	return (0);
1003}
1004
1005void
1006acpi_load_table(paddr_t pa, size_t len, acpi_qhead_t *queue)
1007{
1008	struct acpi_mem_map handle;
1009	struct acpi_q *entry;
1010
1011	entry = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT);
1012
1013	if (entry != NULL) {
1014		if (acpi_map(pa, len, &handle)) {
1015			free(entry, M_DEVBUF);
1016			return;
1017		}
1018		memcpy(entry->q_data, handle.va, len);
1019		entry->q_table = entry->q_data;
1020		acpi_unmap(&handle);
1021		SIMPLEQ_INSERT_TAIL(queue, entry, q_next);
1022	}
1023}
1024
1025void
1026acpi_load_dsdt(paddr_t pa, struct acpi_q **dsdt)
1027{
1028	struct acpi_mem_map handle;
1029	struct acpi_table_header *hdr;
1030	size_t len;
1031
1032	if (acpi_map(pa, sizeof(*hdr), &handle))
1033		return;
1034	hdr = (struct acpi_table_header *)handle.va;
1035	len = hdr->length;
1036	acpi_unmap(&handle);
1037
1038	*dsdt = malloc(len + sizeof(struct acpi_q), M_DEVBUF, M_NOWAIT);
1039
1040	if (*dsdt != NULL) {
1041		if (acpi_map(pa, len, &handle)) {
1042			free(*dsdt, M_DEVBUF);
1043			*dsdt = NULL;
1044			return;
1045		}
1046		memcpy((*dsdt)->q_data, handle.va, len);
1047		(*dsdt)->q_table = (*dsdt)->q_data;
1048		acpi_unmap(&handle);
1049	}
1050}
1051
1052int
1053acpi_interrupt(void *arg)
1054{
1055	struct acpi_softc *sc = (struct acpi_softc *)arg;
1056	u_int32_t processed, sts, en, idx, jdx;
1057
1058	processed = 0;
1059
1060	dnprintf(40, "ACPI Interrupt\n");
1061	for (idx=0; idx<sc->sc_lastgpe; idx+=8) {
1062		sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3);
1063		en  = acpi_read_pmreg(sc, ACPIREG_GPE_EN,  idx>>3);
1064		if (en & sts) {
1065			dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts,
1066			    en);
1067			acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts);
1068			for (jdx=0; jdx<8; jdx++) {
1069				if (en & sts & (1L << jdx)) {
1070					/* Signal this GPE */
1071					sc->gpe_table[idx+jdx].active = 1;
1072					processed = 1;
1073				}
1074			}
1075		}
1076	}
1077
1078	sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0);
1079	en  = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
1080	if (sts & en) {
1081		dnprintf(10,"GEN interrupt: %.4x\n", sts & en);
1082		acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts);
1083		acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, en);
1084		acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
1085		if (sts & ACPI_PM1_PWRBTN_STS)
1086			sc->sc_powerbtn = 1;
1087		if (sts & ACPI_PM1_SLPBTN_STS)
1088			sc->sc_sleepbtn = 1;
1089		processed = 1;
1090	}
1091
1092	if (processed) {
1093		sc->sc_wakeup = 0;
1094		wakeup(sc);
1095	}
1096
1097	return (processed);
1098}
1099
1100void
1101acpi_enable_onegpe(struct acpi_softc *sc, int gpe, int enable)
1102{
1103	uint8_t mask = (1L << (gpe & 7));
1104	uint8_t en;
1105
1106	/* Read enabled register */
1107	en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3);
1108	dnprintf(50, "%sabling GPE %.2x (current: %sabled) %.2x\n",
1109	    enable ? "en" : "dis", gpe, (en & mask) ? "en" : "dis", en);
1110	if (enable)
1111		en |= mask;
1112	else
1113		en &= ~mask;
1114	acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en);
1115}
1116
1117int
1118acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler)
1119    (struct acpi_softc *, int, void *), void *arg, const char *label)
1120{
1121	if (gpe >= sc->sc_lastgpe || handler == NULL)
1122		return -EINVAL;
1123
1124	if (sc->gpe_table[gpe].handler != NULL) {
1125		dnprintf(10, "error: GPE %.2x already enabled!\n", gpe);
1126		return -EBUSY;
1127	}
1128
1129	dnprintf(50, "Adding GPE handler %.2x (%s)\n", gpe, label);
1130	sc->gpe_table[gpe].handler = handler;
1131	sc->gpe_table[gpe].arg = arg;
1132
1133	/* Defer enabling GPEs */
1134
1135	return (0);
1136}
1137
1138int
1139acpi_gpe_level(struct acpi_softc *sc, int gpe, void *arg)
1140{
1141	struct aml_node *node = arg;
1142	uint8_t mask;
1143
1144	dnprintf(10, "handling Level-sensitive GPE %.2x\n", gpe);
1145	mask = (1L << (gpe & 7));
1146
1147	aml_evalnode(sc, node, 0, NULL, NULL);
1148	acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask);
1149	acpi_write_pmreg(sc, ACPIREG_GPE_EN,  gpe>>3, mask);
1150
1151	return (0);
1152}
1153
1154int
1155acpi_gpe_edge(struct acpi_softc *sc, int gpe, void *arg)
1156{
1157
1158	struct aml_node *node = arg;
1159	uint8_t mask;
1160
1161	dnprintf(10, "handling Edge-sensitive GPE %.2x\n", gpe);
1162	mask = (1L << (gpe & 7));
1163
1164	aml_evalnode(sc, node, 0, NULL, NULL);
1165	acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask);
1166	acpi_write_pmreg(sc, ACPIREG_GPE_EN,  gpe>>3, mask);
1167
1168	return (0);
1169}
1170
1171void
1172acpi_init_gpes(struct acpi_softc *sc)
1173{
1174	struct aml_node *gpe;
1175	char name[12];
1176	int  idx, ngpe;
1177
1178	sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2;
1179	if (sc->sc_fadt->gpe1_blk_len) {
1180	}
1181	dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe);
1182
1183	/* Allocate GPE table */
1184	sc->gpe_table = malloc(sc->sc_lastgpe * sizeof(struct gpe_block),
1185	    M_DEVBUF, M_WAITOK);
1186	memset(sc->gpe_table, 0, sc->sc_lastgpe * sizeof(struct gpe_block));
1187
1188	ngpe = 0;
1189
1190	/* Clear GPE status */
1191	for (idx=0; idx<sc->sc_lastgpe; idx+=8) {
1192		acpi_write_pmreg(sc, ACPIREG_GPE_EN,  idx>>3, 0);
1193		acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx>>3, -1);
1194	}
1195	for (idx=0; idx<sc->sc_lastgpe; idx++) {
1196		/* Search Level-sensitive GPES */
1197		snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx);
1198		gpe = aml_searchname(&aml_root, name);
1199		if (gpe != NULL)
1200			acpi_set_gpehandler(sc, idx, acpi_gpe_level, gpe,
1201					    "level");
1202		if (gpe == NULL) {
1203			/* Search Edge-sensitive GPES */
1204			snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx);
1205			gpe = aml_searchname(&aml_root, name);
1206			if (gpe != NULL)
1207				acpi_set_gpehandler(sc, idx, acpi_gpe_edge, gpe,
1208						    "edge");
1209		}
1210	}
1211	sc->sc_maxgpe = ngpe;
1212}
1213
1214void
1215acpi_init_states(struct acpi_softc *sc)
1216{
1217	struct aml_value res;
1218	char name[8];
1219	int i;
1220
1221	for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
1222		snprintf(name, sizeof(name), "_S%d_", i);
1223		sc->sc_sleeptype[i].slp_typa = -1;
1224		sc->sc_sleeptype[i].slp_typb = -1;
1225		if (aml_evalname(sc, aml_root.child, name, 0, NULL, &res) == 0) {
1226			if (res.type == AML_OBJTYPE_PACKAGE) {
1227				sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]);
1228				sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]);
1229			}
1230			aml_freevalue(&res);
1231		}
1232	}
1233}
1234
1235void
1236acpi_init_pm(struct acpi_softc *sc)
1237{
1238	sc->sc_tts = aml_searchname(aml_root.child, "_TTS");
1239	sc->sc_pts = aml_searchname(aml_root.child, "_PTS");
1240	sc->sc_wak = aml_searchname(aml_root.child, "_WAK");
1241	sc->sc_bfs = aml_searchname(aml_root.child, "_BFS");
1242	sc->sc_gts = aml_searchname(aml_root.child, "_GTS");
1243}
1244
1245void
1246acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1247{
1248#ifdef ACPI_ENABLE
1249	struct aml_value env;
1250	u_int16_t rega, regb;
1251	int retries;
1252
1253	if (state == ACPI_STATE_S0)
1254		return;
1255	if (sc->sc_sleeptype[state].slp_typa == -1 ||
1256	    sc->sc_sleeptype[state].slp_typb == -1) {
1257		printf("%s: state S%d unavailable\n",
1258		    sc->sc_dev.dv_xname, state);
1259		return;
1260	}
1261
1262	env.type = AML_OBJTYPE_INTEGER;
1263	env.v_integer = state;
1264	/* _TTS(state) */
1265	if (sc->sc_tts) {
1266		if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) {
1267			dnprintf(10, "%s evaluating method _TTS failed.\n",
1268			    DEVNAME(sc));
1269			return;
1270		}
1271	}
1272	switch (state) {
1273	case ACPI_STATE_S1:
1274	case ACPI_STATE_S2:
1275		resettodr();
1276		dopowerhooks(PWR_SUSPEND);
1277		break;
1278	case ACPI_STATE_S3:
1279		resettodr();
1280		dopowerhooks(PWR_STANDBY);
1281		break;
1282	}
1283	/* _PTS(state) */
1284	if (sc->sc_pts) {
1285		if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) {
1286			dnprintf(10, "%s evaluating method _PTS failed.\n",
1287			    DEVNAME(sc));
1288			return;
1289		}
1290	}
1291	sc->sc_state = state;
1292	/* _GTS(state) */
1293	if (sc->sc_gts) {
1294		if (aml_evalnode(sc, sc->sc_gts, 1, &env, NULL) != 0) {
1295			dnprintf(10, "%s evaluating method _GTS failed.\n",
1296			    DEVNAME(sc));
1297			return;
1298		}
1299	}
1300	disable_intr();
1301
1302	/* Clear WAK_STS bit */
1303	acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS);
1304
1305	/* Write SLP_TYPx values */
1306	rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0);
1307	regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0);
1308	rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
1309	regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
1310	rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa);
1311	regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb);
1312	acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
1313	acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
1314
1315	/* Set SLP_EN bit */
1316	rega |= ACPI_PM1_SLP_EN;
1317	regb |= ACPI_PM1_SLP_EN;
1318	acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
1319	acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
1320
1321	/* Loop on WAK_STS */
1322	for (retries = 1000; retries > 0; retries--) {
1323		rega = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0);
1324		regb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0);
1325		if (rega & ACPI_PM1_WAK_STS ||
1326		    regb & ACPI_PM1_WAK_STS)
1327			break;
1328		DELAY(10);
1329	}
1330
1331	enable_intr();
1332#endif
1333}
1334
1335void
1336acpi_resume(struct acpi_softc *sc)
1337{
1338	struct aml_value env;
1339
1340	env.type = AML_OBJTYPE_INTEGER;
1341	env.v_integer = sc->sc_state;
1342
1343	if (sc->sc_bfs) {
1344		if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) {
1345			dnprintf(10, "%s evaluating method _BFS failed.\n",
1346			    DEVNAME(sc));
1347		}
1348	}
1349	dopowerhooks(PWR_RESUME);
1350	inittodr(0);
1351	if (sc->sc_wak) {
1352		if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) {
1353			dnprintf(10, "%s evaluating method _WAK failed.\n",
1354			    DEVNAME(sc));
1355		}
1356	}
1357	sc->sc_state = ACPI_STATE_S0;
1358	if (sc->sc_tts) {
1359		env.v_integer = sc->sc_state;
1360		if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) {
1361			dnprintf(10, "%s evaluating method _TTS failed.\n",
1362			    DEVNAME(sc));
1363		}
1364	}
1365}
1366
1367void
1368acpi_powerdown(void)
1369{
1370	acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
1371}
1372
1373int
1374acpiopen(dev_t dev, int flag, int mode, struct proc *p)
1375{
1376	struct acpi_softc *sc;
1377	int error = 0;
1378
1379	if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
1380	    !(sc = acpi_cd.cd_devs[minor(dev)]))
1381		return (ENXIO);
1382
1383	return (error);
1384}
1385
1386int
1387acpiclose(dev_t dev, int flag, int mode, struct proc *p)
1388{
1389	struct acpi_softc *sc;
1390
1391	if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
1392	    !(sc = acpi_cd.cd_devs[minor(dev)]))
1393		return (ENXIO);
1394
1395	return (0);
1396}
1397
1398int
1399acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
1400{
1401	struct acpi_softc *sc;
1402	struct acpi_ac *ac;
1403	struct acpi_bat *bat;
1404	struct apm_power_info *pi = (struct apm_power_info *)data;
1405	int error = 0, bats;
1406	unsigned int remaining, rem, minutes, rate;
1407
1408	if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
1409	    !(sc = acpi_cd.cd_devs[minor(dev)]))
1410		return (ENXIO);
1411
1412	ACPI_LOCK(sc);
1413	/* fake APM */
1414	switch (cmd) {
1415	case APM_IOC_GETPOWER:
1416		/* A/C */
1417		pi->ac_state = APM_AC_UNKNOWN;
1418		SLIST_FOREACH(ac, &sc->sc_ac, aac_link) {
1419			if (ac->aac_softc->sc_ac_stat == PSR_ONLINE)
1420				pi->ac_state = APM_AC_ON;
1421			else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE)
1422				if (pi->ac_state == APM_AC_UNKNOWN)
1423					pi->ac_state = APM_AC_OFF;
1424		}
1425
1426		/* battery */
1427		pi->battery_state = APM_BATT_UNKNOWN;
1428		pi->battery_life = 0;
1429		pi->minutes_left = 0;
1430		bats = 0;
1431		remaining = rem = 0;
1432		minutes = 0;
1433		rate = 0;
1434		SLIST_FOREACH(bat, &sc->sc_bat, aba_link) {
1435			if (bat->aba_softc->sc_bat_present == 0)
1436				continue;
1437
1438			if (bat->aba_softc->sc_bif.bif_last_capacity == 0)
1439				continue;
1440
1441			bats++;
1442			rem = (bat->aba_softc->sc_bst.bst_capacity * 100) /
1443			    bat->aba_softc->sc_bif.bif_last_capacity;
1444			if (rem > 100)
1445				rem = 100;
1446			remaining += rem;
1447
1448			if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN)
1449				continue;
1450			else if (bat->aba_softc->sc_bst.bst_rate > 1)
1451				rate = bat->aba_softc->sc_bst.bst_rate;
1452
1453			minutes += bat->aba_softc->sc_bst.bst_capacity;
1454		}
1455
1456		if (bats == 0) {
1457			pi->battery_state = APM_BATTERY_ABSENT;
1458			pi->battery_life = 0;
1459			pi->minutes_left = (unsigned int)-1;
1460			break;
1461		}
1462
1463		if (pi->ac_state == APM_AC_ON || rate == 0)
1464			pi->minutes_left = (unsigned int)-1;
1465		else
1466			pi->minutes_left = minutes / rate * 100;
1467
1468		/* running on battery */
1469		pi->battery_life = remaining / bats;
1470		if (pi->battery_life > 50)
1471			pi->battery_state = APM_BATT_HIGH;
1472		else if (pi->battery_life > 25)
1473			pi->battery_state = APM_BATT_LOW;
1474		else
1475			pi->battery_state = APM_BATT_CRITICAL;
1476
1477		break;
1478
1479	default:
1480		error = ENOTTY;
1481	}
1482
1483	ACPI_UNLOCK(sc);
1484	return (error);
1485}
1486
1487void
1488acpi_filtdetach(struct knote *kn)
1489{
1490	struct acpi_softc *sc = kn->kn_hook;
1491
1492	ACPI_LOCK(sc);
1493	SLIST_REMOVE(sc->sc_note, kn, knote, kn_selnext);
1494	ACPI_UNLOCK(sc);
1495}
1496
1497int
1498acpi_filtread(struct knote *kn, long hint)
1499{
1500	/* XXX weird kqueue_scan() semantics */
1501	if (hint & !kn->kn_data)
1502		kn->kn_data = hint;
1503
1504	return (1);
1505}
1506
1507int
1508acpikqfilter(dev_t dev, struct knote *kn)
1509{
1510	struct acpi_softc *sc;
1511
1512	if (!acpi_cd.cd_ndevs || minor(dev) != 0 ||
1513	    !(sc = acpi_cd.cd_devs[minor(dev)]))
1514		return (ENXIO);
1515
1516	switch (kn->kn_filter) {
1517	case EVFILT_READ:
1518		kn->kn_fop = &acpiread_filtops;
1519		break;
1520	default:
1521		return (1);
1522	}
1523
1524	kn->kn_hook = sc;
1525
1526	ACPI_LOCK(sc);
1527	SLIST_INSERT_HEAD(sc->sc_note, kn, kn_selnext);
1528	ACPI_UNLOCK(sc);
1529
1530	return (0);
1531}
1532
1533void
1534acpi_isr_thread(void *arg)
1535{
1536	struct acpi_thread *thread = arg;
1537	struct acpi_softc  *sc = thread->sc;
1538	u_int32_t gpe;
1539
1540	/*
1541	 * If we have an interrupt handler, we can get notification
1542	 * when certain status bits changes in the ACPI registers,
1543	 * so let us enable some events we can forward to userland
1544	 */
1545	if (sc->sc_interrupt) {
1546		int16_t flag;
1547
1548		dnprintf(1,"slpbtn:%c  pwrbtn:%c\n",
1549		    sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y',
1550		    sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y');
1551		dnprintf(10, "Enabling acpi interrupts...\n");
1552		sc->sc_wakeup = 1;
1553
1554		/* Enable Sleep/Power buttons if they exist */
1555		flag = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
1556		if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) {
1557			flag |= ACPI_PM1_PWRBTN_EN;
1558		}
1559		if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) {
1560			flag |= ACPI_PM1_SLPBTN_EN;
1561		}
1562		acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, flag);
1563
1564		/* Enable handled GPEs here */
1565		for (gpe=0; gpe<sc->sc_lastgpe; gpe++) {
1566			if (sc->gpe_table[gpe].handler)
1567				acpi_enable_onegpe(sc, gpe, 1);
1568		}
1569	}
1570
1571	while (thread->running) {
1572		dnprintf(10, "sleep... %d\n", sc->sc_wakeup);
1573		while (sc->sc_wakeup)
1574			tsleep(sc, PWAIT, "acpi_idle", 0);
1575		sc->sc_wakeup = 1;
1576		dnprintf(10, "wakeup..\n");
1577
1578		for (gpe=0; gpe < sc->sc_lastgpe; gpe++) {
1579			struct gpe_block *pgpe = &sc->gpe_table[gpe];
1580
1581			if (pgpe->active) {
1582				pgpe->active = 0;
1583				dnprintf(50, "softgpe: %.2x\n", gpe);
1584				if (pgpe->handler)
1585					pgpe->handler(sc, gpe, pgpe->arg);
1586			}
1587		}
1588		if (sc->sc_powerbtn) {
1589			sc->sc_powerbtn = 0;
1590
1591			aml_notify_dev(ACPI_DEV_PBD, 0x80);
1592
1593			acpi_evindex++;
1594			dnprintf(1,"power button pressed\n");
1595			KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_PWRBTN,
1596			    acpi_evindex));
1597		}
1598		if (sc->sc_sleepbtn) {
1599			sc->sc_sleepbtn = 0;
1600
1601			aml_notify_dev(ACPI_DEV_SBD, 0x80);
1602
1603			acpi_evindex++;
1604			dnprintf(1,"sleep button pressed\n");
1605			KNOTE(sc->sc_note, ACPI_EVENT_COMPOSE(ACPI_EV_SLPBTN,
1606			    acpi_evindex));
1607		}
1608	}
1609	free(thread, M_DEVBUF);
1610
1611	kthread_exit(0);
1612}
1613
1614void
1615acpi_create_thread(void *arg)
1616{
1617	struct acpi_softc *sc = arg;
1618
1619	if (kthread_create(acpi_isr_thread, sc->sc_thread, NULL, DEVNAME(sc))
1620	    != 0) {
1621		printf("%s: unable to create isr thread, GPEs disabled\n",
1622		    DEVNAME(sc));
1623		return;
1624	}
1625}
1626