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