jcs's openbsd hax
openbsd
1/* $OpenBSD: acpi.c,v 1.456 2025/12/06 13:18:07 kettenis 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/pool.h>
24#include <sys/fcntl.h>
25#include <sys/event.h>
26#include <sys/signalvar.h>
27#include <sys/proc.h>
28#include <sys/kthread.h>
29#include <sys/reboot.h>
30#include <sys/sched.h>
31
32#include <machine/conf.h>
33#include <machine/cpufunc.h>
34
35#include <dev/pci/pcivar.h>
36#include <dev/acpi/acpireg.h>
37#include <dev/acpi/acpivar.h>
38#include <dev/acpi/amltypes.h>
39#include <dev/acpi/acpidev.h>
40#include <dev/acpi/dsdt.h>
41
42#include <dev/pci/pcidevs.h>
43#include <dev/pci/ppbreg.h>
44#include <dev/pci/pciidevar.h>
45
46#include <machine/apmvar.h>
47
48#include "wd.h"
49
50extern int cpu_suspended;
51
52#ifdef ACPI_DEBUG
53int acpi_debug = 16;
54#endif
55
56int acpi_poll_enabled;
57int acpi_hasprocfvs;
58int acpi_haspci;
59int acpi_legacy_free;
60
61struct pool acpiwqpool;
62
63#define ACPIEN_RETRIES 15
64
65pcireg_t acpi_pci_min_powerstate(pci_chipset_tag_t, pcitag_t);
66void acpi_pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int, int);
67int acpi_pci_notify(struct aml_node *, int, void *);
68
69int acpi_submatch(struct device *, void *, void *);
70int acpi_noprint(void *, const char *);
71int acpi_print(void *, const char *);
72
73void acpi_map_pmregs(struct acpi_softc *);
74void acpi_unmap_pmregs(struct acpi_softc *);
75
76int acpi_loadtables(struct acpi_softc *, struct acpi_rsdp *);
77
78int _acpi_matchhids(const char *, const char *[]);
79
80int acpi_inidev(struct aml_node *, void *);
81int acpi_foundprt(struct aml_node *, void *);
82
83int acpi_enable(struct acpi_softc *);
84void acpi_init_states(struct acpi_softc *);
85
86void acpi_gpe_task(void *, int);
87void acpi_sbtn_task(void *, int);
88void acpi_pbtn_task(void *, int);
89
90int acpi_enabled;
91
92void acpi_init_gpes(struct acpi_softc *);
93void acpi_disable_allgpes(struct acpi_softc *);
94struct gpe_block *acpi_find_gpe(struct acpi_softc *, int);
95void acpi_enable_onegpe(struct acpi_softc *, int);
96int acpi_gpe(struct acpi_softc *, int, void *);
97
98void acpi_enable_rungpes(struct acpi_softc *);
99
100#ifdef __arm64__
101int acpi_foundsectwo(struct aml_node *, void *);
102#endif
103int acpi_foundec(struct aml_node *, void *);
104int acpi_foundsony(struct aml_node *node, void *arg);
105int acpi_foundhid(struct aml_node *, void *);
106int acpi_add_device(struct aml_node *node, void *arg);
107
108void acpi_thread(void *);
109void acpi_create_thread(void *);
110
111#ifndef SMALL_KERNEL
112
113void acpi_init_pm(struct acpi_softc *);
114
115int acpi_founddock(struct aml_node *, void *);
116int acpi_foundprw(struct aml_node *, void *);
117int acpi_foundvideo(struct aml_node *, void *);
118int acpi_foundsbs(struct aml_node *node, void *);
119
120int acpi_foundide(struct aml_node *node, void *arg);
121int acpiide_notify(struct aml_node *, int, void *);
122void wdcattach(struct channel_softc *);
123int wdcdetach(struct channel_softc *, int);
124int is_ejectable_bay(struct aml_node *node);
125int is_ata(struct aml_node *node);
126int is_ejectable(struct aml_node *node);
127
128struct idechnl {
129 struct acpi_softc *sc;
130 int64_t addr;
131 int64_t chnl;
132 int64_t sta;
133};
134
135/*
136 * This is a list of Synaptics devices with a 'top button area'
137 * based on the list in Linux supplied by Synaptics
138 * Synaptics clickpads with the following pnp ids will get a unique
139 * wscons mouse type that is used to define trackpad regions that will
140 * emulate mouse buttons
141 */
142static const char *sbtn_pnp[] = {
143 "LEN0017",
144 "LEN0018",
145 "LEN0019",
146 "LEN0023",
147 "LEN002A",
148 "LEN002B",
149 "LEN002C",
150 "LEN002D",
151 "LEN002E",
152 "LEN0033",
153 "LEN0034",
154 "LEN0035",
155 "LEN0036",
156 "LEN0037",
157 "LEN0038",
158 "LEN0039",
159 "LEN0041",
160 "LEN0042",
161 "LEN0045",
162 "LEN0047",
163 "LEN0049",
164 "LEN2000",
165 "LEN2001",
166 "LEN2002",
167 "LEN2003",
168 "LEN2004",
169 "LEN2005",
170 "LEN2006",
171 "LEN2007",
172 "LEN2008",
173 "LEN2009",
174 "LEN200A",
175 "LEN200B",
176};
177
178int mouse_has_softbtn;
179#endif /* SMALL_KERNEL */
180
181struct acpi_softc *acpi_softc;
182
183extern struct aml_node aml_root;
184
185struct cfdriver acpi_cd = {
186 NULL, "acpi", DV_DULL, CD_COCOVM
187};
188
189uint8_t
190acpi_pci_conf_read_1(pci_chipset_tag_t pc, pcitag_t tag, int reg)
191{
192 uint32_t val = pci_conf_read(pc, tag, reg & ~0x3);
193 return (val >> ((reg & 0x3) << 3));
194}
195
196uint16_t
197acpi_pci_conf_read_2(pci_chipset_tag_t pc, pcitag_t tag, int reg)
198{
199 uint32_t val = pci_conf_read(pc, tag, reg & ~0x2);
200 return (val >> ((reg & 0x2) << 3));
201}
202
203uint32_t
204acpi_pci_conf_read_4(pci_chipset_tag_t pc, pcitag_t tag, int reg)
205{
206 return pci_conf_read(pc, tag, reg);
207}
208
209void
210acpi_pci_conf_write_1(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val)
211{
212 uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x3);
213 tmp &= ~(0xff << ((reg & 0x3) << 3));
214 tmp |= (val << ((reg & 0x3) << 3));
215 pci_conf_write(pc, tag, reg & ~0x3, tmp);
216}
217
218void
219acpi_pci_conf_write_2(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint16_t val)
220{
221 uint32_t tmp = pci_conf_read(pc, tag, reg & ~0x2);
222 tmp &= ~(0xffff << ((reg & 0x2) << 3));
223 tmp |= (val << ((reg & 0x2) << 3));
224 pci_conf_write(pc, tag, reg & ~0x2, tmp);
225}
226
227void
228acpi_pci_conf_write_4(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint32_t val)
229{
230 pci_conf_write(pc, tag, reg, val);
231}
232
233int
234acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
235 int access_size, int len, void *buffer)
236{
237 uint8_t *pb;
238 bus_space_tag_t iot;
239 bus_space_handle_t ioh;
240 pci_chipset_tag_t pc;
241 pcitag_t tag;
242 int reg, idx;
243
244 dnprintf(50, "gasio: %.2x 0x%.8llx %s\n",
245 iospace, address, (iodir == ACPI_IOWRITE) ? "write" : "read");
246
247 KASSERT((len % access_size) == 0);
248
249 pb = (uint8_t *)buffer;
250 switch (iospace) {
251 case GAS_SYSTEM_MEMORY:
252 case GAS_SYSTEM_IOSPACE:
253 if (iospace == GAS_SYSTEM_MEMORY)
254 iot = sc->sc_memt;
255 else
256 iot = sc->sc_iot;
257
258 if (acpi_bus_space_map(iot, address, len, 0, &ioh) != 0) {
259 printf("%s: unable to map iospace\n", DEVNAME(sc));
260 return (-1);
261 }
262 for (reg = 0; reg < len; reg += access_size) {
263 if (iodir == ACPI_IOREAD) {
264 switch (access_size) {
265 case 1:
266 *(uint8_t *)(pb + reg) =
267 bus_space_read_1(iot, ioh, reg);
268 dnprintf(80, "os_in8(%llx) = %x\n",
269 reg+address, *(uint8_t *)(pb+reg));
270 break;
271 case 2:
272 *(uint16_t *)(pb + reg) =
273 bus_space_read_2(iot, ioh, reg);
274 dnprintf(80, "os_in16(%llx) = %x\n",
275 reg+address, *(uint16_t *)(pb+reg));
276 break;
277 case 4:
278 *(uint32_t *)(pb + reg) =
279 bus_space_read_4(iot, ioh, reg);
280 break;
281 default:
282 printf("%s: rdio: invalid size %d\n",
283 DEVNAME(sc), access_size);
284 return (-1);
285 }
286 } else {
287 switch (access_size) {
288 case 1:
289 bus_space_write_1(iot, ioh, reg,
290 *(uint8_t *)(pb + reg));
291 dnprintf(80, "os_out8(%llx,%x)\n",
292 reg+address, *(uint8_t *)(pb+reg));
293 break;
294 case 2:
295 bus_space_write_2(iot, ioh, reg,
296 *(uint16_t *)(pb + reg));
297 dnprintf(80, "os_out16(%llx,%x)\n",
298 reg+address, *(uint16_t *)(pb+reg));
299 break;
300 case 4:
301 bus_space_write_4(iot, ioh, reg,
302 *(uint32_t *)(pb + reg));
303 break;
304 default:
305 printf("%s: wrio: invalid size %d\n",
306 DEVNAME(sc), access_size);
307 return (-1);
308 }
309 }
310 }
311 acpi_bus_space_unmap(iot, ioh, len);
312 break;
313
314 case GAS_PCI_CFG_SPACE:
315 /*
316 * The ACPI standard says that a function number of
317 * FFFF can be used to refer to all functions on a
318 * device. This makes no sense though in the context
319 * of accessing PCI config space. Yet there is AML
320 * out there that does this. We simulate a read from
321 * a nonexistent device here. Writes will panic when
322 * we try to construct the tag below.
323 */
324 if (ACPI_PCI_FN(address) == 0xffff && iodir == ACPI_IOREAD) {
325 memset(buffer, 0xff, len);
326 return (0);
327 }
328
329 pc = pci_lookup_segment(ACPI_PCI_SEG(address),
330 ACPI_PCI_BUS(address));
331 tag = pci_make_tag(pc,
332 ACPI_PCI_BUS(address), ACPI_PCI_DEV(address),
333 ACPI_PCI_FN(address));
334
335 reg = ACPI_PCI_REG(address);
336 for (idx = 0; idx < len; idx += access_size) {
337 if (iodir == ACPI_IOREAD) {
338 switch (access_size) {
339 case 1:
340 *(uint8_t *)(pb + idx) =
341 acpi_pci_conf_read_1(pc, tag, reg + idx);
342 break;
343 case 2:
344 *(uint16_t *)(pb + idx) =
345 acpi_pci_conf_read_2(pc, tag, reg + idx);
346 break;
347 case 4:
348 *(uint32_t *)(pb + idx) =
349 acpi_pci_conf_read_4(pc, tag, reg + idx);
350 break;
351 default:
352 printf("%s: rdcfg: invalid size %d\n",
353 DEVNAME(sc), access_size);
354 return (-1);
355 }
356 } else {
357 switch (access_size) {
358 case 1:
359 acpi_pci_conf_write_1(pc, tag, reg + idx,
360 *(uint8_t *)(pb + idx));
361 break;
362 case 2:
363 acpi_pci_conf_write_2(pc, tag, reg + idx,
364 *(uint16_t *)(pb + idx));
365 break;
366 case 4:
367 acpi_pci_conf_write_4(pc, tag, reg + idx,
368 *(uint32_t *)(pb + idx));
369 break;
370 default:
371 printf("%s: wrcfg: invalid size %d\n",
372 DEVNAME(sc), access_size);
373 return (-1);
374 }
375 }
376 }
377 break;
378
379 case GAS_EMBEDDED:
380 if (sc->sc_ec == NULL) {
381 printf("%s: WARNING EC not initialized\n", DEVNAME(sc));
382 return (-1);
383 }
384 if (iodir == ACPI_IOREAD)
385 acpiec_read(sc->sc_ec, (uint8_t)address, len, buffer);
386 else
387 acpiec_write(sc->sc_ec, (uint8_t)address, len, buffer);
388 break;
389 }
390 return (0);
391}
392
393int
394acpi_inidev(struct aml_node *node, void *arg)
395{
396 struct acpi_softc *sc = (struct acpi_softc *)arg;
397 int64_t sta;
398
399 /*
400 * Per the ACPI spec 6.5.1, only run _INI when device is there or
401 * when there is no _STA. We terminate the tree walk (with return 1)
402 * early if necessary.
403 */
404
405 /* Evaluate _STA to decide _INI fate and walk fate */
406 sta = acpi_getsta(sc, node->parent);
407
408 /* Evaluate _INI if we are present */
409 if (sta & STA_PRESENT)
410 aml_evalnode(sc, node, 0, NULL, NULL);
411
412 /* If we are functioning, we walk/search our children */
413 if (sta & STA_DEV_OK)
414 return 0;
415
416 /* If we are not enabled, or not present, terminate search */
417 if (!(sta & (STA_PRESENT|STA_ENABLED)))
418 return 1;
419
420 /* Default just continue search */
421 return 0;
422}
423
424int
425acpi_foundprt(struct aml_node *node, void *arg)
426{
427 struct acpi_softc *sc = (struct acpi_softc *)arg;
428 struct device *self = (struct device *)arg;
429 struct acpi_attach_args aaa;
430 int64_t sta;
431
432 dnprintf(10, "found prt entry: %s\n", node->parent->name);
433
434 /* Evaluate _STA to decide _PRT fate and walk fate */
435 sta = acpi_getsta(sc, node->parent);
436 if (sta & STA_PRESENT) {
437 memset(&aaa, 0, sizeof(aaa));
438 aaa.aaa_iot = sc->sc_iot;
439 aaa.aaa_memt = sc->sc_memt;
440 aaa.aaa_node = node;
441 aaa.aaa_name = "acpiprt";
442
443 config_found(self, &aaa, acpi_print);
444 }
445
446 /* If we are functioning, we walk/search our children */
447 if (sta & STA_DEV_OK)
448 return 0;
449
450 /* If we are not enabled, or not present, terminate search */
451 if (!(sta & (STA_PRESENT|STA_ENABLED)))
452 return 1;
453
454 /* Default just continue search */
455 return 0;
456}
457
458TAILQ_HEAD(, acpi_pci) acpi_pcidevs =
459 TAILQ_HEAD_INITIALIZER(acpi_pcidevs);
460TAILQ_HEAD(, acpi_pci) acpi_pcirootdevs =
461 TAILQ_HEAD_INITIALIZER(acpi_pcirootdevs);
462
463int acpi_getpci(struct aml_node *node, void *arg);
464int acpi_getminbus(int crsidx, union acpi_resource *crs, void *arg);
465
466int
467acpi_getminbus(int crsidx, union acpi_resource *crs, void *arg)
468{
469 int *bbn = arg;
470 int typ = AML_CRSTYPE(crs);
471
472 /* Check for embedded bus number */
473 if (typ == LR_WORD && crs->lr_word.type == 2) {
474 /* If _MIN > _MAX, the resource is considered to be invalid. */
475 if (crs->lr_word._min > crs->lr_word._max)
476 return -1;
477 *bbn = crs->lr_word._min;
478 }
479 return 0;
480}
481
482int
483acpi_matchcls(struct acpi_attach_args *aaa, int class, int subclass,
484 int interface)
485{
486 struct acpi_softc *sc = acpi_softc;
487 struct aml_value res;
488
489 if (aaa->aaa_dev == NULL || aaa->aaa_node == NULL)
490 return (0);
491
492 if (aml_evalname(sc, aaa->aaa_node, "_CLS", 0, NULL, &res))
493 return (0);
494
495 if (res.type != AML_OBJTYPE_PACKAGE || res.length != 3 ||
496 res.v_package[0]->type != AML_OBJTYPE_INTEGER ||
497 res.v_package[1]->type != AML_OBJTYPE_INTEGER ||
498 res.v_package[2]->type != AML_OBJTYPE_INTEGER)
499 return (0);
500
501 if (res.v_package[0]->v_integer == class &&
502 res.v_package[1]->v_integer == subclass &&
503 res.v_package[2]->v_integer == interface)
504 return (1);
505
506 return (0);
507}
508
509int
510_acpi_matchhids(const char *hid, const char *hids[])
511{
512 int i;
513
514 for (i = 0; hids[i]; i++)
515 if (!strcmp(hid, hids[i]))
516 return (1);
517 return (0);
518}
519
520int
521acpi_matchhids(struct acpi_attach_args *aa, const char *hids[],
522 const char *driver)
523{
524 if (aa->aaa_dev == NULL || aa->aaa_node == NULL)
525 return (0);
526
527 if (_acpi_matchhids(aa->aaa_dev, hids)) {
528 dnprintf(5, "driver %s matches at least one hid\n", driver);
529 return (2);
530 }
531 if (aa->aaa_cdev && _acpi_matchhids(aa->aaa_cdev, hids)) {
532 dnprintf(5, "driver %s matches at least one cid\n", driver);
533 return (1);
534 }
535
536 return (0);
537}
538
539int64_t
540acpi_getsta(struct acpi_softc *sc, struct aml_node *node)
541{
542 int64_t sta;
543
544 if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta))
545 sta = STA_PRESENT | STA_ENABLED | STA_SHOW_UI |
546 STA_DEV_OK | STA_BATTERY;
547
548 return sta;
549}
550
551int
552acpi_storaged3enable(struct acpi_softc *sc, struct aml_node *node)
553{
554 struct aml_value dsd;
555 int i;
556
557 /* 5025030f-842f-4ab4-a561-99a5189762d0 */
558 static uint8_t prop_guid[] = {
559 0x0f, 0x03, 0x25, 0x50, 0x2f, 0x84, 0xb4, 0x4a,
560 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0,
561 };
562
563 if (aml_evalname(sc, node, "_DSD", 0, NULL, &dsd))
564 return 0;
565
566 if (dsd.type != AML_OBJTYPE_PACKAGE || dsd.length != 2 ||
567 dsd.v_package[0]->type != AML_OBJTYPE_BUFFER ||
568 dsd.v_package[1]->type != AML_OBJTYPE_PACKAGE)
569 return 0;
570
571 /* Check UUID. */
572 if (dsd.v_package[0]->length != sizeof(prop_guid) ||
573 memcmp(dsd.v_package[0]->v_buffer, prop_guid,
574 sizeof(prop_guid)) != 0)
575 return 0;
576
577 /* Check properties. */
578 for (i = 0; i < dsd.v_package[1]->length; i++) {
579 struct aml_value *res = dsd.v_package[1]->v_package[i];
580 struct aml_value *val;
581
582 if (res->type != AML_OBJTYPE_PACKAGE || res->length != 2 ||
583 res->v_package[0]->type != AML_OBJTYPE_STRING ||
584 strcmp(res->v_package[0]->v_string, "StorageD3Enable") != 0)
585 continue;
586
587 val = res->v_package[1];
588 if (val->type == AML_OBJTYPE_OBJREF)
589 val = val->v_objref.ref;
590
591 if (val->type == AML_OBJTYPE_INTEGER)
592 return val->v_integer;
593 }
594
595 return 0;
596}
597
598/* Map ACPI device node to PCI */
599int
600acpi_getpci(struct aml_node *node, void *arg)
601{
602 const char *pcihid[] = { ACPI_DEV_PCIB, ACPI_DEV_PCIEB, "HWP0002", 0 };
603 struct acpi_pci *pci, *ppci;
604 struct aml_value res;
605 struct acpi_softc *sc = arg;
606 pci_chipset_tag_t pc;
607 pcitag_t tag;
608 uint64_t val;
609 int64_t sta;
610 uint32_t reg;
611
612 sta = acpi_getsta(sc, node);
613 if ((sta & STA_PRESENT) == 0)
614 return 0;
615
616 if (!node->value || node->value->type != AML_OBJTYPE_DEVICE)
617 return 0;
618 if (!aml_evalhid(node, &res)) {
619 /* Check if this is a PCI Root node */
620 if (_acpi_matchhids(res.v_string, pcihid)) {
621 aml_freevalue(&res);
622
623 pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
624
625 pci->bus = -1;
626 if (!aml_evalinteger(sc, node, "_SEG", 0, NULL, &val))
627 pci->seg = val;
628 if (!aml_evalname(sc, node, "_CRS", 0, NULL, &res)) {
629 aml_parse_resource(&res, acpi_getminbus,
630 &pci->bus);
631 dnprintf(10, "%s post-crs: %d\n",
632 aml_nodename(node), pci->bus);
633 }
634 if (!aml_evalinteger(sc, node, "_BBN", 0, NULL, &val)) {
635 dnprintf(10, "%s post-bbn: %d, %lld\n",
636 aml_nodename(node), pci->bus, val);
637 if (pci->bus == -1)
638 pci->bus = val;
639 }
640 pci->sub = pci->bus;
641 node->pci = pci;
642 dnprintf(10, "found PCI root: %s %d\n",
643 aml_nodename(node), pci->bus);
644 TAILQ_INSERT_TAIL(&acpi_pcirootdevs, pci, next);
645 }
646 aml_freevalue(&res);
647 return 0;
648 }
649
650 /* If parent is not PCI, or device does not have _ADR, return */
651 if (!node->parent || (ppci = node->parent->pci) == NULL)
652 return 0;
653 if (aml_evalinteger(sc, node, "_ADR", 0, NULL, &val))
654 return 0;
655
656 pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
657 pci->seg = ppci->seg;
658 pci->bus = ppci->sub;
659 pci->dev = ACPI_ADR_PCIDEV(val);
660 pci->fun = ACPI_ADR_PCIFUN(val);
661 pci->node = node;
662 pci->sub = -1;
663
664 dnprintf(10, "%.2x:%.2x.%x -> %s\n",
665 pci->bus, pci->dev, pci->fun,
666 aml_nodename(node));
667
668 /* Collect device power state information. */
669 if (aml_evalinteger(sc, node, "_S0W", 0, NULL, &val) == 0)
670 pci->_s0w = val;
671 else
672 pci->_s0w = -1;
673 if (aml_evalinteger(sc, node, "_S3D", 0, NULL, &val) == 0)
674 pci->_s3d = val;
675 else
676 pci->_s3d = -1;
677 if (aml_evalinteger(sc, node, "_S3W", 0, NULL, &val) == 0)
678 pci->_s3w = val;
679 else
680 pci->_s3w = -1;
681 if (aml_evalinteger(sc, node, "_S4D", 0, NULL, &val) == 0)
682 pci->_s4d = val;
683 else
684 pci->_s4d = -1;
685 if (aml_evalinteger(sc, node, "_S4W", 0, NULL, &val) == 0)
686 pci->_s4w = val;
687 else
688 pci->_s4w = -1;
689 pci->d3cold = acpi_storaged3enable(sc, node);
690
691 /* Check if PCI device exists */
692 if (pci->dev > 0x1F || pci->fun > 7) {
693 free(pci, M_DEVBUF, sizeof(*pci));
694 return (1);
695 }
696 pc = pci_lookup_segment(pci->seg, pci->bus);
697 tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun);
698 reg = pci_conf_read(pc, tag, PCI_ID_REG);
699 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) {
700 free(pci, M_DEVBUF, sizeof(*pci));
701 return (1);
702 }
703 node->pci = pci;
704
705 TAILQ_INSERT_TAIL(&acpi_pcidevs, pci, next);
706
707 /* Check if this is a PCI bridge */
708 reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
709 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
710 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) {
711 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
712 pci->sub = PPB_BUSINFO_SECONDARY(reg);
713
714 dnprintf(10, "found PCI bridge: %s %d\n",
715 aml_nodename(node), pci->sub);
716
717 /* Continue scanning */
718 return (0);
719 }
720
721 /* Device does not have children, stop scanning */
722 return (1);
723}
724
725struct aml_node *
726acpi_find_pci(pci_chipset_tag_t pc, pcitag_t tag)
727{
728 struct acpi_pci *pdev;
729 int bus, dev, fun;
730
731 pci_decompose_tag(pc, tag, &bus, &dev, &fun);
732 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
733 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun)
734 return pdev->node;
735 }
736
737 return NULL;
738}
739
740struct aml_node *
741acpi_pci_match(struct device *dev, struct pci_attach_args *pa)
742{
743 struct acpi_pci *pdev;
744 int state;
745
746 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
747 if (pdev->bus != pa->pa_bus ||
748 pdev->dev != pa->pa_device ||
749 pdev->fun != pa->pa_function)
750 continue;
751
752 dnprintf(10,"%s at acpi0 %s\n", dev->dv_xname,
753 aml_nodename(pdev->node));
754
755 pdev->device = dev;
756
757 /*
758 * If some Power Resources are dependent on this device
759 * initialize them.
760 */
761 state = pci_get_powerstate(pa->pa_pc, pa->pa_tag);
762 acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 1);
763 acpi_pci_set_powerstate(pa->pa_pc, pa->pa_tag, state, 0);
764
765 aml_register_notify(pdev->node, NULL, acpi_pci_notify, pdev, 0);
766
767 return pdev->node;
768 }
769
770 return NULL;
771}
772
773pcireg_t
774acpi_pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag)
775{
776 struct acpi_pci *pdev;
777 int bus, dev, fun;
778 int state = -1, defaultstate = pci_get_powerstate(pc, tag);
779
780 pci_decompose_tag(pc, tag, &bus, &dev, &fun);
781 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
782 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) {
783 switch (acpi_softc->sc_state) {
784 case ACPI_STATE_S0:
785 if (boothowto & RB_POWERDOWN) {
786 defaultstate = PCI_PMCSR_STATE_D3;
787 state = pdev->_s0w;
788 }
789 break;
790 case ACPI_STATE_S3:
791 defaultstate = PCI_PMCSR_STATE_D3;
792 state = MAX(pdev->_s3d, pdev->_s3w);
793 break;
794 case ACPI_STATE_S4:
795 state = MAX(pdev->_s4d, pdev->_s4w);
796 break;
797 case ACPI_STATE_S5:
798 default:
799 break;
800 }
801
802 if (state >= PCI_PMCSR_STATE_D0 &&
803 state <= PCI_PMCSR_STATE_D3)
804 return state;
805 }
806 }
807
808 return defaultstate;
809}
810
811void
812acpi_pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state, int pre)
813{
814 struct acpi_softc *sc = acpi_softc;
815#if NACPIPWRRES > 0
816 struct acpi_pwrres *pr;
817#endif
818 struct acpi_pci *pdev;
819 int bus, dev, fun;
820 char name[5];
821
822 pci_decompose_tag(pc, tag, &bus, &dev, &fun);
823 TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
824 if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun)
825 break;
826 }
827
828 if (pdev == NULL)
829 return;
830
831 if (state != ACPI_STATE_D0 && !pre) {
832 snprintf(name, sizeof(name), "_PS%d", state);
833 aml_evalname(sc, pdev->node, name, 0, NULL, NULL);
834 }
835
836#if NACPIPWRRES > 0
837 SIMPLEQ_FOREACH(pr, &sc->sc_pwrresdevs, p_next) {
838 if (pr->p_node != pdev->node)
839 continue;
840
841 /*
842 * If the firmware is already aware that the device
843 * is in the given state, there's nothing to do.
844 */
845 if (pr->p_state == state)
846 continue;
847
848 /*
849 * If the device supports D3cold, ignore the Resource
850 * for the D3 state.
851 */
852 if (pr->p_res_state == ACPI_STATE_D3 && pdev->d3cold)
853 continue;
854
855 if (pre) {
856 /*
857 * If a Resource is dependent on this device for
858 * the given state, make sure it is turned "_ON".
859 */
860 if (pr->p_res_state == state)
861 acpipwrres_ref_incr(pr->p_res_sc, pr->p_node);
862 } else {
863 /*
864 * If a Resource was referenced for the state we
865 * left, drop a reference and turn it "_OFF" if
866 * it was the last one.
867 */
868 if (pr->p_res_state == pr->p_state)
869 acpipwrres_ref_decr(pr->p_res_sc, pr->p_node);
870
871 if (pr->p_res_state == state) {
872 snprintf(name, sizeof(name), "_PS%d", state);
873 aml_evalname(sc, pr->p_node, name, 0,
874 NULL, NULL);
875 }
876
877 pr->p_state = state;
878 }
879 }
880#endif /* NACPIPWRRES > 0 */
881
882 if (state == ACPI_STATE_D0 && pre)
883 aml_evalname(sc, pdev->node, "_PS0", 0, NULL, NULL);
884}
885
886int
887acpi_pci_notify(struct aml_node *node, int ntype, void *arg)
888{
889 struct acpi_pci *pdev = arg;
890 pci_chipset_tag_t pc;
891 pcitag_t tag;
892 pcireg_t reg;
893 int offset;
894
895 /* We're only interested in Device Wake notifications. */
896 if (ntype != 2)
897 return (0);
898
899 pc = pci_lookup_segment(pdev->seg, pdev->bus);
900 tag = pci_make_tag(pc, pdev->bus, pdev->dev, pdev->fun);
901 if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) {
902 /* Clear the PME Status bit if it is set. */
903 reg = pci_conf_read(pc, tag, offset + PCI_PMCSR);
904 pci_conf_write(pc, tag, offset + PCI_PMCSR, reg);
905 }
906
907 return (0);
908}
909
910void
911acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr)
912{
913 struct acpi_pci *pdev;
914 struct pcibus_attach_args *pba = aux;
915
916 KASSERT(pba->pba_busex != NULL);
917
918 TAILQ_FOREACH(pdev, &acpi_pcirootdevs, next) {
919 if (extent_alloc_region(pba->pba_busex, pdev->bus,
920 1, EX_NOWAIT) != 0)
921 continue;
922 pba->pba_bus = pdev->bus;
923 config_found(dev, pba, pr);
924 }
925}
926
927/* GPIO support */
928
929struct acpi_gpio_event {
930 struct aml_node *node;
931 uint16_t tflags;
932 uint16_t pin;
933};
934
935void
936acpi_gpio_event_task(void *arg0, int arg1)
937{
938 struct acpi_softc *sc = acpi_softc;
939 struct acpi_gpio_event *ev = arg0;
940 struct acpi_gpio *gpio = ev->node->gpio;
941 struct aml_value evt;
942 uint16_t pin = arg1;
943 char name[5];
944
945 if (pin < 256) {
946 if ((ev->tflags & LR_GPIO_MODE) == LR_GPIO_LEVEL)
947 snprintf(name, sizeof(name), "_L%.2X", pin);
948 else
949 snprintf(name, sizeof(name), "_E%.2X", pin);
950 if (aml_evalname(sc, ev->node, name, 0, NULL, NULL) == 0)
951 goto intr_enable;
952 }
953
954 memset(&evt, 0, sizeof(evt));
955 evt.v_integer = pin;
956 evt.type = AML_OBJTYPE_INTEGER;
957 aml_evalname(sc, ev->node, "_EVT", 1, &evt, NULL);
958
959intr_enable:
960 if ((ev->tflags & LR_GPIO_MODE) == LR_GPIO_LEVEL) {
961 if (gpio->intr_enable)
962 gpio->intr_enable(gpio->cookie, pin);
963 }
964}
965
966int
967acpi_gpio_event(void *arg)
968{
969 struct acpi_softc *sc = acpi_softc;
970 struct acpi_gpio_event *ev = arg;
971 struct acpi_gpio *gpio = ev->node->gpio;
972
973 if ((ev->tflags & LR_GPIO_MODE) == LR_GPIO_LEVEL) {
974 if(gpio->intr_disable)
975 gpio->intr_disable(gpio->cookie, ev->pin);
976 }
977
978 if (cpu_suspended) {
979 cpu_suspended = 0;
980 sc->sc_wakegpe = -3;
981 sc->sc_wakegpio = ev->pin;
982 }
983
984 acpi_addtask(acpi_softc, acpi_gpio_event_task, ev, ev->pin);
985 acpi_wakeup(acpi_softc);
986
987 return 1;
988}
989
990int
991acpi_gpio_parse_events(int crsidx, union acpi_resource *crs, void *arg)
992{
993 struct aml_node *devnode = arg;
994 struct aml_node *node;
995 uint16_t pin;
996
997 switch (AML_CRSTYPE(crs)) {
998 case LR_GPIO:
999 node = aml_searchname(devnode,
1000 (char *)&crs->pad[crs->lr_gpio.res_off]);
1001 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
1002 if (crs->lr_gpio.type == LR_GPIO_INT &&
1003 node && node->gpio && node->gpio->intr_establish) {
1004 struct acpi_gpio *gpio = node->gpio;
1005 struct acpi_gpio_event *ev;
1006
1007 ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK);
1008 ev->node = devnode;
1009 ev->tflags = crs->lr_gpio.tflags;
1010 ev->pin = pin;
1011 gpio->intr_establish(gpio->cookie, pin,
1012 crs->lr_gpio.tflags, IPL_BIO | IPL_WAKEUP,
1013 acpi_gpio_event, ev);
1014 }
1015 break;
1016 default:
1017 printf("%s: unknown resource type %d\n", __func__,
1018 AML_CRSTYPE(crs));
1019 }
1020
1021 return 0;
1022}
1023
1024void
1025acpi_register_gpio(struct acpi_softc *sc, struct aml_node *devnode)
1026{
1027 struct aml_value arg[2];
1028 struct aml_node *node;
1029 struct aml_value res;
1030
1031 /* Register GeneralPurposeIO address space. */
1032 memset(&arg, 0, sizeof(arg));
1033 arg[0].type = AML_OBJTYPE_INTEGER;
1034 arg[0].v_integer = ACPI_OPREG_GPIO;
1035 arg[1].type = AML_OBJTYPE_INTEGER;
1036 arg[1].v_integer = 1;
1037 node = aml_searchname(devnode, "_REG");
1038 if (node && aml_evalnode(sc, node, 2, arg, NULL))
1039 printf("%s: _REG failed\n", node->name);
1040
1041 /* Register GPIO signaled ACPI events. */
1042 if (aml_evalname(sc, devnode, "_AEI", 0, NULL, &res))
1043 return;
1044 aml_parse_resource(&res, acpi_gpio_parse_events, devnode);
1045}
1046
1047#ifndef SMALL_KERNEL
1048
1049void
1050acpi_register_gsb(struct acpi_softc *sc, struct aml_node *devnode)
1051{
1052 struct aml_value arg[2];
1053 struct aml_node *node;
1054
1055 /* Register GenericSerialBus address space. */
1056 memset(&arg, 0, sizeof(arg));
1057 arg[0].type = AML_OBJTYPE_INTEGER;
1058 arg[0].v_integer = ACPI_OPREG_GSB;
1059 arg[1].type = AML_OBJTYPE_INTEGER;
1060 arg[1].v_integer = 1;
1061 node = aml_searchname(devnode, "_REG");
1062 if (node && aml_evalnode(sc, node, 2, arg, NULL))
1063 printf("%s: _REG failed\n", node->name);
1064}
1065
1066#endif
1067
1068void
1069acpi_attach_common(struct acpi_softc *sc, paddr_t base)
1070{
1071 struct acpi_mem_map handle;
1072 struct acpi_rsdp *rsdp;
1073 struct acpi_q *entry;
1074 struct acpi_dsdt *p_dsdt;
1075#ifndef SMALL_KERNEL
1076 int wakeup_dev_ct;
1077 struct acpi_wakeq *wentry;
1078 struct device *dev;
1079#endif /* SMALL_KERNEL */
1080 paddr_t facspa;
1081 uint16_t pm1;
1082 int s;
1083
1084 rw_init(&sc->sc_lck, "acpilk");
1085
1086 acpi_softc = sc;
1087 sc->sc_root = &aml_root;
1088
1089 if (acpi_map(base, sizeof(struct acpi_rsdp), &handle)) {
1090 printf(": can't map memory\n");
1091 return;
1092 }
1093 rsdp = (struct acpi_rsdp *)handle.va;
1094
1095 pool_init(&acpiwqpool, sizeof(struct acpi_taskq), 0, IPL_BIO, 0,
1096 "acpiwqpl", NULL);
1097 pool_setlowat(&acpiwqpool, 16);
1098
1099 SIMPLEQ_INIT(&sc->sc_tables);
1100 SIMPLEQ_INIT(&sc->sc_wakedevs);
1101#if NACPIPWRRES > 0
1102 SIMPLEQ_INIT(&sc->sc_pwrresdevs);
1103#endif /* NACPIPWRRES > 0 */
1104
1105 if (acpi_loadtables(sc, rsdp)) {
1106 printf(": can't load tables\n");
1107 acpi_unmap(&handle);
1108 return;
1109 }
1110
1111 acpi_unmap(&handle);
1112
1113 /*
1114 * Find the FADT
1115 */
1116 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1117 if (memcmp(entry->q_table, FADT_SIG,
1118 sizeof(FADT_SIG) - 1) == 0) {
1119 sc->sc_fadt = entry->q_table;
1120 break;
1121 }
1122 }
1123 if (sc->sc_fadt == NULL) {
1124 printf(": no FADT\n");
1125 return;
1126 }
1127
1128 sc->sc_major = sc->sc_fadt->hdr.revision;
1129 if (sc->sc_major > 4)
1130 sc->sc_minor = sc->sc_fadt->fadt_minor;
1131 printf(": ACPI %d.%d", sc->sc_major, sc->sc_minor);
1132
1133 /*
1134 * A bunch of things need to be done differently for
1135 * Hardware-reduced ACPI.
1136 */
1137 if (sc->sc_fadt->hdr_revision >= 5 &&
1138 sc->sc_fadt->flags & FADT_HW_REDUCED_ACPI)
1139 sc->sc_hw_reduced = 1;
1140
1141 /* Map Power Management registers */
1142 acpi_map_pmregs(sc);
1143
1144 /*
1145 * Check if we can and need to enable ACPI control.
1146 */
1147 pm1 = acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0);
1148 if ((pm1 & ACPI_PM1_SCI_EN) == 0 && sc->sc_fadt->smi_cmd &&
1149 (!sc->sc_fadt->acpi_enable && !sc->sc_fadt->acpi_disable)) {
1150 printf(", ACPI control unavailable\n");
1151 acpi_unmap_pmregs(sc);
1152 return;
1153 }
1154
1155 /*
1156 * Set up a pointer to the firmware control structure
1157 */
1158 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_firmware_ctl == 0)
1159 facspa = sc->sc_fadt->firmware_ctl;
1160 else
1161 facspa = sc->sc_fadt->x_firmware_ctl;
1162
1163 if (acpi_map(facspa, sizeof(struct acpi_facs), &handle))
1164 printf(" !FACS");
1165 else
1166 sc->sc_facs = (struct acpi_facs *)handle.va;
1167
1168 /* Create opcode hashtable */
1169 aml_hashopcodes();
1170
1171 /* Create Default AML objects */
1172 aml_create_defaultobjects();
1173
1174 /*
1175 * Load the DSDT from the FADT pointer -- use the
1176 * extended (64-bit) pointer if it exists
1177 */
1178 if (sc->sc_fadt->hdr_revision < 3 || sc->sc_fadt->x_dsdt == 0)
1179 entry = acpi_maptable(sc, sc->sc_fadt->dsdt, NULL, NULL, NULL,
1180 -1);
1181 else
1182 entry = acpi_maptable(sc, sc->sc_fadt->x_dsdt, NULL, NULL, NULL,
1183 -1);
1184
1185 if (entry == NULL)
1186 printf(" !DSDT");
1187
1188 p_dsdt = entry->q_table;
1189 acpi_parse_aml(sc, NULL, p_dsdt->aml,
1190 p_dsdt->hdr_length - sizeof(p_dsdt->hdr));
1191
1192 /* Load SSDT's */
1193 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1194 if (memcmp(entry->q_table, SSDT_SIG,
1195 sizeof(SSDT_SIG) - 1) == 0) {
1196 p_dsdt = entry->q_table;
1197 acpi_parse_aml(sc, NULL, p_dsdt->aml,
1198 p_dsdt->hdr_length - sizeof(p_dsdt->hdr));
1199 }
1200 }
1201
1202 /* Perform post-parsing fixups */
1203 aml_postparse();
1204
1205#if 0
1206 if (sc->sc_fadt->hdr_revision > 2 &&
1207 !ISSET(sc->sc_fadt->iapc_boot_arch, FADT_LEGACY_DEVICES))
1208 acpi_legacy_free = 1;
1209#endif
1210
1211#ifndef SMALL_KERNEL
1212 /* Find available sleeping states */
1213 acpi_init_states(sc);
1214
1215 /* Find available sleep/resume related methods. */
1216 acpi_init_pm(sc);
1217#endif /* SMALL_KERNEL */
1218
1219 /* Initialize GPE handlers */
1220 s = splbio();
1221 acpi_init_gpes(sc);
1222 splx(s);
1223
1224 /* some devices require periodic polling */
1225 timeout_set(&sc->sc_dev_timeout, acpi_poll, sc);
1226
1227 acpi_enabled = 1;
1228
1229 /*
1230 * Take over ACPI control. Note that once we do this, we
1231 * effectively tell the system that we have ownership of
1232 * the ACPI hardware registers, and that SMI should leave
1233 * them alone
1234 *
1235 * This may prevent thermal control on some systems where
1236 * that actually does work
1237 */
1238 if ((pm1 & ACPI_PM1_SCI_EN) == 0 && sc->sc_fadt->smi_cmd) {
1239 if (acpi_enable(sc)) {
1240 printf(", can't enable ACPI\n");
1241 return;
1242 }
1243 }
1244
1245 printf("\n%s: tables", DEVNAME(sc));
1246 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1247 printf(" %.4s", (char *)entry->q_table);
1248 }
1249 printf("\n");
1250
1251#ifndef SMALL_KERNEL
1252 /* Display wakeup devices and lowest S-state */
1253 wakeup_dev_ct = 0;
1254 printf("%s: wakeup devices", DEVNAME(sc));
1255 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) {
1256 if (wakeup_dev_ct < 16)
1257 printf(" %.4s(S%d)", wentry->q_node->name,
1258 wentry->q_state);
1259 else if (wakeup_dev_ct == 16)
1260 printf(" [...]");
1261 wakeup_dev_ct++;
1262 }
1263 printf("\n");
1264
1265#ifdef SUSPEND
1266 if (wakeup_dev_ct > 0)
1267 device_register_wakeup(&sc->sc_dev);
1268#endif
1269#endif /* SMALL_KERNEL */
1270
1271 /*
1272 * ACPI is enabled now -- attach timer
1273 */
1274 if (!sc->sc_hw_reduced &&
1275 (sc->sc_fadt->pm_tmr_blk || sc->sc_fadt->x_pm_tmr_blk.address)) {
1276 struct acpi_attach_args aaa;
1277
1278 memset(&aaa, 0, sizeof(aaa));
1279 aaa.aaa_name = "acpitimer";
1280 aaa.aaa_iot = sc->sc_iot;
1281 aaa.aaa_memt = sc->sc_memt;
1282 config_found(&sc->sc_dev, &aaa, acpi_print);
1283 }
1284
1285 /*
1286 * Attach table-defined devices
1287 */
1288 SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
1289 struct acpi_attach_args aaa;
1290
1291 memset(&aaa, 0, sizeof(aaa));
1292 aaa.aaa_iot = sc->sc_iot;
1293 aaa.aaa_memt = sc->sc_memt;
1294 aaa.aaa_dmat = sc->sc_ci_dmat;
1295 aaa.aaa_table = entry->q_table;
1296 config_found_sm(&sc->sc_dev, &aaa, acpi_print, acpi_submatch);
1297 }
1298
1299 /* initialize runtime environment */
1300 aml_find_node(sc->sc_root, "_INI", acpi_inidev, sc);
1301
1302#ifdef __arm64__
1303 aml_find_node(sc->sc_root, "ECTC", acpi_foundsectwo, sc);
1304#endif
1305
1306 /* Get PCI mapping */
1307 aml_walknodes(sc->sc_root, AML_WALK_PRE, acpi_getpci, sc);
1308
1309#if defined (__amd64__) || defined(__i386__)
1310 /* attach pci interrupt routing tables */
1311 aml_find_node(sc->sc_root, "_PRT", acpi_foundprt, sc);
1312#endif
1313
1314 aml_find_node(sc->sc_root, "_HID", acpi_foundec, sc);
1315
1316 /* check if we're running on a sony */
1317 aml_find_node(sc->sc_root, "GBRT", acpi_foundsony, sc);
1318
1319#ifndef SMALL_KERNEL
1320 /* try to find smart battery first */
1321 aml_find_node(sc->sc_root, "_HID", acpi_foundsbs, sc);
1322#endif /* SMALL_KERNEL */
1323
1324 /* attach battery, power supply and button devices */
1325 aml_find_node(sc->sc_root, "_HID", acpi_foundhid, sc);
1326
1327 aml_walknodes(sc->sc_root, AML_WALK_PRE, acpi_add_device, sc);
1328
1329#ifndef SMALL_KERNEL
1330#if NWD > 0
1331 /* Attach IDE bay */
1332 aml_walknodes(sc->sc_root, AML_WALK_PRE, acpi_foundide, sc);
1333#endif
1334
1335 /* attach docks */
1336 aml_find_node(sc->sc_root, "_DCK", acpi_founddock, sc);
1337
1338 /* attach video */
1339 aml_find_node(sc->sc_root, "_DOS", acpi_foundvideo, sc);
1340
1341 /* create list of devices we want to query when APM comes in */
1342 SLIST_INIT(&sc->sc_ac);
1343 SLIST_INIT(&sc->sc_bat);
1344 TAILQ_FOREACH(dev, &alldevs, dv_list) {
1345 if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpiac")) {
1346 struct acpi_ac *ac;
1347
1348 ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO);
1349 ac->aac_softc = (struct acpiac_softc *)dev;
1350 SLIST_INSERT_HEAD(&sc->sc_ac, ac, aac_link);
1351 } else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpibat")) {
1352 struct acpi_bat *bat;
1353
1354 bat = malloc(sizeof(*bat), M_DEVBUF, M_WAITOK | M_ZERO);
1355 bat->aba_softc = (struct acpibat_softc *)dev;
1356 SLIST_INSERT_HEAD(&sc->sc_bat, bat, aba_link);
1357 } else if (!strcmp(dev->dv_cfdata->cf_driver->cd_name, "acpisbs")) {
1358 struct acpi_sbs *sbs;
1359
1360 sbs = malloc(sizeof(*sbs), M_DEVBUF, M_WAITOK | M_ZERO);
1361 sbs->asbs_softc = (struct acpisbs_softc *)dev;
1362 SLIST_INSERT_HEAD(&sc->sc_sbs, sbs, asbs_link);
1363 }
1364 }
1365
1366#endif /* SMALL_KERNEL */
1367
1368 /* Setup threads */
1369 sc->sc_thread = malloc(sizeof(struct acpi_thread), M_DEVBUF, M_WAITOK);
1370 sc->sc_thread->sc = sc;
1371 sc->sc_thread->running = 1;
1372
1373 /* Enable PCI Power Management. */
1374 pci_dopm = 1;
1375
1376 acpi_attach_machdep(sc);
1377
1378 kthread_create_deferred(acpi_create_thread, sc);
1379}
1380
1381int
1382acpi_submatch(struct device *parent, void *match, void *aux)
1383{
1384 struct acpi_attach_args *aaa = (struct acpi_attach_args *)aux;
1385 struct cfdata *cf = match;
1386
1387 if (aaa->aaa_table == NULL)
1388 return (0);
1389 return ((*cf->cf_attach->ca_match)(parent, match, aux));
1390}
1391
1392int
1393acpi_noprint(void *aux, const char *pnp)
1394{
1395 return (QUIET);
1396}
1397
1398int
1399acpi_print(void *aux, const char *pnp)
1400{
1401 struct acpi_attach_args *aa = aux;
1402
1403 if (pnp) {
1404 if (aa->aaa_name)
1405 printf("%s at %s", aa->aaa_name, pnp);
1406 else if (aa->aaa_dev)
1407 printf("\"%s\" at %s", aa->aaa_dev, pnp);
1408 else
1409 return (QUIET);
1410 }
1411
1412 return (UNCONF);
1413}
1414
1415struct acpi_q *
1416acpi_maptable(struct acpi_softc *sc, paddr_t addr, const char *sig,
1417 const char *oem, const char *tbl, int flag)
1418{
1419 static int tblid;
1420 struct acpi_mem_map handle;
1421 struct acpi_table_header *hdr;
1422 struct acpi_q *entry;
1423 size_t len;
1424
1425 /* Check if we can map address */
1426 if (addr == 0)
1427 return NULL;
1428 if (acpi_map(addr, sizeof(*hdr), &handle))
1429 return NULL;
1430 hdr = (struct acpi_table_header *)handle.va;
1431 len = hdr->length;
1432 acpi_unmap(&handle);
1433
1434 /* Validate length/checksum */
1435 if (acpi_map(addr, len, &handle))
1436 return NULL;
1437 hdr = (struct acpi_table_header *)handle.va;
1438 if (acpi_checksum(hdr, len))
1439 printf("\n%s: %.4s checksum error",
1440 DEVNAME(sc), hdr->signature);
1441
1442 if ((sig && memcmp(sig, hdr->signature, 4)) ||
1443 (oem && memcmp(oem, hdr->oemid, 6)) ||
1444 (tbl && memcmp(tbl, hdr->oemtableid, 8))) {
1445 acpi_unmap(&handle);
1446 return NULL;
1447 }
1448
1449 /* Allocate copy */
1450 entry = malloc(sizeof(*entry) + len, M_DEVBUF, M_NOWAIT);
1451 if (entry != NULL) {
1452 memcpy(entry->q_data, handle.va, len);
1453 entry->q_table = entry->q_data;
1454 entry->q_id = ++tblid;
1455
1456 if (flag < 0)
1457 SIMPLEQ_INSERT_HEAD(&sc->sc_tables, entry,
1458 q_next);
1459 else if (flag > 0)
1460 SIMPLEQ_INSERT_TAIL(&sc->sc_tables, entry,
1461 q_next);
1462 }
1463 acpi_unmap(&handle);
1464 return entry;
1465}
1466
1467int
1468acpi_loadtables(struct acpi_softc *sc, struct acpi_rsdp *rsdp)
1469{
1470 struct acpi_q *sdt;
1471 int i, ntables;
1472 size_t len;
1473
1474 if (rsdp->rsdp_revision == 2 && rsdp->rsdp_xsdt) {
1475 struct acpi_xsdt *xsdt;
1476
1477 sdt = acpi_maptable(sc, rsdp->rsdp_xsdt, NULL, NULL, NULL, 0);
1478 if (sdt == NULL) {
1479 printf("couldn't map xsdt\n");
1480 return (ENOMEM);
1481 }
1482
1483 xsdt = (struct acpi_xsdt *)sdt->q_data;
1484 len = xsdt->hdr.length;
1485 ntables = (len - sizeof(struct acpi_table_header)) /
1486 sizeof(xsdt->table_offsets[0]);
1487
1488 for (i = 0; i < ntables; i++)
1489 acpi_maptable(sc, xsdt->table_offsets[i], NULL, NULL,
1490 NULL, 1);
1491
1492 free(sdt, M_DEVBUF, sizeof(*sdt) + len);
1493 } else {
1494 struct acpi_rsdt *rsdt;
1495
1496 sdt = acpi_maptable(sc, rsdp->rsdp_rsdt, NULL, NULL, NULL, 0);
1497 if (sdt == NULL) {
1498 printf("couldn't map rsdt\n");
1499 return (ENOMEM);
1500 }
1501
1502 rsdt = (struct acpi_rsdt *)sdt->q_data;
1503 len = rsdt->hdr.length;
1504 ntables = (len - sizeof(struct acpi_table_header)) /
1505 sizeof(rsdt->table_offsets[0]);
1506
1507 for (i = 0; i < ntables; i++)
1508 acpi_maptable(sc, rsdt->table_offsets[i], NULL, NULL,
1509 NULL, 1);
1510
1511 free(sdt, M_DEVBUF, sizeof(*sdt) + len);
1512 }
1513
1514 return (0);
1515}
1516
1517/* Read from power management register */
1518int
1519acpi_read_pmreg(struct acpi_softc *sc, int reg, int offset)
1520{
1521 bus_space_handle_t ioh;
1522 bus_size_t size;
1523 int regval;
1524
1525 /*
1526 * For Hardware-reduced ACPI we emulate PM1B_CNT to reflect
1527 * that the system is always in ACPI mode.
1528 */
1529 if (sc->sc_hw_reduced && reg == ACPIREG_PM1B_CNT) {
1530 KASSERT(offset == 0);
1531 return ACPI_PM1_SCI_EN;
1532 }
1533
1534 /*
1535 * For Hardware-reduced ACPI we also emulate PM1A_STS using
1536 * SLEEP_STATUS_REG.
1537 */
1538 if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_STS &&
1539 sc->sc_fadt->sleep_status_reg.register_bit_width > 0) {
1540 uint8_t value;
1541
1542 KASSERT(offset == 0);
1543 acpi_gasio(sc, ACPI_IOREAD,
1544 sc->sc_fadt->sleep_status_reg.address_space_id,
1545 sc->sc_fadt->sleep_status_reg.address,
1546 sc->sc_fadt->sleep_status_reg.register_bit_width / 8,
1547 sc->sc_fadt->sleep_status_reg.access_size, &value);
1548 return ((int)value << 8);
1549 }
1550
1551 /* Special cases: 1A/1B blocks can be OR'ed together */
1552 switch (reg) {
1553 case ACPIREG_PM1_EN:
1554 return (acpi_read_pmreg(sc, ACPIREG_PM1A_EN, offset) |
1555 acpi_read_pmreg(sc, ACPIREG_PM1B_EN, offset));
1556 case ACPIREG_PM1_STS:
1557 return (acpi_read_pmreg(sc, ACPIREG_PM1A_STS, offset) |
1558 acpi_read_pmreg(sc, ACPIREG_PM1B_STS, offset));
1559 case ACPIREG_PM1_CNT:
1560 return (acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, offset) |
1561 acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, offset));
1562 case ACPIREG_GPE_STS:
1563 dnprintf(50, "read GPE_STS offset: %.2x %.2x %.2x\n", offset,
1564 sc->sc_fadt->gpe0_blk_len>>1, sc->sc_fadt->gpe1_blk_len>>1);
1565 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1566 reg = ACPIREG_GPE0_STS;
1567 }
1568 break;
1569 case ACPIREG_GPE_EN:
1570 dnprintf(50, "read GPE_EN offset: %.2x %.2x %.2x\n",
1571 offset, sc->sc_fadt->gpe0_blk_len>>1,
1572 sc->sc_fadt->gpe1_blk_len>>1);
1573 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1574 reg = ACPIREG_GPE0_EN;
1575 }
1576 break;
1577 }
1578
1579 if (reg >= ACPIREG_MAXREG || sc->sc_pmregs[reg].size == 0)
1580 return (0);
1581
1582 regval = 0;
1583 ioh = sc->sc_pmregs[reg].ioh;
1584 size = sc->sc_pmregs[reg].size;
1585 if (size > sc->sc_pmregs[reg].access)
1586 size = sc->sc_pmregs[reg].access;
1587
1588 switch (size) {
1589 case 1:
1590 regval = bus_space_read_1(sc->sc_iot, ioh, offset);
1591 break;
1592 case 2:
1593 regval = bus_space_read_2(sc->sc_iot, ioh, offset);
1594 break;
1595 case 4:
1596 regval = bus_space_read_4(sc->sc_iot, ioh, offset);
1597 break;
1598 }
1599
1600 dnprintf(30, "acpi_readpm: %s = %.4x:%.4x %x\n",
1601 sc->sc_pmregs[reg].name,
1602 sc->sc_pmregs[reg].addr, offset, regval);
1603 return (regval);
1604}
1605
1606/* Write to power management register */
1607void
1608acpi_write_pmreg(struct acpi_softc *sc, int reg, int offset, int regval)
1609{
1610 bus_space_handle_t ioh;
1611 bus_size_t size;
1612
1613 /*
1614 * For Hardware-reduced ACPI we also emulate PM1A_STS using
1615 * SLEEP_STATUS_REG.
1616 */
1617 if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_STS &&
1618 sc->sc_fadt->sleep_status_reg.register_bit_width > 0) {
1619 uint8_t value = (regval >> 8);
1620
1621 KASSERT(offset == 0);
1622 acpi_gasio(sc, ACPI_IOWRITE,
1623 sc->sc_fadt->sleep_status_reg.address_space_id,
1624 sc->sc_fadt->sleep_status_reg.address,
1625 sc->sc_fadt->sleep_status_reg.register_bit_width / 8,
1626 sc->sc_fadt->sleep_status_reg.access_size, &value);
1627 return;
1628 }
1629
1630 /*
1631 * For Hardware-reduced ACPI we also emulate PM1A_CNT using
1632 * SLEEP_CONTROL_REG.
1633 */
1634 if (sc->sc_hw_reduced && reg == ACPIREG_PM1A_CNT &&
1635 sc->sc_fadt->sleep_control_reg.register_bit_width > 0) {
1636 uint8_t value = (regval >> 8);
1637
1638 KASSERT(offset == 0);
1639 acpi_gasio(sc, ACPI_IOWRITE,
1640 sc->sc_fadt->sleep_control_reg.address_space_id,
1641 sc->sc_fadt->sleep_control_reg.address,
1642 sc->sc_fadt->sleep_control_reg.register_bit_width / 8,
1643 sc->sc_fadt->sleep_control_reg.access_size, &value);
1644 return;
1645 }
1646
1647 /* Special cases: 1A/1B blocks can be written with same value */
1648 switch (reg) {
1649 case ACPIREG_PM1_EN:
1650 acpi_write_pmreg(sc, ACPIREG_PM1A_EN, offset, regval);
1651 acpi_write_pmreg(sc, ACPIREG_PM1B_EN, offset, regval);
1652 break;
1653 case ACPIREG_PM1_STS:
1654 acpi_write_pmreg(sc, ACPIREG_PM1A_STS, offset, regval);
1655 acpi_write_pmreg(sc, ACPIREG_PM1B_STS, offset, regval);
1656 break;
1657 case ACPIREG_PM1_CNT:
1658 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, offset, regval);
1659 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, offset, regval);
1660 break;
1661 case ACPIREG_GPE_STS:
1662 dnprintf(50, "write GPE_STS offset: %.2x %.2x %.2x %.2x\n",
1663 offset, sc->sc_fadt->gpe0_blk_len>>1,
1664 sc->sc_fadt->gpe1_blk_len>>1, regval);
1665 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1666 reg = ACPIREG_GPE0_STS;
1667 }
1668 break;
1669 case ACPIREG_GPE_EN:
1670 dnprintf(50, "write GPE_EN offset: %.2x %.2x %.2x %.2x\n",
1671 offset, sc->sc_fadt->gpe0_blk_len>>1,
1672 sc->sc_fadt->gpe1_blk_len>>1, regval);
1673 if (offset < (sc->sc_fadt->gpe0_blk_len >> 1)) {
1674 reg = ACPIREG_GPE0_EN;
1675 }
1676 break;
1677 }
1678
1679 /* All special case return here */
1680 if (reg >= ACPIREG_MAXREG)
1681 return;
1682
1683 ioh = sc->sc_pmregs[reg].ioh;
1684 size = sc->sc_pmregs[reg].size;
1685 if (size > sc->sc_pmregs[reg].access)
1686 size = sc->sc_pmregs[reg].access;
1687
1688 switch (size) {
1689 case 1:
1690 bus_space_write_1(sc->sc_iot, ioh, offset, regval);
1691 break;
1692 case 2:
1693 bus_space_write_2(sc->sc_iot, ioh, offset, regval);
1694 break;
1695 case 4:
1696 bus_space_write_4(sc->sc_iot, ioh, offset, regval);
1697 break;
1698 }
1699
1700 dnprintf(30, "acpi_writepm: %s = %.4x:%.4x %x\n",
1701 sc->sc_pmregs[reg].name, sc->sc_pmregs[reg].addr, offset, regval);
1702}
1703
1704/* Map Power Management registers */
1705void
1706acpi_map_pmregs(struct acpi_softc *sc)
1707{
1708 struct acpi_fadt *fadt = sc->sc_fadt;
1709 bus_addr_t addr;
1710 bus_size_t size, access;
1711 const char *name;
1712 int reg;
1713
1714 for (reg = 0; reg < ACPIREG_MAXREG; reg++) {
1715 size = 0;
1716 access = 0;
1717 switch (reg) {
1718 case ACPIREG_SMICMD:
1719 name = "smi";
1720 size = access = 1;
1721 addr = fadt->smi_cmd;
1722 break;
1723 case ACPIREG_PM1A_STS:
1724 case ACPIREG_PM1A_EN:
1725 name = "pm1a_sts";
1726 size = fadt->pm1_evt_len >> 1;
1727 if (fadt->pm1a_evt_blk) {
1728 addr = fadt->pm1a_evt_blk;
1729 access = 2;
1730 } else if (fadt->hdr_revision >= 3) {
1731 addr = fadt->x_pm1a_evt_blk.address;
1732 access = 1 << fadt->x_pm1a_evt_blk.access_size;
1733 }
1734 if (reg == ACPIREG_PM1A_EN && addr) {
1735 addr += size;
1736 name = "pm1a_en";
1737 }
1738 break;
1739 case ACPIREG_PM1A_CNT:
1740 name = "pm1a_cnt";
1741 size = fadt->pm1_cnt_len;
1742 if (fadt->pm1a_cnt_blk) {
1743 addr = fadt->pm1a_cnt_blk;
1744 access = 2;
1745 } else if (fadt->hdr_revision >= 3) {
1746 addr = fadt->x_pm1a_cnt_blk.address;
1747 access = 1 << fadt->x_pm1a_cnt_blk.access_size;
1748 }
1749 break;
1750 case ACPIREG_PM1B_STS:
1751 case ACPIREG_PM1B_EN:
1752 name = "pm1b_sts";
1753 size = fadt->pm1_evt_len >> 1;
1754 if (fadt->pm1b_evt_blk) {
1755 addr = fadt->pm1b_evt_blk;
1756 access = 2;
1757 } else if (fadt->hdr_revision >= 3) {
1758 addr = fadt->x_pm1b_evt_blk.address;
1759 access = 1 << fadt->x_pm1b_evt_blk.access_size;
1760 }
1761 if (reg == ACPIREG_PM1B_EN && addr) {
1762 addr += size;
1763 name = "pm1b_en";
1764 }
1765 break;
1766 case ACPIREG_PM1B_CNT:
1767 name = "pm1b_cnt";
1768 size = fadt->pm1_cnt_len;
1769 if (fadt->pm1b_cnt_blk) {
1770 addr = fadt->pm1b_cnt_blk;
1771 access = 2;
1772 } else if (fadt->hdr_revision >= 3) {
1773 addr = fadt->x_pm1b_cnt_blk.address;
1774 access = 1 << fadt->x_pm1b_cnt_blk.access_size;
1775 }
1776 break;
1777 case ACPIREG_PM2_CNT:
1778 name = "pm2_cnt";
1779 size = fadt->pm2_cnt_len;
1780 if (fadt->pm2_cnt_blk) {
1781 addr = fadt->pm2_cnt_blk;
1782 access = size;
1783 } else if (fadt->hdr_revision >= 3) {
1784 addr = fadt->x_pm2_cnt_blk.address;
1785 access = 1 << fadt->x_pm2_cnt_blk.access_size;
1786 }
1787 break;
1788#if 0
1789 case ACPIREG_PM_TMR:
1790 /* Allocated in acpitimer */
1791 name = "pm_tmr";
1792 size = fadt->pm_tmr_len;
1793 if (fadt->pm_tmr_blk) {
1794 addr = fadt->pm_tmr_blk;
1795 access = 4;
1796 } else if (fadt->hdr_revision >= 3) {
1797 addr = fadt->x_pm_tmr_blk.address;
1798 access = 1 << fadt->x_pm_tmr_blk.access_size;
1799 }
1800 break;
1801#endif
1802 case ACPIREG_GPE0_STS:
1803 case ACPIREG_GPE0_EN:
1804 name = "gpe0_sts";
1805 size = fadt->gpe0_blk_len >> 1;
1806 if (fadt->gpe0_blk) {
1807 addr = fadt->gpe0_blk;
1808 access = 1;
1809 } else if (fadt->hdr_revision >= 3) {
1810 addr = fadt->x_gpe0_blk.address;
1811 access = 1 << fadt->x_gpe0_blk.access_size;
1812 }
1813
1814 dnprintf(20, "gpe0 block len : %x\n",
1815 fadt->gpe0_blk_len >> 1);
1816 dnprintf(20, "gpe0 block addr: %x\n",
1817 fadt->gpe0_blk);
1818 if (reg == ACPIREG_GPE0_EN && addr) {
1819 addr += size;
1820 name = "gpe0_en";
1821 }
1822 break;
1823 case ACPIREG_GPE1_STS:
1824 case ACPIREG_GPE1_EN:
1825 name = "gpe1_sts";
1826 size = fadt->gpe1_blk_len >> 1;
1827 if (fadt->gpe1_blk) {
1828 addr = fadt->gpe1_blk;
1829 access = 1;
1830 } else if (fadt->hdr_revision >= 3) {
1831 addr = fadt->x_gpe1_blk.address;
1832 access = 1 << fadt->x_gpe1_blk.access_size;
1833 }
1834
1835 dnprintf(20, "gpe1 block len : %x\n",
1836 fadt->gpe1_blk_len >> 1);
1837 dnprintf(20, "gpe1 block addr: %x\n",
1838 fadt->gpe1_blk);
1839 if (reg == ACPIREG_GPE1_EN && addr) {
1840 addr += size;
1841 name = "gpe1_en";
1842 }
1843 break;
1844 }
1845 if (size && addr) {
1846 dnprintf(50, "mapping: %.4lx %.4lx %s\n",
1847 addr, size, name);
1848
1849 /* Size and address exist; map register space */
1850 bus_space_map(sc->sc_iot, addr, size, 0,
1851 &sc->sc_pmregs[reg].ioh);
1852
1853 sc->sc_pmregs[reg].name = name;
1854 sc->sc_pmregs[reg].size = size;
1855 sc->sc_pmregs[reg].addr = addr;
1856 sc->sc_pmregs[reg].access = min(access, 4);
1857 }
1858 }
1859}
1860
1861void
1862acpi_unmap_pmregs(struct acpi_softc *sc)
1863{
1864 int reg;
1865
1866 for (reg = 0; reg < ACPIREG_MAXREG; reg++) {
1867 if (sc->sc_pmregs[reg].size && sc->sc_pmregs[reg].addr)
1868 bus_space_unmap(sc->sc_iot, sc->sc_pmregs[reg].ioh,
1869 sc->sc_pmregs[reg].size);
1870 }
1871}
1872
1873int
1874acpi_enable(struct acpi_softc *sc)
1875{
1876 int idx;
1877
1878 acpi_write_pmreg(sc, ACPIREG_SMICMD, 0, sc->sc_fadt->acpi_enable);
1879 idx = 0;
1880 do {
1881 if (idx++ > ACPIEN_RETRIES) {
1882 return ETIMEDOUT;
1883 }
1884 } while (!(acpi_read_pmreg(sc, ACPIREG_PM1_CNT, 0) & ACPI_PM1_SCI_EN));
1885
1886 return 0;
1887}
1888
1889/* ACPI Workqueue support */
1890SIMPLEQ_HEAD(,acpi_taskq) acpi_taskq =
1891 SIMPLEQ_HEAD_INITIALIZER(acpi_taskq);
1892
1893void
1894acpi_addtask(struct acpi_softc *sc, void (*handler)(void *, int),
1895 void *arg0, int arg1)
1896{
1897 struct acpi_taskq *wq;
1898 int s;
1899
1900 wq = pool_get(&acpiwqpool, PR_ZERO | PR_NOWAIT);
1901 if (wq == NULL) {
1902 printf("unable to create task");
1903 return;
1904 }
1905 wq->handler = handler;
1906 wq->arg0 = arg0;
1907 wq->arg1 = arg1;
1908
1909 s = splbio();
1910 SIMPLEQ_INSERT_TAIL(&acpi_taskq, wq, next);
1911 splx(s);
1912}
1913
1914int
1915acpi_dotask(struct acpi_softc *sc)
1916{
1917 struct acpi_taskq *wq;
1918 int s;
1919
1920 s = splbio();
1921 if (SIMPLEQ_EMPTY(&acpi_taskq)) {
1922 splx(s);
1923
1924 /* we don't have anything to do */
1925 return (0);
1926 }
1927 wq = SIMPLEQ_FIRST(&acpi_taskq);
1928 SIMPLEQ_REMOVE_HEAD(&acpi_taskq, next);
1929 splx(s);
1930
1931 wq->handler(wq->arg0, wq->arg1);
1932
1933 pool_put(&acpiwqpool, wq);
1934
1935 /* We did something */
1936 return (1);
1937}
1938
1939#ifndef SMALL_KERNEL
1940
1941int
1942is_ata(struct aml_node *node)
1943{
1944 return (aml_searchname(node, "_GTM") != NULL ||
1945 aml_searchname(node, "_GTF") != NULL ||
1946 aml_searchname(node, "_STM") != NULL ||
1947 aml_searchname(node, "_SDD") != NULL);
1948}
1949
1950int
1951is_ejectable(struct aml_node *node)
1952{
1953 return (aml_searchname(node, "_EJ0") != NULL);
1954}
1955
1956int
1957is_ejectable_bay(struct aml_node *node)
1958{
1959 return ((is_ata(node) || is_ata(node->parent)) && is_ejectable(node));
1960}
1961
1962#if NWD > 0
1963int
1964acpiide_notify(struct aml_node *node, int ntype, void *arg)
1965{
1966 struct idechnl *ide = arg;
1967 struct acpi_softc *sc = ide->sc;
1968 struct pciide_softc *wsc;
1969 struct device *dev;
1970 int b,d,f;
1971 int64_t sta;
1972
1973 if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta) != 0)
1974 return (0);
1975
1976 dnprintf(10, "IDE notify! %s %d status:%llx\n", aml_nodename(node),
1977 ntype, sta);
1978
1979 /* Walk device list looking for IDE device match */
1980 TAILQ_FOREACH(dev, &alldevs, dv_list) {
1981 if (strcmp(dev->dv_cfdata->cf_driver->cd_name, "pciide"))
1982 continue;
1983
1984 wsc = (struct pciide_softc *)dev;
1985 pci_decompose_tag(NULL, wsc->sc_tag, &b, &d, &f);
1986 if (b != ACPI_PCI_BUS(ide->addr) ||
1987 d != ACPI_PCI_DEV(ide->addr) ||
1988 f != ACPI_PCI_FN(ide->addr))
1989 continue;
1990 dnprintf(10, "Found pciide: %s %x.%x.%x channel:%llx\n",
1991 dev->dv_xname, b,d,f, ide->chnl);
1992
1993 if (sta == 0 && ide->sta)
1994 wdcdetach(
1995 &wsc->pciide_channels[ide->chnl].wdc_channel, 0);
1996 else if (sta && !ide->sta)
1997 wdcattach(
1998 &wsc->pciide_channels[ide->chnl].wdc_channel);
1999 ide->sta = sta;
2000 }
2001 return (0);
2002}
2003
2004int
2005acpi_foundide(struct aml_node *node, void *arg)
2006{
2007 struct acpi_softc *sc = arg;
2008 struct aml_node *pp;
2009 struct idechnl *ide;
2010 union amlpci_t pi;
2011 int lvl;
2012
2013 /* Check if this is an ejectable bay */
2014 if (!is_ejectable_bay(node))
2015 return (0);
2016
2017 ide = malloc(sizeof(struct idechnl), M_DEVBUF, M_NOWAIT | M_ZERO);
2018 ide->sc = sc;
2019
2020 /* GTM/GTF can be at 2/3 levels: pciX.ideX.channelX[.driveX] */
2021 lvl = 0;
2022 for (pp=node->parent; pp; pp=pp->parent) {
2023 lvl++;
2024 if (aml_searchname(pp, "_HID"))
2025 break;
2026 }
2027
2028 /* Get PCI address and channel */
2029 if (lvl == 3) {
2030 aml_evalinteger(sc, node->parent, "_ADR", 0, NULL,
2031 &ide->chnl);
2032 aml_rdpciaddr(node->parent->parent, &pi);
2033 ide->addr = pi.addr;
2034 } else if (lvl == 4) {
2035 aml_evalinteger(sc, node->parent->parent, "_ADR", 0, NULL,
2036 &ide->chnl);
2037 aml_rdpciaddr(node->parent->parent->parent, &pi);
2038 ide->addr = pi.addr;
2039 }
2040 dnprintf(10, "%s %llx channel:%llx\n",
2041 aml_nodename(node), ide->addr, ide->chnl);
2042
2043 aml_evalinteger(sc, node, "_STA", 0, NULL, &ide->sta);
2044 dnprintf(10, "Got Initial STA: %llx\n", ide->sta);
2045
2046 aml_register_notify(node, "acpiide", acpiide_notify, ide, 0);
2047 return (0);
2048}
2049#endif /* NWD > 0 */
2050
2051void
2052acpi_sleep_task(void *arg0, int sleepmode)
2053{
2054 struct acpi_softc *sc = arg0;
2055
2056#ifdef SUSPEND
2057 sleep_state(sc, sleepmode);
2058#endif
2059 /* Tell userland to recheck A/C and battery status */
2060 acpi_record_event(sc, APM_POWER_CHANGE);
2061}
2062
2063#endif /* SMALL_KERNEL */
2064
2065void
2066acpi_reset(void)
2067{
2068 uint32_t reset_as, reset_len;
2069 uint32_t value;
2070 struct acpi_softc *sc = acpi_softc;
2071 struct acpi_fadt *fadt = sc->sc_fadt;
2072
2073 if (acpi_enabled == 0)
2074 return;
2075
2076 /*
2077 * RESET_REG_SUP is not properly set in some implementations,
2078 * but not testing against it breaks more machines than it fixes
2079 */
2080 if (fadt->hdr_revision <= 1 ||
2081 !(fadt->flags & FADT_RESET_REG_SUP) || fadt->reset_reg.address == 0)
2082 return;
2083
2084 value = fadt->reset_value;
2085
2086 reset_as = fadt->reset_reg.register_bit_width / 8;
2087 if (reset_as == 0)
2088 reset_as = 1;
2089
2090 reset_len = fadt->reset_reg.access_size;
2091 if (reset_len == 0)
2092 reset_len = reset_as;
2093
2094 acpi_gasio(sc, ACPI_IOWRITE,
2095 fadt->reset_reg.address_space_id,
2096 fadt->reset_reg.address, reset_as, reset_len, &value);
2097
2098 delay(100000);
2099}
2100
2101void
2102acpi_gpe_task(void *arg0, int gpe)
2103{
2104 struct acpi_softc *sc = acpi_softc;
2105 struct gpe_block *pgpe = &sc->gpe_table[gpe];
2106
2107 dnprintf(10, "handle gpe: %x\n", gpe);
2108 if (pgpe->handler && pgpe->active) {
2109 pgpe->active = 0;
2110 pgpe->handler(sc, gpe, pgpe->arg);
2111 }
2112}
2113
2114void
2115acpi_pbtn_task(void *arg0, int dummy)
2116{
2117 struct acpi_softc *sc = arg0;
2118 extern int pwr_action;
2119 uint16_t en;
2120 int s;
2121
2122 dnprintf(1,"power button pressed\n");
2123
2124 /* Reset the latch and re-enable the GPE */
2125 s = splbio();
2126 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2127 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0,
2128 en | ACPI_PM1_PWRBTN_EN);
2129 splx(s);
2130
2131#ifdef SUSPEND
2132 /* Ignore button events if we're resuming. */
2133 if (resuming())
2134 return;
2135#endif /* SUSPEND */
2136
2137 switch (pwr_action) {
2138 case 0:
2139 break;
2140 case 1:
2141 powerbutton_event();
2142 break;
2143#ifndef SMALL_KERNEL
2144 case 2:
2145 acpi_addtask(sc, acpi_sleep_task, sc, SLEEP_SUSPEND);
2146 break;
2147#endif
2148 }
2149}
2150
2151void
2152acpi_sbtn_task(void *arg0, int dummy)
2153{
2154 struct acpi_softc *sc = arg0;
2155 uint16_t en;
2156 int s;
2157
2158 dnprintf(1,"sleep button pressed\n");
2159 aml_notify_dev(ACPI_DEV_SBD, 0x80);
2160
2161 /* Reset the latch and re-enable the GPE */
2162 s = splbio();
2163 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2164 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0,
2165 en | ACPI_PM1_SLPBTN_EN);
2166 splx(s);
2167}
2168
2169int
2170acpi_interrupt(void *arg)
2171{
2172 struct acpi_softc *sc = (struct acpi_softc *)arg;
2173 uint32_t processed = 0, idx, jdx;
2174 uint16_t sts, en;
2175 int gpe;
2176
2177 dnprintf(40, "ACPI Interrupt\n");
2178 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
2179 sts = acpi_read_pmreg(sc, ACPIREG_GPE_STS, idx>>3);
2180 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, idx>>3);
2181 if (en & sts) {
2182 dnprintf(10, "GPE block: %.2x %.2x %.2x\n", idx, sts,
2183 en);
2184 /* Mask the GPE until it is serviced */
2185 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx>>3, en & ~sts);
2186 for (jdx = 0; jdx < 8; jdx++) {
2187 if (!(en & sts & (1L << jdx)))
2188 continue;
2189
2190 if (cpu_suspended) {
2191 cpu_suspended = 0;
2192 sc->sc_wakegpe = idx + jdx;
2193 }
2194
2195 /* Signal this GPE */
2196 gpe = idx + jdx;
2197 sc->gpe_table[gpe].active = 1;
2198 dnprintf(10, "queue gpe: %x\n", gpe);
2199 acpi_addtask(sc, acpi_gpe_task, NULL, gpe);
2200
2201 /*
2202 * Edge interrupts need their STS bits cleared
2203 * now. Level interrupts will have their STS
2204 * bits cleared just before they are
2205 * re-enabled.
2206 */
2207 if (sc->gpe_table[gpe].flags & GPE_EDGE)
2208 acpi_write_pmreg(sc,
2209 ACPIREG_GPE_STS, idx>>3, 1L << jdx);
2210
2211 processed = 1;
2212 }
2213 }
2214 }
2215
2216 sts = acpi_read_pmreg(sc, ACPIREG_PM1_STS, 0);
2217 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2218 if (sts & en) {
2219 dnprintf(10,"GEN interrupt: %.4x\n", sts & en);
2220 sts &= en;
2221 if (sts & ACPI_PM1_PWRBTN_STS) {
2222 /* Mask and acknowledge */
2223 en &= ~ACPI_PM1_PWRBTN_EN;
2224 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2225 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
2226 ACPI_PM1_PWRBTN_STS);
2227 sts &= ~ACPI_PM1_PWRBTN_STS;
2228
2229 if (cpu_suspended) {
2230 cpu_suspended = 0;
2231 sc->sc_wakegpe = -1;
2232 }
2233
2234 acpi_addtask(sc, acpi_pbtn_task, sc, 0);
2235 }
2236 if (sts & ACPI_PM1_SLPBTN_STS) {
2237 /* Mask and acknowledge */
2238 en &= ~ACPI_PM1_SLPBTN_EN;
2239 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2240 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
2241 ACPI_PM1_SLPBTN_STS);
2242 sts &= ~ACPI_PM1_SLPBTN_STS;
2243
2244 if (cpu_suspended) {
2245 cpu_suspended = 0;
2246 sc->sc_wakegpe = -2;
2247 }
2248
2249 acpi_addtask(sc, acpi_sbtn_task, sc, 0);
2250 }
2251 if (sts) {
2252 printf("%s: PM1 stuck (en 0x%x st 0x%x), clearing\n",
2253 sc->sc_dev.dv_xname, en, sts);
2254 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts);
2255 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, sts);
2256 }
2257 processed = 1;
2258 }
2259
2260 if (processed) {
2261 acpi_wakeup(sc);
2262 }
2263
2264 return (processed);
2265}
2266
2267int
2268acpi_add_device(struct aml_node *node, void *arg)
2269{
2270 static int nacpicpus = 0;
2271 struct device *self = arg;
2272 struct acpi_softc *sc = arg;
2273 struct acpi_attach_args aaa;
2274 struct aml_value res;
2275 CPU_INFO_ITERATOR cii;
2276 struct cpu_info *ci;
2277 int proc_id = -1;
2278 int64_t sta;
2279
2280 memset(&aaa, 0, sizeof(aaa));
2281 aaa.aaa_node = node;
2282 aaa.aaa_iot = sc->sc_iot;
2283 aaa.aaa_memt = sc->sc_memt;
2284 if (node == NULL || node->value == NULL)
2285 return 0;
2286
2287 switch (node->value->type) {
2288 case AML_OBJTYPE_PROCESSOR:
2289 if (sc->sc_skip_processor != 0)
2290 return 0;
2291 if (nacpicpus >= ncpus)
2292 return 0;
2293 if (aml_evalnode(sc, aaa.aaa_node, 0, NULL, &res) == 0) {
2294 if (res.type == AML_OBJTYPE_PROCESSOR)
2295 proc_id = res.v_processor.proc_id;
2296 aml_freevalue(&res);
2297 }
2298 CPU_INFO_FOREACH(cii, ci) {
2299 if (ci->ci_acpi_proc_id == proc_id)
2300 break;
2301 }
2302 if (ci == NULL)
2303 return 0;
2304 nacpicpus++;
2305
2306 aaa.aaa_name = "acpicpu";
2307 break;
2308 case AML_OBJTYPE_THERMZONE:
2309 sta = acpi_getsta(sc, node);
2310 if ((sta & STA_PRESENT) == 0)
2311 return 0;
2312
2313 aaa.aaa_name = "acpitz";
2314 break;
2315 case AML_OBJTYPE_POWERRSRC:
2316 aaa.aaa_name = "acpipwrres";
2317 break;
2318 default:
2319 return 0;
2320 }
2321 config_found(self, &aaa, acpi_print);
2322 return 0;
2323}
2324
2325void
2326acpi_enable_onegpe(struct acpi_softc *sc, int gpe)
2327{
2328 uint8_t mask, en;
2329
2330 /* Read enabled register */
2331 mask = (1L << (gpe & 7));
2332 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3);
2333 dnprintf(50, "enabling GPE %.2x (current: %sabled) %.2x\n",
2334 gpe, (en & mask) ? "en" : "dis", en);
2335 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask);
2336}
2337
2338/* Clear all GPEs */
2339void
2340acpi_disable_allgpes(struct acpi_softc *sc)
2341{
2342 int idx;
2343
2344 for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
2345 acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx >> 3, 0);
2346 acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx >> 3, -1);
2347 }
2348}
2349
2350/* Enable runtime GPEs */
2351void
2352acpi_enable_rungpes(struct acpi_softc *sc)
2353{
2354 int idx;
2355
2356 for (idx = 0; idx < sc->sc_lastgpe; idx++)
2357 if (sc->gpe_table[idx].handler)
2358 acpi_enable_onegpe(sc, idx);
2359}
2360
2361/* Enable wakeup GPEs */
2362void
2363acpi_enable_wakegpes(struct acpi_softc *sc, int state)
2364{
2365 struct acpi_wakeq *wentry;
2366
2367 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) {
2368 dnprintf(10, "%.4s(S%d) gpe %.2x\n", wentry->q_node->name,
2369 wentry->q_state,
2370 wentry->q_gpe);
2371 if (wentry->q_enabled && state <= wentry->q_state)
2372 acpi_enable_onegpe(sc, wentry->q_gpe);
2373 }
2374}
2375
2376int
2377acpi_set_gpehandler(struct acpi_softc *sc, int gpe, int (*handler)
2378 (struct acpi_softc *, int, void *), void *arg, int flags)
2379{
2380 struct gpe_block *ptbl;
2381
2382 ptbl = acpi_find_gpe(sc, gpe);
2383 if (ptbl == NULL || handler == NULL)
2384 return -EINVAL;
2385 if ((flags & GPE_LEVEL) && (flags & GPE_EDGE))
2386 return -EINVAL;
2387 if (!(flags & (GPE_LEVEL | GPE_EDGE)))
2388 return -EINVAL;
2389 if (ptbl->handler != NULL)
2390 printf("%s: GPE 0x%.2x already enabled\n", DEVNAME(sc), gpe);
2391
2392 dnprintf(50, "Adding GPE handler 0x%.2x (%s)\n", gpe,
2393 (flags & GPE_EDGE ? "edge" : "level"));
2394 ptbl->handler = handler;
2395 ptbl->arg = arg;
2396 ptbl->flags = flags;
2397
2398 return (0);
2399}
2400
2401int
2402acpi_gpe(struct acpi_softc *sc, int gpe, void *arg)
2403{
2404 struct aml_node *node = arg;
2405 uint8_t mask, en;
2406
2407 dnprintf(10, "handling GPE %.2x\n", gpe);
2408 aml_evalnode(sc, node, 0, NULL, NULL);
2409
2410 mask = (1L << (gpe & 7));
2411 if (sc->gpe_table[gpe].flags & GPE_LEVEL)
2412 acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask);
2413 en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3);
2414 acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask);
2415 return (0);
2416}
2417
2418/* Discover Devices that can wakeup the system
2419 * _PRW returns a package
2420 * pkg[0] = integer (FADT gpe bit) or package (gpe block,gpe bit)
2421 * pkg[1] = lowest sleep state
2422 * pkg[2+] = power resource devices (optional)
2423 *
2424 * To enable wakeup devices:
2425 * Evaluate _ON method in each power resource device
2426 * Evaluate _PSW method
2427 */
2428int
2429acpi_foundprw(struct aml_node *node, void *arg)
2430{
2431 struct acpi_softc *sc = arg;
2432 struct acpi_wakeq *wq;
2433 int64_t sta;
2434
2435 sta = acpi_getsta(sc, node->parent);
2436 if ((sta & STA_PRESENT) == 0)
2437 return 0;
2438
2439 wq = malloc(sizeof(struct acpi_wakeq), M_DEVBUF, M_NOWAIT | M_ZERO);
2440 if (wq == NULL)
2441 return 0;
2442
2443 wq->q_wakepkg = malloc(sizeof(struct aml_value), M_DEVBUF,
2444 M_NOWAIT | M_ZERO);
2445 if (wq->q_wakepkg == NULL) {
2446 free(wq, M_DEVBUF, sizeof(*wq));
2447 return 0;
2448 }
2449 dnprintf(10, "Found _PRW (%s)\n", node->parent->name);
2450 aml_evalnode(sc, node, 0, NULL, wq->q_wakepkg);
2451 wq->q_node = node->parent;
2452 wq->q_gpe = -1;
2453
2454 /* Get GPE of wakeup device, and lowest sleep level */
2455 if (wq->q_wakepkg->type == AML_OBJTYPE_PACKAGE &&
2456 wq->q_wakepkg->length >= 2) {
2457 if (wq->q_wakepkg->v_package[0]->type == AML_OBJTYPE_INTEGER)
2458 wq->q_gpe = wq->q_wakepkg->v_package[0]->v_integer;
2459 if (wq->q_wakepkg->v_package[1]->type == AML_OBJTYPE_INTEGER)
2460 wq->q_state = wq->q_wakepkg->v_package[1]->v_integer;
2461 wq->q_enabled = 0;
2462 }
2463 SIMPLEQ_INSERT_TAIL(&sc->sc_wakedevs, wq, q_next);
2464 return 0;
2465}
2466
2467int
2468acpi_toggle_wakedev(struct acpi_softc *sc, struct aml_node *node, int enable)
2469{
2470 struct acpi_wakeq *wentry;
2471 int ret = -1;
2472
2473 SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) {
2474 if (wentry->q_node == node) {
2475 wentry->q_enabled = enable ? 1 : 0;
2476 dnprintf(10, "%.4s(S%d) gpe %.2x %sabled\n",
2477 wentry->q_node->name, wentry->q_state,
2478 wentry->q_gpe, enable ? "en" : "dis");
2479 ret = 0;
2480 break;
2481 }
2482 }
2483
2484 return ret;
2485}
2486
2487struct gpe_block *
2488acpi_find_gpe(struct acpi_softc *sc, int gpe)
2489{
2490 if (gpe >= sc->sc_lastgpe)
2491 return NULL;
2492 return &sc->gpe_table[gpe];
2493}
2494
2495void
2496acpi_init_gpes(struct acpi_softc *sc)
2497{
2498 struct aml_node *gpe;
2499 char name[12];
2500 int idx;
2501
2502 sc->sc_lastgpe = sc->sc_fadt->gpe0_blk_len << 2;
2503 dnprintf(50, "Last GPE: %.2x\n", sc->sc_lastgpe);
2504
2505 /* Allocate GPE table */
2506 sc->gpe_table = mallocarray(sc->sc_lastgpe, sizeof(struct gpe_block),
2507 M_DEVBUF, M_WAITOK | M_ZERO);
2508
2509 /* Clear GPE status */
2510 acpi_disable_allgpes(sc);
2511 for (idx = 0; idx < sc->sc_lastgpe; idx++) {
2512 /* Search Level-sensitive GPES */
2513 snprintf(name, sizeof(name), "\\_GPE._L%.2X", idx);
2514 gpe = aml_searchname(sc->sc_root, name);
2515 if (gpe != NULL)
2516 acpi_set_gpehandler(sc, idx, acpi_gpe, gpe, GPE_LEVEL);
2517 if (gpe == NULL) {
2518 /* Search Edge-sensitive GPES */
2519 snprintf(name, sizeof(name), "\\_GPE._E%.2X", idx);
2520 gpe = aml_searchname(sc->sc_root, name);
2521 if (gpe != NULL)
2522 acpi_set_gpehandler(sc, idx, acpi_gpe, gpe,
2523 GPE_EDGE);
2524 }
2525 }
2526 aml_find_node(sc->sc_root, "_PRW", acpi_foundprw, sc);
2527}
2528
2529void
2530acpi_init_pm(struct acpi_softc *sc)
2531{
2532 sc->sc_tts = aml_searchname(sc->sc_root, "_TTS");
2533 sc->sc_pts = aml_searchname(sc->sc_root, "_PTS");
2534 sc->sc_wak = aml_searchname(sc->sc_root, "_WAK");
2535 sc->sc_bfs = aml_searchname(sc->sc_root, "_BFS");
2536 sc->sc_gts = aml_searchname(sc->sc_root, "_GTS");
2537 sc->sc_sst = aml_searchname(sc->sc_root, "_SI_._SST");
2538}
2539
2540#ifndef SMALL_KERNEL
2541
2542void
2543acpi_init_states(struct acpi_softc *sc)
2544{
2545 struct aml_value res;
2546 char name[8];
2547 int i;
2548
2549 printf("\n%s: sleep states", DEVNAME(sc));
2550 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
2551 snprintf(name, sizeof(name), "_S%d_", i);
2552 sc->sc_sleeptype[i].slp_typa = -1;
2553 sc->sc_sleeptype[i].slp_typb = -1;
2554 if (aml_evalname(sc, sc->sc_root, name, 0, NULL, &res) != 0)
2555 continue;
2556 if (res.type != AML_OBJTYPE_PACKAGE) {
2557 aml_freevalue(&res);
2558 continue;
2559 }
2560 sc->sc_sleeptype[i].slp_typa = aml_val2int(res.v_package[0]);
2561 sc->sc_sleeptype[i].slp_typb = aml_val2int(res.v_package[1]);
2562 aml_freevalue(&res);
2563
2564 printf(" S%d", i);
2565 if (i == 0 && (sc->sc_fadt->flags & FADT_POWER_S0_IDLE_CAPABLE))
2566 printf("ix");
2567 }
2568}
2569
2570void
2571acpi_sleep_pm(struct acpi_softc *sc, int state)
2572{
2573 uint16_t rega, regb, regra, regrb;
2574 int retry = 0;
2575
2576 intr_disable();
2577
2578 /* Clear WAK_STS bit */
2579 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS);
2580
2581 /* Disable BM arbitration at deep sleep and beyond */
2582 if (state >= ACPI_STATE_S3 &&
2583 sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len)
2584 acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, ACPI_PM2_ARB_DIS);
2585
2586 /* Write SLP_TYPx values */
2587 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0);
2588 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0);
2589 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2590 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2591 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typa);
2592 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[state].slp_typb);
2593 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
2594 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
2595
2596 /* Loop on WAK_STS, setting the SLP_EN bits once in a while */
2597 rega |= ACPI_PM1_SLP_EN;
2598 regb |= ACPI_PM1_SLP_EN;
2599 while (1) {
2600 if (retry == 0) {
2601 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
2602 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
2603 }
2604 retry = (retry + 1) % 100000;
2605
2606 regra = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0);
2607 regrb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0);
2608 if ((regra & ACPI_PM1_WAK_STS) ||
2609 (regrb & ACPI_PM1_WAK_STS))
2610 break;
2611 }
2612}
2613
2614uint32_t acpi_force_bm;
2615
2616void
2617acpi_resume_pm(struct acpi_softc *sc, int fromstate)
2618{
2619 uint16_t rega, regb, en;
2620
2621 /* Write SLP_TYPx values */
2622 rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0);
2623 regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0);
2624 rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2625 regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN);
2626 rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typa);
2627 regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typb);
2628 acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
2629 acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
2630
2631 /* Force SCI_EN on resume to fix horribly broken machines */
2632 acpi_write_pmreg(sc, ACPIREG_PM1_CNT, 0,
2633 ACPI_PM1_SCI_EN | acpi_force_bm);
2634
2635 /* Clear fixed event status */
2636 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
2637
2638 /* acpica-reference.pdf page 148 says do not call _BFS */
2639 /* 1st resume AML step: _BFS(fromstate) */
2640 aml_node_setval(sc, sc->sc_bfs, fromstate);
2641
2642 /* Enable runtime GPEs */
2643 acpi_disable_allgpes(sc);
2644 acpi_enable_rungpes(sc);
2645
2646 /* 2nd resume AML step: _WAK(fromstate) */
2647 aml_node_setval(sc, sc->sc_wak, fromstate);
2648
2649 /* Clear WAK_STS bit */
2650 acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS);
2651
2652 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2653 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON))
2654 en |= ACPI_PM1_PWRBTN_EN;
2655 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON))
2656 en |= ACPI_PM1_SLPBTN_EN;
2657 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2658
2659 /*
2660 * If PM2 exists, re-enable BM arbitration (reportedly some
2661 * BIOS forget to)
2662 */
2663 if (sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) {
2664 rega = acpi_read_pmreg(sc, ACPIREG_PM2_CNT, 0);
2665 rega &= ~ACPI_PM2_ARB_DIS;
2666 acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, rega);
2667 }
2668}
2669
2670/* Set the indicator light to some state */
2671void
2672acpi_indicator(struct acpi_softc *sc, int led_state)
2673{
2674 static int save_led_state = -1;
2675
2676 if (save_led_state != led_state) {
2677 aml_node_setval(sc, sc->sc_sst, led_state);
2678 save_led_state = led_state;
2679 }
2680}
2681
2682/* XXX
2683 * We are going to do AML execution but are not in the acpi thread.
2684 * We do not know if the acpi thread is sleeping on acpiec in some
2685 * intermediate context. Wish us luck.
2686 */
2687void
2688acpi_powerdown(void)
2689{
2690 int state = ACPI_STATE_S5, s;
2691 struct acpi_softc *sc = acpi_softc;
2692
2693 if (acpi_enabled == 0)
2694 return;
2695
2696 s = splhigh();
2697 intr_disable();
2698 cold = 1;
2699
2700 /* 1st powerdown AML step: _PTS(tostate) */
2701 aml_node_setval(sc, sc->sc_pts, state);
2702
2703 acpi_disable_allgpes(sc);
2704 acpi_enable_wakegpes(sc, state);
2705
2706 /* 2nd powerdown AML step: _GTS(tostate) */
2707 aml_node_setval(sc, sc->sc_gts, state);
2708
2709 acpi_sleep_pm(sc, state);
2710 panic("acpi S5 transition did not happen");
2711 while (1)
2712 ;
2713}
2714
2715#endif /* SMALL_KERNEL */
2716
2717int
2718acpi_map_address(struct acpi_softc *sc, struct acpi_gas *gas, bus_addr_t base,
2719 bus_size_t size, bus_space_handle_t *pioh, bus_space_tag_t *piot)
2720{
2721 int iospace = GAS_SYSTEM_IOSPACE;
2722
2723 /* No GAS structure, default to I/O space */
2724 if (gas != NULL) {
2725 base += gas->address;
2726 iospace = gas->address_space_id;
2727 }
2728 switch (iospace) {
2729 case GAS_SYSTEM_MEMORY:
2730 *piot = sc->sc_memt;
2731 break;
2732 case GAS_SYSTEM_IOSPACE:
2733 *piot = sc->sc_iot;
2734 break;
2735 default:
2736 return -1;
2737 }
2738 if (bus_space_map(*piot, base, size, 0, pioh))
2739 return -1;
2740
2741 return 0;
2742}
2743
2744void
2745acpi_wakeup(void *arg)
2746{
2747 struct acpi_softc *sc = (struct acpi_softc *)arg;
2748
2749 sc->sc_threadwaiting = 0;
2750 wakeup(sc);
2751}
2752
2753
2754void
2755acpi_thread(void *arg)
2756{
2757 struct acpi_thread *thread = arg;
2758 struct acpi_softc *sc = thread->sc;
2759 extern int aml_busy;
2760 int s;
2761
2762 /* AML/SMI cannot be trusted -- only run on the BSP */
2763 sched_peg_curproc(&cpu_info_primary);
2764
2765 rw_enter_write(&sc->sc_lck);
2766
2767 /*
2768 * If we have an interrupt handler, we can get notification
2769 * when certain status bits changes in the ACPI registers,
2770 * so let us enable some events we can forward to userland
2771 */
2772 if (sc->sc_interrupt) {
2773 int16_t en;
2774
2775 dnprintf(1,"slpbtn:%c pwrbtn:%c\n",
2776 sc->sc_fadt->flags & FADT_SLP_BUTTON ? 'n' : 'y',
2777 sc->sc_fadt->flags & FADT_PWR_BUTTON ? 'n' : 'y');
2778 dnprintf(10, "Enabling acpi interrupts...\n");
2779 sc->sc_threadwaiting = 1;
2780
2781 /* Enable Sleep/Power buttons if they exist */
2782 s = splbio();
2783 en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
2784 if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON))
2785 en |= ACPI_PM1_PWRBTN_EN;
2786 if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON))
2787 en |= ACPI_PM1_SLPBTN_EN;
2788 acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
2789
2790 /* Enable handled GPEs here */
2791 acpi_enable_rungpes(sc);
2792 splx(s);
2793 }
2794
2795 while (thread->running) {
2796 s = splbio();
2797 while (sc->sc_threadwaiting) {
2798 dnprintf(10, "acpi thread going to sleep...\n");
2799 rw_exit_write(&sc->sc_lck);
2800 tsleep_nsec(sc, PWAIT, "acpi0", INFSLP);
2801 rw_enter_write(&sc->sc_lck);
2802 }
2803 sc->sc_threadwaiting = 1;
2804 splx(s);
2805 if (aml_busy) {
2806 panic("thread woke up to find aml was busy");
2807 continue;
2808 }
2809
2810 /* Run ACPI taskqueue */
2811 while(acpi_dotask(acpi_softc))
2812 ;
2813 }
2814 free(thread, M_DEVBUF, sizeof(*thread));
2815
2816 kthread_exit(0);
2817}
2818
2819void
2820acpi_create_thread(void *arg)
2821{
2822 struct acpi_softc *sc = arg;
2823
2824 if (kthread_create(acpi_thread, sc->sc_thread, NULL, DEVNAME(sc))
2825 != 0)
2826 printf("%s: unable to create isr thread, GPEs disabled\n",
2827 DEVNAME(sc));
2828}
2829
2830#ifdef __arm64__
2831int
2832acpi_foundsectwo(struct aml_node *node, void *arg)
2833{
2834 struct acpi_softc *sc = (struct acpi_softc *)arg;
2835 struct device *self = (struct device *)arg;
2836 struct acpi_attach_args aaa;
2837
2838 memset(&aaa, 0, sizeof(aaa));
2839 aaa.aaa_iot = sc->sc_iot;
2840 aaa.aaa_memt = sc->sc_memt;
2841 aaa.aaa_node = node->parent;
2842 aaa.aaa_name = "acpisectwo";
2843
2844 config_found(self, &aaa, acpi_print);
2845
2846 return 0;
2847}
2848#endif
2849
2850int
2851acpi_foundec(struct aml_node *node, void *arg)
2852{
2853 struct acpi_softc *sc = (struct acpi_softc *)arg;
2854 struct device *self = (struct device *)arg;
2855 const char *dev;
2856 struct aml_value res;
2857 struct acpi_attach_args aaa;
2858
2859 if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
2860 return 0;
2861
2862 switch (res.type) {
2863 case AML_OBJTYPE_STRING:
2864 dev = res.v_string;
2865 break;
2866 case AML_OBJTYPE_INTEGER:
2867 dev = aml_eisaid(aml_val2int(&res));
2868 break;
2869 default:
2870 dev = "unknown";
2871 break;
2872 }
2873
2874 if (strcmp(dev, ACPI_DEV_ECD))
2875 return 0;
2876
2877 /* Check if we're already attached */
2878 if (sc->sc_ec && sc->sc_ec->sc_devnode == node->parent)
2879 return 0;
2880
2881 memset(&aaa, 0, sizeof(aaa));
2882 aaa.aaa_iot = sc->sc_iot;
2883 aaa.aaa_memt = sc->sc_memt;
2884 aaa.aaa_node = node->parent;
2885 aaa.aaa_dev = dev;
2886 aaa.aaa_name = "acpiec";
2887 config_found(self, &aaa, acpi_print);
2888 aml_freevalue(&res);
2889
2890 return 0;
2891}
2892
2893int
2894acpi_foundsony(struct aml_node *node, void *arg)
2895{
2896 struct acpi_softc *sc = (struct acpi_softc *)arg;
2897 struct device *self = (struct device *)arg;
2898 struct acpi_attach_args aaa;
2899
2900 memset(&aaa, 0, sizeof(aaa));
2901 aaa.aaa_iot = sc->sc_iot;
2902 aaa.aaa_memt = sc->sc_memt;
2903 aaa.aaa_node = node->parent;
2904 aaa.aaa_name = "acpisony";
2905
2906 config_found(self, &aaa, acpi_print);
2907
2908 return 0;
2909}
2910
2911/* Support for _DSD Device Properties. */
2912
2913int
2914acpi_getprop(struct aml_node *node, const char *prop, void *buf, int buflen)
2915{
2916 struct aml_value dsd;
2917 int i;
2918
2919 /* daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
2920 static uint8_t prop_guid[] = {
2921 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
2922 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01,
2923 };
2924
2925 if (aml_evalname(acpi_softc, node, "_DSD", 0, NULL, &dsd))
2926 return -1;
2927
2928 if (dsd.type != AML_OBJTYPE_PACKAGE || dsd.length != 2 ||
2929 dsd.v_package[0]->type != AML_OBJTYPE_BUFFER ||
2930 dsd.v_package[1]->type != AML_OBJTYPE_PACKAGE)
2931 return -1;
2932
2933 /* Check UUID. */
2934 if (dsd.v_package[0]->length != sizeof(prop_guid) ||
2935 memcmp(dsd.v_package[0]->v_buffer, prop_guid,
2936 sizeof(prop_guid)) != 0)
2937 return -1;
2938
2939 /* Check properties. */
2940 for (i = 0; i < dsd.v_package[1]->length; i++) {
2941 struct aml_value *res = dsd.v_package[1]->v_package[i];
2942 struct aml_value *val;
2943 int len;
2944
2945 if (res->type != AML_OBJTYPE_PACKAGE || res->length != 2 ||
2946 res->v_package[0]->type != AML_OBJTYPE_STRING ||
2947 strcmp(res->v_package[0]->v_string, prop) != 0)
2948 continue;
2949
2950 val = res->v_package[1];
2951 if (val->type == AML_OBJTYPE_OBJREF)
2952 val = val->v_objref.ref;
2953
2954 len = val->length;
2955 switch (val->type) {
2956 case AML_OBJTYPE_BUFFER:
2957 memcpy(buf, val->v_buffer, min(len, buflen));
2958 return len;
2959 case AML_OBJTYPE_STRING:
2960 memcpy(buf, val->v_string, min(len, buflen));
2961 return len;
2962 }
2963 }
2964
2965 return -1;
2966}
2967
2968uint64_t
2969acpi_getpropint(struct aml_node *node, const char *prop, uint64_t defval)
2970{
2971 struct aml_value dsd;
2972 int i;
2973
2974 /* daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
2975 static uint8_t prop_guid[] = {
2976 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
2977 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01,
2978 };
2979
2980 if (aml_evalname(acpi_softc, node, "_DSD", 0, NULL, &dsd))
2981 return defval;
2982
2983 if (dsd.type != AML_OBJTYPE_PACKAGE || dsd.length != 2 ||
2984 dsd.v_package[0]->type != AML_OBJTYPE_BUFFER ||
2985 dsd.v_package[1]->type != AML_OBJTYPE_PACKAGE)
2986 return defval;
2987
2988 /* Check UUID. */
2989 if (dsd.v_package[0]->length != sizeof(prop_guid) ||
2990 memcmp(dsd.v_package[0]->v_buffer, prop_guid,
2991 sizeof(prop_guid)) != 0)
2992 return defval;
2993
2994 /* Check properties. */
2995 for (i = 0; i < dsd.v_package[1]->length; i++) {
2996 struct aml_value *res = dsd.v_package[1]->v_package[i];
2997 struct aml_value *val;
2998
2999 if (res->type != AML_OBJTYPE_PACKAGE || res->length != 2 ||
3000 res->v_package[0]->type != AML_OBJTYPE_STRING ||
3001 strcmp(res->v_package[0]->v_string, prop) != 0)
3002 continue;
3003
3004 val = res->v_package[1];
3005 if (val->type == AML_OBJTYPE_OBJREF)
3006 val = val->v_objref.ref;
3007
3008 if (val->type == AML_OBJTYPE_INTEGER)
3009 return val->v_integer;
3010 }
3011
3012 return defval;
3013}
3014
3015int
3016acpi_parsehid(struct aml_node *node, void *arg, char *outcdev, char *outdev,
3017 size_t devlen)
3018{
3019 struct acpi_softc *sc = (struct acpi_softc *)arg;
3020 struct aml_value res, *cid;
3021 const char *dev;
3022
3023 /* NB aml_eisaid returns a static buffer, this must come first */
3024 if (aml_evalname(acpi_softc, node->parent, "_CID", 0, NULL, &res) == 0) {
3025 if (res.type == AML_OBJTYPE_PACKAGE && res.length >= 1) {
3026 cid = res.v_package[0];
3027 } else {
3028 cid = &res;
3029 }
3030 switch (cid->type) {
3031 case AML_OBJTYPE_STRING:
3032 dev = cid->v_string;
3033 break;
3034 case AML_OBJTYPE_INTEGER:
3035 dev = aml_eisaid(aml_val2int(cid));
3036 break;
3037 default:
3038 dev = "unknown";
3039 break;
3040 }
3041 strlcpy(outcdev, dev, devlen);
3042 aml_freevalue(&res);
3043
3044 dnprintf(10, "compatible with device: %s\n", outcdev);
3045 } else {
3046 outcdev[0] = '\0';
3047 }
3048
3049 dnprintf(10, "found hid device: %s ", node->parent->name);
3050 if (aml_evalnode(sc, node, 0, NULL, &res) != 0)
3051 return (1);
3052
3053 switch (res.type) {
3054 case AML_OBJTYPE_STRING:
3055 dev = res.v_string;
3056 break;
3057 case AML_OBJTYPE_INTEGER:
3058 dev = aml_eisaid(aml_val2int(&res));
3059 break;
3060 default:
3061 dev = "unknown";
3062 break;
3063 }
3064 dnprintf(10, " device: %s\n", dev);
3065
3066 strlcpy(outdev, dev, devlen);
3067
3068 aml_freevalue(&res);
3069
3070 return (0);
3071}
3072
3073/* Devices for which we don't want to attach a driver */
3074const char *acpi_skip_hids[] = {
3075 "INT0800", /* Intel 82802Firmware Hub Device */
3076 "PNP0000", /* 8259-compatible Programmable Interrupt Controller */
3077 "PNP0001", /* EISA Interrupt Controller */
3078 "PNP0100", /* PC-class System Timer */
3079 "PNP0103", /* HPET System Timer */
3080 "PNP0200", /* PC-class DMA Controller */
3081 "PNP0201", /* EISA DMA Controller */
3082 "PNP0800", /* Microsoft Sound System Compatible Device */
3083 "PNP0C01", /* System Board */
3084 "PNP0C02", /* PNP Motherboard Resources */
3085 "PNP0C04", /* x87-compatible Floating Point Processing Unit */
3086 "PNP0C09", /* Embedded Controller Device */
3087 "PNP0C0F", /* PCI Interrupt Link Device */
3088 NULL
3089};
3090
3091/* ISA devices for which we attach a driver later */
3092const char *acpi_isa_hids[] = {
3093 "PNP0400", /* Standard LPT Parallel Port */
3094 "PNP0401", /* ECP Parallel Port */
3095 "PNP0700", /* PC-class Floppy Disk Controller */
3096 NULL
3097};
3098
3099/* Overly abundant devices to avoid printing details for */
3100const char *acpi_quiet_hids[] = {
3101 "ACPI0007",
3102 NULL
3103};
3104
3105void
3106acpi_attach_deps(struct acpi_softc *sc, struct aml_node *node)
3107{
3108 struct aml_value res, *val;
3109 struct aml_node *dep;
3110 int i;
3111
3112 if (aml_evalname(sc, node, "_DEP", 0, NULL, &res))
3113 return;
3114
3115 if (res.type != AML_OBJTYPE_PACKAGE)
3116 return;
3117
3118 for (i = 0; i < res.length; i++) {
3119 val = res.v_package[i];
3120 if (val->type == AML_OBJTYPE_NAMEREF) {
3121 node = aml_searchrel(node,
3122 aml_getname(val->v_nameref));
3123 if (node)
3124 val = node->value;
3125 }
3126 if (val->type == AML_OBJTYPE_OBJREF)
3127 val = val->v_objref.ref;
3128 if (val->type != AML_OBJTYPE_DEVICE)
3129 continue;
3130 dep = val->node;
3131 if (dep == NULL || dep->attached)
3132 continue;
3133 dep = aml_searchname(dep, "_HID");
3134 if (dep)
3135 acpi_foundhid(dep, sc);
3136 }
3137
3138 aml_freevalue(&res);
3139}
3140
3141int
3142acpi_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
3143{
3144 struct acpi_attach_args *aaa = arg;
3145 int type = AML_CRSTYPE(crs);
3146 uint8_t flags;
3147
3148 switch (type) {
3149 case SR_IOPORT:
3150 case SR_FIXEDPORT:
3151 case LR_MEM24:
3152 case LR_MEM32:
3153 case LR_MEM32FIXED:
3154 case LR_WORD:
3155 case LR_DWORD:
3156 case LR_QWORD:
3157 if (aaa->aaa_naddr >= nitems(aaa->aaa_addr))
3158 return 0;
3159 break;
3160 case SR_IRQ:
3161 case LR_EXTIRQ:
3162 if (aaa->aaa_nirq >= nitems(aaa->aaa_irq))
3163 return 0;
3164 }
3165
3166 switch (type) {
3167 case SR_IOPORT:
3168 case SR_FIXEDPORT:
3169 aaa->aaa_bst[aaa->aaa_naddr] = aaa->aaa_iot;
3170 break;
3171 case LR_MEM24:
3172 case LR_MEM32:
3173 case LR_MEM32FIXED:
3174 aaa->aaa_bst[aaa->aaa_naddr] = aaa->aaa_memt;
3175 break;
3176 case LR_WORD:
3177 case LR_DWORD:
3178 case LR_QWORD:
3179 switch (crs->lr_word.type) {
3180 case LR_TYPE_MEMORY:
3181 aaa->aaa_bst[aaa->aaa_naddr] = aaa->aaa_memt;
3182 break;
3183 case LR_TYPE_IO:
3184 aaa->aaa_bst[aaa->aaa_naddr] = aaa->aaa_iot;
3185 break;
3186 default:
3187 /* Bus number range or something else; skip. */
3188 return 0;
3189 }
3190 }
3191
3192 switch (type) {
3193 case SR_IOPORT:
3194 aaa->aaa_addr[aaa->aaa_naddr] = crs->sr_ioport._min;
3195 aaa->aaa_size[aaa->aaa_naddr] = crs->sr_ioport._len;
3196 aaa->aaa_naddr++;
3197 break;
3198 case SR_FIXEDPORT:
3199 aaa->aaa_addr[aaa->aaa_naddr] = crs->sr_fioport._bas;
3200 aaa->aaa_size[aaa->aaa_naddr] = crs->sr_fioport._len;
3201 aaa->aaa_naddr++;
3202 break;
3203 case LR_MEM24:
3204 aaa->aaa_addr[aaa->aaa_naddr] = crs->lr_m24._min;
3205 aaa->aaa_size[aaa->aaa_naddr] = crs->lr_m24._len;
3206 aaa->aaa_naddr++;
3207 break;
3208 case LR_MEM32:
3209 aaa->aaa_addr[aaa->aaa_naddr] = crs->lr_m32._min;
3210 aaa->aaa_size[aaa->aaa_naddr] = crs->lr_m32._len;
3211 aaa->aaa_naddr++;
3212 break;
3213 case LR_MEM32FIXED:
3214 aaa->aaa_addr[aaa->aaa_naddr] = crs->lr_m32fixed._bas;
3215 aaa->aaa_size[aaa->aaa_naddr] = crs->lr_m32fixed._len;
3216 aaa->aaa_naddr++;
3217 break;
3218 case LR_WORD:
3219 aaa->aaa_addr[aaa->aaa_naddr] = crs->lr_word._min;
3220 aaa->aaa_size[aaa->aaa_naddr] = crs->lr_word._len;
3221 aaa->aaa_naddr++;
3222 break;
3223 case LR_DWORD:
3224 aaa->aaa_addr[aaa->aaa_naddr] = crs->lr_dword._min;
3225 aaa->aaa_size[aaa->aaa_naddr] = crs->lr_dword._len;
3226 aaa->aaa_naddr++;
3227 break;
3228 case LR_QWORD:
3229 aaa->aaa_addr[aaa->aaa_naddr] = crs->lr_qword._min;
3230 aaa->aaa_size[aaa->aaa_naddr] = crs->lr_qword._len;
3231 aaa->aaa_naddr++;
3232 break;
3233 case SR_IRQ:
3234 aaa->aaa_irq[aaa->aaa_nirq] = ffs(crs->sr_irq.irq_mask) - 1;
3235 /* Default is exclusive, active-high, edge triggered. */
3236 if (AML_CRSLEN(crs) < 4)
3237 flags = SR_IRQ_MODE;
3238 else
3239 flags = crs->sr_irq.irq_flags;
3240 /* Map flags to those of the extended interrupt descriptor. */
3241 if (flags & SR_IRQ_SHR)
3242 aaa->aaa_irq_flags[aaa->aaa_nirq] |= LR_EXTIRQ_SHR;
3243 if (flags & SR_IRQ_POLARITY)
3244 aaa->aaa_irq_flags[aaa->aaa_nirq] |= LR_EXTIRQ_POLARITY;
3245 if (flags & SR_IRQ_MODE)
3246 aaa->aaa_irq_flags[aaa->aaa_nirq] |= LR_EXTIRQ_MODE;
3247 aaa->aaa_nirq++;
3248 break;
3249 case LR_EXTIRQ:
3250 aaa->aaa_irq[aaa->aaa_nirq] = crs->lr_extirq.irq[0];
3251 aaa->aaa_irq_flags[aaa->aaa_nirq] = crs->lr_extirq.flags;
3252 aaa->aaa_nirq++;
3253 break;
3254 }
3255
3256 return 0;
3257}
3258
3259void
3260acpi_parse_crs(struct acpi_softc *sc, struct acpi_attach_args *aaa)
3261{
3262 struct aml_value res;
3263
3264 if (aml_evalname(sc, aaa->aaa_node, "_CRS", 0, NULL, &res))
3265 return;
3266
3267 aml_parse_resource(&res, acpi_parse_resources, aaa);
3268}
3269
3270int
3271acpi_foundhid(struct aml_node *node, void *arg)
3272{
3273 struct acpi_softc *sc = (struct acpi_softc *)arg;
3274 struct device *self = (struct device *)arg;
3275 char cdev[32];
3276 char dev[32];
3277 struct acpi_attach_args aaa;
3278 int64_t sta;
3279 int64_t cca;
3280#ifndef SMALL_KERNEL
3281 int i;
3282#endif
3283
3284 if (acpi_parsehid(node, arg, cdev, dev, sizeof(dev)) != 0)
3285 return (0);
3286
3287 sta = acpi_getsta(sc, node->parent);
3288 if ((sta & STA_PRESENT) == 0 && (sta & STA_DEV_OK) == 0)
3289 return (1);
3290 if ((sta & STA_ENABLED) == 0)
3291 return (0);
3292
3293 if (aml_evalinteger(sc, node->parent, "_CCA", 0, NULL, &cca))
3294 cca = 1;
3295
3296 acpi_attach_deps(sc, node->parent);
3297
3298 memset(&aaa, 0, sizeof(aaa));
3299 aaa.aaa_iot = sc->sc_iot;
3300 aaa.aaa_memt = sc->sc_memt;
3301 aaa.aaa_dmat = cca ? sc->sc_cc_dmat : sc->sc_ci_dmat;
3302 aaa.aaa_node = node->parent;
3303 aaa.aaa_dev = dev;
3304 aaa.aaa_cdev = cdev;
3305
3306#ifndef SMALL_KERNEL
3307 if (!strcmp(cdev, ACPI_DEV_MOUSE)) {
3308 for (i = 0; i < nitems(sbtn_pnp); i++) {
3309 if (!strcmp(dev, sbtn_pnp[i])) {
3310 mouse_has_softbtn = 1;
3311 break;
3312 }
3313 }
3314 }
3315#endif
3316
3317 if (acpi_matchhids(&aaa, acpi_skip_hids, "none") ||
3318 acpi_matchhids(&aaa, acpi_isa_hids, "none"))
3319 return (0);
3320
3321 acpi_parse_crs(sc, &aaa);
3322
3323 aaa.aaa_dmat = acpi_iommu_device_map(node->parent, aaa.aaa_dmat);
3324
3325 if (!node->parent->attached) {
3326 node->parent->attached = 1;
3327 if (acpi_matchhids(&aaa, acpi_quiet_hids, "none"))
3328 config_found(self, &aaa, acpi_noprint);
3329 else
3330 config_found(self, &aaa, acpi_print);
3331 }
3332
3333 return (0);
3334}
3335
3336#ifndef SMALL_KERNEL
3337int
3338acpi_founddock(struct aml_node *node, void *arg)
3339{
3340 struct acpi_softc *sc = (struct acpi_softc *)arg;
3341 struct device *self = (struct device *)arg;
3342 struct acpi_attach_args aaa;
3343
3344 dnprintf(10, "found dock entry: %s\n", node->parent->name);
3345
3346 memset(&aaa, 0, sizeof(aaa));
3347 aaa.aaa_iot = sc->sc_iot;
3348 aaa.aaa_memt = sc->sc_memt;
3349 aaa.aaa_node = node->parent;
3350 aaa.aaa_name = "acpidock";
3351
3352 config_found(self, &aaa, acpi_print);
3353
3354 return 0;
3355}
3356
3357int
3358acpi_foundvideo(struct aml_node *node, void *arg)
3359{
3360 struct acpi_softc *sc = (struct acpi_softc *)arg;
3361 struct device *self = (struct device *)arg;
3362 struct acpi_attach_args aaa;
3363
3364 memset(&aaa, 0, sizeof(aaa));
3365 aaa.aaa_iot = sc->sc_iot;
3366 aaa.aaa_memt = sc->sc_memt;
3367 aaa.aaa_node = node->parent;
3368 aaa.aaa_name = "acpivideo";
3369
3370 config_found(self, &aaa, acpi_print);
3371
3372 return (0);
3373}
3374
3375int
3376acpi_foundsbs(struct aml_node *node, void *arg)
3377{
3378 struct acpi_softc *sc = (struct acpi_softc *)arg;
3379 struct device *self = (struct device *)arg;
3380 char cdev[32], dev[32];
3381 struct acpi_attach_args aaa;
3382 int64_t sta;
3383
3384 if (acpi_parsehid(node, arg, cdev, dev, sizeof(dev)) != 0)
3385 return (0);
3386
3387 sta = acpi_getsta(sc, node->parent);
3388 if ((sta & STA_PRESENT) == 0)
3389 return (0);
3390
3391 acpi_attach_deps(sc, node->parent);
3392
3393 if (strcmp(dev, ACPI_DEV_SBS) != 0)
3394 return (0);
3395
3396 if (node->parent->attached)
3397 return (0);
3398
3399 memset(&aaa, 0, sizeof(aaa));
3400 aaa.aaa_iot = sc->sc_iot;
3401 aaa.aaa_memt = sc->sc_memt;
3402 aaa.aaa_node = node->parent;
3403 aaa.aaa_dev = dev;
3404 aaa.aaa_cdev = cdev;
3405
3406 config_found(self, &aaa, acpi_print);
3407 node->parent->attached = 1;
3408
3409 return (0);
3410}
3411
3412int
3413acpi_batcount(struct acpi_softc *sc)
3414{
3415 struct acpi_bat *bat;
3416 int count = 0;
3417
3418 SLIST_FOREACH(bat, &sc->sc_bat, aba_link)
3419 count++;
3420 return count;
3421}
3422
3423int
3424acpi_apminfo(struct apm_power_info *pi)
3425{
3426 struct acpi_softc *sc = acpi_softc;
3427 struct acpi_ac *ac;
3428 struct acpi_bat *bat;
3429 struct acpi_sbs *sbs;
3430 int bats;
3431 unsigned int capacity, remaining, minutes, rate;
3432
3433 /* A/C */
3434 pi->ac_state = APM_AC_UNKNOWN;
3435// XXX replace with new power code
3436 SLIST_FOREACH(ac, &sc->sc_ac, aac_link) {
3437 if (ac->aac_softc->sc_ac_stat == PSR_ONLINE)
3438 pi->ac_state = APM_AC_ON;
3439 else if (ac->aac_softc->sc_ac_stat == PSR_OFFLINE)
3440 if (pi->ac_state == APM_AC_UNKNOWN)
3441 pi->ac_state = APM_AC_OFF;
3442 }
3443
3444 /* battery */
3445 pi->battery_state = APM_BATT_UNKNOWN;
3446 pi->battery_life = 0;
3447 pi->minutes_left = 0;
3448 bats = 0;
3449 capacity = 0;
3450 remaining = 0;
3451 minutes = 0;
3452 rate = 0;
3453 SLIST_FOREACH(bat, &sc->sc_bat, aba_link) {
3454 if (bat->aba_softc->sc_bat_present == 0)
3455 continue;
3456
3457 if (bat->aba_softc->sc_bix.bix_last_capacity == 0)
3458 continue;
3459
3460 bats++;
3461 capacity += bat->aba_softc->sc_bix.bix_last_capacity;
3462 remaining += min(bat->aba_softc->sc_bst.bst_capacity,
3463 bat->aba_softc->sc_bix.bix_last_capacity);
3464
3465 if (bat->aba_softc->sc_bst.bst_state & BST_CHARGE)
3466 pi->battery_state = APM_BATT_CHARGING;
3467
3468 if (bat->aba_softc->sc_bst.bst_rate == BST_UNKNOWN)
3469 continue;
3470 else if (bat->aba_softc->sc_bst.bst_rate > 1)
3471 rate = bat->aba_softc->sc_bst.bst_rate;
3472
3473 minutes += bat->aba_softc->sc_bst.bst_capacity;
3474 }
3475
3476 SLIST_FOREACH(sbs, &sc->sc_sbs, asbs_link) {
3477 if (sbs->asbs_softc->sc_batteries_present == 0)
3478 continue;
3479
3480 if (sbs->asbs_softc->sc_battery.rel_charge == 0)
3481 continue;
3482
3483 bats++;
3484 capacity += 100;
3485 remaining += min(100,
3486 sbs->asbs_softc->sc_battery.rel_charge);
3487
3488 if (sbs->asbs_softc->sc_battery.run_time ==
3489 ACPISBS_VALUE_UNKNOWN)
3490 continue;
3491
3492 rate = 60; /* XXX */
3493 minutes += sbs->asbs_softc->sc_battery.run_time;
3494 }
3495
3496 if (bats == 0) {
3497 pi->battery_state = APM_BATTERY_ABSENT;
3498 pi->battery_life = 0;
3499 pi->minutes_left = (unsigned int)-1;
3500 return 0;
3501 }
3502
3503 if (rate == 0)
3504 pi->minutes_left = (unsigned int)-1;
3505 else if (pi->battery_state == APM_BATT_CHARGING)
3506 pi->minutes_left = 60 * (capacity - remaining) / rate;
3507 else
3508 pi->minutes_left = 60 * minutes / rate;
3509
3510 pi->battery_life = remaining * 100 / capacity;
3511
3512 if (pi->battery_state == APM_BATT_CHARGING)
3513 return 0;
3514
3515 /* running on battery */
3516 if (pi->battery_life > 50)
3517 pi->battery_state = APM_BATT_HIGH;
3518 else if (pi->battery_life > 25)
3519 pi->battery_state = APM_BATT_LOW;
3520 else
3521 pi->battery_state = APM_BATT_CRITICAL;
3522
3523 return 0;
3524}
3525
3526int acpi_evindex;
3527
3528int
3529acpi_record_event(struct acpi_softc *sc, u_int type)
3530{
3531 if ((sc->sc_flags & SCFLAG_OPEN) == 0)
3532 return (1);
3533
3534 acpi_evindex++;
3535 knote_locked(&sc->sc_note, APM_EVENT_COMPOSE(type, acpi_evindex));
3536 return (0);
3537}
3538
3539#endif /* SMALL_KERNEL */