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