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