Bug Summary

File:dev/acpi/acpi.c
Warning:line 1637, column 34
Branch condition evaluates to a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

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