Bug Summary

File:dev/acpi/acpi.c
Warning:line 2766, column 2
Value stored to 's' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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