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