add a machdep.dmi sysctl tree with the following read-only keys: system-vendor, system-product, system-version, system-serial, system-uuid bios-vendor, bios-version board-vendor, board-product, board-version, board-serial the *-serial and *-uuid keys are marked with CTLFLAG_PRIVATE a few of the pmf platform key names changed so update callers to matchdiff -r1.11 -r1.12 src/sys/arch/x86/x86/platform.c
(jmcneill)
--- src/sys/arch/x86/x86/Attic/platform.c 2011/01/18 07:47:16 1.11
+++ src/sys/arch/x86/x86/Attic/platform.c 2011/11/14 02:44:59 1.12
@@ -1,176 +1,302 @@ | @@ -1,176 +1,302 @@ | |||
1 | /* $NetBSD: platform.c,v 1.11 2011/01/18 07:47:16 jmmv Exp $ */ | 1 | /* $NetBSD: platform.c,v 1.12 2011/11/14 02:44:59 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> | 4 | * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | 26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include "isa.h" | 29 | #include "isa.h" | |
30 | 30 | |||
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: platform.c,v 1.11 2011/01/18 07:47:16 jmmv Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: platform.c,v 1.12 2011/11/14 02:44:59 jmcneill Exp $"); | |
33 | 33 | |||
34 | #include <sys/types.h> | 34 | #include <sys/types.h> | |
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/kernel.h> | 36 | #include <sys/kernel.h> | |
37 | #include <sys/sysctl.h> | |||
38 | #include <sys/uuid.h> | |||
37 | #include <sys/pmf.h> | 39 | #include <sys/pmf.h> | |
38 | 40 | |||
39 | #include <dev/isa/isavar.h> | 41 | #include <dev/isa/isavar.h> | |
40 | 42 | |||
41 | #include <arch/x86/include/smbiosvar.h> | 43 | #include <arch/x86/include/smbiosvar.h> | |
42 | 44 | |||
45 | static int platform_dminode = CTL_EOL; | |||
46 | ||||
43 | void platform_init(void); /* XXX */ | 47 | void platform_init(void); /* XXX */ | |
44 | static void platform_add(struct smbtable *, const char *, int); | 48 | static void platform_add(struct smbtable *, const char *, int); | |
45 | static void platform_add_date(struct smbtable *, const char *, int); | 49 | static void platform_add_date(struct smbtable *, const char *, int); | |
50 | static void platform_add_uuid(struct smbtable *, const char *, | |||
51 | const uint8_t *); | |||
52 | static int platform_dmi_sysctl(SYSCTLFN_PROTO); | |||
46 | static void platform_print(void); | 53 | static void platform_print(void); | |
47 | 54 | |||
55 | /* list of private DMI sysctl nodes */ | |||
56 | static const char *platform_private_nodes[] = { | |||
57 | "board-serial", | |||
58 | "system-serial", | |||
59 | "system-uuid", | |||
60 | NULL | |||
61 | }; | |||
62 | ||||
48 | void | 63 | void | |
49 | platform_init(void) | 64 | platform_init(void) | |
50 | { | 65 | { | |
51 | struct smbtable smbios; | 66 | struct smbtable smbios; | |
52 | struct smbios_sys *psys; | 67 | struct smbios_sys *psys; | |
53 | struct smbios_struct_bios *pbios; | 68 | struct smbios_struct_bios *pbios; | |
69 | struct smbios_board *pboard; | |||
54 | struct smbios_slot *pslot; | 70 | struct smbios_slot *pslot; | |
55 | int nisa, nother; | 71 | int nisa, nother; | |
56 | 72 | |||
57 | smbios.cookie = 0; | 73 | smbios.cookie = 0; | |
58 | if (smbios_find_table(SMBIOS_TYPE_SYSTEM, &smbios)) { | 74 | if (smbios_find_table(SMBIOS_TYPE_SYSTEM, &smbios)) { | |
59 | psys = smbios.tblhdr; | 75 | psys = smbios.tblhdr; | |
60 | 76 | |||
61 | platform_add(&smbios, "system-manufacturer", psys->vendor); | 77 | platform_add(&smbios, "system-vendor", psys->vendor); | |
62 | platform_add(&smbios, "system-product-name", psys->product); | 78 | platform_add(&smbios, "system-product", psys->product); | |
63 | platform_add(&smbios, "system-version", psys->version); | 79 | platform_add(&smbios, "system-version", psys->version); | |
64 | platform_add(&smbios, "system-serial-number", psys->serial); | 80 | platform_add(&smbios, "system-serial", psys->serial); | |
81 | platform_add_uuid(&smbios, "system-uuid", psys->uuid); | |||
65 | } | 82 | } | |
66 | 83 | |||
67 | smbios.cookie = 0; | 84 | smbios.cookie = 0; | |
68 | if (smbios_find_table(SMBIOS_TYPE_BIOS, &smbios)) { | 85 | if (smbios_find_table(SMBIOS_TYPE_BIOS, &smbios)) { | |
69 | pbios = smbios.tblhdr; | 86 | pbios = smbios.tblhdr; | |
70 | 87 | |||
71 | platform_add(&smbios, "firmware-vendor", pbios->vendor); | 88 | platform_add(&smbios, "bios-vendor", pbios->vendor); | |
72 | platform_add(&smbios, "firmware-version", pbios->version); | 89 | platform_add(&smbios, "bios-version", pbios->version); | |
73 | platform_add_date(&smbios, "firmware-date", pbios->release); | 90 | platform_add_date(&smbios, "bios-date", pbios->release); | |
91 | } | |||
92 | ||||
93 | smbios.cookie = 0; | |||
94 | if (smbios_find_table(SMBIOS_TYPE_BASEBOARD, &smbios)) { | |||
95 | pboard = smbios.tblhdr; | |||
96 | ||||
97 | platform_add(&smbios, "board-vendor", pboard->vendor); | |||
98 | platform_add(&smbios, "board-product", pboard->product); | |||
99 | platform_add(&smbios, "board-version", pboard->version); | |||
100 | platform_add(&smbios, "board-serial", pboard->serial); | |||
101 | platform_add(&smbios, "board-asset-tag", pboard->asset); | |||
74 | } | 102 | } | |
75 | 103 | |||
76 | smbios.cookie = 0; | 104 | smbios.cookie = 0; | |
77 | nisa = 0; | 105 | nisa = 0; | |
78 | nother = 0; | 106 | nother = 0; | |
79 | while (smbios_find_table(SMBIOS_TYPE_SLOTS, &smbios)) { | 107 | while (smbios_find_table(SMBIOS_TYPE_SLOTS, &smbios)) { | |
80 | pslot = smbios.tblhdr; | 108 | pslot = smbios.tblhdr; | |
81 | switch (pslot->type) { | 109 | switch (pslot->type) { | |
82 | case SMBIOS_SLOT_ISA: | 110 | case SMBIOS_SLOT_ISA: | |
83 | case SMBIOS_SLOT_EISA: | 111 | case SMBIOS_SLOT_EISA: | |
84 | nisa++; | 112 | nisa++; | |
85 | break; | 113 | break; | |
86 | default: | 114 | default: | |
87 | nother++; | 115 | nother++; | |
88 | break; | 116 | break; | |
89 | } | 117 | } | |
90 | } | 118 | } | |
91 | 119 | |||
92 | #if NISA > 0 | 120 | #if NISA > 0 | |
93 | if ((nother | nisa) != 0) { | 121 | if ((nother | nisa) != 0) { | |
94 | /* Only if there seems to be good expansion slot info. */ | 122 | /* Only if there seems to be good expansion slot info. */ | |
95 | isa_set_slotcount(nisa); | 123 | isa_set_slotcount(nisa); | |
96 | } | 124 | } | |
97 | #endif | 125 | #endif | |
98 | 126 | |||
99 | platform_print(); | 127 | platform_print(); | |
100 | } | 128 | } | |
101 | 129 | |||
102 | static void | 130 | static void | |
103 | platform_print(void) | 131 | platform_print(void) | |
104 | { | 132 | { | |
105 | const char *manuf, *prod, *ver; | 133 | const char *vend, *prod, *ver; | |
106 | 134 | |||
107 | manuf = pmf_get_platform("system-manufacturer"); | 135 | vend = pmf_get_platform("system-vendor"); | |
108 | prod = pmf_get_platform("system-product-name"); | 136 | prod = pmf_get_platform("system-product"); | |
109 | ver = pmf_get_platform("system-version"); | 137 | ver = pmf_get_platform("system-version"); | |
110 | 138 | |||
111 | if (manuf == NULL) | 139 | if (vend == NULL) | |
112 | aprint_verbose("Generic"); | 140 | aprint_verbose("Generic"); | |
113 | else | 141 | else | |
114 | aprint_verbose("%s", manuf); | 142 | aprint_verbose("%s", vend); | |
115 | if (prod == NULL) | 143 | if (prod == NULL) | |
116 | aprint_verbose(" PC"); | 144 | aprint_verbose(" PC"); | |
117 | else | 145 | else | |
118 | aprint_verbose(" %s", prod); | 146 | aprint_verbose(" %s", prod); | |
119 | if (ver != NULL) | 147 | if (ver != NULL) | |
120 | aprint_verbose(" (%s)", ver); | 148 | aprint_verbose(" (%s)", ver); | |
121 | aprint_verbose("\n"); | 149 | aprint_verbose("\n"); | |
122 | } | 150 | } | |
123 | 151 | |||
152 | static bool | |||
153 | platform_sysctl_is_private(const char *key) | |||
154 | { | |||
155 | unsigned int n; | |||
156 | ||||
157 | for (n = 0; platform_private_nodes[n] != NULL; n++) { | |||
158 | if (strcmp(key, platform_private_nodes[n]) == 0) { | |||
159 | return true; | |||
160 | } | |||
161 | } | |||
162 | ||||
163 | return false; | |||
164 | } | |||
165 | ||||
166 | static void | |||
167 | platform_create_sysctl(const char *key) | |||
168 | { | |||
169 | int flags = 0, err; | |||
170 | ||||
171 | if (pmf_get_platform(key) == NULL) | |||
172 | return; | |||
173 | ||||
174 | /* If the key is marked private, set CTLFLAG_PRIVATE flag */ | |||
175 | if (platform_sysctl_is_private(key)) | |||
176 | flags |= CTLFLAG_PRIVATE; | |||
177 | ||||
178 | err = sysctl_createv(NULL, 0, NULL, NULL, | |||
179 | CTLFLAG_READONLY | flags, CTLTYPE_STRING, | |||
180 | key, NULL, platform_dmi_sysctl, 0, NULL, 0, | |||
181 | CTL_MACHDEP, platform_dminode, CTL_CREATE, CTL_EOL); | |||
182 | if (err != 0) | |||
183 | printf("platform: sysctl_createv " | |||
184 | "(machdep.dmi.%s) failed, err = %d\n", | |||
185 | key, err); | |||
186 | } | |||
187 | ||||
124 | static void | 188 | static void | |
125 | platform_add(struct smbtable *tbl, const char *key, int idx) | 189 | platform_add(struct smbtable *tbl, const char *key, int idx) | |
126 | { | 190 | { | |
127 | char tmpbuf[128]; /* XXX is this long enough? */ | 191 | char tmpbuf[128]; /* XXX is this long enough? */ | |
128 | 192 | |||
129 | if (smbios_get_string(tbl, idx, tmpbuf, 128) != NULL) | 193 | if (smbios_get_string(tbl, idx, tmpbuf, 128) != NULL) { | |
194 | /* add to platform dictionary */ | |||
130 | pmf_set_platform(key, tmpbuf); | 195 | pmf_set_platform(key, tmpbuf); | |
196 | ||||
197 | /* create sysctl node */ | |||
198 | platform_create_sysctl(key); | |||
199 | } | |||
131 | } | 200 | } | |
132 | 201 | |||
133 | static int | 202 | static int | |
134 | platform_scan_date(char *buf, unsigned int *month, unsigned int *day, | 203 | platform_scan_date(char *buf, unsigned int *month, unsigned int *day, | |
135 | unsigned int *year) | 204 | unsigned int *year) | |
136 | { | 205 | { | |
137 | char *p, *s; | 206 | char *p, *s; | |
138 | 207 | |||
139 | s = buf; | 208 | s = buf; | |
140 | p = strchr(s, '/'); | 209 | p = strchr(s, '/'); | |
141 | if (p) *p = '\0'; | 210 | if (p) *p = '\0'; | |
142 | *month = strtoul(s, NULL, 10); | 211 | *month = strtoul(s, NULL, 10); | |
143 | if (!p) return 1; | 212 | if (!p) return 1; | |
144 | 213 | |||
145 | s = p + 1; | 214 | s = p + 1; | |
146 | p = strchr(s, '/'); | 215 | p = strchr(s, '/'); | |
147 | if (p) *p = '\0'; | 216 | if (p) *p = '\0'; | |
148 | *day = strtoul(s, NULL, 10); | 217 | *day = strtoul(s, NULL, 10); | |
149 | if (!p) return 2; | 218 | if (!p) return 2; | |
150 | 219 | |||
151 | s = p + 1; | 220 | s = p + 1; | |
152 | *year = strtoul(s, NULL, 10); | 221 | *year = strtoul(s, NULL, 10); | |
153 | return 3; | 222 | return 3; | |
154 | } | 223 | } | |
155 | 224 | |||
156 | static void | 225 | static void | |
157 | platform_add_date(struct smbtable *tbl, const char *key, int idx) | 226 | platform_add_date(struct smbtable *tbl, const char *key, int idx) | |
158 | { | 227 | { | |
159 | unsigned int month, day, year; | 228 | unsigned int month, day, year; | |
160 | char tmpbuf[128], datestr[9]; | 229 | char tmpbuf[128], datestr[9]; | |
161 | 230 | |||
162 | if (smbios_get_string(tbl, idx, tmpbuf, 128) == NULL) | 231 | if (smbios_get_string(tbl, idx, tmpbuf, 128) == NULL) | |
163 | return; | 232 | return; | |
164 | if (platform_scan_date(tmpbuf, &month, &day, &year) != 3) | 233 | if (platform_scan_date(tmpbuf, &month, &day, &year) != 3) | |
165 | return; | 234 | return; | |
166 | if (month == 0 || month > 12 || day == 0 || day > 31) | 235 | if (month == 0 || month > 12 || day == 0 || day > 31) | |
167 | return; | 236 | return; | |
168 | if (year > 9999) | 237 | if (year > 9999) | |
169 | return; | 238 | return; | |
170 | if (year < 70) | 239 | if (year < 70) | |
171 | year += 2000; | 240 | year += 2000; | |
172 | else if (year < 100) | 241 | else if (year < 100) | |
173 | year += 1900; | 242 | year += 1900; | |
174 | sprintf(datestr, "%04u%02u%02u", year, month, day); | 243 | sprintf(datestr, "%04u%02u%02u", year, month, day); | |
175 | pmf_set_platform(key, datestr); | 244 | pmf_set_platform(key, datestr); | |
176 | } | 245 | } | |
246 | ||||
247 | static void | |||
248 | platform_add_uuid(struct smbtable *tbl, const char *key, const uint8_t *buf) | |||
249 | { | |||
250 | struct uuid uuid; | |||
251 | char tmpbuf[UUID_STR_LEN]; | |||
252 | ||||
253 | uuid_dec_le(buf, &uuid); | |||
254 | uuid_snprintf(tmpbuf, sizeof(tmpbuf), &uuid); | |||
255 | ||||
256 | pmf_set_platform(key, tmpbuf); | |||
257 | platform_create_sysctl(key); | |||
258 | } | |||
259 | ||||
260 | static int | |||
261 | platform_dmi_sysctl(SYSCTLFN_ARGS) | |||
262 | { | |||
263 | struct sysctlnode node; | |||
264 | const char *v; | |||
265 | int err = 0; | |||
266 | ||||
267 | node = *rnode; | |||
268 | ||||
269 | v = pmf_get_platform(node.sysctl_name); | |||
270 | if (v == NULL) | |||
271 | return ENOENT; | |||
272 | ||||
273 | node.sysctl_data = __UNCONST(v); | |||
274 | err = sysctl_lookup(SYSCTLFN_CALL(&node)); | |||
275 | if (err || newp == NULL) | |||
276 | return err; | |||
277 | ||||
278 | return 0; | |||
279 | } | |||
280 | ||||
281 | SYSCTL_SETUP(sysctl_dmi_setup, "sysctl machdep.dmi subtree setup") | |||
282 | { | |||
283 | const struct sysctlnode *rnode; | |||
284 | int err; | |||
285 | ||||
286 | err = sysctl_createv(clog, 0, NULL, &rnode, | |||
287 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", | |||
288 | NULL, NULL, 0, NULL, 0, | |||
289 | CTL_MACHDEP, CTL_EOL); | |||
290 | if (err) | |||
291 | return; | |||
292 | ||||
293 | err = sysctl_createv(clog, 0, &rnode, &rnode, | |||
294 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "dmi", | |||
295 | SYSCTL_DESCR("DMI table information"), | |||
296 | NULL, 0, NULL, 0, | |||
297 | CTL_CREATE, CTL_EOL); | |||
298 | if (err) | |||
299 | return; | |||
300 | ||||
301 | platform_dminode = rnode->sysctl_num; | |||
302 | } |
--- src/sys/dev/acpi/acpi.c 2011/10/18 23:47:26 1.251
+++ src/sys/dev/acpi/acpi.c 2011/11/14 02:44:59 1.252
@@ -1,1308 +1,1308 @@ | @@ -1,1308 +1,1308 @@ | |||
1 | /* $NetBSD: acpi.c,v 1.251 2011/10/18 23:47:26 jmcneill Exp $ */ | 1 | /* $NetBSD: acpi.c,v 1.252 2011/11/14 02:44:59 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Charles M. Hannum of By Noon Software, Inc. | 8 | * by Charles M. Hannum of By Noon Software, Inc. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * Copyright (c) 2003 Wasabi Systems, Inc. | 33 | * Copyright (c) 2003 Wasabi Systems, Inc. | |
34 | * All rights reserved. | 34 | * All rights reserved. | |
35 | * | 35 | * | |
36 | * Written by Frank van der Linden for Wasabi Systems, Inc. | 36 | * Written by Frank van der Linden for Wasabi Systems, Inc. | |
37 | * | 37 | * | |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without | |
39 | * modification, are permitted provided that the following conditions | 39 | * modification, are permitted provided that the following conditions | |
40 | * are met: | 40 | * are met: | |
41 | * 1. Redistributions of source code must retain the above copyright | 41 | * 1. Redistributions of source code must retain the above copyright | |
42 | * notice, this list of conditions and the following disclaimer. | 42 | * notice, this list of conditions and the following disclaimer. | |
43 | * 2. Redistributions in binary form must reproduce the above copyright | 43 | * 2. Redistributions in binary form must reproduce the above copyright | |
44 | * notice, this list of conditions and the following disclaimer in the | 44 | * notice, this list of conditions and the following disclaimer in the | |
45 | * documentation and/or other materials provided with the distribution. | 45 | * documentation and/or other materials provided with the distribution. | |
46 | * 3. All advertising materials mentioning features or use of this software | 46 | * 3. All advertising materials mentioning features or use of this software | |
47 | * must display the following acknowledgement: | 47 | * must display the following acknowledgement: | |
48 | * This product includes software developed for the NetBSD Project by | 48 | * This product includes software developed for the NetBSD Project by | |
49 | * Wasabi Systems, Inc. | 49 | * Wasabi Systems, Inc. | |
50 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | 50 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | |
51 | * or promote products derived from this software without specific prior | 51 | * or promote products derived from this software without specific prior | |
52 | * written permission. | 52 | * written permission. | |
53 | * | 53 | * | |
54 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | 54 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | |
55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
56 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 56 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | 57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | |
58 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 58 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
64 | * POSSIBILITY OF SUCH DAMAGE. | 64 | * POSSIBILITY OF SUCH DAMAGE. | |
65 | */ | 65 | */ | |
66 | 66 | |||
67 | /* | 67 | /* | |
68 | * Copyright 2001, 2003 Wasabi Systems, Inc. | 68 | * Copyright 2001, 2003 Wasabi Systems, Inc. | |
69 | * All rights reserved. | 69 | * All rights reserved. | |
70 | * | 70 | * | |
71 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | 71 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | |
72 | * | 72 | * | |
73 | * Redistribution and use in source and binary forms, with or without | 73 | * Redistribution and use in source and binary forms, with or without | |
74 | * modification, are permitted provided that the following conditions | 74 | * modification, are permitted provided that the following conditions | |
75 | * are met: | 75 | * are met: | |
76 | * 1. Redistributions of source code must retain the above copyright | 76 | * 1. Redistributions of source code must retain the above copyright | |
77 | * notice, this list of conditions and the following disclaimer. | 77 | * notice, this list of conditions and the following disclaimer. | |
78 | * 2. Redistributions in binary form must reproduce the above copyright | 78 | * 2. Redistributions in binary form must reproduce the above copyright | |
79 | * notice, this list of conditions and the following disclaimer in the | 79 | * notice, this list of conditions and the following disclaimer in the | |
80 | * documentation and/or other materials provided with the distribution. | 80 | * documentation and/or other materials provided with the distribution. | |
81 | * 3. All advertising materials mentioning features or use of this software | 81 | * 3. All advertising materials mentioning features or use of this software | |
82 | * must display the following acknowledgement: | 82 | * must display the following acknowledgement: | |
83 | * This product includes software developed for the NetBSD Project by | 83 | * This product includes software developed for the NetBSD Project by | |
84 | * Wasabi Systems, Inc. | 84 | * Wasabi Systems, Inc. | |
85 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | 85 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | |
86 | * or promote products derived from this software without specific prior | 86 | * or promote products derived from this software without specific prior | |
87 | * written permission. | 87 | * written permission. | |
88 | * | 88 | * | |
89 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | 89 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | |
90 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 90 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
91 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 91 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
92 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | 92 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | |
93 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 93 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
94 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 94 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
95 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 95 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
96 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 96 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
97 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 97 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
98 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 98 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
99 | * POSSIBILITY OF SUCH DAMAGE. | 99 | * POSSIBILITY OF SUCH DAMAGE. | |
100 | */ | 100 | */ | |
101 | 101 | |||
102 | #include <sys/cdefs.h> | 102 | #include <sys/cdefs.h> | |
103 | __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.251 2011/10/18 23:47:26 jmcneill Exp $"); | 103 | __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.252 2011/11/14 02:44:59 jmcneill Exp $"); | |
104 | 104 | |||
105 | #include "opt_acpi.h" | 105 | #include "opt_acpi.h" | |
106 | #include "opt_pcifixup.h" | 106 | #include "opt_pcifixup.h" | |
107 | 107 | |||
108 | #include <sys/param.h> | 108 | #include <sys/param.h> | |
109 | #include <sys/device.h> | 109 | #include <sys/device.h> | |
110 | #include <sys/kernel.h> | 110 | #include <sys/kernel.h> | |
111 | #include <sys/kmem.h> | 111 | #include <sys/kmem.h> | |
112 | #include <sys/malloc.h> | 112 | #include <sys/malloc.h> | |
113 | #include <sys/module.h> | 113 | #include <sys/module.h> | |
114 | #include <sys/mutex.h> | 114 | #include <sys/mutex.h> | |
115 | #include <sys/sysctl.h> | 115 | #include <sys/sysctl.h> | |
116 | #include <sys/systm.h> | 116 | #include <sys/systm.h> | |
117 | #include <sys/timetc.h> | 117 | #include <sys/timetc.h> | |
118 | 118 | |||
119 | #include <dev/acpi/acpireg.h> | 119 | #include <dev/acpi/acpireg.h> | |
120 | #include <dev/acpi/acpivar.h> | 120 | #include <dev/acpi/acpivar.h> | |
121 | #include <dev/acpi/acpi_osd.h> | 121 | #include <dev/acpi/acpi_osd.h> | |
122 | #include <dev/acpi/acpi_pci.h> | 122 | #include <dev/acpi/acpi_pci.h> | |
123 | #include <dev/acpi/acpi_power.h> | 123 | #include <dev/acpi/acpi_power.h> | |
124 | #include <dev/acpi/acpi_timer.h> | 124 | #include <dev/acpi/acpi_timer.h> | |
125 | #include <dev/acpi/acpi_wakedev.h> | 125 | #include <dev/acpi/acpi_wakedev.h> | |
126 | 126 | |||
127 | #include <machine/acpi_machdep.h> | 127 | #include <machine/acpi_machdep.h> | |
128 | 128 | |||
129 | #define _COMPONENT ACPI_BUS_COMPONENT | 129 | #define _COMPONENT ACPI_BUS_COMPONENT | |
130 | ACPI_MODULE_NAME ("acpi") | 130 | ACPI_MODULE_NAME ("acpi") | |
131 | 131 | |||
132 | /* | 132 | /* | |
133 | * The acpi_active variable is set when the ACPI subsystem is active. | 133 | * The acpi_active variable is set when the ACPI subsystem is active. | |
134 | * Machine-dependent code may wish to skip other steps (such as attaching | 134 | * Machine-dependent code may wish to skip other steps (such as attaching | |
135 | * subsystems that ACPI supercedes) when ACPI is active. | 135 | * subsystems that ACPI supercedes) when ACPI is active. | |
136 | */ | 136 | */ | |
137 | int acpi_active = 0; | 137 | int acpi_active = 0; | |
138 | int acpi_suspended = 0; | 138 | int acpi_suspended = 0; | |
139 | int acpi_force_load = 0; | 139 | int acpi_force_load = 0; | |
140 | int acpi_verbose_loaded = 0; | 140 | int acpi_verbose_loaded = 0; | |
141 | 141 | |||
142 | struct acpi_softc *acpi_softc = NULL; | 142 | struct acpi_softc *acpi_softc = NULL; | |
143 | static uint64_t acpi_root_pointer; | 143 | static uint64_t acpi_root_pointer; | |
144 | extern kmutex_t acpi_interrupt_list_mtx; | 144 | extern kmutex_t acpi_interrupt_list_mtx; | |
145 | extern struct cfdriver acpi_cd; | 145 | extern struct cfdriver acpi_cd; | |
146 | static ACPI_HANDLE acpi_scopes[4]; | 146 | static ACPI_HANDLE acpi_scopes[4]; | |
147 | ACPI_TABLE_HEADER *madt_header; | 147 | ACPI_TABLE_HEADER *madt_header; | |
148 | 148 | |||
149 | /* | 149 | /* | |
150 | * This structure provides a context for the ACPI | 150 | * This structure provides a context for the ACPI | |
151 | * namespace walk performed in acpi_build_tree(). | 151 | * namespace walk performed in acpi_build_tree(). | |
152 | */ | 152 | */ | |
153 | struct acpi_walkcontext { | 153 | struct acpi_walkcontext { | |
154 | struct acpi_softc *aw_sc; | 154 | struct acpi_softc *aw_sc; | |
155 | struct acpi_devnode *aw_parent; | 155 | struct acpi_devnode *aw_parent; | |
156 | }; | 156 | }; | |
157 | 157 | |||
158 | /* | 158 | /* | |
159 | * Ignored HIDs. | 159 | * Ignored HIDs. | |
160 | */ | 160 | */ | |
161 | static const char * const acpi_ignored_ids[] = { | 161 | static const char * const acpi_ignored_ids[] = { | |
162 | #if defined(i386) || defined(x86_64) | 162 | #if defined(i386) || defined(x86_64) | |
163 | "ACPI0007", /* ACPI CPUs do not attach to acpi(4) */ | 163 | "ACPI0007", /* ACPI CPUs do not attach to acpi(4) */ | |
164 | "PNP0000", /* AT interrupt controller is handled internally */ | 164 | "PNP0000", /* AT interrupt controller is handled internally */ | |
165 | "PNP0200", /* AT DMA controller is handled internally */ | 165 | "PNP0200", /* AT DMA controller is handled internally */ | |
166 | "PNP0A??", /* PCI Busses are handled internally */ | 166 | "PNP0A??", /* PCI Busses are handled internally */ | |
167 | "PNP0B00", /* AT RTC is handled internally */ | 167 | "PNP0B00", /* AT RTC is handled internally */ | |
168 | "PNP0C0F", /* ACPI PCI link devices are handled internally */ | 168 | "PNP0C0F", /* ACPI PCI link devices are handled internally */ | |
169 | #endif | 169 | #endif | |
170 | #if defined(x86_64) | 170 | #if defined(x86_64) | |
171 | "PNP0C04", /* FPU is handled internally */ | 171 | "PNP0C04", /* FPU is handled internally */ | |
172 | #endif | 172 | #endif | |
173 | NULL | 173 | NULL | |
174 | }; | 174 | }; | |
175 | 175 | |||
176 | /* | 176 | /* | |
177 | * Devices that should be attached early. | 177 | * Devices that should be attached early. | |
178 | */ | 178 | */ | |
179 | static const char * const acpi_early_ids[] = { | 179 | static const char * const acpi_early_ids[] = { | |
180 | "PNP0C09", /* acpiec(4) */ | 180 | "PNP0C09", /* acpiec(4) */ | |
181 | NULL | 181 | NULL | |
182 | }; | 182 | }; | |
183 | 183 | |||
184 | static int acpi_match(device_t, cfdata_t, void *); | 184 | static int acpi_match(device_t, cfdata_t, void *); | |
185 | static int acpi_submatch(device_t, cfdata_t, const int *, void *); | 185 | static int acpi_submatch(device_t, cfdata_t, const int *, void *); | |
186 | static void acpi_attach(device_t, device_t, void *); | 186 | static void acpi_attach(device_t, device_t, void *); | |
187 | static int acpi_detach(device_t, int); | 187 | static int acpi_detach(device_t, int); | |
188 | static void acpi_childdet(device_t, device_t); | 188 | static void acpi_childdet(device_t, device_t); | |
189 | static bool acpi_suspend(device_t, const pmf_qual_t *); | 189 | static bool acpi_suspend(device_t, const pmf_qual_t *); | |
190 | static bool acpi_resume(device_t, const pmf_qual_t *); | 190 | static bool acpi_resume(device_t, const pmf_qual_t *); | |
191 | 191 | |||
192 | static void acpi_build_tree(struct acpi_softc *); | 192 | static void acpi_build_tree(struct acpi_softc *); | |
193 | static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, uint32_t, | 193 | static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, uint32_t, | |
194 | void *, void **); | 194 | void *, void **); | |
195 | static ACPI_STATUS acpi_make_devnode_post(ACPI_HANDLE, uint32_t, | 195 | static ACPI_STATUS acpi_make_devnode_post(ACPI_HANDLE, uint32_t, | |
196 | void *, void **); | 196 | void *, void **); | |
197 | static void acpi_make_name(struct acpi_devnode *, uint32_t); | 197 | static void acpi_make_name(struct acpi_devnode *, uint32_t); | |
198 | 198 | |||
199 | static int acpi_rescan(device_t, const char *, const int *); | 199 | static int acpi_rescan(device_t, const char *, const int *); | |
200 | static void acpi_rescan_early(struct acpi_softc *); | 200 | static void acpi_rescan_early(struct acpi_softc *); | |
201 | static void acpi_rescan_nodes(struct acpi_softc *); | 201 | static void acpi_rescan_nodes(struct acpi_softc *); | |
202 | static void acpi_rescan_capabilities(device_t); | 202 | static void acpi_rescan_capabilities(device_t); | |
203 | static int acpi_print(void *aux, const char *); | 203 | static int acpi_print(void *aux, const char *); | |
204 | 204 | |||
205 | static void acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); | 205 | static void acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); | |
206 | 206 | |||
207 | static void acpi_register_fixed_button(struct acpi_softc *, int); | 207 | static void acpi_register_fixed_button(struct acpi_softc *, int); | |
208 | static void acpi_deregister_fixed_button(struct acpi_softc *, int); | 208 | static void acpi_deregister_fixed_button(struct acpi_softc *, int); | |
209 | static uint32_t acpi_fixed_button_handler(void *); | 209 | static uint32_t acpi_fixed_button_handler(void *); | |
210 | static void acpi_fixed_button_pressed(void *); | 210 | static void acpi_fixed_button_pressed(void *); | |
211 | 211 | |||
212 | static void acpi_sleep_init(struct acpi_softc *); | 212 | static void acpi_sleep_init(struct acpi_softc *); | |
213 | 213 | |||
214 | static int sysctl_hw_acpi_fixedstats(SYSCTLFN_PROTO); | 214 | static int sysctl_hw_acpi_fixedstats(SYSCTLFN_PROTO); | |
215 | static int sysctl_hw_acpi_sleepstate(SYSCTLFN_PROTO); | 215 | static int sysctl_hw_acpi_sleepstate(SYSCTLFN_PROTO); | |
216 | static int sysctl_hw_acpi_sleepstates(SYSCTLFN_PROTO); | 216 | static int sysctl_hw_acpi_sleepstates(SYSCTLFN_PROTO); | |
217 | 217 | |||
218 | static bool acpi_is_scope(struct acpi_devnode *); | 218 | static bool acpi_is_scope(struct acpi_devnode *); | |
219 | static ACPI_TABLE_HEADER *acpi_map_rsdt(void); | 219 | static ACPI_TABLE_HEADER *acpi_map_rsdt(void); | |
220 | static void acpi_unmap_rsdt(ACPI_TABLE_HEADER *); | 220 | static void acpi_unmap_rsdt(ACPI_TABLE_HEADER *); | |
221 | 221 | |||
222 | void acpi_print_verbose_stub(struct acpi_softc *); | 222 | void acpi_print_verbose_stub(struct acpi_softc *); | |
223 | void acpi_print_dev_stub(const char *); | 223 | void acpi_print_dev_stub(const char *); | |
224 | 224 | |||
225 | static void acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **); | 225 | static void acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **); | |
226 | ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE); | 226 | ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE); | |
227 | 227 | |||
228 | void (*acpi_print_verbose)(struct acpi_softc *) = acpi_print_verbose_stub; | 228 | void (*acpi_print_verbose)(struct acpi_softc *) = acpi_print_verbose_stub; | |
229 | void (*acpi_print_dev)(const char *) = acpi_print_dev_stub; | 229 | void (*acpi_print_dev)(const char *) = acpi_print_dev_stub; | |
230 | 230 | |||
231 | CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc), | 231 | CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc), | |
232 | acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet); | 232 | acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet); | |
233 | 233 | |||
234 | /* | 234 | /* | |
235 | * Probe for ACPI support. | 235 | * Probe for ACPI support. | |
236 | * | 236 | * | |
237 | * This is called by the machine-dependent ACPI front-end. | 237 | * This is called by the machine-dependent ACPI front-end. | |
238 | * Note: this is not an autoconfiguration interface function. | 238 | * Note: this is not an autoconfiguration interface function. | |
239 | */ | 239 | */ | |
240 | int | 240 | int | |
241 | acpi_probe(void) | 241 | acpi_probe(void) | |
242 | { | 242 | { | |
243 | ACPI_TABLE_HEADER *rsdt; | 243 | ACPI_TABLE_HEADER *rsdt; | |
244 | ACPI_STATUS rv; | 244 | ACPI_STATUS rv; | |
245 | int quirks; | 245 | int quirks; | |
246 | 246 | |||
247 | if (acpi_softc != NULL) | 247 | if (acpi_softc != NULL) | |
248 | panic("%s: already probed", __func__); | 248 | panic("%s: already probed", __func__); | |
249 | 249 | |||
250 | mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE); | 250 | mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE); | |
251 | 251 | |||
252 | /* | 252 | /* | |
253 | * Start up ACPICA. | 253 | * Start up ACPICA. | |
254 | */ | 254 | */ | |
255 | AcpiGbl_AllMethodsSerialized = false; | 255 | AcpiGbl_AllMethodsSerialized = false; | |
256 | AcpiGbl_EnableInterpreterSlack = true; | 256 | AcpiGbl_EnableInterpreterSlack = true; | |
257 | 257 | |||
258 | rv = AcpiInitializeSubsystem(); | 258 | rv = AcpiInitializeSubsystem(); | |
259 | 259 | |||
260 | if (ACPI_FAILURE(rv)) { | 260 | if (ACPI_FAILURE(rv)) { | |
261 | aprint_error("%s: failed to initialize subsystem\n", __func__); | 261 | aprint_error("%s: failed to initialize subsystem\n", __func__); | |
262 | return 0; | 262 | return 0; | |
263 | } | 263 | } | |
264 | 264 | |||
265 | /* | 265 | /* | |
266 | * Allocate space for RSDT/XSDT and DSDT, | 266 | * Allocate space for RSDT/XSDT and DSDT, | |
267 | * but allow resizing if more tables exist. | 267 | * but allow resizing if more tables exist. | |
268 | */ | 268 | */ | |
269 | rv = AcpiInitializeTables(NULL, 2, true); | 269 | rv = AcpiInitializeTables(NULL, 2, true); | |
270 | 270 | |||
271 | if (ACPI_FAILURE(rv)) { | 271 | if (ACPI_FAILURE(rv)) { | |
272 | aprint_error("%s: failed to initialize tables\n", __func__); | 272 | aprint_error("%s: failed to initialize tables\n", __func__); | |
273 | goto fail; | 273 | goto fail; | |
274 | } | 274 | } | |
275 | 275 | |||
276 | rv = AcpiLoadTables(); | 276 | rv = AcpiLoadTables(); | |
277 | 277 | |||
278 | if (ACPI_FAILURE(rv)) { | 278 | if (ACPI_FAILURE(rv)) { | |
279 | aprint_error("%s: failed to load tables\n", __func__); | 279 | aprint_error("%s: failed to load tables\n", __func__); | |
280 | goto fail; | 280 | goto fail; | |
281 | } | 281 | } | |
282 | 282 | |||
283 | rsdt = acpi_map_rsdt(); | 283 | rsdt = acpi_map_rsdt(); | |
284 | 284 | |||
285 | if (rsdt == NULL) { | 285 | if (rsdt == NULL) { | |
286 | aprint_error("%s: failed to map RSDT\n", __func__); | 286 | aprint_error("%s: failed to map RSDT\n", __func__); | |
287 | goto fail; | 287 | goto fail; | |
288 | } | 288 | } | |
289 | 289 | |||
290 | quirks = acpi_find_quirks(); | 290 | quirks = acpi_find_quirks(); | |
291 | 291 | |||
292 | if (acpi_force_load == 0 && (quirks & ACPI_QUIRK_BROKEN) != 0) { | 292 | if (acpi_force_load == 0 && (quirks & ACPI_QUIRK_BROKEN) != 0) { | |
293 | 293 | |||
294 | aprint_normal("ACPI: BIOS is listed as broken:\n"); | 294 | aprint_normal("ACPI: BIOS is listed as broken:\n"); | |
295 | aprint_normal("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, " | 295 | aprint_normal("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, " | |
296 | "AslId <%4.4s,%08x>\n", rsdt->OemId, rsdt->OemTableId, | 296 | "AslId <%4.4s,%08x>\n", rsdt->OemId, rsdt->OemTableId, | |
297 | rsdt->OemRevision, rsdt->AslCompilerId, | 297 | rsdt->OemRevision, rsdt->AslCompilerId, | |
298 | rsdt->AslCompilerRevision); | 298 | rsdt->AslCompilerRevision); | |
299 | aprint_normal("ACPI: Not used. Set acpi_force_load to use.\n"); | 299 | aprint_normal("ACPI: Not used. Set acpi_force_load to use.\n"); | |
300 | 300 | |||
301 | acpi_unmap_rsdt(rsdt); | 301 | acpi_unmap_rsdt(rsdt); | |
302 | goto fail; | 302 | goto fail; | |
303 | } | 303 | } | |
304 | 304 | |||
305 | if (acpi_force_load == 0 && (quirks & ACPI_QUIRK_OLDBIOS) != 0) { | 305 | if (acpi_force_load == 0 && (quirks & ACPI_QUIRK_OLDBIOS) != 0) { | |
306 | 306 | |||
307 | aprint_normal("ACPI: BIOS is too old (%s). " | 307 | aprint_normal("ACPI: BIOS is too old (%s). " | |
308 | "Set acpi_force_load to use.\n", | 308 | "Set acpi_force_load to use.\n", | |
309 | pmf_get_platform("firmware-date")); | 309 | pmf_get_platform("bios-date")); | |
310 | 310 | |||
311 | acpi_unmap_rsdt(rsdt); | 311 | acpi_unmap_rsdt(rsdt); | |
312 | goto fail; | 312 | goto fail; | |
313 | } | 313 | } | |
314 | 314 | |||
315 | acpi_unmap_rsdt(rsdt); | 315 | acpi_unmap_rsdt(rsdt); | |
316 | 316 | |||
317 | rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE)); | 317 | rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE)); | |
318 | 318 | |||
319 | if (ACPI_FAILURE(rv)) { | 319 | if (ACPI_FAILURE(rv)) { | |
320 | aprint_error("%s: failed to enable subsystem\n", __func__); | 320 | aprint_error("%s: failed to enable subsystem\n", __func__); | |
321 | goto fail; | 321 | goto fail; | |
322 | } | 322 | } | |
323 | 323 | |||
324 | return 1; | 324 | return 1; | |
325 | 325 | |||
326 | fail: | 326 | fail: | |
327 | (void)AcpiTerminate(); | 327 | (void)AcpiTerminate(); | |
328 | 328 | |||
329 | return 0; | 329 | return 0; | |
330 | } | 330 | } | |
331 | 331 | |||
332 | void | 332 | void | |
333 | acpi_disable(void) | 333 | acpi_disable(void) | |
334 | { | 334 | { | |
335 | 335 | |||
336 | if (acpi_softc == NULL) | 336 | if (acpi_softc == NULL) | |
337 | return; | 337 | return; | |
338 | 338 | |||
339 | KASSERT(acpi_active != 0); | 339 | KASSERT(acpi_active != 0); | |
340 | 340 | |||
341 | if (AcpiGbl_FADT.SmiCommand != 0) | 341 | if (AcpiGbl_FADT.SmiCommand != 0) | |
342 | AcpiDisable(); | 342 | AcpiDisable(); | |
343 | } | 343 | } | |
344 | 344 | |||
345 | int | 345 | int | |
346 | acpi_check(device_t parent, const char *ifattr) | 346 | acpi_check(device_t parent, const char *ifattr) | |
347 | { | 347 | { | |
348 | return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL); | 348 | return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL); | |
349 | } | 349 | } | |
350 | 350 | |||
351 | int | 351 | int | |
352 | acpi_reset(void) | 352 | acpi_reset(void) | |
353 | { | 353 | { | |
354 | struct acpi_softc *sc = acpi_softc; | 354 | struct acpi_softc *sc = acpi_softc; | |
355 | ACPI_GENERIC_ADDRESS *ResetReg; | 355 | ACPI_GENERIC_ADDRESS *ResetReg; | |
356 | ACPI_PCI_ID PciId; | 356 | ACPI_PCI_ID PciId; | |
357 | ACPI_STATUS status; | 357 | ACPI_STATUS status; | |
358 | 358 | |||
359 | if (sc == NULL) | 359 | if (sc == NULL) | |
360 | return ENXIO; | 360 | return ENXIO; | |
361 | 361 | |||
362 | ResetReg = &AcpiGbl_FADT.ResetRegister; | 362 | ResetReg = &AcpiGbl_FADT.ResetRegister; | |
363 | 363 | |||
364 | /* Check if the reset register is supported */ | 364 | /* Check if the reset register is supported */ | |
365 | if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) || | 365 | if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) || | |
366 | !ResetReg->Address) { | 366 | !ResetReg->Address) { | |
367 | return ENOENT; | 367 | return ENOENT; | |
368 | } | 368 | } | |
369 | 369 | |||
370 | switch (ResetReg->SpaceId) { | 370 | switch (ResetReg->SpaceId) { | |
371 | case ACPI_ADR_SPACE_PCI_CONFIG: | 371 | case ACPI_ADR_SPACE_PCI_CONFIG: | |
372 | PciId.Segment = PciId.Bus = 0; | 372 | PciId.Segment = PciId.Bus = 0; | |
373 | PciId.Device = ACPI_GAS_PCI_DEV(ResetReg->Address); | 373 | PciId.Device = ACPI_GAS_PCI_DEV(ResetReg->Address); | |
374 | PciId.Function = ACPI_GAS_PCI_FUNC(ResetReg->Address); | 374 | PciId.Function = ACPI_GAS_PCI_FUNC(ResetReg->Address); | |
375 | status = AcpiOsWritePciConfiguration(&PciId, | 375 | status = AcpiOsWritePciConfiguration(&PciId, | |
376 | ACPI_GAS_PCI_REGOFF(ResetReg->Address), | 376 | ACPI_GAS_PCI_REGOFF(ResetReg->Address), | |
377 | AcpiGbl_FADT.ResetValue, ResetReg->BitWidth); | 377 | AcpiGbl_FADT.ResetValue, ResetReg->BitWidth); | |
378 | break; | 378 | break; | |
379 | case ACPI_ADR_SPACE_SYSTEM_IO: | 379 | case ACPI_ADR_SPACE_SYSTEM_IO: | |
380 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 380 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | |
381 | status = AcpiReset(); | 381 | status = AcpiReset(); | |
382 | break; | 382 | break; | |
383 | default: | 383 | default: | |
384 | status = AE_TYPE; | 384 | status = AE_TYPE; | |
385 | break; | 385 | break; | |
386 | } | 386 | } | |
387 | 387 | |||
388 | return ACPI_FAILURE(status) ? EIO : 0; | 388 | return ACPI_FAILURE(status) ? EIO : 0; | |
389 | } | 389 | } | |
390 | 390 | |||
391 | /* | 391 | /* | |
392 | * Autoconfiguration. | 392 | * Autoconfiguration. | |
393 | */ | 393 | */ | |
394 | static int | 394 | static int | |
395 | acpi_match(device_t parent, cfdata_t match, void *aux) | 395 | acpi_match(device_t parent, cfdata_t match, void *aux) | |
396 | { | 396 | { | |
397 | /* | 397 | /* | |
398 | * XXX: Nada; MD code has called acpi_probe(). | 398 | * XXX: Nada; MD code has called acpi_probe(). | |
399 | */ | 399 | */ | |
400 | return 1; | 400 | return 1; | |
401 | } | 401 | } | |
402 | 402 | |||
403 | static int | 403 | static int | |
404 | acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux) | 404 | acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux) | |
405 | { | 405 | { | |
406 | struct cfattach *ca; | 406 | struct cfattach *ca; | |
407 | 407 | |||
408 | ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname); | 408 | ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname); | |
409 | 409 | |||
410 | return (ca == &acpi_ca); | 410 | return (ca == &acpi_ca); | |
411 | } | 411 | } | |
412 | 412 | |||
413 | static void | 413 | static void | |
414 | acpi_attach(device_t parent, device_t self, void *aux) | 414 | acpi_attach(device_t parent, device_t self, void *aux) | |
415 | { | 415 | { | |
416 | struct acpi_softc *sc = device_private(self); | 416 | struct acpi_softc *sc = device_private(self); | |
417 | struct acpibus_attach_args *aa = aux; | 417 | struct acpibus_attach_args *aa = aux; | |
418 | ACPI_TABLE_HEADER *rsdt; | 418 | ACPI_TABLE_HEADER *rsdt; | |
419 | ACPI_STATUS rv; | 419 | ACPI_STATUS rv; | |
420 | 420 | |||
421 | aprint_naive("\n"); | 421 | aprint_naive("\n"); | |
422 | aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION); | 422 | aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION); | |
423 | 423 | |||
424 | if (acpi_softc != NULL) | 424 | if (acpi_softc != NULL) | |
425 | panic("%s: already attached", __func__); | 425 | panic("%s: already attached", __func__); | |
426 | 426 | |||
427 | rsdt = acpi_map_rsdt(); | 427 | rsdt = acpi_map_rsdt(); | |
428 | 428 | |||
429 | if (rsdt == NULL) | 429 | if (rsdt == NULL) | |
430 | aprint_error_dev(self, "X/RSDT: Not found\n"); | 430 | aprint_error_dev(self, "X/RSDT: Not found\n"); | |
431 | else { | 431 | else { | |
432 | aprint_verbose_dev(self, | 432 | aprint_verbose_dev(self, | |
433 | "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n", | 433 | "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n", | |
434 | rsdt->OemId, rsdt->OemTableId, | 434 | rsdt->OemId, rsdt->OemTableId, | |
435 | rsdt->OemRevision, | 435 | rsdt->OemRevision, | |
436 | rsdt->AslCompilerId, rsdt->AslCompilerRevision); | 436 | rsdt->AslCompilerId, rsdt->AslCompilerRevision); | |
437 | } | 437 | } | |
438 | 438 | |||
439 | acpi_unmap_rsdt(rsdt); | 439 | acpi_unmap_rsdt(rsdt); | |
440 | 440 | |||
441 | sc->sc_dev = self; | 441 | sc->sc_dev = self; | |
442 | sc->sc_root = NULL; | 442 | sc->sc_root = NULL; | |
443 | 443 | |||
444 | sc->sc_sleepstate = ACPI_STATE_S0; | 444 | sc->sc_sleepstate = ACPI_STATE_S0; | |
445 | sc->sc_quirks = acpi_find_quirks(); | 445 | sc->sc_quirks = acpi_find_quirks(); | |
446 | 446 | |||
447 | sysmon_power_settype("acpi"); | 447 | sysmon_power_settype("acpi"); | |
448 | 448 | |||
449 | sc->sc_iot = aa->aa_iot; | 449 | sc->sc_iot = aa->aa_iot; | |
450 | sc->sc_memt = aa->aa_memt; | 450 | sc->sc_memt = aa->aa_memt; | |
451 | sc->sc_pc = aa->aa_pc; | 451 | sc->sc_pc = aa->aa_pc; | |
452 | sc->sc_pciflags = aa->aa_pciflags; | 452 | sc->sc_pciflags = aa->aa_pciflags; | |
453 | sc->sc_ic = aa->aa_ic; | 453 | sc->sc_ic = aa->aa_ic; | |
454 | 454 | |||
455 | SIMPLEQ_INIT(&sc->ad_head); | 455 | SIMPLEQ_INIT(&sc->ad_head); | |
456 | 456 | |||
457 | acpi_softc = sc; | 457 | acpi_softc = sc; | |
458 | 458 | |||
459 | if (pmf_device_register(self, acpi_suspend, acpi_resume) != true) | 459 | if (pmf_device_register(self, acpi_suspend, acpi_resume) != true) | |
460 | aprint_error_dev(self, "couldn't establish power handler\n"); | 460 | aprint_error_dev(self, "couldn't establish power handler\n"); | |
461 | 461 | |||
462 | /* | 462 | /* | |
463 | * Bring ACPICA on-line. | 463 | * Bring ACPICA on-line. | |
464 | */ | 464 | */ | |
465 | #define ACPI_ENABLE_PHASE1 \ | 465 | #define ACPI_ENABLE_PHASE1 \ | |
466 | (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT) | 466 | (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT) | |
467 | #define ACPI_ENABLE_PHASE2 \ | 467 | #define ACPI_ENABLE_PHASE2 \ | |
468 | (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \ | 468 | (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \ | |
469 | ACPI_NO_ADDRESS_SPACE_INIT) | 469 | ACPI_NO_ADDRESS_SPACE_INIT) | |
470 | 470 | |||
471 | rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1); | 471 | rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1); | |
472 | 472 | |||
473 | if (ACPI_FAILURE(rv)) | 473 | if (ACPI_FAILURE(rv)) | |
474 | goto fail; | 474 | goto fail; | |
475 | 475 | |||
476 | acpi_md_callback(); | 476 | acpi_md_callback(); | |
477 | 477 | |||
478 | rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2); | 478 | rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2); | |
479 | 479 | |||
480 | if (ACPI_FAILURE(rv)) | 480 | if (ACPI_FAILURE(rv)) | |
481 | goto fail; | 481 | goto fail; | |
482 | 482 | |||
483 | /* | 483 | /* | |
484 | * Early initialization of acpiec(4) via ECDT. | 484 | * Early initialization of acpiec(4) via ECDT. | |
485 | */ | 485 | */ | |
486 | (void)config_found_ia(self, "acpiecdtbus", aa, NULL); | 486 | (void)config_found_ia(self, "acpiecdtbus", aa, NULL); | |
487 | 487 | |||
488 | rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); | 488 | rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); | |
489 | 489 | |||
490 | if (ACPI_FAILURE(rv)) | 490 | if (ACPI_FAILURE(rv)) | |
491 | goto fail; | 491 | goto fail; | |
492 | 492 | |||
493 | /* | 493 | /* | |
494 | * Early initialization of the _PDC control method | 494 | * Early initialization of the _PDC control method | |
495 | * that may load additional SSDT tables dynamically. | 495 | * that may load additional SSDT tables dynamically. | |
496 | */ | 496 | */ | |
497 | (void)acpi_md_pdc(); | 497 | (void)acpi_md_pdc(); | |
498 | 498 | |||
499 | /* | 499 | /* | |
500 | * Install global notify handlers. | 500 | * Install global notify handlers. | |
501 | */ | 501 | */ | |
502 | rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, | 502 | rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, | |
503 | ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL); | 503 | ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL); | |
504 | 504 | |||
505 | if (ACPI_FAILURE(rv)) | 505 | if (ACPI_FAILURE(rv)) | |
506 | goto fail; | 506 | goto fail; | |
507 | 507 | |||
508 | rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, | 508 | rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, | |
509 | ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL); | 509 | ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL); | |
510 | 510 | |||
511 | if (ACPI_FAILURE(rv)) | 511 | if (ACPI_FAILURE(rv)) | |
512 | goto fail; | 512 | goto fail; | |
513 | 513 | |||
514 | acpi_active = 1; | 514 | acpi_active = 1; | |
515 | 515 | |||
516 | /* Show SCI interrupt. */ | 516 | /* Show SCI interrupt. */ | |
517 | aprint_verbose_dev(self, "SCI interrupting at int %u\n", | 517 | aprint_verbose_dev(self, "SCI interrupting at int %u\n", | |
518 | AcpiGbl_FADT.SciInterrupt); | 518 | AcpiGbl_FADT.SciInterrupt); | |
519 | 519 | |||
520 | /* | 520 | /* | |
521 | * Install fixed-event handlers. | 521 | * Install fixed-event handlers. | |
522 | */ | 522 | */ | |
523 | acpi_register_fixed_button(sc, ACPI_EVENT_POWER_BUTTON); | 523 | acpi_register_fixed_button(sc, ACPI_EVENT_POWER_BUTTON); | |
524 | acpi_register_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON); | 524 | acpi_register_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON); | |
525 | 525 | |||
526 | acpitimer_init(sc); | 526 | acpitimer_init(sc); | |
527 | 527 | |||
528 | /* | 528 | /* | |
529 | * Scan the namespace and build our device tree. | 529 | * Scan the namespace and build our device tree. | |
530 | */ | 530 | */ | |
531 | acpi_build_tree(sc); | 531 | acpi_build_tree(sc); | |
532 | acpi_sleep_init(sc); | 532 | acpi_sleep_init(sc); | |
533 | 533 | |||
534 | #ifdef ACPI_DEBUG | 534 | #ifdef ACPI_DEBUG | |
535 | acpi_debug_init(); | 535 | acpi_debug_init(); | |
536 | #endif | 536 | #endif | |
537 | 537 | |||
538 | /* | 538 | /* | |
539 | * Print debug information. | 539 | * Print debug information. | |
540 | */ | 540 | */ | |
541 | acpi_print_verbose(sc); | 541 | acpi_print_verbose(sc); | |
542 | 542 | |||
543 | return; | 543 | return; | |
544 | 544 | |||
545 | fail: | 545 | fail: | |
546 | aprint_error("%s: failed to initialize ACPI: %s\n", | 546 | aprint_error("%s: failed to initialize ACPI: %s\n", | |
547 | __func__, AcpiFormatException(rv)); | 547 | __func__, AcpiFormatException(rv)); | |
548 | } | 548 | } | |
549 | 549 | |||
550 | /* | 550 | /* | |
551 | * XXX: This is incomplete. | 551 | * XXX: This is incomplete. | |
552 | */ | 552 | */ | |
553 | static int | 553 | static int | |
554 | acpi_detach(device_t self, int flags) | 554 | acpi_detach(device_t self, int flags) | |
555 | { | 555 | { | |
556 | struct acpi_softc *sc = device_private(self); | 556 | struct acpi_softc *sc = device_private(self); | |
557 | ACPI_STATUS rv; | 557 | ACPI_STATUS rv; | |
558 | int rc; | 558 | int rc; | |
559 | 559 | |||
560 | rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT, | 560 | rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT, | |
561 | ACPI_SYSTEM_NOTIFY, acpi_notify_handler); | 561 | ACPI_SYSTEM_NOTIFY, acpi_notify_handler); | |
562 | 562 | |||
563 | if (ACPI_FAILURE(rv)) | 563 | if (ACPI_FAILURE(rv)) | |
564 | return EBUSY; | 564 | return EBUSY; | |
565 | 565 | |||
566 | rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT, | 566 | rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT, | |
567 | ACPI_DEVICE_NOTIFY, acpi_notify_handler); | 567 | ACPI_DEVICE_NOTIFY, acpi_notify_handler); | |
568 | 568 | |||
569 | if (ACPI_FAILURE(rv)) | 569 | if (ACPI_FAILURE(rv)) | |
570 | return EBUSY; | 570 | return EBUSY; | |
571 | 571 | |||
572 | if ((rc = config_detach_children(self, flags)) != 0) | 572 | if ((rc = config_detach_children(self, flags)) != 0) | |
573 | return rc; | 573 | return rc; | |
574 | 574 | |||
575 | if ((rc = acpitimer_detach()) != 0) | 575 | if ((rc = acpitimer_detach()) != 0) | |
576 | return rc; | 576 | return rc; | |
577 | 577 | |||
578 | acpi_deregister_fixed_button(sc, ACPI_EVENT_POWER_BUTTON); | 578 | acpi_deregister_fixed_button(sc, ACPI_EVENT_POWER_BUTTON); | |
579 | acpi_deregister_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON); | 579 | acpi_deregister_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON); | |
580 | 580 | |||
581 | pmf_device_deregister(self); | 581 | pmf_device_deregister(self); | |
582 | 582 | |||
583 | acpi_softc = NULL; | 583 | acpi_softc = NULL; | |
584 | 584 | |||
585 | return 0; | 585 | return 0; | |
586 | } | 586 | } | |
587 | 587 | |||
588 | static void | 588 | static void | |
589 | acpi_childdet(device_t self, device_t child) | 589 | acpi_childdet(device_t self, device_t child) | |
590 | { | 590 | { | |
591 | struct acpi_softc *sc = device_private(self); | 591 | struct acpi_softc *sc = device_private(self); | |
592 | struct acpi_devnode *ad; | 592 | struct acpi_devnode *ad; | |
593 | 593 | |||
594 | if (sc->sc_apmbus == child) | 594 | if (sc->sc_apmbus == child) | |
595 | sc->sc_apmbus = NULL; | 595 | sc->sc_apmbus = NULL; | |
596 | 596 | |||
597 | if (sc->sc_hpet == child) | 597 | if (sc->sc_hpet == child) | |
598 | sc->sc_hpet = NULL; | 598 | sc->sc_hpet = NULL; | |
599 | 599 | |||
600 | if (sc->sc_wdrt == child) | 600 | if (sc->sc_wdrt == child) | |
601 | sc->sc_wdrt = NULL; | 601 | sc->sc_wdrt = NULL; | |
602 | 602 | |||
603 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | 603 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | |
604 | 604 | |||
605 | if (ad->ad_device == child) | 605 | if (ad->ad_device == child) | |
606 | ad->ad_device = NULL; | 606 | ad->ad_device = NULL; | |
607 | } | 607 | } | |
608 | } | 608 | } | |
609 | 609 | |||
610 | static bool | 610 | static bool | |
611 | acpi_suspend(device_t dv, const pmf_qual_t *qual) | 611 | acpi_suspend(device_t dv, const pmf_qual_t *qual) | |
612 | { | 612 | { | |
613 | 613 | |||
614 | acpi_suspended = 1; | 614 | acpi_suspended = 1; | |
615 | 615 | |||
616 | return true; | 616 | return true; | |
617 | } | 617 | } | |
618 | 618 | |||
619 | static bool | 619 | static bool | |
620 | acpi_resume(device_t dv, const pmf_qual_t *qual) | 620 | acpi_resume(device_t dv, const pmf_qual_t *qual) | |
621 | { | 621 | { | |
622 | 622 | |||
623 | acpi_suspended = 0; | 623 | acpi_suspended = 0; | |
624 | 624 | |||
625 | return true; | 625 | return true; | |
626 | } | 626 | } | |
627 | 627 | |||
628 | /* | 628 | /* | |
629 | * Namespace scan. | 629 | * Namespace scan. | |
630 | */ | 630 | */ | |
631 | static void | 631 | static void | |
632 | acpi_build_tree(struct acpi_softc *sc) | 632 | acpi_build_tree(struct acpi_softc *sc) | |
633 | { | 633 | { | |
634 | struct acpi_walkcontext awc; | 634 | struct acpi_walkcontext awc; | |
635 | 635 | |||
636 | /* | 636 | /* | |
637 | * Get the root scope handles. | 637 | * Get the root scope handles. | |
638 | */ | 638 | */ | |
639 | KASSERT(__arraycount(acpi_scopes) == 4); | 639 | KASSERT(__arraycount(acpi_scopes) == 4); | |
640 | 640 | |||
641 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_PR_", &acpi_scopes[0]); | 641 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_PR_", &acpi_scopes[0]); | |
642 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &acpi_scopes[1]); | 642 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &acpi_scopes[1]); | |
643 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SI_", &acpi_scopes[2]); | 643 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SI_", &acpi_scopes[2]); | |
644 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_TZ_", &acpi_scopes[3]); | 644 | (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_TZ_", &acpi_scopes[3]); | |
645 | 645 | |||
646 | /* | 646 | /* | |
647 | * Make the root node. | 647 | * Make the root node. | |
648 | */ | 648 | */ | |
649 | awc.aw_sc = sc; | 649 | awc.aw_sc = sc; | |
650 | awc.aw_parent = NULL; | 650 | awc.aw_parent = NULL; | |
651 | 651 | |||
652 | (void)acpi_make_devnode(ACPI_ROOT_OBJECT, 0, &awc, NULL); | 652 | (void)acpi_make_devnode(ACPI_ROOT_OBJECT, 0, &awc, NULL); | |
653 | 653 | |||
654 | KASSERT(sc->sc_root == NULL); | 654 | KASSERT(sc->sc_root == NULL); | |
655 | KASSERT(awc.aw_parent != NULL); | 655 | KASSERT(awc.aw_parent != NULL); | |
656 | 656 | |||
657 | sc->sc_root = awc.aw_parent; | 657 | sc->sc_root = awc.aw_parent; | |
658 | 658 | |||
659 | /* | 659 | /* | |
660 | * Build the internal namespace. | 660 | * Build the internal namespace. | |
661 | */ | 661 | */ | |
662 | (void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, UINT32_MAX, | 662 | (void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, UINT32_MAX, | |
663 | acpi_make_devnode, acpi_make_devnode_post, &awc, NULL); | 663 | acpi_make_devnode, acpi_make_devnode_post, &awc, NULL); | |
664 | 664 | |||
665 | /* | 665 | /* | |
666 | * Scan the internal namespace. | 666 | * Scan the internal namespace. | |
667 | */ | 667 | */ | |
668 | (void)acpi_pcidev_scan(sc->sc_root); | 668 | (void)acpi_pcidev_scan(sc->sc_root); | |
669 | (void)acpi_rescan(sc->sc_dev, NULL, NULL); | 669 | (void)acpi_rescan(sc->sc_dev, NULL, NULL); | |
670 | 670 | |||
671 | /* | 671 | /* | |
672 | * Update GPE information. | 672 | * Update GPE information. | |
673 | * | 673 | * | |
674 | * Note that this must be called after | 674 | * Note that this must be called after | |
675 | * all GPE handlers have been installed. | 675 | * all GPE handlers have been installed. | |
676 | */ | 676 | */ | |
677 | (void)AcpiUpdateAllGpes(); | 677 | (void)AcpiUpdateAllGpes(); | |
678 | 678 | |||
679 | /* | 679 | /* | |
680 | * Defer rest of the configuration. | 680 | * Defer rest of the configuration. | |
681 | */ | 681 | */ | |
682 | (void)config_defer(sc->sc_dev, acpi_rescan_capabilities); | 682 | (void)config_defer(sc->sc_dev, acpi_rescan_capabilities); | |
683 | } | 683 | } | |
684 | 684 | |||
685 | static ACPI_STATUS | 685 | static ACPI_STATUS | |
686 | acpi_make_devnode(ACPI_HANDLE handle, uint32_t level, | 686 | acpi_make_devnode(ACPI_HANDLE handle, uint32_t level, | |
687 | void *context, void **status) | 687 | void *context, void **status) | |
688 | { | 688 | { | |
689 | struct acpi_walkcontext *awc = context; | 689 | struct acpi_walkcontext *awc = context; | |
690 | struct acpi_softc *sc = awc->aw_sc; | 690 | struct acpi_softc *sc = awc->aw_sc; | |
691 | struct acpi_devnode *ad; | 691 | struct acpi_devnode *ad; | |
692 | ACPI_DEVICE_INFO *devinfo; | 692 | ACPI_DEVICE_INFO *devinfo; | |
693 | ACPI_OBJECT_TYPE type; | 693 | ACPI_OBJECT_TYPE type; | |
694 | ACPI_STATUS rv; | 694 | ACPI_STATUS rv; | |
695 | 695 | |||
696 | rv = AcpiGetObjectInfo(handle, &devinfo); | 696 | rv = AcpiGetObjectInfo(handle, &devinfo); | |
697 | 697 | |||
698 | if (ACPI_FAILURE(rv)) | 698 | if (ACPI_FAILURE(rv)) | |
699 | return AE_OK; /* Do not terminate the walk. */ | 699 | return AE_OK; /* Do not terminate the walk. */ | |
700 | 700 | |||
701 | type = devinfo->Type; | 701 | type = devinfo->Type; | |
702 | 702 | |||
703 | switch (type) { | 703 | switch (type) { | |
704 | 704 | |||
705 | case ACPI_TYPE_DEVICE: | 705 | case ACPI_TYPE_DEVICE: | |
706 | acpi_activate_device(handle, &devinfo); | 706 | acpi_activate_device(handle, &devinfo); | |
707 | case ACPI_TYPE_PROCESSOR: | 707 | case ACPI_TYPE_PROCESSOR: | |
708 | case ACPI_TYPE_THERMAL: | 708 | case ACPI_TYPE_THERMAL: | |
709 | case ACPI_TYPE_POWER: | 709 | case ACPI_TYPE_POWER: | |
710 | 710 | |||
711 | ad = kmem_zalloc(sizeof(*ad), KM_NOSLEEP); | 711 | ad = kmem_zalloc(sizeof(*ad), KM_NOSLEEP); | |
712 | 712 | |||
713 | if (ad == NULL) | 713 | if (ad == NULL) | |
714 | return AE_NO_MEMORY; | 714 | return AE_NO_MEMORY; | |
715 | 715 | |||
716 | ad->ad_device = NULL; | 716 | ad->ad_device = NULL; | |
717 | ad->ad_notify = NULL; | 717 | ad->ad_notify = NULL; | |
718 | ad->ad_pciinfo = NULL; | 718 | ad->ad_pciinfo = NULL; | |
719 | ad->ad_wakedev = NULL; | 719 | ad->ad_wakedev = NULL; | |
720 | 720 | |||
721 | ad->ad_type = type; | 721 | ad->ad_type = type; | |
722 | ad->ad_handle = handle; | 722 | ad->ad_handle = handle; | |
723 | ad->ad_devinfo = devinfo; | 723 | ad->ad_devinfo = devinfo; | |
724 | 724 | |||
725 | ad->ad_root = sc->sc_dev; | 725 | ad->ad_root = sc->sc_dev; | |
726 | ad->ad_parent = awc->aw_parent; | 726 | ad->ad_parent = awc->aw_parent; | |
727 | 727 | |||
728 | acpi_match_node_init(ad); | 728 | acpi_match_node_init(ad); | |
729 | acpi_make_name(ad, devinfo->Name); | 729 | acpi_make_name(ad, devinfo->Name); | |
730 | 730 | |||
731 | /* | 731 | /* | |
732 | * Identify wake GPEs from the _PRW. Note that | 732 | * Identify wake GPEs from the _PRW. Note that | |
733 | * AcpiUpdateAllGpes() must be called afterwards. | 733 | * AcpiUpdateAllGpes() must be called afterwards. | |
734 | */ | 734 | */ | |
735 | if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) | 735 | if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) | |
736 | acpi_wakedev_init(ad); | 736 | acpi_wakedev_init(ad); | |
737 | 737 | |||
738 | SIMPLEQ_INIT(&ad->ad_child_head); | 738 | SIMPLEQ_INIT(&ad->ad_child_head); | |
739 | SIMPLEQ_INSERT_TAIL(&sc->ad_head, ad, ad_list); | 739 | SIMPLEQ_INSERT_TAIL(&sc->ad_head, ad, ad_list); | |
740 | 740 | |||
741 | if (ad->ad_parent != NULL) { | 741 | if (ad->ad_parent != NULL) { | |
742 | 742 | |||
743 | SIMPLEQ_INSERT_TAIL(&ad->ad_parent->ad_child_head, | 743 | SIMPLEQ_INSERT_TAIL(&ad->ad_parent->ad_child_head, | |
744 | ad, ad_child_list); | 744 | ad, ad_child_list); | |
745 | } | 745 | } | |
746 | 746 | |||
747 | awc->aw_parent = ad; | 747 | awc->aw_parent = ad; | |
748 | } | 748 | } | |
749 | 749 | |||
750 | return AE_OK; | 750 | return AE_OK; | |
751 | } | 751 | } | |
752 | 752 | |||
753 | static ACPI_STATUS | 753 | static ACPI_STATUS | |
754 | acpi_make_devnode_post(ACPI_HANDLE handle, uint32_t level, | 754 | acpi_make_devnode_post(ACPI_HANDLE handle, uint32_t level, | |
755 | void *context, void **status) | 755 | void *context, void **status) | |
756 | { | 756 | { | |
757 | struct acpi_walkcontext *awc = context; | 757 | struct acpi_walkcontext *awc = context; | |
758 | 758 | |||
759 | KASSERT(awc != NULL); | 759 | KASSERT(awc != NULL); | |
760 | KASSERT(awc->aw_parent != NULL); | 760 | KASSERT(awc->aw_parent != NULL); | |
761 | 761 | |||
762 | if (handle == awc->aw_parent->ad_handle) | 762 | if (handle == awc->aw_parent->ad_handle) | |
763 | awc->aw_parent = awc->aw_parent->ad_parent; | 763 | awc->aw_parent = awc->aw_parent->ad_parent; | |
764 | 764 | |||
765 | return AE_OK; | 765 | return AE_OK; | |
766 | } | 766 | } | |
767 | 767 | |||
768 | static void | 768 | static void | |
769 | acpi_make_name(struct acpi_devnode *ad, uint32_t name) | 769 | acpi_make_name(struct acpi_devnode *ad, uint32_t name) | |
770 | { | 770 | { | |
771 | ACPI_NAME_UNION *anu; | 771 | ACPI_NAME_UNION *anu; | |
772 | int clear, i; | 772 | int clear, i; | |
773 | 773 | |||
774 | anu = (ACPI_NAME_UNION *)&name; | 774 | anu = (ACPI_NAME_UNION *)&name; | |
775 | ad->ad_name[4] = '\0'; | 775 | ad->ad_name[4] = '\0'; | |
776 | 776 | |||
777 | for (i = 3, clear = 0; i >= 0; i--) { | 777 | for (i = 3, clear = 0; i >= 0; i--) { | |
778 | 778 | |||
779 | if (clear == 0 && anu->Ascii[i] == '_') | 779 | if (clear == 0 && anu->Ascii[i] == '_') | |
780 | ad->ad_name[i] = '\0'; | 780 | ad->ad_name[i] = '\0'; | |
781 | else { | 781 | else { | |
782 | ad->ad_name[i] = anu->Ascii[i]; | 782 | ad->ad_name[i] = anu->Ascii[i]; | |
783 | clear = 1; | 783 | clear = 1; | |
784 | } | 784 | } | |
785 | } | 785 | } | |
786 | 786 | |||
787 | if (ad->ad_name[0] == '\0') | 787 | if (ad->ad_name[0] == '\0') | |
788 | ad->ad_name[0] = '_'; | 788 | ad->ad_name[0] = '_'; | |
789 | } | 789 | } | |
790 | 790 | |||
791 | /* | 791 | /* | |
792 | * Device attachment. | 792 | * Device attachment. | |
793 | */ | 793 | */ | |
794 | static int | 794 | static int | |
795 | acpi_rescan(device_t self, const char *ifattr, const int *locators) | 795 | acpi_rescan(device_t self, const char *ifattr, const int *locators) | |
796 | { | 796 | { | |
797 | struct acpi_softc *sc = device_private(self); | 797 | struct acpi_softc *sc = device_private(self); | |
798 | struct acpi_attach_args aa; | 798 | struct acpi_attach_args aa; | |
799 | 799 | |||
800 | /* | 800 | /* | |
801 | * Try to attach hpet(4) first via a specific table. | 801 | * Try to attach hpet(4) first via a specific table. | |
802 | */ | 802 | */ | |
803 | aa.aa_memt = sc->sc_memt; | 803 | aa.aa_memt = sc->sc_memt; | |
804 | 804 | |||
805 | if (ifattr_match(ifattr, "acpihpetbus") && sc->sc_hpet == NULL) | 805 | if (ifattr_match(ifattr, "acpihpetbus") && sc->sc_hpet == NULL) | |
806 | sc->sc_hpet = config_found_ia(sc->sc_dev, | 806 | sc->sc_hpet = config_found_ia(sc->sc_dev, | |
807 | "acpihpetbus", &aa, NULL); | 807 | "acpihpetbus", &aa, NULL); | |
808 | 808 | |||
809 | /* | 809 | /* | |
810 | * A two-pass scan for acpinodebus. | 810 | * A two-pass scan for acpinodebus. | |
811 | */ | 811 | */ | |
812 | if (ifattr_match(ifattr, "acpinodebus")) { | 812 | if (ifattr_match(ifattr, "acpinodebus")) { | |
813 | acpi_rescan_early(sc); | 813 | acpi_rescan_early(sc); | |
814 | acpi_rescan_nodes(sc); | 814 | acpi_rescan_nodes(sc); | |
815 | } | 815 | } | |
816 | 816 | |||
817 | /* | 817 | /* | |
818 | * Attach APM emulation and acpiwdrt(4). | 818 | * Attach APM emulation and acpiwdrt(4). | |
819 | */ | 819 | */ | |
820 | if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) | 820 | if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) | |
821 | sc->sc_apmbus = config_found_ia(sc->sc_dev, | 821 | sc->sc_apmbus = config_found_ia(sc->sc_dev, | |
822 | "acpiapmbus", NULL, NULL); | 822 | "acpiapmbus", NULL, NULL); | |
823 | 823 | |||
824 | if (ifattr_match(ifattr, "acpiwdrtbus") && sc->sc_wdrt == NULL) | 824 | if (ifattr_match(ifattr, "acpiwdrtbus") && sc->sc_wdrt == NULL) | |
825 | sc->sc_wdrt = config_found_ia(sc->sc_dev, | 825 | sc->sc_wdrt = config_found_ia(sc->sc_dev, | |
826 | "acpiwdrtbus", NULL, NULL); | 826 | "acpiwdrtbus", NULL, NULL); | |
827 | 827 | |||
828 | return 0; | 828 | return 0; | |
829 | } | 829 | } | |
830 | 830 | |||
831 | static void | 831 | static void | |
832 | acpi_rescan_early(struct acpi_softc *sc) | 832 | acpi_rescan_early(struct acpi_softc *sc) | |
833 | { | 833 | { | |
834 | struct acpi_attach_args aa; | 834 | struct acpi_attach_args aa; | |
835 | struct acpi_devnode *ad; | 835 | struct acpi_devnode *ad; | |
836 | 836 | |||
837 | /* | 837 | /* | |
838 | * First scan for devices such as acpiec(4) that | 838 | * First scan for devices such as acpiec(4) that | |
839 | * should be always attached before anything else. | 839 | * should be always attached before anything else. | |
840 | * We want these devices to attach regardless of | 840 | * We want these devices to attach regardless of | |
841 | * the device status and other restrictions. | 841 | * the device status and other restrictions. | |
842 | */ | 842 | */ | |
843 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | 843 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | |
844 | 844 | |||
845 | if (ad->ad_device != NULL) | 845 | if (ad->ad_device != NULL) | |
846 | continue; | 846 | continue; | |
847 | 847 | |||
848 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) | 848 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) | |
849 | continue; | 849 | continue; | |
850 | 850 | |||
851 | if (acpi_match_hid(ad->ad_devinfo, acpi_early_ids) == 0) | 851 | if (acpi_match_hid(ad->ad_devinfo, acpi_early_ids) == 0) | |
852 | continue; | 852 | continue; | |
853 | 853 | |||
854 | aa.aa_node = ad; | 854 | aa.aa_node = ad; | |
855 | aa.aa_iot = sc->sc_iot; | 855 | aa.aa_iot = sc->sc_iot; | |
856 | aa.aa_memt = sc->sc_memt; | 856 | aa.aa_memt = sc->sc_memt; | |
857 | aa.aa_pc = sc->sc_pc; | 857 | aa.aa_pc = sc->sc_pc; | |
858 | aa.aa_pciflags = sc->sc_pciflags; | 858 | aa.aa_pciflags = sc->sc_pciflags; | |
859 | aa.aa_ic = sc->sc_ic; | 859 | aa.aa_ic = sc->sc_ic; | |
860 | 860 | |||
861 | ad->ad_device = config_found_ia(sc->sc_dev, | 861 | ad->ad_device = config_found_ia(sc->sc_dev, | |
862 | "acpinodebus", &aa, acpi_print); | 862 | "acpinodebus", &aa, acpi_print); | |
863 | } | 863 | } | |
864 | } | 864 | } | |
865 | 865 | |||
866 | static void | 866 | static void | |
867 | acpi_rescan_nodes(struct acpi_softc *sc) | 867 | acpi_rescan_nodes(struct acpi_softc *sc) | |
868 | { | 868 | { | |
869 | const char * const hpet_ids[] = { "PNP0103", NULL }; | 869 | const char * const hpet_ids[] = { "PNP0103", NULL }; | |
870 | struct acpi_attach_args aa; | 870 | struct acpi_attach_args aa; | |
871 | struct acpi_devnode *ad; | 871 | struct acpi_devnode *ad; | |
872 | ACPI_DEVICE_INFO *di; | 872 | ACPI_DEVICE_INFO *di; | |
873 | 873 | |||
874 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | 874 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | |
875 | 875 | |||
876 | if (ad->ad_device != NULL) | 876 | if (ad->ad_device != NULL) | |
877 | continue; | 877 | continue; | |
878 | 878 | |||
879 | /* | 879 | /* | |
880 | * There is a bug in ACPICA: it defines the type | 880 | * There is a bug in ACPICA: it defines the type | |
881 | * of the scopes incorrectly for its own reasons. | 881 | * of the scopes incorrectly for its own reasons. | |
882 | */ | 882 | */ | |
883 | if (acpi_is_scope(ad) != false) | 883 | if (acpi_is_scope(ad) != false) | |
884 | continue; | 884 | continue; | |
885 | 885 | |||
886 | di = ad->ad_devinfo; | 886 | di = ad->ad_devinfo; | |
887 | 887 | |||
888 | /* | 888 | /* | |
889 | * We only attach devices which are present, enabled, and | 889 | * We only attach devices which are present, enabled, and | |
890 | * functioning properly. However, if a device is enabled, | 890 | * functioning properly. However, if a device is enabled, | |
891 | * it is decoding resources and we should claim these, | 891 | * it is decoding resources and we should claim these, | |
892 | * if possible. This requires changes to bus_space(9). | 892 | * if possible. This requires changes to bus_space(9). | |
893 | * Note: there is a possible race condition, because _STA | 893 | * Note: there is a possible race condition, because _STA | |
894 | * may have changed since di->CurrentStatus was set. | 894 | * may have changed since di->CurrentStatus was set. | |
895 | */ | 895 | */ | |
896 | if (di->Type == ACPI_TYPE_DEVICE) { | 896 | if (di->Type == ACPI_TYPE_DEVICE) { | |
897 | 897 | |||
898 | if ((di->Valid & ACPI_VALID_STA) != 0 && | 898 | if ((di->Valid & ACPI_VALID_STA) != 0 && | |
899 | (di->CurrentStatus & ACPI_STA_OK) != ACPI_STA_OK) | 899 | (di->CurrentStatus & ACPI_STA_OK) != ACPI_STA_OK) | |
900 | continue; | 900 | continue; | |
901 | } | 901 | } | |
902 | 902 | |||
903 | if (di->Type == ACPI_TYPE_POWER) | 903 | if (di->Type == ACPI_TYPE_POWER) | |
904 | continue; | 904 | continue; | |
905 | 905 | |||
906 | if (di->Type == ACPI_TYPE_PROCESSOR) | 906 | if (di->Type == ACPI_TYPE_PROCESSOR) | |
907 | continue; | 907 | continue; | |
908 | 908 | |||
909 | if (acpi_match_hid(di, acpi_early_ids) != 0) | 909 | if (acpi_match_hid(di, acpi_early_ids) != 0) | |
910 | continue; | 910 | continue; | |
911 | 911 | |||
912 | if (acpi_match_hid(di, acpi_ignored_ids) != 0) | 912 | if (acpi_match_hid(di, acpi_ignored_ids) != 0) | |
913 | continue; | 913 | continue; | |
914 | 914 | |||
915 | if (acpi_match_hid(di, hpet_ids) != 0 && sc->sc_hpet != NULL) | 915 | if (acpi_match_hid(di, hpet_ids) != 0 && sc->sc_hpet != NULL) | |
916 | continue; | 916 | continue; | |
917 | 917 | |||
918 | aa.aa_node = ad; | 918 | aa.aa_node = ad; | |
919 | aa.aa_iot = sc->sc_iot; | 919 | aa.aa_iot = sc->sc_iot; | |
920 | aa.aa_memt = sc->sc_memt; | 920 | aa.aa_memt = sc->sc_memt; | |
921 | aa.aa_pc = sc->sc_pc; | 921 | aa.aa_pc = sc->sc_pc; | |
922 | aa.aa_pciflags = sc->sc_pciflags; | 922 | aa.aa_pciflags = sc->sc_pciflags; | |
923 | aa.aa_ic = sc->sc_ic; | 923 | aa.aa_ic = sc->sc_ic; | |
924 | 924 | |||
925 | ad->ad_device = config_found_ia(sc->sc_dev, | 925 | ad->ad_device = config_found_ia(sc->sc_dev, | |
926 | "acpinodebus", &aa, acpi_print); | 926 | "acpinodebus", &aa, acpi_print); | |
927 | } | 927 | } | |
928 | } | 928 | } | |
929 | 929 | |||
930 | static void | 930 | static void | |
931 | acpi_rescan_capabilities(device_t self) | 931 | acpi_rescan_capabilities(device_t self) | |
932 | { | 932 | { | |
933 | struct acpi_softc *sc = device_private(self); | 933 | struct acpi_softc *sc = device_private(self); | |
934 | struct acpi_devnode *ad; | 934 | struct acpi_devnode *ad; | |
935 | ACPI_HANDLE tmp; | 935 | ACPI_HANDLE tmp; | |
936 | ACPI_STATUS rv; | 936 | ACPI_STATUS rv; | |
937 | 937 | |||
938 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | 938 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | |
939 | 939 | |||
940 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) | 940 | if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) | |
941 | continue; | 941 | continue; | |
942 | 942 | |||
943 | /* | 943 | /* | |
944 | * Scan power resource capabilities. | 944 | * Scan power resource capabilities. | |
945 | * | 945 | * | |
946 | * If any power states are supported, | 946 | * If any power states are supported, | |
947 | * at least _PR0 and _PR3 must be present. | 947 | * at least _PR0 and _PR3 must be present. | |
948 | */ | 948 | */ | |
949 | rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp); | 949 | rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp); | |
950 | 950 | |||
951 | if (ACPI_SUCCESS(rv)) { | 951 | if (ACPI_SUCCESS(rv)) { | |
952 | ad->ad_flags |= ACPI_DEVICE_POWER; | 952 | ad->ad_flags |= ACPI_DEVICE_POWER; | |
953 | acpi_power_add(ad); | 953 | acpi_power_add(ad); | |
954 | } | 954 | } | |
955 | 955 | |||
956 | /* | 956 | /* | |
957 | * Scan wake-up capabilities. | 957 | * Scan wake-up capabilities. | |
958 | */ | 958 | */ | |
959 | if (ad->ad_wakedev != NULL) { | 959 | if (ad->ad_wakedev != NULL) { | |
960 | ad->ad_flags |= ACPI_DEVICE_WAKEUP; | 960 | ad->ad_flags |= ACPI_DEVICE_WAKEUP; | |
961 | acpi_wakedev_add(ad); | 961 | acpi_wakedev_add(ad); | |
962 | } | 962 | } | |
963 | 963 | |||
964 | /* | 964 | /* | |
965 | * Scan docking stations. | 965 | * Scan docking stations. | |
966 | */ | 966 | */ | |
967 | rv = AcpiGetHandle(ad->ad_handle, "_DCK", &tmp); | 967 | rv = AcpiGetHandle(ad->ad_handle, "_DCK", &tmp); | |
968 | 968 | |||
969 | if (ACPI_SUCCESS(rv)) | 969 | if (ACPI_SUCCESS(rv)) | |
970 | ad->ad_flags |= ACPI_DEVICE_DOCK; | 970 | ad->ad_flags |= ACPI_DEVICE_DOCK; | |
971 | 971 | |||
972 | /* | 972 | /* | |
973 | * Scan devices that are ejectable. | 973 | * Scan devices that are ejectable. | |
974 | */ | 974 | */ | |
975 | rv = AcpiGetHandle(ad->ad_handle, "_EJ0", &tmp); | 975 | rv = AcpiGetHandle(ad->ad_handle, "_EJ0", &tmp); | |
976 | 976 | |||
977 | if (ACPI_SUCCESS(rv)) | 977 | if (ACPI_SUCCESS(rv)) | |
978 | ad->ad_flags |= ACPI_DEVICE_EJECT; | 978 | ad->ad_flags |= ACPI_DEVICE_EJECT; | |
979 | } | 979 | } | |
980 | } | 980 | } | |
981 | 981 | |||
982 | static int | 982 | static int | |
983 | acpi_print(void *aux, const char *pnp) | 983 | acpi_print(void *aux, const char *pnp) | |
984 | { | 984 | { | |
985 | struct acpi_attach_args *aa = aux; | 985 | struct acpi_attach_args *aa = aux; | |
986 | struct acpi_devnode *ad; | 986 | struct acpi_devnode *ad; | |
987 | const char *hid, *uid; | 987 | const char *hid, *uid; | |
988 | ACPI_DEVICE_INFO *di; | 988 | ACPI_DEVICE_INFO *di; | |
989 | 989 | |||
990 | ad = aa->aa_node; | 990 | ad = aa->aa_node; | |
991 | di = ad->ad_devinfo; | 991 | di = ad->ad_devinfo; | |
992 | 992 | |||
993 | hid = di->HardwareId.String; | 993 | hid = di->HardwareId.String; | |
994 | uid = di->UniqueId.String; | 994 | uid = di->UniqueId.String; | |
995 | 995 | |||
996 | if (pnp != NULL) { | 996 | if (pnp != NULL) { | |
997 | 997 | |||
998 | if (di->Type != ACPI_TYPE_DEVICE) { | 998 | if (di->Type != ACPI_TYPE_DEVICE) { | |
999 | 999 | |||
1000 | aprint_normal("%s (ACPI Object Type '%s') at %s", | 1000 | aprint_normal("%s (ACPI Object Type '%s') at %s", | |
1001 | ad->ad_name, AcpiUtGetTypeName(ad->ad_type), pnp); | 1001 | ad->ad_name, AcpiUtGetTypeName(ad->ad_type), pnp); | |
1002 | 1002 | |||
1003 | return UNCONF; | 1003 | return UNCONF; | |
1004 | } | 1004 | } | |
1005 | 1005 | |||
1006 | if ((di->Valid & ACPI_VALID_HID) == 0 || hid == NULL) | 1006 | if ((di->Valid & ACPI_VALID_HID) == 0 || hid == NULL) | |
1007 | return 0; | 1007 | return 0; | |
1008 | 1008 | |||
1009 | aprint_normal("%s (%s) ", ad->ad_name, hid); | 1009 | aprint_normal("%s (%s) ", ad->ad_name, hid); | |
1010 | acpi_print_dev(hid); | 1010 | acpi_print_dev(hid); | |
1011 | aprint_normal("at %s", pnp); | 1011 | aprint_normal("at %s", pnp); | |
1012 | 1012 | |||
1013 | return UNCONF; | 1013 | return UNCONF; | |
1014 | } | 1014 | } | |
1015 | 1015 | |||
1016 | aprint_normal(" (%s", ad->ad_name); | 1016 | aprint_normal(" (%s", ad->ad_name); | |
1017 | 1017 | |||
1018 | if ((di->Valid & ACPI_VALID_HID) != 0 && hid != NULL) { | 1018 | if ((di->Valid & ACPI_VALID_HID) != 0 && hid != NULL) { | |
1019 | 1019 | |||
1020 | aprint_normal(", %s", hid); | 1020 | aprint_normal(", %s", hid); | |
1021 | 1021 | |||
1022 | if ((di->Valid & ACPI_VALID_UID) != 0 && uid != NULL) { | 1022 | if ((di->Valid & ACPI_VALID_UID) != 0 && uid != NULL) { | |
1023 | 1023 | |||
1024 | if (uid[0] == '\0') | 1024 | if (uid[0] == '\0') | |
1025 | uid = "<null>"; | 1025 | uid = "<null>"; | |
1026 | 1026 | |||
1027 | aprint_normal("-%s", uid); | 1027 | aprint_normal("-%s", uid); | |
1028 | } | 1028 | } | |
1029 | } | 1029 | } | |
1030 | 1030 | |||
1031 | aprint_normal(")"); | 1031 | aprint_normal(")"); | |
1032 | 1032 | |||
1033 | return UNCONF; | 1033 | return UNCONF; | |
1034 | } | 1034 | } | |
1035 | 1035 | |||
1036 | /* | 1036 | /* | |
1037 | * Notify. | 1037 | * Notify. | |
1038 | */ | 1038 | */ | |
1039 | static void | 1039 | static void | |
1040 | acpi_notify_handler(ACPI_HANDLE handle, uint32_t event, void *aux) | 1040 | acpi_notify_handler(ACPI_HANDLE handle, uint32_t event, void *aux) | |
1041 | { | 1041 | { | |
1042 | struct acpi_softc *sc = acpi_softc; | 1042 | struct acpi_softc *sc = acpi_softc; | |
1043 | struct acpi_devnode *ad; | 1043 | struct acpi_devnode *ad; | |
1044 | 1044 | |||
1045 | KASSERT(sc != NULL); | 1045 | KASSERT(sc != NULL); | |
1046 | KASSERT(aux == NULL); | 1046 | KASSERT(aux == NULL); | |
1047 | KASSERT(acpi_active != 0); | 1047 | KASSERT(acpi_active != 0); | |
1048 | 1048 | |||
1049 | if (acpi_suspended != 0) | 1049 | if (acpi_suspended != 0) | |
1050 | return; | 1050 | return; | |
1051 | 1051 | |||
1052 | /* | 1052 | /* | |
1053 | * System: 0x00 - 0x7F. | 1053 | * System: 0x00 - 0x7F. | |
1054 | * Device: 0x80 - 0xFF. | 1054 | * Device: 0x80 - 0xFF. | |
1055 | */ | 1055 | */ | |
1056 | switch (event) { | 1056 | switch (event) { | |
1057 | 1057 | |||
1058 | case ACPI_NOTIFY_BUS_CHECK: | 1058 | case ACPI_NOTIFY_BUS_CHECK: | |
1059 | case ACPI_NOTIFY_DEVICE_CHECK: | 1059 | case ACPI_NOTIFY_DEVICE_CHECK: | |
1060 | case ACPI_NOTIFY_DEVICE_WAKE: | 1060 | case ACPI_NOTIFY_DEVICE_WAKE: | |
1061 | case ACPI_NOTIFY_EJECT_REQUEST: | 1061 | case ACPI_NOTIFY_EJECT_REQUEST: | |
1062 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: | 1062 | case ACPI_NOTIFY_DEVICE_CHECK_LIGHT: | |
1063 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 1063 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | |
1064 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 1064 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | |
1065 | case ACPI_NOTIFY_POWER_FAULT: | 1065 | case ACPI_NOTIFY_POWER_FAULT: | |
1066 | case ACPI_NOTIFY_CAPABILITIES_CHECK: | 1066 | case ACPI_NOTIFY_CAPABILITIES_CHECK: | |
1067 | case ACPI_NOTIFY_DEVICE_PLD_CHECK: | 1067 | case ACPI_NOTIFY_DEVICE_PLD_CHECK: | |
1068 | case ACPI_NOTIFY_RESERVED: | 1068 | case ACPI_NOTIFY_RESERVED: | |
1069 | case ACPI_NOTIFY_LOCALITY_UPDATE: | 1069 | case ACPI_NOTIFY_LOCALITY_UPDATE: | |
1070 | break; | 1070 | break; | |
1071 | } | 1071 | } | |
1072 | 1072 | |||
1073 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "notification 0x%02X for " | 1073 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "notification 0x%02X for " | |
1074 | "%s (%p)\n", event, acpi_name(handle), handle)); | 1074 | "%s (%p)\n", event, acpi_name(handle), handle)); | |
1075 | 1075 | |||
1076 | /* | 1076 | /* | |
1077 | * We deliver notifications only to drivers | 1077 | * We deliver notifications only to drivers | |
1078 | * that have been successfully attached and | 1078 | * that have been successfully attached and | |
1079 | * that have registered a handler with us. | 1079 | * that have registered a handler with us. | |
1080 | * The opaque pointer is always the device_t. | 1080 | * The opaque pointer is always the device_t. | |
1081 | */ | 1081 | */ | |
1082 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | 1082 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | |
1083 | 1083 | |||
1084 | if (ad->ad_device == NULL) | 1084 | if (ad->ad_device == NULL) | |
1085 | continue; | 1085 | continue; | |
1086 | 1086 | |||
1087 | if (ad->ad_notify == NULL) | 1087 | if (ad->ad_notify == NULL) | |
1088 | continue; | 1088 | continue; | |
1089 | 1089 | |||
1090 | if (ad->ad_handle != handle) | 1090 | if (ad->ad_handle != handle) | |
1091 | continue; | 1091 | continue; | |
1092 | 1092 | |||
1093 | (*ad->ad_notify)(ad->ad_handle, event, ad->ad_device); | 1093 | (*ad->ad_notify)(ad->ad_handle, event, ad->ad_device); | |
1094 | 1094 | |||
1095 | return; | 1095 | return; | |
1096 | } | 1096 | } | |
1097 | 1097 | |||
1098 | aprint_debug_dev(sc->sc_dev, "unhandled notify 0x%02X " | 1098 | aprint_debug_dev(sc->sc_dev, "unhandled notify 0x%02X " | |
1099 | "for %s (%p)\n", event, acpi_name(handle), handle); | 1099 | "for %s (%p)\n", event, acpi_name(handle), handle); | |
1100 | } | 1100 | } | |
1101 | 1101 | |||
1102 | bool | 1102 | bool | |
1103 | acpi_register_notify(struct acpi_devnode *ad, ACPI_NOTIFY_HANDLER notify) | 1103 | acpi_register_notify(struct acpi_devnode *ad, ACPI_NOTIFY_HANDLER notify) | |
1104 | { | 1104 | { | |
1105 | struct acpi_softc *sc = acpi_softc; | 1105 | struct acpi_softc *sc = acpi_softc; | |
1106 | 1106 | |||
1107 | KASSERT(sc != NULL); | 1107 | KASSERT(sc != NULL); | |
1108 | KASSERT(acpi_active != 0); | 1108 | KASSERT(acpi_active != 0); | |
1109 | 1109 | |||
1110 | if (acpi_suspended != 0) | 1110 | if (acpi_suspended != 0) | |
1111 | goto fail; | 1111 | goto fail; | |
1112 | 1112 | |||
1113 | if (ad == NULL || notify == NULL) | 1113 | if (ad == NULL || notify == NULL) | |
1114 | goto fail; | 1114 | goto fail; | |
1115 | 1115 | |||
1116 | ad->ad_notify = notify; | 1116 | ad->ad_notify = notify; | |
1117 | 1117 | |||
1118 | return true; | 1118 | return true; | |
1119 | 1119 | |||
1120 | fail: | 1120 | fail: | |
1121 | aprint_error_dev(sc->sc_dev, "failed to register notify " | 1121 | aprint_error_dev(sc->sc_dev, "failed to register notify " | |
1122 | "handler for %s (%p)\n", ad->ad_name, ad->ad_handle); | 1122 | "handler for %s (%p)\n", ad->ad_name, ad->ad_handle); | |
1123 | 1123 | |||
1124 | return false; | 1124 | return false; | |
1125 | } | 1125 | } | |
1126 | 1126 | |||
1127 | void | 1127 | void | |
1128 | acpi_deregister_notify(struct acpi_devnode *ad) | 1128 | acpi_deregister_notify(struct acpi_devnode *ad) | |
1129 | { | 1129 | { | |
1130 | 1130 | |||
1131 | ad->ad_notify = NULL; | 1131 | ad->ad_notify = NULL; | |
1132 | } | 1132 | } | |
1133 | 1133 | |||
1134 | /* | 1134 | /* | |
1135 | * Fixed buttons. | 1135 | * Fixed buttons. | |
1136 | */ | 1136 | */ | |
1137 | static void | 1137 | static void | |
1138 | acpi_register_fixed_button(struct acpi_softc *sc, int event) | 1138 | acpi_register_fixed_button(struct acpi_softc *sc, int event) | |
1139 | { | 1139 | { | |
1140 | struct sysmon_pswitch *smpsw; | 1140 | struct sysmon_pswitch *smpsw; | |
1141 | ACPI_STATUS rv; | 1141 | ACPI_STATUS rv; | |
1142 | int type; | 1142 | int type; | |
1143 | 1143 | |||
1144 | switch (event) { | 1144 | switch (event) { | |
1145 | 1145 | |||
1146 | case ACPI_EVENT_POWER_BUTTON: | 1146 | case ACPI_EVENT_POWER_BUTTON: | |
1147 | 1147 | |||
1148 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) | 1148 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) | |
1149 | return; | 1149 | return; | |
1150 | 1150 | |||
1151 | type = PSWITCH_TYPE_POWER; | 1151 | type = PSWITCH_TYPE_POWER; | |
1152 | smpsw = &sc->sc_smpsw_power; | 1152 | smpsw = &sc->sc_smpsw_power; | |
1153 | break; | 1153 | break; | |
1154 | 1154 | |||
1155 | case ACPI_EVENT_SLEEP_BUTTON: | 1155 | case ACPI_EVENT_SLEEP_BUTTON: | |
1156 | 1156 | |||
1157 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) | 1157 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) | |
1158 | return; | 1158 | return; | |
1159 | 1159 | |||
1160 | type = PSWITCH_TYPE_SLEEP; | 1160 | type = PSWITCH_TYPE_SLEEP; | |
1161 | smpsw = &sc->sc_smpsw_sleep; | 1161 | smpsw = &sc->sc_smpsw_sleep; | |
1162 | break; | 1162 | break; | |
1163 | 1163 | |||
1164 | default: | 1164 | default: | |
1165 | rv = AE_TYPE; | 1165 | rv = AE_TYPE; | |
1166 | goto fail; | 1166 | goto fail; | |
1167 | } | 1167 | } | |
1168 | 1168 | |||
1169 | smpsw->smpsw_type = type; | 1169 | smpsw->smpsw_type = type; | |
1170 | smpsw->smpsw_name = device_xname(sc->sc_dev); | 1170 | smpsw->smpsw_name = device_xname(sc->sc_dev); | |
1171 | 1171 | |||
1172 | if (sysmon_pswitch_register(smpsw) != 0) { | 1172 | if (sysmon_pswitch_register(smpsw) != 0) { | |
1173 | rv = AE_ERROR; | 1173 | rv = AE_ERROR; | |
1174 | goto fail; | 1174 | goto fail; | |
1175 | } | 1175 | } | |
1176 | 1176 | |||
1177 | AcpiClearEvent(event); | 1177 | AcpiClearEvent(event); | |
1178 | 1178 | |||
1179 | rv = AcpiInstallFixedEventHandler(event, | 1179 | rv = AcpiInstallFixedEventHandler(event, | |
1180 | acpi_fixed_button_handler, smpsw); | 1180 | acpi_fixed_button_handler, smpsw); | |
1181 | 1181 | |||
1182 | if (ACPI_FAILURE(rv)) { | 1182 | if (ACPI_FAILURE(rv)) { | |
1183 | sysmon_pswitch_unregister(smpsw); | 1183 | sysmon_pswitch_unregister(smpsw); | |
1184 | goto fail; | 1184 | goto fail; | |
1185 | } | 1185 | } | |
1186 | 1186 | |||
1187 | aprint_debug_dev(sc->sc_dev, "fixed %s button present\n", | 1187 | aprint_debug_dev(sc->sc_dev, "fixed %s button present\n", | |
1188 | (type != ACPI_EVENT_SLEEP_BUTTON) ? "power" : "sleep"); | 1188 | (type != ACPI_EVENT_SLEEP_BUTTON) ? "power" : "sleep"); | |
1189 | 1189 | |||
1190 | return; | 1190 | return; | |
1191 | 1191 | |||
1192 | fail: | 1192 | fail: | |
1193 | aprint_error_dev(sc->sc_dev, "failed to register " | 1193 | aprint_error_dev(sc->sc_dev, "failed to register " | |
1194 | "fixed event %d: %s\n", event, AcpiFormatException(rv)); | 1194 | "fixed event %d: %s\n", event, AcpiFormatException(rv)); | |
1195 | } | 1195 | } | |
1196 | 1196 | |||
1197 | static void | 1197 | static void | |
1198 | acpi_deregister_fixed_button(struct acpi_softc *sc, int event) | 1198 | acpi_deregister_fixed_button(struct acpi_softc *sc, int event) | |
1199 | { | 1199 | { | |
1200 | struct sysmon_pswitch *smpsw; | 1200 | struct sysmon_pswitch *smpsw; | |
1201 | ACPI_STATUS rv; | 1201 | ACPI_STATUS rv; | |
1202 | 1202 | |||
1203 | switch (event) { | 1203 | switch (event) { | |
1204 | 1204 | |||
1205 | case ACPI_EVENT_POWER_BUTTON: | 1205 | case ACPI_EVENT_POWER_BUTTON: | |
1206 | smpsw = &sc->sc_smpsw_power; | 1206 | smpsw = &sc->sc_smpsw_power; | |
1207 | 1207 | |||
1208 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) { | 1208 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) { | |
1209 | KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_POWER); | 1209 | KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_POWER); | |
1210 | return; | 1210 | return; | |
1211 | } | 1211 | } | |
1212 | 1212 | |||
1213 | break; | 1213 | break; | |
1214 | 1214 | |||
1215 | case ACPI_EVENT_SLEEP_BUTTON: | 1215 | case ACPI_EVENT_SLEEP_BUTTON: | |
1216 | smpsw = &sc->sc_smpsw_sleep; | 1216 | smpsw = &sc->sc_smpsw_sleep; | |
1217 | 1217 | |||
1218 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) { | 1218 | if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) { | |
1219 | KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_SLEEP); | 1219 | KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_SLEEP); | |
1220 | return; | 1220 | return; | |
1221 | } | 1221 | } | |
1222 | 1222 | |||
1223 | break; | 1223 | break; | |
1224 | 1224 | |||
1225 | default: | 1225 | default: | |
1226 | rv = AE_TYPE; | 1226 | rv = AE_TYPE; | |
1227 | goto fail; | 1227 | goto fail; | |
1228 | } | 1228 | } | |
1229 | 1229 | |||
1230 | rv = AcpiRemoveFixedEventHandler(event, acpi_fixed_button_handler); | 1230 | rv = AcpiRemoveFixedEventHandler(event, acpi_fixed_button_handler); | |
1231 | 1231 | |||
1232 | if (ACPI_SUCCESS(rv)) { | 1232 | if (ACPI_SUCCESS(rv)) { | |
1233 | sysmon_pswitch_unregister(smpsw); | 1233 | sysmon_pswitch_unregister(smpsw); | |
1234 | return; | 1234 | return; | |
1235 | } | 1235 | } | |
1236 | 1236 | |||
1237 | fail: | 1237 | fail: | |
1238 | aprint_error_dev(sc->sc_dev, "failed to deregister " | 1238 | aprint_error_dev(sc->sc_dev, "failed to deregister " | |
1239 | "fixed event: %s\n", AcpiFormatException(rv)); | 1239 | "fixed event: %s\n", AcpiFormatException(rv)); | |
1240 | } | 1240 | } | |
1241 | 1241 | |||
1242 | static uint32_t | 1242 | static uint32_t | |
1243 | acpi_fixed_button_handler(void *context) | 1243 | acpi_fixed_button_handler(void *context) | |
1244 | { | 1244 | { | |
1245 | static const int handler = OSL_NOTIFY_HANDLER; | 1245 | static const int handler = OSL_NOTIFY_HANDLER; | |
1246 | struct sysmon_pswitch *smpsw = context; | 1246 | struct sysmon_pswitch *smpsw = context; | |
1247 | 1247 | |||
1248 | (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw); | 1248 | (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw); | |
1249 | 1249 | |||
1250 | return ACPI_INTERRUPT_HANDLED; | 1250 | return ACPI_INTERRUPT_HANDLED; | |
1251 | } | 1251 | } | |
1252 | 1252 | |||
1253 | static void | 1253 | static void | |
1254 | acpi_fixed_button_pressed(void *context) | 1254 | acpi_fixed_button_pressed(void *context) | |
1255 | { | 1255 | { | |
1256 | struct sysmon_pswitch *smpsw = context; | 1256 | struct sysmon_pswitch *smpsw = context; | |
1257 | 1257 | |||
1258 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s fixed button pressed\n", | 1258 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s fixed button pressed\n", | |
1259 | (smpsw->smpsw_type != ACPI_EVENT_SLEEP_BUTTON) ? | 1259 | (smpsw->smpsw_type != ACPI_EVENT_SLEEP_BUTTON) ? | |
1260 | "power" : "sleep")); | 1260 | "power" : "sleep")); | |
1261 | 1261 | |||
1262 | sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED); | 1262 | sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED); | |
1263 | } | 1263 | } | |
1264 | 1264 | |||
1265 | /* | 1265 | /* | |
1266 | * Sleep. | 1266 | * Sleep. | |
1267 | */ | 1267 | */ | |
1268 | static void | 1268 | static void | |
1269 | acpi_sleep_init(struct acpi_softc *sc) | 1269 | acpi_sleep_init(struct acpi_softc *sc) | |
1270 | { | 1270 | { | |
1271 | uint8_t a, b, i; | 1271 | uint8_t a, b, i; | |
1272 | ACPI_STATUS rv; | 1272 | ACPI_STATUS rv; | |
1273 | 1273 | |||
1274 | CTASSERT(ACPI_STATE_S0 == 0 && ACPI_STATE_S1 == 1); | 1274 | CTASSERT(ACPI_STATE_S0 == 0 && ACPI_STATE_S1 == 1); | |
1275 | CTASSERT(ACPI_STATE_S2 == 2 && ACPI_STATE_S3 == 3); | 1275 | CTASSERT(ACPI_STATE_S2 == 2 && ACPI_STATE_S3 == 3); | |
1276 | CTASSERT(ACPI_STATE_S4 == 4 && ACPI_STATE_S5 == 5); | 1276 | CTASSERT(ACPI_STATE_S4 == 4 && ACPI_STATE_S5 == 5); | |
1277 | 1277 | |||
1278 | /* | 1278 | /* | |
1279 | * Evaluate supported sleep states. | 1279 | * Evaluate supported sleep states. | |
1280 | */ | 1280 | */ | |
1281 | for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) { | 1281 | for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) { | |
1282 | 1282 | |||
1283 | rv = AcpiGetSleepTypeData(i, &a, &b); | 1283 | rv = AcpiGetSleepTypeData(i, &a, &b); | |
1284 | 1284 | |||
1285 | if (ACPI_SUCCESS(rv)) | 1285 | if (ACPI_SUCCESS(rv)) | |
1286 | sc->sc_sleepstates |= __BIT(i); | 1286 | sc->sc_sleepstates |= __BIT(i); | |
1287 | } | 1287 | } | |
1288 | } | 1288 | } | |
1289 | 1289 | |||
1290 | /* | 1290 | /* | |
1291 | * Must be called with interrupts enabled. | 1291 | * Must be called with interrupts enabled. | |
1292 | */ | 1292 | */ | |
1293 | void | 1293 | void | |
1294 | acpi_enter_sleep_state(int state) | 1294 | acpi_enter_sleep_state(int state) | |
1295 | { | 1295 | { | |
1296 | struct acpi_softc *sc = acpi_softc; | 1296 | struct acpi_softc *sc = acpi_softc; | |
1297 | ACPI_STATUS rv; | 1297 | ACPI_STATUS rv; | |
1298 | int err; | 1298 | int err; | |
1299 | 1299 | |||
1300 | if (acpi_softc == NULL) | 1300 | if (acpi_softc == NULL) | |
1301 | return; | 1301 | return; | |
1302 | 1302 | |||
1303 | if (state == sc->sc_sleepstate) | 1303 | if (state == sc->sc_sleepstate) | |
1304 | return; | 1304 | return; | |
1305 | 1305 | |||
1306 | if (state < ACPI_STATE_S0 || state > ACPI_STATE_S5) | 1306 | if (state < ACPI_STATE_S0 || state > ACPI_STATE_S5) | |
1307 | return; | 1307 | return; | |
1308 | 1308 |
--- src/sys/dev/acpi/acpi_cpu.c 2011/10/27 05:25:07 1.47
+++ src/sys/dev/acpi/acpi_cpu.c 2011/11/14 02:44:59 1.48
@@ -1,918 +1,918 @@ | @@ -1,918 +1,918 @@ | |||
1 | /* $NetBSD: acpi_cpu.c,v 1.47 2011/10/27 05:25:07 jruoho Exp $ */ | 1 | /* $NetBSD: acpi_cpu.c,v 1.48 2011/11/14 02:44:59 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi> | 4 | * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * | 10 | * | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.47 2011/10/27 05:25:07 jruoho Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.48 2011/11/14 02:44:59 jmcneill Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/cpu.h> | 33 | #include <sys/cpu.h> | |
34 | #include <sys/evcnt.h> | 34 | #include <sys/evcnt.h> | |
35 | #include <sys/kernel.h> | 35 | #include <sys/kernel.h> | |
36 | #include <sys/kmem.h> | 36 | #include <sys/kmem.h> | |
37 | #include <sys/module.h> | 37 | #include <sys/module.h> | |
38 | #include <sys/mutex.h> | 38 | #include <sys/mutex.h> | |
39 | #include <sys/sysctl.h> | 39 | #include <sys/sysctl.h> | |
40 | #include <sys/cpufreq.h> | 40 | #include <sys/cpufreq.h> | |
41 | 41 | |||
42 | #include <dev/acpi/acpireg.h> | 42 | #include <dev/acpi/acpireg.h> | |
43 | #include <dev/acpi/acpivar.h> | 43 | #include <dev/acpi/acpivar.h> | |
44 | #include <dev/acpi/acpi_cpu.h> | 44 | #include <dev/acpi/acpi_cpu.h> | |
45 | 45 | |||
46 | #include <machine/acpi_machdep.h> | 46 | #include <machine/acpi_machdep.h> | |
47 | #include <machine/cpuvar.h> | 47 | #include <machine/cpuvar.h> | |
48 | 48 | |||
49 | #define _COMPONENT ACPI_BUS_COMPONENT | 49 | #define _COMPONENT ACPI_BUS_COMPONENT | |
50 | ACPI_MODULE_NAME ("acpi_cpu") | 50 | ACPI_MODULE_NAME ("acpi_cpu") | |
51 | 51 | |||
52 | static int acpicpu_match(device_t, cfdata_t, void *); | 52 | static int acpicpu_match(device_t, cfdata_t, void *); | |
53 | static void acpicpu_attach(device_t, device_t, void *); | 53 | static void acpicpu_attach(device_t, device_t, void *); | |
54 | static int acpicpu_detach(device_t, int); | 54 | static int acpicpu_detach(device_t, int); | |
55 | static int acpicpu_once_attach(void); | 55 | static int acpicpu_once_attach(void); | |
56 | static int acpicpu_once_detach(void); | 56 | static int acpicpu_once_detach(void); | |
57 | static void acpicpu_start(device_t); | 57 | static void acpicpu_start(device_t); | |
58 | static void acpicpu_sysctl(device_t); | 58 | static void acpicpu_sysctl(device_t); | |
59 | 59 | |||
60 | static ACPI_STATUS acpicpu_object(ACPI_HANDLE, struct acpicpu_object *); | 60 | static ACPI_STATUS acpicpu_object(ACPI_HANDLE, struct acpicpu_object *); | |
61 | static uint32_t acpicpu_cap(struct acpicpu_softc *); | 61 | static uint32_t acpicpu_cap(struct acpicpu_softc *); | |
62 | static ACPI_STATUS acpicpu_cap_osc(struct acpicpu_softc *, | 62 | static ACPI_STATUS acpicpu_cap_osc(struct acpicpu_softc *, | |
63 | uint32_t, uint32_t *); | 63 | uint32_t, uint32_t *); | |
64 | static void acpicpu_notify(ACPI_HANDLE, uint32_t, void *); | 64 | static void acpicpu_notify(ACPI_HANDLE, uint32_t, void *); | |
65 | static bool acpicpu_suspend(device_t, const pmf_qual_t *); | 65 | static bool acpicpu_suspend(device_t, const pmf_qual_t *); | |
66 | static bool acpicpu_resume(device_t, const pmf_qual_t *); | 66 | static bool acpicpu_resume(device_t, const pmf_qual_t *); | |
67 | static void acpicpu_evcnt_attach(device_t); | 67 | static void acpicpu_evcnt_attach(device_t); | |
68 | static void acpicpu_evcnt_detach(device_t); | 68 | static void acpicpu_evcnt_detach(device_t); | |
69 | static void acpicpu_debug_print(device_t); | 69 | static void acpicpu_debug_print(device_t); | |
70 | static const char *acpicpu_debug_print_method_c(uint8_t); | 70 | static const char *acpicpu_debug_print_method_c(uint8_t); | |
71 | static const char *acpicpu_debug_print_method_pt(uint8_t); | 71 | static const char *acpicpu_debug_print_method_pt(uint8_t); | |
72 | static const char *acpicpu_debug_print_dep(uint32_t); | 72 | static const char *acpicpu_debug_print_dep(uint32_t); | |
73 | 73 | |||
74 | static uint32_t acpicpu_count = 0; | 74 | static uint32_t acpicpu_count = 0; | |
75 | struct acpicpu_softc **acpicpu_sc = NULL; | 75 | struct acpicpu_softc **acpicpu_sc = NULL; | |
76 | static struct sysctllog *acpicpu_log = NULL; | 76 | static struct sysctllog *acpicpu_log = NULL; | |
77 | static bool acpicpu_dynamic = true; | 77 | static bool acpicpu_dynamic = true; | |
78 | static bool acpicpu_passive = true; | 78 | static bool acpicpu_passive = true; | |
79 | 79 | |||
80 | static const struct { | 80 | static const struct { | |
81 | const char *manu; | 81 | const char *manu; | |
82 | const char *prod; | 82 | const char *prod; | |
83 | const char *vers; | 83 | const char *vers; | |
84 | } acpicpu_quirks[] = { | 84 | } acpicpu_quirks[] = { | |
85 | { "Supermicro", "PDSMi-LN4", "0123456789" }, | 85 | { "Supermicro", "PDSMi-LN4", "0123456789" }, | |
86 | }; | 86 | }; | |
87 | 87 | |||
88 | CFATTACH_DECL_NEW(acpicpu, sizeof(struct acpicpu_softc), | 88 | CFATTACH_DECL_NEW(acpicpu, sizeof(struct acpicpu_softc), | |
89 | acpicpu_match, acpicpu_attach, acpicpu_detach, NULL); | 89 | acpicpu_match, acpicpu_attach, acpicpu_detach, NULL); | |
90 | 90 | |||
91 | static int | 91 | static int | |
92 | acpicpu_match(device_t parent, cfdata_t match, void *aux) | 92 | acpicpu_match(device_t parent, cfdata_t match, void *aux) | |
93 | { | 93 | { | |
94 | const char *manu, *prod, *vers; | 94 | const char *manu, *prod, *vers; | |
95 | struct cpu_info *ci; | 95 | struct cpu_info *ci; | |
96 | size_t i; | 96 | size_t i; | |
97 | 97 | |||
98 | if (acpi_softc == NULL) | 98 | if (acpi_softc == NULL) | |
99 | return 0; | 99 | return 0; | |
100 | 100 | |||
101 | manu = pmf_get_platform("system-manufacturer"); | 101 | manu = pmf_get_platform("system-vendor"); | |
102 | prod = pmf_get_platform("system-product-name"); | 102 | prod = pmf_get_platform("system-product"); | |
103 | vers = pmf_get_platform("system-version"); | 103 | vers = pmf_get_platform("system-version"); | |
104 | 104 | |||
105 | if (manu != NULL && prod != NULL && vers != NULL) { | 105 | if (manu != NULL && prod != NULL && vers != NULL) { | |
106 | 106 | |||
107 | for (i = 0; i < __arraycount(acpicpu_quirks); i++) { | 107 | for (i = 0; i < __arraycount(acpicpu_quirks); i++) { | |
108 | 108 | |||
109 | if (strcasecmp(acpicpu_quirks[i].manu, manu) == 0 && | 109 | if (strcasecmp(acpicpu_quirks[i].manu, manu) == 0 && | |
110 | strcasecmp(acpicpu_quirks[i].prod, prod) == 0 && | 110 | strcasecmp(acpicpu_quirks[i].prod, prod) == 0 && | |
111 | strcasecmp(acpicpu_quirks[i].vers, vers) == 0) | 111 | strcasecmp(acpicpu_quirks[i].vers, vers) == 0) | |
112 | return 0; | 112 | return 0; | |
113 | } | 113 | } | |
114 | } | 114 | } | |
115 | 115 | |||
116 | ci = acpicpu_md_match(parent, match, aux); | 116 | ci = acpicpu_md_match(parent, match, aux); | |
117 | 117 | |||
118 | if (ci == NULL) | 118 | if (ci == NULL) | |
119 | return 0; | 119 | return 0; | |
120 | 120 | |||
121 | if (acpi_match_cpu_info(ci) == NULL) | 121 | if (acpi_match_cpu_info(ci) == NULL) | |
122 | return 0; | 122 | return 0; | |
123 | 123 | |||
124 | return 10; | 124 | return 10; | |
125 | } | 125 | } | |
126 | 126 | |||
127 | static void | 127 | static void | |
128 | acpicpu_attach(device_t parent, device_t self, void *aux) | 128 | acpicpu_attach(device_t parent, device_t self, void *aux) | |
129 | { | 129 | { | |
130 | struct acpicpu_softc *sc = device_private(self); | 130 | struct acpicpu_softc *sc = device_private(self); | |
131 | struct cpu_info *ci; | 131 | struct cpu_info *ci; | |
132 | ACPI_HANDLE hdl; | 132 | ACPI_HANDLE hdl; | |
133 | cpuid_t id; | 133 | cpuid_t id; | |
134 | int rv; | 134 | int rv; | |
135 | 135 | |||
136 | ci = acpicpu_md_attach(parent, self, aux); | 136 | ci = acpicpu_md_attach(parent, self, aux); | |
137 | 137 | |||
138 | if (ci == NULL) | 138 | if (ci == NULL) | |
139 | return; | 139 | return; | |
140 | 140 | |||
141 | sc->sc_ci = ci; | 141 | sc->sc_ci = ci; | |
142 | sc->sc_dev = self; | 142 | sc->sc_dev = self; | |
143 | sc->sc_cold = true; | 143 | sc->sc_cold = true; | |
144 | 144 | |||
145 | hdl = acpi_match_cpu_info(ci); | 145 | hdl = acpi_match_cpu_info(ci); | |
146 | 146 | |||
147 | if (hdl == NULL) { | 147 | if (hdl == NULL) { | |
148 | aprint_normal(": failed to match processor\n"); | 148 | aprint_normal(": failed to match processor\n"); | |
149 | return; | 149 | return; | |
150 | } | 150 | } | |
151 | 151 | |||
152 | sc->sc_node = acpi_match_node(hdl); | 152 | sc->sc_node = acpi_match_node(hdl); | |
153 | 153 | |||
154 | if (acpicpu_once_attach() != 0) { | 154 | if (acpicpu_once_attach() != 0) { | |
155 | aprint_normal(": failed to initialize\n"); | 155 | aprint_normal(": failed to initialize\n"); | |
156 | return; | 156 | return; | |
157 | } | 157 | } | |
158 | 158 | |||
159 | KASSERT(acpi_softc != NULL); | 159 | KASSERT(acpi_softc != NULL); | |
160 | KASSERT(acpicpu_sc != NULL); | 160 | KASSERT(acpicpu_sc != NULL); | |
161 | KASSERT(sc->sc_node != NULL); | 161 | KASSERT(sc->sc_node != NULL); | |
162 | 162 | |||
163 | id = sc->sc_ci->ci_acpiid; | 163 | id = sc->sc_ci->ci_acpiid; | |
164 | 164 | |||
165 | if (acpicpu_sc[id] != NULL) { | 165 | if (acpicpu_sc[id] != NULL) { | |
166 | aprint_normal(": already attached\n"); | 166 | aprint_normal(": already attached\n"); | |
167 | return; | 167 | return; | |
168 | } | 168 | } | |
169 | 169 | |||
170 | aprint_naive("\n"); | 170 | aprint_naive("\n"); | |
171 | aprint_normal(": ACPI CPU\n"); | 171 | aprint_normal(": ACPI CPU\n"); | |
172 | 172 | |||
173 | rv = acpicpu_object(sc->sc_node->ad_handle, &sc->sc_object); | 173 | rv = acpicpu_object(sc->sc_node->ad_handle, &sc->sc_object); | |
174 | 174 | |||
175 | if (ACPI_FAILURE(rv)) | 175 | if (ACPI_FAILURE(rv)) | |
176 | aprint_verbose_dev(self, "failed to obtain CPU object\n"); | 176 | aprint_verbose_dev(self, "failed to obtain CPU object\n"); | |
177 | 177 | |||
178 | acpicpu_count++; | 178 | acpicpu_count++; | |
179 | acpicpu_sc[id] = sc; | 179 | acpicpu_sc[id] = sc; | |
180 | 180 | |||
181 | sc->sc_cap = acpicpu_cap(sc); | 181 | sc->sc_cap = acpicpu_cap(sc); | |
182 | sc->sc_ncpus = acpi_md_ncpus(); | 182 | sc->sc_ncpus = acpi_md_ncpus(); | |
183 | sc->sc_flags = acpicpu_md_flags(); | 183 | sc->sc_flags = acpicpu_md_flags(); | |
184 | 184 | |||
185 | KASSERT(acpicpu_count <= sc->sc_ncpus); | 185 | KASSERT(acpicpu_count <= sc->sc_ncpus); | |
186 | KASSERT(sc->sc_node->ad_device == NULL); | 186 | KASSERT(sc->sc_node->ad_device == NULL); | |
187 | 187 | |||
188 | sc->sc_node->ad_device = self; | 188 | sc->sc_node->ad_device = self; | |
189 | mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE); | 189 | mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE); | |
190 | 190 | |||
191 | acpicpu_cstate_attach(self); | 191 | acpicpu_cstate_attach(self); | |
192 | acpicpu_pstate_attach(self); | 192 | acpicpu_pstate_attach(self); | |
193 | acpicpu_tstate_attach(self); | 193 | acpicpu_tstate_attach(self); | |
194 | 194 | |||
195 | acpicpu_debug_print(self); | 195 | acpicpu_debug_print(self); | |
196 | acpicpu_evcnt_attach(self); | 196 | acpicpu_evcnt_attach(self); | |
197 | 197 | |||
198 | (void)config_interrupts(self, acpicpu_start); | 198 | (void)config_interrupts(self, acpicpu_start); | |
199 | (void)acpi_register_notify(sc->sc_node, acpicpu_notify); | 199 | (void)acpi_register_notify(sc->sc_node, acpicpu_notify); | |
200 | (void)pmf_device_register(self, acpicpu_suspend, acpicpu_resume); | 200 | (void)pmf_device_register(self, acpicpu_suspend, acpicpu_resume); | |
201 | } | 201 | } | |
202 | 202 | |||
203 | static int | 203 | static int | |
204 | acpicpu_detach(device_t self, int flags) | 204 | acpicpu_detach(device_t self, int flags) | |
205 | { | 205 | { | |
206 | struct acpicpu_softc *sc = device_private(self); | 206 | struct acpicpu_softc *sc = device_private(self); | |
207 | 207 | |||
208 | sc->sc_cold = true; | 208 | sc->sc_cold = true; | |
209 | 209 | |||
210 | acpicpu_evcnt_detach(self); | 210 | acpicpu_evcnt_detach(self); | |
211 | acpi_deregister_notify(sc->sc_node); | 211 | acpi_deregister_notify(sc->sc_node); | |
212 | 212 | |||
213 | acpicpu_cstate_detach(self); | 213 | acpicpu_cstate_detach(self); | |
214 | acpicpu_pstate_detach(self); | 214 | acpicpu_pstate_detach(self); | |
215 | acpicpu_tstate_detach(self); | 215 | acpicpu_tstate_detach(self); | |
216 | 216 | |||
217 | mutex_destroy(&sc->sc_mtx); | 217 | mutex_destroy(&sc->sc_mtx); | |
218 | sc->sc_node->ad_device = NULL; | 218 | sc->sc_node->ad_device = NULL; | |
219 | 219 | |||
220 | acpicpu_count--; | 220 | acpicpu_count--; | |
221 | acpicpu_once_detach(); | 221 | acpicpu_once_detach(); | |
222 | 222 | |||
223 | return 0; | 223 | return 0; | |
224 | } | 224 | } | |
225 | 225 | |||
226 | static int | 226 | static int | |
227 | acpicpu_once_attach(void) | 227 | acpicpu_once_attach(void) | |
228 | { | 228 | { | |
229 | struct acpicpu_softc *sc; | 229 | struct acpicpu_softc *sc; | |
230 | unsigned int i; | 230 | unsigned int i; | |
231 | 231 | |||
232 | if (acpicpu_count != 0) | 232 | if (acpicpu_count != 0) | |
233 | return 0; | 233 | return 0; | |
234 | 234 | |||
235 | KASSERT(acpicpu_sc == NULL); | 235 | KASSERT(acpicpu_sc == NULL); | |
236 | KASSERT(acpicpu_log == NULL); | 236 | KASSERT(acpicpu_log == NULL); | |
237 | 237 | |||
238 | acpicpu_sc = kmem_zalloc(maxcpus * sizeof(*sc), KM_SLEEP); | 238 | acpicpu_sc = kmem_zalloc(maxcpus * sizeof(*sc), KM_SLEEP); | |
239 | 239 | |||
240 | if (acpicpu_sc == NULL) | 240 | if (acpicpu_sc == NULL) | |
241 | return ENOMEM; | 241 | return ENOMEM; | |
242 | 242 | |||
243 | for (i = 0; i < maxcpus; i++) | 243 | for (i = 0; i < maxcpus; i++) | |
244 | acpicpu_sc[i] = NULL; | 244 | acpicpu_sc[i] = NULL; | |
245 | 245 | |||
246 | return 0; | 246 | return 0; | |
247 | } | 247 | } | |
248 | 248 | |||
249 | static int | 249 | static int | |
250 | acpicpu_once_detach(void) | 250 | acpicpu_once_detach(void) | |
251 | { | 251 | { | |
252 | struct acpicpu_softc *sc; | 252 | struct acpicpu_softc *sc; | |
253 | 253 | |||
254 | if (acpicpu_count != 0) | 254 | if (acpicpu_count != 0) | |
255 | return EDEADLK; | 255 | return EDEADLK; | |
256 | 256 | |||
257 | cpufreq_deregister(); | 257 | cpufreq_deregister(); | |
258 | 258 | |||
259 | if (acpicpu_log != NULL) | 259 | if (acpicpu_log != NULL) | |
260 | sysctl_teardown(&acpicpu_log); | 260 | sysctl_teardown(&acpicpu_log); | |
261 | 261 | |||
262 | if (acpicpu_sc != NULL) | 262 | if (acpicpu_sc != NULL) | |
263 | kmem_free(acpicpu_sc, maxcpus * sizeof(*sc)); | 263 | kmem_free(acpicpu_sc, maxcpus * sizeof(*sc)); | |
264 | 264 | |||
265 | return 0; | 265 | return 0; | |
266 | } | 266 | } | |
267 | 267 | |||
268 | static void | 268 | static void | |
269 | acpicpu_start(device_t self) | 269 | acpicpu_start(device_t self) | |
270 | { | 270 | { | |
271 | struct acpicpu_softc *sc = device_private(self); | 271 | struct acpicpu_softc *sc = device_private(self); | |
272 | static uint32_t count = 0; | 272 | static uint32_t count = 0; | |
273 | struct cpufreq cf; | 273 | struct cpufreq cf; | |
274 | uint32_t i; | 274 | uint32_t i; | |
275 | 275 | |||
276 | /* | 276 | /* | |
277 | * Run the state-specific initialization routines. These | 277 | * Run the state-specific initialization routines. These | |
278 | * must run only once, after interrupts have been enabled, | 278 | * must run only once, after interrupts have been enabled, | |
279 | * all CPUs are running, and all ACPI CPUs have attached. | 279 | * all CPUs are running, and all ACPI CPUs have attached. | |
280 | */ | 280 | */ | |
281 | if (++count != acpicpu_count || acpicpu_count != sc->sc_ncpus) { | 281 | if (++count != acpicpu_count || acpicpu_count != sc->sc_ncpus) { | |
282 | sc->sc_cold = false; | 282 | sc->sc_cold = false; | |
283 | return; | 283 | return; | |
284 | } | 284 | } | |
285 | 285 | |||
286 | /* | 286 | /* | |
287 | * Set the last ACPI CPU as non-cold | 287 | * Set the last ACPI CPU as non-cold | |
288 | * only after C-states are enabled. | 288 | * only after C-states are enabled. | |
289 | */ | 289 | */ | |
290 | if ((sc->sc_flags & ACPICPU_FLAG_C) != 0) | 290 | if ((sc->sc_flags & ACPICPU_FLAG_C) != 0) | |
291 | acpicpu_cstate_start(self); | 291 | acpicpu_cstate_start(self); | |
292 | 292 | |||
293 | sc->sc_cold = false; | 293 | sc->sc_cold = false; | |
294 | 294 | |||
295 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) | 295 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) | |
296 | acpicpu_pstate_start(self); | 296 | acpicpu_pstate_start(self); | |
297 | 297 | |||
298 | if ((sc->sc_flags & ACPICPU_FLAG_T) != 0) | 298 | if ((sc->sc_flags & ACPICPU_FLAG_T) != 0) | |
299 | acpicpu_tstate_start(self); | 299 | acpicpu_tstate_start(self); | |
300 | 300 | |||
301 | acpicpu_sysctl(self); | 301 | acpicpu_sysctl(self); | |
302 | aprint_debug_dev(self, "ACPI CPUs started\n"); | 302 | aprint_debug_dev(self, "ACPI CPUs started\n"); | |
303 | 303 | |||
304 | /* | 304 | /* | |
305 | * Register with cpufreq(9). | 305 | * Register with cpufreq(9). | |
306 | */ | 306 | */ | |
307 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) { | 307 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) { | |
308 | 308 | |||
309 | (void)memset(&cf, 0, sizeof(struct cpufreq)); | 309 | (void)memset(&cf, 0, sizeof(struct cpufreq)); | |
310 | 310 | |||
311 | cf.cf_mp = false; | 311 | cf.cf_mp = false; | |
312 | cf.cf_cookie = NULL; | 312 | cf.cf_cookie = NULL; | |
313 | cf.cf_get_freq = acpicpu_pstate_get; | 313 | cf.cf_get_freq = acpicpu_pstate_get; | |
314 | cf.cf_set_freq = acpicpu_pstate_set; | 314 | cf.cf_set_freq = acpicpu_pstate_set; | |
315 | cf.cf_state_count = sc->sc_pstate_count; | 315 | cf.cf_state_count = sc->sc_pstate_count; | |
316 | 316 | |||
317 | (void)strlcpy(cf.cf_name, "acpicpu", sizeof(cf.cf_name)); | 317 | (void)strlcpy(cf.cf_name, "acpicpu", sizeof(cf.cf_name)); | |
318 | 318 | |||
319 | for (i = 0; i < sc->sc_pstate_count; i++) { | 319 | for (i = 0; i < sc->sc_pstate_count; i++) { | |
320 | 320 | |||
321 | if (sc->sc_pstate[i].ps_freq == 0) | 321 | if (sc->sc_pstate[i].ps_freq == 0) | |
322 | continue; | 322 | continue; | |
323 | 323 | |||
324 | cf.cf_state[i].cfs_freq = sc->sc_pstate[i].ps_freq; | 324 | cf.cf_state[i].cfs_freq = sc->sc_pstate[i].ps_freq; | |
325 | cf.cf_state[i].cfs_power = sc->sc_pstate[i].ps_power; | 325 | cf.cf_state[i].cfs_power = sc->sc_pstate[i].ps_power; | |
326 | } | 326 | } | |
327 | 327 | |||
328 | if (cpufreq_register(&cf) != 0) | 328 | if (cpufreq_register(&cf) != 0) | |
329 | aprint_error_dev(self, "failed to register cpufreq\n"); | 329 | aprint_error_dev(self, "failed to register cpufreq\n"); | |
330 | } | 330 | } | |
331 | } | 331 | } | |
332 | 332 | |||
333 | static void | 333 | static void | |
334 | acpicpu_sysctl(device_t self) | 334 | acpicpu_sysctl(device_t self) | |
335 | { | 335 | { | |
336 | const struct sysctlnode *node; | 336 | const struct sysctlnode *node; | |
337 | int err; | 337 | int err; | |
338 | 338 | |||
339 | KASSERT(acpicpu_log == NULL); | 339 | KASSERT(acpicpu_log == NULL); | |
340 | 340 | |||
341 | err = sysctl_createv(&acpicpu_log, 0, NULL, &node, | 341 | err = sysctl_createv(&acpicpu_log, 0, NULL, &node, | |
342 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, | 342 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, | |
343 | NULL, 0, NULL, 0, CTL_HW, CTL_EOL); | 343 | NULL, 0, NULL, 0, CTL_HW, CTL_EOL); | |
344 | 344 | |||
345 | if (err != 0) | 345 | if (err != 0) | |
346 | goto fail; | 346 | goto fail; | |
347 | 347 | |||
348 | err = sysctl_createv(&acpicpu_log, 0, &node, &node, | 348 | err = sysctl_createv(&acpicpu_log, 0, &node, &node, | |
349 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "acpi", NULL, | 349 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "acpi", NULL, | |
350 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); | 350 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); | |
351 | 351 | |||
352 | if (err != 0) | 352 | if (err != 0) | |
353 | goto fail; | 353 | goto fail; | |
354 | 354 | |||
355 | err = sysctl_createv(&acpicpu_log, 0, &node, &node, | 355 | err = sysctl_createv(&acpicpu_log, 0, &node, &node, | |
356 | 0, CTLTYPE_NODE, "cpu", SYSCTL_DESCR("ACPI CPU"), | 356 | 0, CTLTYPE_NODE, "cpu", SYSCTL_DESCR("ACPI CPU"), | |
357 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); | 357 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); | |
358 | 358 | |||
359 | if (err != 0) | 359 | if (err != 0) | |
360 | goto fail; | 360 | goto fail; | |
361 | 361 | |||
362 | err = sysctl_createv(&acpicpu_log, 0, &node, NULL, | 362 | err = sysctl_createv(&acpicpu_log, 0, &node, NULL, | |
363 | CTLFLAG_READWRITE, CTLTYPE_BOOL, "dynamic", | 363 | CTLFLAG_READWRITE, CTLTYPE_BOOL, "dynamic", | |
364 | SYSCTL_DESCR("Dynamic states"), NULL, 0, | 364 | SYSCTL_DESCR("Dynamic states"), NULL, 0, | |
365 | &acpicpu_dynamic, 0, CTL_CREATE, CTL_EOL); | 365 | &acpicpu_dynamic, 0, CTL_CREATE, CTL_EOL); | |
366 | 366 | |||
367 | if (err != 0) | 367 | if (err != 0) | |
368 | goto fail; | 368 | goto fail; | |
369 | 369 | |||
370 | err = sysctl_createv(&acpicpu_log, 0, &node, NULL, | 370 | err = sysctl_createv(&acpicpu_log, 0, &node, NULL, | |
371 | CTLFLAG_READWRITE, CTLTYPE_BOOL, "passive", | 371 | CTLFLAG_READWRITE, CTLTYPE_BOOL, "passive", | |
372 | SYSCTL_DESCR("Passive cooling"), NULL, 0, | 372 | SYSCTL_DESCR("Passive cooling"), NULL, 0, | |
373 | &acpicpu_passive, 0, CTL_CREATE, CTL_EOL); | 373 | &acpicpu_passive, 0, CTL_CREATE, CTL_EOL); | |
374 | 374 | |||
375 | if (err != 0) | 375 | if (err != 0) | |
376 | goto fail; | 376 | goto fail; | |
377 | 377 | |||
378 | return; | 378 | return; | |
379 | 379 | |||
380 | fail: | 380 | fail: | |
381 | aprint_error_dev(self, "failed to initialize sysctl (err %d)\n", err); | 381 | aprint_error_dev(self, "failed to initialize sysctl (err %d)\n", err); | |
382 | } | 382 | } | |
383 | 383 | |||
384 | static ACPI_STATUS | 384 | static ACPI_STATUS | |
385 | acpicpu_object(ACPI_HANDLE hdl, struct acpicpu_object *ao) | 385 | acpicpu_object(ACPI_HANDLE hdl, struct acpicpu_object *ao) | |
386 | { | 386 | { | |
387 | ACPI_OBJECT *obj; | 387 | ACPI_OBJECT *obj; | |
388 | ACPI_BUFFER buf; | 388 | ACPI_BUFFER buf; | |
389 | ACPI_STATUS rv; | 389 | ACPI_STATUS rv; | |
390 | 390 | |||
391 | rv = acpi_eval_struct(hdl, NULL, &buf); | 391 | rv = acpi_eval_struct(hdl, NULL, &buf); | |
392 | 392 | |||
393 | if (ACPI_FAILURE(rv)) | 393 | if (ACPI_FAILURE(rv)) | |
394 | goto out; | 394 | goto out; | |
395 | 395 | |||
396 | obj = buf.Pointer; | 396 | obj = buf.Pointer; | |
397 | 397 | |||
398 | if (obj->Type != ACPI_TYPE_PROCESSOR) { | 398 | if (obj->Type != ACPI_TYPE_PROCESSOR) { | |
399 | rv = AE_TYPE; | 399 | rv = AE_TYPE; | |
400 | goto out; | 400 | goto out; | |
401 | } | 401 | } | |
402 | 402 | |||
403 | if (obj->Processor.ProcId > (uint32_t)maxcpus) { | 403 | if (obj->Processor.ProcId > (uint32_t)maxcpus) { | |
404 | rv = AE_LIMIT; | 404 | rv = AE_LIMIT; | |
405 | goto out; | 405 | goto out; | |
406 | } | 406 | } | |
407 | 407 | |||
408 | KDASSERT((uint64_t)obj->Processor.PblkAddress < UINT32_MAX); | 408 | KDASSERT((uint64_t)obj->Processor.PblkAddress < UINT32_MAX); | |
409 | 409 | |||
410 | if (ao != NULL) { | 410 | if (ao != NULL) { | |
411 | ao->ao_procid = obj->Processor.ProcId; | 411 | ao->ao_procid = obj->Processor.ProcId; | |
412 | ao->ao_pblklen = obj->Processor.PblkLength; | 412 | ao->ao_pblklen = obj->Processor.PblkLength; | |
413 | ao->ao_pblkaddr = obj->Processor.PblkAddress; | 413 | ao->ao_pblkaddr = obj->Processor.PblkAddress; | |
414 | } | 414 | } | |
415 | 415 | |||
416 | out: | 416 | out: | |
417 | if (buf.Pointer != NULL) | 417 | if (buf.Pointer != NULL) | |
418 | ACPI_FREE(buf.Pointer); | 418 | ACPI_FREE(buf.Pointer); | |
419 | 419 | |||
420 | return rv; | 420 | return rv; | |
421 | } | 421 | } | |
422 | 422 | |||
423 | static uint32_t | 423 | static uint32_t | |
424 | acpicpu_cap(struct acpicpu_softc *sc) | 424 | acpicpu_cap(struct acpicpu_softc *sc) | |
425 | { | 425 | { | |
426 | uint32_t flags, cap = 0; | 426 | uint32_t flags, cap = 0; | |
427 | ACPI_STATUS rv; | 427 | ACPI_STATUS rv; | |
428 | 428 | |||
429 | /* | 429 | /* | |
430 | * Query and set machine-dependent capabilities. | 430 | * Query and set machine-dependent capabilities. | |
431 | * Note that the Intel-specific _PDC method has | 431 | * Note that the Intel-specific _PDC method has | |
432 | * already been evaluated. It was furthermore | 432 | * already been evaluated. It was furthermore | |
433 | * deprecated in the ACPI 3.0 in favor of _OSC. | 433 | * deprecated in the ACPI 3.0 in favor of _OSC. | |
434 | */ | 434 | */ | |
435 | flags = acpi_md_pdc(); | 435 | flags = acpi_md_pdc(); | |
436 | rv = acpicpu_cap_osc(sc, flags, &cap); | 436 | rv = acpicpu_cap_osc(sc, flags, &cap); | |
437 | 437 | |||
438 | if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) { | 438 | if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) { | |
439 | 439 | |||
440 | aprint_error_dev(sc->sc_dev, "failed to evaluate " | 440 | aprint_error_dev(sc->sc_dev, "failed to evaluate " | |
441 | "_OSC: %s\n", AcpiFormatException(rv)); | 441 | "_OSC: %s\n", AcpiFormatException(rv)); | |
442 | } | 442 | } | |
443 | 443 | |||
444 | return (cap != 0) ? cap : flags; | 444 | return (cap != 0) ? cap : flags; | |
445 | } | 445 | } | |
446 | 446 | |||
447 | static ACPI_STATUS | 447 | static ACPI_STATUS | |
448 | acpicpu_cap_osc(struct acpicpu_softc *sc, uint32_t flags, uint32_t *val) | 448 | acpicpu_cap_osc(struct acpicpu_softc *sc, uint32_t flags, uint32_t *val) | |
449 | { | 449 | { | |
450 | ACPI_OBJECT_LIST arg; | 450 | ACPI_OBJECT_LIST arg; | |
451 | ACPI_OBJECT obj[4]; | 451 | ACPI_OBJECT obj[4]; | |
452 | ACPI_OBJECT *osc; | 452 | ACPI_OBJECT *osc; | |
453 | ACPI_BUFFER buf; | 453 | ACPI_BUFFER buf; | |
454 | ACPI_STATUS rv; | 454 | ACPI_STATUS rv; | |
455 | uint32_t cap[2]; | 455 | uint32_t cap[2]; | |
456 | uint32_t *ptr; | 456 | uint32_t *ptr; | |
457 | int i = 5; | 457 | int i = 5; | |
458 | 458 | |||
459 | static uint8_t intel_uuid[16] = { | 459 | static uint8_t intel_uuid[16] = { | |
460 | 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47, | 460 | 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47, | |
461 | 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53 | 461 | 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53 | |
462 | }; | 462 | }; | |
463 | 463 | |||
464 | cap[0] = ACPI_OSC_QUERY; | 464 | cap[0] = ACPI_OSC_QUERY; | |
465 | cap[1] = flags; | 465 | cap[1] = flags; | |
466 | 466 | |||
467 | again: | 467 | again: | |
468 | arg.Count = 4; | 468 | arg.Count = 4; | |
469 | arg.Pointer = obj; | 469 | arg.Pointer = obj; | |
470 | 470 | |||
471 | obj[0].Type = ACPI_TYPE_BUFFER; | 471 | obj[0].Type = ACPI_TYPE_BUFFER; | |
472 | obj[0].Buffer.Length = sizeof(intel_uuid); | 472 | obj[0].Buffer.Length = sizeof(intel_uuid); | |
473 | obj[0].Buffer.Pointer = intel_uuid; | 473 | obj[0].Buffer.Pointer = intel_uuid; | |
474 | 474 | |||
475 | obj[1].Type = ACPI_TYPE_INTEGER; | 475 | obj[1].Type = ACPI_TYPE_INTEGER; | |
476 | obj[1].Integer.Value = ACPICPU_PDC_REVID; | 476 | obj[1].Integer.Value = ACPICPU_PDC_REVID; | |
477 | 477 | |||
478 | obj[2].Type = ACPI_TYPE_INTEGER; | 478 | obj[2].Type = ACPI_TYPE_INTEGER; | |
479 | obj[2].Integer.Value = __arraycount(cap); | 479 | obj[2].Integer.Value = __arraycount(cap); | |
480 | 480 | |||
481 | obj[3].Type = ACPI_TYPE_BUFFER; | 481 | obj[3].Type = ACPI_TYPE_BUFFER; | |
482 | obj[3].Buffer.Length = sizeof(cap); | 482 | obj[3].Buffer.Length = sizeof(cap); | |
483 | obj[3].Buffer.Pointer = (void *)cap; | 483 | obj[3].Buffer.Pointer = (void *)cap; | |
484 | 484 | |||
485 | buf.Pointer = NULL; | 485 | buf.Pointer = NULL; | |
486 | buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; | 486 | buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
487 | 487 | |||
488 | rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OSC", &arg, &buf); | 488 | rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OSC", &arg, &buf); | |
489 | 489 | |||
490 | if (ACPI_FAILURE(rv)) | 490 | if (ACPI_FAILURE(rv)) | |
491 | goto out; | 491 | goto out; | |
492 | 492 | |||
493 | osc = buf.Pointer; | 493 | osc = buf.Pointer; | |
494 | 494 | |||
495 | if (osc->Type != ACPI_TYPE_BUFFER) { | 495 | if (osc->Type != ACPI_TYPE_BUFFER) { | |
496 | rv = AE_TYPE; | 496 | rv = AE_TYPE; | |
497 | goto out; | 497 | goto out; | |
498 | } | 498 | } | |
499 | 499 | |||
500 | if (osc->Buffer.Length != sizeof(cap)) { | 500 | if (osc->Buffer.Length != sizeof(cap)) { | |
501 | rv = AE_BUFFER_OVERFLOW; | 501 | rv = AE_BUFFER_OVERFLOW; | |
502 | goto out; | 502 | goto out; | |
503 | } | 503 | } | |
504 | 504 | |||
505 | ptr = (uint32_t *)osc->Buffer.Pointer; | 505 | ptr = (uint32_t *)osc->Buffer.Pointer; | |
506 | 506 | |||
507 | if ((ptr[0] & ACPI_OSC_ERROR) != 0) { | 507 | if ((ptr[0] & ACPI_OSC_ERROR) != 0) { | |
508 | rv = AE_ERROR; | 508 | rv = AE_ERROR; | |
509 | goto out; | 509 | goto out; | |
510 | } | 510 | } | |
511 | 511 | |||
512 | if ((ptr[0] & (ACPI_OSC_ERROR_REV | ACPI_OSC_ERROR_UUID)) != 0) { | 512 | if ((ptr[0] & (ACPI_OSC_ERROR_REV | ACPI_OSC_ERROR_UUID)) != 0) { | |
513 | rv = AE_BAD_PARAMETER; | 513 | rv = AE_BAD_PARAMETER; | |
514 | goto out; | 514 | goto out; | |
515 | } | 515 | } | |
516 | 516 | |||
517 | /* | 517 | /* | |
518 | * "It is strongly recommended that the OS evaluate | 518 | * "It is strongly recommended that the OS evaluate | |
519 | * _OSC with the Query Support Flag set until _OSC | 519 | * _OSC with the Query Support Flag set until _OSC | |
520 | * returns the Capabilities Masked bit clear, to | 520 | * returns the Capabilities Masked bit clear, to | |
521 | * negotiate the set of features to be granted to | 521 | * negotiate the set of features to be granted to | |
522 | * the OS for native support (ACPI 4.0, 6.2.10)." | 522 | * the OS for native support (ACPI 4.0, 6.2.10)." | |
523 | */ | 523 | */ | |
524 | if ((ptr[0] & ACPI_OSC_ERROR_MASKED) != 0 && i >= 0) { | 524 | if ((ptr[0] & ACPI_OSC_ERROR_MASKED) != 0 && i >= 0) { | |
525 | 525 | |||
526 | ACPI_FREE(buf.Pointer); | 526 | ACPI_FREE(buf.Pointer); | |
527 | i--; | 527 | i--; | |
528 | 528 | |||
529 | goto again; | 529 | goto again; | |
530 | } | 530 | } | |
531 | 531 | |||
532 | if ((cap[0] & ACPI_OSC_QUERY) != 0) { | 532 | if ((cap[0] & ACPI_OSC_QUERY) != 0) { | |
533 | 533 | |||
534 | ACPI_FREE(buf.Pointer); | 534 | ACPI_FREE(buf.Pointer); | |
535 | cap[0] &= ~ACPI_OSC_QUERY; | 535 | cap[0] &= ~ACPI_OSC_QUERY; | |
536 | 536 | |||
537 | goto again; | 537 | goto again; | |
538 | } | 538 | } | |
539 | 539 | |||
540 | /* | 540 | /* | |
541 | * It is permitted for _OSC to return all | 541 | * It is permitted for _OSC to return all | |
542 | * bits cleared, but this is specified to | 542 | * bits cleared, but this is specified to | |
543 | * vary on per-device basis. Assume that | 543 | * vary on per-device basis. Assume that | |
544 | * everything rather than nothing will be | 544 | * everything rather than nothing will be | |
545 | * supported in this case; we do not need | 545 | * supported in this case; we do not need | |
546 | * the firmware to know the CPU features. | 546 | * the firmware to know the CPU features. | |
547 | */ | 547 | */ | |
548 | *val = (ptr[1] != 0) ? ptr[1] : cap[1]; | 548 | *val = (ptr[1] != 0) ? ptr[1] : cap[1]; | |
549 | 549 | |||
550 | out: | 550 | out: | |
551 | if (buf.Pointer != NULL) | 551 | if (buf.Pointer != NULL) | |
552 | ACPI_FREE(buf.Pointer); | 552 | ACPI_FREE(buf.Pointer); | |
553 | 553 | |||
554 | return rv; | 554 | return rv; | |
555 | } | 555 | } | |
556 | 556 | |||
557 | static void | 557 | static void | |
558 | acpicpu_notify(ACPI_HANDLE hdl, uint32_t evt, void *aux) | 558 | acpicpu_notify(ACPI_HANDLE hdl, uint32_t evt, void *aux) | |
559 | { | 559 | { | |
560 | ACPI_OSD_EXEC_CALLBACK func; | 560 | ACPI_OSD_EXEC_CALLBACK func; | |
561 | struct acpicpu_softc *sc; | 561 | struct acpicpu_softc *sc; | |
562 | device_t self = aux; | 562 | device_t self = aux; | |
563 | 563 | |||
564 | sc = device_private(self); | 564 | sc = device_private(self); | |
565 | 565 | |||
566 | if (sc->sc_cold != false) | 566 | if (sc->sc_cold != false) | |
567 | return; | 567 | return; | |
568 | 568 | |||
569 | if (acpicpu_dynamic != true) | 569 | if (acpicpu_dynamic != true) | |
570 | return; | 570 | return; | |
571 | 571 | |||
572 | switch (evt) { | 572 | switch (evt) { | |
573 | 573 | |||
574 | case ACPICPU_C_NOTIFY: | 574 | case ACPICPU_C_NOTIFY: | |
575 | 575 | |||
576 | if ((sc->sc_flags & ACPICPU_FLAG_C) == 0) | 576 | if ((sc->sc_flags & ACPICPU_FLAG_C) == 0) | |
577 | return; | 577 | return; | |
578 | 578 | |||
579 | func = acpicpu_cstate_callback; | 579 | func = acpicpu_cstate_callback; | |
580 | break; | 580 | break; | |
581 | 581 | |||
582 | case ACPICPU_P_NOTIFY: | 582 | case ACPICPU_P_NOTIFY: | |
583 | 583 | |||
584 | if ((sc->sc_flags & ACPICPU_FLAG_P) == 0) | 584 | if ((sc->sc_flags & ACPICPU_FLAG_P) == 0) | |
585 | return; | 585 | return; | |
586 | 586 | |||
587 | func = acpicpu_pstate_callback; | 587 | func = acpicpu_pstate_callback; | |
588 | break; | 588 | break; | |
589 | 589 | |||
590 | case ACPICPU_T_NOTIFY: | 590 | case ACPICPU_T_NOTIFY: | |
591 | 591 | |||
592 | if ((sc->sc_flags & ACPICPU_FLAG_T) == 0) | 592 | if ((sc->sc_flags & ACPICPU_FLAG_T) == 0) | |
593 | return; | 593 | return; | |
594 | 594 | |||
595 | func = acpicpu_tstate_callback; | 595 | func = acpicpu_tstate_callback; | |
596 | break; | 596 | break; | |
597 | 597 | |||
598 | default: | 598 | default: | |
599 | aprint_error_dev(sc->sc_dev, "unknown notify: 0x%02X\n", evt); | 599 | aprint_error_dev(sc->sc_dev, "unknown notify: 0x%02X\n", evt); | |
600 | return; | 600 | return; | |
601 | } | 601 | } | |
602 | 602 | |||
603 | (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, sc->sc_dev); | 603 | (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, sc->sc_dev); | |
604 | } | 604 | } | |
605 | 605 | |||
606 | static bool | 606 | static bool | |
607 | acpicpu_suspend(device_t self, const pmf_qual_t *qual) | 607 | acpicpu_suspend(device_t self, const pmf_qual_t *qual) | |
608 | { | 608 | { | |
609 | struct acpicpu_softc *sc = device_private(self); | 609 | struct acpicpu_softc *sc = device_private(self); | |
610 | 610 | |||
611 | if ((sc->sc_flags & ACPICPU_FLAG_C) != 0) | 611 | if ((sc->sc_flags & ACPICPU_FLAG_C) != 0) | |
612 | (void)acpicpu_cstate_suspend(self); | 612 | (void)acpicpu_cstate_suspend(self); | |
613 | 613 | |||
614 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) | 614 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) | |
615 | (void)acpicpu_pstate_suspend(self); | 615 | (void)acpicpu_pstate_suspend(self); | |
616 | 616 | |||
617 | if ((sc->sc_flags & ACPICPU_FLAG_T) != 0) | 617 | if ((sc->sc_flags & ACPICPU_FLAG_T) != 0) | |
618 | (void)acpicpu_tstate_suspend(self); | 618 | (void)acpicpu_tstate_suspend(self); | |
619 | 619 | |||
620 | sc->sc_cold = true; | 620 | sc->sc_cold = true; | |
621 | 621 | |||
622 | return true; | 622 | return true; | |
623 | } | 623 | } | |
624 | 624 | |||
625 | static bool | 625 | static bool | |
626 | acpicpu_resume(device_t self, const pmf_qual_t *qual) | 626 | acpicpu_resume(device_t self, const pmf_qual_t *qual) | |
627 | { | 627 | { | |
628 | struct acpicpu_softc *sc = device_private(self); | 628 | struct acpicpu_softc *sc = device_private(self); | |
629 | static const int handler = OSL_NOTIFY_HANDLER; | 629 | static const int handler = OSL_NOTIFY_HANDLER; | |
630 | 630 | |||
631 | sc->sc_cold = false; | 631 | sc->sc_cold = false; | |
632 | 632 | |||
633 | if ((sc->sc_flags & ACPICPU_FLAG_C) != 0) | 633 | if ((sc->sc_flags & ACPICPU_FLAG_C) != 0) | |
634 | (void)AcpiOsExecute(handler, acpicpu_cstate_resume, self); | 634 | (void)AcpiOsExecute(handler, acpicpu_cstate_resume, self); | |
635 | 635 | |||
636 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) | 636 | if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) | |
637 | (void)AcpiOsExecute(handler, acpicpu_pstate_resume, self); | 637 | (void)AcpiOsExecute(handler, acpicpu_pstate_resume, self); | |
638 | 638 | |||
639 | if ((sc->sc_flags & ACPICPU_FLAG_T) != 0) | 639 | if ((sc->sc_flags & ACPICPU_FLAG_T) != 0) | |
640 | (void)AcpiOsExecute(handler, acpicpu_tstate_resume, self); | 640 | (void)AcpiOsExecute(handler, acpicpu_tstate_resume, self); | |
641 | 641 | |||
642 | return true; | 642 | return true; | |
643 | } | 643 | } | |
644 | 644 | |||
645 | static void | 645 | static void | |
646 | acpicpu_evcnt_attach(device_t self) | 646 | acpicpu_evcnt_attach(device_t self) | |
647 | { | 647 | { | |
648 | struct acpicpu_softc *sc = device_private(self); | 648 | struct acpicpu_softc *sc = device_private(self); | |
649 | struct acpicpu_cstate *cs; | 649 | struct acpicpu_cstate *cs; | |
650 | struct acpicpu_pstate *ps; | 650 | struct acpicpu_pstate *ps; | |
651 | struct acpicpu_tstate *ts; | 651 | struct acpicpu_tstate *ts; | |
652 | const char *str; | 652 | const char *str; | |
653 | uint32_t i; | 653 | uint32_t i; | |
654 | 654 | |||
655 | for (i = 0; i < __arraycount(sc->sc_cstate); i++) { | 655 | for (i = 0; i < __arraycount(sc->sc_cstate); i++) { | |
656 | 656 | |||
657 | cs = &sc->sc_cstate[i]; | 657 | cs = &sc->sc_cstate[i]; | |
658 | 658 | |||
659 | if (cs->cs_method == 0) | 659 | if (cs->cs_method == 0) | |
660 | continue; | 660 | continue; | |
661 | 661 | |||
662 | str = "HALT"; | 662 | str = "HALT"; | |
663 | 663 | |||
664 | if (cs->cs_method == ACPICPU_C_STATE_FFH) | 664 | if (cs->cs_method == ACPICPU_C_STATE_FFH) | |
665 | str = "MWAIT"; | 665 | str = "MWAIT"; | |
666 | 666 | |||
667 | if (cs->cs_method == ACPICPU_C_STATE_SYSIO) | 667 | if (cs->cs_method == ACPICPU_C_STATE_SYSIO) | |
668 | str = "I/O"; | 668 | str = "I/O"; | |
669 | 669 | |||
670 | (void)snprintf(cs->cs_name, sizeof(cs->cs_name), | 670 | (void)snprintf(cs->cs_name, sizeof(cs->cs_name), | |
671 | "C%d (%s)", i, str); | 671 | "C%d (%s)", i, str); | |
672 | 672 | |||
673 | evcnt_attach_dynamic(&cs->cs_evcnt, EVCNT_TYPE_MISC, | 673 | evcnt_attach_dynamic(&cs->cs_evcnt, EVCNT_TYPE_MISC, | |
674 | NULL, device_xname(sc->sc_dev), cs->cs_name); | 674 | NULL, device_xname(sc->sc_dev), cs->cs_name); | |
675 | } | 675 | } | |
676 | 676 | |||
677 | for (i = 0; i < sc->sc_pstate_count; i++) { | 677 | for (i = 0; i < sc->sc_pstate_count; i++) { | |
678 | 678 | |||
679 | ps = &sc->sc_pstate[i]; | 679 | ps = &sc->sc_pstate[i]; | |
680 | 680 | |||
681 | if (ps->ps_freq == 0) | 681 | if (ps->ps_freq == 0) | |
682 | continue; | 682 | continue; | |
683 | 683 | |||
684 | (void)snprintf(ps->ps_name, sizeof(ps->ps_name), | 684 | (void)snprintf(ps->ps_name, sizeof(ps->ps_name), | |
685 | "P%u (%u MHz)", i, ps->ps_freq); | 685 | "P%u (%u MHz)", i, ps->ps_freq); | |
686 | 686 | |||
687 | evcnt_attach_dynamic(&ps->ps_evcnt, EVCNT_TYPE_MISC, | 687 | evcnt_attach_dynamic(&ps->ps_evcnt, EVCNT_TYPE_MISC, | |
688 | NULL, device_xname(sc->sc_dev), ps->ps_name); | 688 | NULL, device_xname(sc->sc_dev), ps->ps_name); | |
689 | } | 689 | } | |
690 | 690 | |||
691 | for (i = 0; i < sc->sc_tstate_count; i++) { | 691 | for (i = 0; i < sc->sc_tstate_count; i++) { | |
692 | 692 | |||
693 | ts = &sc->sc_tstate[i]; | 693 | ts = &sc->sc_tstate[i]; | |
694 | 694 | |||
695 | if (ts->ts_percent == 0) | 695 | if (ts->ts_percent == 0) | |
696 | continue; | 696 | continue; | |
697 | 697 | |||
698 | (void)snprintf(ts->ts_name, sizeof(ts->ts_name), | 698 | (void)snprintf(ts->ts_name, sizeof(ts->ts_name), | |
699 | "T%u (%u %%)", i, ts->ts_percent); | 699 | "T%u (%u %%)", i, ts->ts_percent); | |
700 | 700 | |||
701 | evcnt_attach_dynamic(&ts->ts_evcnt, EVCNT_TYPE_MISC, | 701 | evcnt_attach_dynamic(&ts->ts_evcnt, EVCNT_TYPE_MISC, | |
702 | NULL, device_xname(sc->sc_dev), ts->ts_name); | 702 | NULL, device_xname(sc->sc_dev), ts->ts_name); | |
703 | } | 703 | } | |
704 | } | 704 | } | |
705 | 705 | |||
706 | static void | 706 | static void | |
707 | acpicpu_evcnt_detach(device_t self) | 707 | acpicpu_evcnt_detach(device_t self) | |
708 | { | 708 | { | |
709 | struct acpicpu_softc *sc = device_private(self); | 709 | struct acpicpu_softc *sc = device_private(self); | |
710 | struct acpicpu_cstate *cs; | 710 | struct acpicpu_cstate *cs; | |
711 | struct acpicpu_pstate *ps; | 711 | struct acpicpu_pstate *ps; | |
712 | struct acpicpu_tstate *ts; | 712 | struct acpicpu_tstate *ts; | |
713 | uint32_t i; | 713 | uint32_t i; | |
714 | 714 | |||
715 | for (i = 0; i < __arraycount(sc->sc_cstate); i++) { | 715 | for (i = 0; i < __arraycount(sc->sc_cstate); i++) { | |
716 | 716 | |||
717 | cs = &sc->sc_cstate[i]; | 717 | cs = &sc->sc_cstate[i]; | |
718 | 718 | |||
719 | if (cs->cs_method != 0) | 719 | if (cs->cs_method != 0) | |
720 | evcnt_detach(&cs->cs_evcnt); | 720 | evcnt_detach(&cs->cs_evcnt); | |
721 | } | 721 | } | |
722 | 722 | |||
723 | for (i = 0; i < sc->sc_pstate_count; i++) { | 723 | for (i = 0; i < sc->sc_pstate_count; i++) { | |
724 | 724 | |||
725 | ps = &sc->sc_pstate[i]; | 725 | ps = &sc->sc_pstate[i]; | |
726 | 726 | |||
727 | if (ps->ps_freq != 0) | 727 | if (ps->ps_freq != 0) | |
728 | evcnt_detach(&ps->ps_evcnt); | 728 | evcnt_detach(&ps->ps_evcnt); | |
729 | } | 729 | } | |
730 | 730 | |||
731 | for (i = 0; i < sc->sc_tstate_count; i++) { | 731 | for (i = 0; i < sc->sc_tstate_count; i++) { | |
732 | 732 | |||
733 | ts = &sc->sc_tstate[i]; | 733 | ts = &sc->sc_tstate[i]; | |
734 | 734 | |||
735 | if (ts->ts_percent != 0) | 735 | if (ts->ts_percent != 0) | |
736 | evcnt_detach(&ts->ts_evcnt); | 736 | evcnt_detach(&ts->ts_evcnt); | |
737 | } | 737 | } | |
738 | } | 738 | } | |
739 | 739 | |||
740 | static void | 740 | static void | |
741 | acpicpu_debug_print(device_t self) | 741 | acpicpu_debug_print(device_t self) | |
742 | { | 742 | { | |
743 | struct acpicpu_softc *sc = device_private(self); | 743 | struct acpicpu_softc *sc = device_private(self); | |
744 | struct cpu_info *ci = sc->sc_ci; | 744 | struct cpu_info *ci = sc->sc_ci; | |
745 | struct acpicpu_cstate *cs; | 745 | struct acpicpu_cstate *cs; | |
746 | struct acpicpu_pstate *ps; | 746 | struct acpicpu_pstate *ps; | |
747 | struct acpicpu_tstate *ts; | 747 | struct acpicpu_tstate *ts; | |
748 | static bool once = false; | 748 | static bool once = false; | |
749 | struct acpicpu_dep *dep; | 749 | struct acpicpu_dep *dep; | |
750 | uint32_t i, method; | 750 | uint32_t i, method; | |
751 | 751 | |||
752 | if (once != true) { | 752 | if (once != true) { | |
753 | 753 | |||
754 | for (i = 0; i < __arraycount(sc->sc_cstate); i++) { | 754 | for (i = 0; i < __arraycount(sc->sc_cstate); i++) { | |
755 | 755 | |||
756 | cs = &sc->sc_cstate[i]; | 756 | cs = &sc->sc_cstate[i]; | |
757 | 757 | |||
758 | if (cs->cs_method == 0) | 758 | if (cs->cs_method == 0) | |
759 | continue; | 759 | continue; | |
760 | 760 | |||
761 | aprint_verbose_dev(sc->sc_dev, "C%d: %3s, " | 761 | aprint_verbose_dev(sc->sc_dev, "C%d: %3s, " | |
762 | "lat %3u us, pow %5u mW%s\n", i, | 762 | "lat %3u us, pow %5u mW%s\n", i, | |
763 | acpicpu_debug_print_method_c(cs->cs_method), | 763 | acpicpu_debug_print_method_c(cs->cs_method), | |
764 | cs->cs_latency, cs->cs_power, | 764 | cs->cs_latency, cs->cs_power, | |
765 | (cs->cs_flags != 0) ? ", bus master check" : ""); | 765 | (cs->cs_flags != 0) ? ", bus master check" : ""); | |
766 | } | 766 | } | |
767 | 767 | |||
768 | method = sc->sc_pstate_control.reg_spaceid; | 768 | method = sc->sc_pstate_control.reg_spaceid; | |
769 | 769 | |||
770 | for (i = 0; i < sc->sc_pstate_count; i++) { | 770 | for (i = 0; i < sc->sc_pstate_count; i++) { | |
771 | 771 | |||
772 | ps = &sc->sc_pstate[i]; | 772 | ps = &sc->sc_pstate[i]; | |
773 | 773 | |||
774 | if (ps->ps_freq == 0) | 774 | if (ps->ps_freq == 0) | |
775 | continue; | 775 | continue; | |
776 | 776 | |||
777 | aprint_verbose_dev(sc->sc_dev, "P%d: %3s, " | 777 | aprint_verbose_dev(sc->sc_dev, "P%d: %3s, " | |
778 | "lat %3u us, pow %5u mW, %4u MHz%s\n", i, | 778 | "lat %3u us, pow %5u mW, %4u MHz%s\n", i, | |
779 | acpicpu_debug_print_method_pt(method), | 779 | acpicpu_debug_print_method_pt(method), | |
780 | ps->ps_latency, ps->ps_power, ps->ps_freq, | 780 | ps->ps_latency, ps->ps_power, ps->ps_freq, | |
781 | (ps->ps_flags & ACPICPU_FLAG_P_TURBO) != 0 ? | 781 | (ps->ps_flags & ACPICPU_FLAG_P_TURBO) != 0 ? | |
782 | ", turbo boost" : ""); | 782 | ", turbo boost" : ""); | |
783 | } | 783 | } | |
784 | 784 | |||
785 | method = sc->sc_tstate_control.reg_spaceid; | 785 | method = sc->sc_tstate_control.reg_spaceid; | |
786 | 786 | |||
787 | for (i = 0; i < sc->sc_tstate_count; i++) { | 787 | for (i = 0; i < sc->sc_tstate_count; i++) { | |
788 | 788 | |||
789 | ts = &sc->sc_tstate[i]; | 789 | ts = &sc->sc_tstate[i]; | |
790 | 790 | |||
791 | if (ts->ts_percent == 0) | 791 | if (ts->ts_percent == 0) | |
792 | continue; | 792 | continue; | |
793 | 793 | |||
794 | aprint_verbose_dev(sc->sc_dev, "T%u: %3s, " | 794 | aprint_verbose_dev(sc->sc_dev, "T%u: %3s, " | |
795 | "lat %3u us, pow %5u mW, %3u %%\n", i, | 795 | "lat %3u us, pow %5u mW, %3u %%\n", i, | |
796 | acpicpu_debug_print_method_pt(method), | 796 | acpicpu_debug_print_method_pt(method), | |
797 | ts->ts_latency, ts->ts_power, ts->ts_percent); | 797 | ts->ts_latency, ts->ts_power, ts->ts_percent); | |
798 | } | 798 | } | |
799 | 799 | |||
800 | once = true; | 800 | once = true; | |
801 | } | 801 | } | |
802 | 802 | |||
803 | aprint_debug_dev(sc->sc_dev, "id %u, lapic id %u, " | 803 | aprint_debug_dev(sc->sc_dev, "id %u, lapic id %u, " | |
804 | "cap 0x%04x, flags 0x%08x\n", ci->ci_acpiid, | 804 | "cap 0x%04x, flags 0x%08x\n", ci->ci_acpiid, | |
805 | (uint32_t)ci->ci_cpuid, sc->sc_cap, sc->sc_flags); | 805 | (uint32_t)ci->ci_cpuid, sc->sc_cap, sc->sc_flags); | |
806 | 806 | |||
807 | if ((sc->sc_flags & ACPICPU_FLAG_C_DEP) != 0) { | 807 | if ((sc->sc_flags & ACPICPU_FLAG_C_DEP) != 0) { | |
808 | 808 | |||
809 | dep = &sc->sc_cstate_dep; | 809 | dep = &sc->sc_cstate_dep; | |
810 | 810 | |||
811 | aprint_debug_dev(sc->sc_dev, "C-state coordination: " | 811 | aprint_debug_dev(sc->sc_dev, "C-state coordination: " | |
812 | "%u CPUs, domain %u, type %s\n", dep->dep_ncpus, | 812 | "%u CPUs, domain %u, type %s\n", dep->dep_ncpus, | |
813 | dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type)); | 813 | dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type)); | |
814 | } | 814 | } | |
815 | 815 | |||
816 | if ((sc->sc_flags & ACPICPU_FLAG_P_DEP) != 0) { | 816 | if ((sc->sc_flags & ACPICPU_FLAG_P_DEP) != 0) { | |
817 | 817 | |||
818 | dep = &sc->sc_pstate_dep; | 818 | dep = &sc->sc_pstate_dep; | |
819 | 819 | |||
820 | aprint_debug_dev(sc->sc_dev, "P-state coordination: " | 820 | aprint_debug_dev(sc->sc_dev, "P-state coordination: " | |
821 | "%u CPUs, domain %u, type %s\n", dep->dep_ncpus, | 821 | "%u CPUs, domain %u, type %s\n", dep->dep_ncpus, | |
822 | dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type)); | 822 | dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type)); | |
823 | } | 823 | } | |
824 | 824 | |||
825 | if ((sc->sc_flags & ACPICPU_FLAG_T_DEP) != 0) { | 825 | if ((sc->sc_flags & ACPICPU_FLAG_T_DEP) != 0) { | |
826 | 826 | |||
827 | dep = &sc->sc_tstate_dep; | 827 | dep = &sc->sc_tstate_dep; | |
828 | 828 | |||
829 | aprint_debug_dev(sc->sc_dev, "T-state coordination: " | 829 | aprint_debug_dev(sc->sc_dev, "T-state coordination: " | |
830 | "%u CPUs, domain %u, type %s\n", dep->dep_ncpus, | 830 | "%u CPUs, domain %u, type %s\n", dep->dep_ncpus, | |
831 | dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type)); | 831 | dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type)); | |
832 | } | 832 | } | |
833 | } | 833 | } | |
834 | 834 | |||
835 | static const char * | 835 | static const char * | |
836 | acpicpu_debug_print_method_c(uint8_t val) | 836 | acpicpu_debug_print_method_c(uint8_t val) | |
837 | { | 837 | { | |
838 | 838 | |||
839 | if (val == ACPICPU_C_STATE_FFH) | 839 | if (val == ACPICPU_C_STATE_FFH) | |
840 | return "FFH"; | 840 | return "FFH"; | |
841 | 841 | |||
842 | if (val == ACPICPU_C_STATE_HALT) | 842 | if (val == ACPICPU_C_STATE_HALT) | |
843 | return "HLT"; | 843 | return "HLT"; | |
844 | 844 | |||
845 | if (val == ACPICPU_C_STATE_SYSIO) | 845 | if (val == ACPICPU_C_STATE_SYSIO) | |
846 | return "I/O"; | 846 | return "I/O"; | |
847 | 847 | |||
848 | return "???"; | 848 | return "???"; | |
849 | } | 849 | } | |
850 | 850 | |||
851 | static const char * | 851 | static const char * | |
852 | acpicpu_debug_print_method_pt(uint8_t val) | 852 | acpicpu_debug_print_method_pt(uint8_t val) | |
853 | { | 853 | { | |
854 | 854 | |||
855 | if (val == ACPI_ADR_SPACE_SYSTEM_IO) | 855 | if (val == ACPI_ADR_SPACE_SYSTEM_IO) | |
856 | return "I/O"; | 856 | return "I/O"; | |
857 | 857 | |||
858 | if (val == ACPI_ADR_SPACE_FIXED_HARDWARE) | 858 | if (val == ACPI_ADR_SPACE_FIXED_HARDWARE) | |
859 | return "FFH"; | 859 | return "FFH"; | |
860 | 860 | |||
861 | return "???"; | 861 | return "???"; | |
862 | } | 862 | } | |
863 | 863 | |||
864 | static const char * | 864 | static const char * | |
865 | acpicpu_debug_print_dep(uint32_t val) | 865 | acpicpu_debug_print_dep(uint32_t val) | |
866 | { | 866 | { | |
867 | 867 | |||
868 | switch (val) { | 868 | switch (val) { | |
869 | 869 | |||
870 | case ACPICPU_DEP_SW_ALL: | 870 | case ACPICPU_DEP_SW_ALL: | |
871 | return "SW_ALL"; | 871 | return "SW_ALL"; | |
872 | 872 | |||
873 | case ACPICPU_DEP_SW_ANY: | 873 | case ACPICPU_DEP_SW_ANY: | |
874 | return "SW_ANY"; | 874 | return "SW_ANY"; | |
875 | 875 | |||
876 | case ACPICPU_DEP_HW_ALL: | 876 | case ACPICPU_DEP_HW_ALL: | |
877 | return "HW_ALL"; | 877 | return "HW_ALL"; | |
878 | 878 | |||
879 | default: | 879 | default: | |
880 | return "unknown"; | 880 | return "unknown"; | |
881 | } | 881 | } | |
882 | } | 882 | } | |
883 | 883 | |||
884 | MODULE(MODULE_CLASS_DRIVER, acpicpu, NULL); | 884 | MODULE(MODULE_CLASS_DRIVER, acpicpu, NULL); | |
885 | 885 | |||
886 | #ifdef _MODULE | 886 | #ifdef _MODULE | |
887 | #include "ioconf.c" | 887 | #include "ioconf.c" | |
888 | #endif | 888 | #endif | |
889 | 889 | |||
890 | static int | 890 | static int | |
891 | acpicpu_modcmd(modcmd_t cmd, void *aux) | 891 | acpicpu_modcmd(modcmd_t cmd, void *aux) | |
892 | { | 892 | { | |
893 | int rv = 0; | 893 | int rv = 0; | |
894 | 894 | |||
895 | switch (cmd) { | 895 | switch (cmd) { | |
896 | 896 | |||
897 | case MODULE_CMD_INIT: | 897 | case MODULE_CMD_INIT: | |
898 | 898 | |||
899 | #ifdef _MODULE | 899 | #ifdef _MODULE | |
900 | rv = config_init_component(cfdriver_ioconf_acpicpu, | 900 | rv = config_init_component(cfdriver_ioconf_acpicpu, | |
901 | cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu); | 901 | cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu); | |
902 | #endif | 902 | #endif | |
903 | break; | 903 | break; | |
904 | 904 | |||
905 | case MODULE_CMD_FINI: | 905 | case MODULE_CMD_FINI: | |
906 | 906 | |||
907 | #ifdef _MODULE | 907 | #ifdef _MODULE | |
908 | rv = config_fini_component(cfdriver_ioconf_acpicpu, | 908 | rv = config_fini_component(cfdriver_ioconf_acpicpu, | |
909 | cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu); | 909 | cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu); | |
910 | #endif | 910 | #endif | |
911 | break; | 911 | break; | |
912 | 912 | |||
913 | default: | 913 | default: | |
914 | rv = ENOTTY; | 914 | rv = ENOTTY; | |
915 | } | 915 | } | |
916 | 916 | |||
917 | return rv; | 917 | return rv; | |
918 | } | 918 | } |
--- src/sys/dev/acpi/acpi_quirks.c 2011/02/20 06:45:32 1.19
+++ src/sys/dev/acpi/acpi_quirks.c 2011/11/14 02:44:59 1.20
@@ -1,271 +1,271 @@ | @@ -1,271 +1,271 @@ | |||
1 | /* $NetBSD: acpi_quirks.c,v 1.19 2011/02/20 06:45:32 jruoho Exp $ */ | 1 | /* $NetBSD: acpi_quirks.c,v 1.20 2011/11/14 02:44:59 jmcneill Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * | 10 | * | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | 29 | |||
30 | /* | 30 | /* | |
31 | * Copyright 2002 Wasabi Systems, Inc. | 31 | * Copyright 2002 Wasabi Systems, Inc. | |
32 | * All rights reserved. | 32 | * All rights reserved. | |
33 | * | 33 | * | |
34 | * Written by Frank van der Linden for Wasabi Systems, Inc. | 34 | * Written by Frank van der Linden for Wasabi Systems, Inc. | |
35 | * | 35 | * | |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without | |
37 | * modification, are permitted provided that the following conditions | 37 | * modification, are permitted provided that the following conditions | |
38 | * are met: | 38 | * are met: | |
39 | * 1. Redistributions of source code must retain the above copyright | 39 | * 1. Redistributions of source code must retain the above copyright | |
40 | * notice, this list of conditions and the following disclaimer. | 40 | * notice, this list of conditions and the following disclaimer. | |
41 | * 2. Redistributions in binary form must reproduce the above copyright | 41 | * 2. Redistributions in binary form must reproduce the above copyright | |
42 | * notice, this list of conditions and the following disclaimer in the | 42 | * notice, this list of conditions and the following disclaimer in the | |
43 | * documentation and/or other materials provided with the distribution. | 43 | * documentation and/or other materials provided with the distribution. | |
44 | * 3. All advertising materials mentioning features or use of this software | 44 | * 3. All advertising materials mentioning features or use of this software | |
45 | * must display the following acknowledgement: | 45 | * must display the following acknowledgement: | |
46 | * This product includes software developed for the NetBSD Project by | 46 | * This product includes software developed for the NetBSD Project by | |
47 | * Wasabi Systems, Inc. | 47 | * Wasabi Systems, Inc. | |
48 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | 48 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | |
49 | * or promote products derived from this software without specific prior | 49 | * or promote products derived from this software without specific prior | |
50 | * written permission. | 50 | * written permission. | |
51 | * | 51 | * | |
52 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | 52 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | |
53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
54 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 54 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
55 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | 55 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | |
56 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 56 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
57 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 57 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
58 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 58 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
59 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 59 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
60 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 60 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
61 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 61 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
62 | * POSSIBILITY OF SUCH DAMAGE. | 62 | * POSSIBILITY OF SUCH DAMAGE. | |
63 | */ | 63 | */ | |
64 | 64 | |||
65 | #include <sys/cdefs.h> | 65 | #include <sys/cdefs.h> | |
66 | 66 | |||
67 | __KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.19 2011/02/20 06:45:32 jruoho Exp $"); | 67 | __KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.20 2011/11/14 02:44:59 jmcneill Exp $"); | |
68 | 68 | |||
69 | #include "opt_acpi.h" | 69 | #include "opt_acpi.h" | |
70 | 70 | |||
71 | #include <sys/param.h> | 71 | #include <sys/param.h> | |
72 | 72 | |||
73 | #include <dev/acpi/acpireg.h> | 73 | #include <dev/acpi/acpireg.h> | |
74 | #include <dev/acpi/acpivar.h> | 74 | #include <dev/acpi/acpivar.h> | |
75 | 75 | |||
76 | #define _COMPONENT ACPI_UTILITIES | 76 | #define _COMPONENT ACPI_UTILITIES | |
77 | ACPI_MODULE_NAME ("acpi_quirks") | 77 | ACPI_MODULE_NAME ("acpi_quirks") | |
78 | 78 | |||
79 | #define AQ_GT 0 /* > */ | 79 | #define AQ_GT 0 /* > */ | |
80 | #define AQ_LT 1 /* < */ | 80 | #define AQ_LT 1 /* < */ | |
81 | #define AQ_GTE 2 /* >= */ | 81 | #define AQ_GTE 2 /* >= */ | |
82 | #define AQ_LTE 3 /* <= */ | 82 | #define AQ_LTE 3 /* <= */ | |
83 | #define AQ_EQ 4 /* == */ | 83 | #define AQ_EQ 4 /* == */ | |
84 | 84 | |||
85 | static int acpi_quirks_revcmp(uint32_t, uint32_t, int); | 85 | static int acpi_quirks_revcmp(uint32_t, uint32_t, int); | |
86 | 86 | |||
87 | static struct acpi_quirk acpi_quirks[] = { | 87 | static struct acpi_quirk acpi_quirks[] = { | |
88 | 88 | |||
89 | { ACPI_SIG_FADT, "ASUS ", 0x30303031, AQ_LTE, "CUV4X-D ", | 89 | { ACPI_SIG_FADT, "ASUS ", 0x30303031, AQ_LTE, "CUV4X-D ", | |
90 | ACPI_QUIRK_BROKEN }, | 90 | ACPI_QUIRK_BROKEN }, | |
91 | 91 | |||
92 | { ACPI_SIG_FADT, "PTLTD ", 0x06040000, AQ_LTE, " FACP ", | 92 | { ACPI_SIG_FADT, "PTLTD ", 0x06040000, AQ_LTE, " FACP ", | |
93 | ACPI_QUIRK_BROKEN }, | 93 | ACPI_QUIRK_BROKEN }, | |
94 | 94 | |||
95 | { ACPI_SIG_FADT, "NVIDIA", 0x06040000, AQ_EQ, "CK8 ", | 95 | { ACPI_SIG_FADT, "NVIDIA", 0x06040000, AQ_EQ, "CK8 ", | |
96 | ACPI_QUIRK_IRQ0 }, | 96 | ACPI_QUIRK_IRQ0 }, | |
97 | 97 | |||
98 | { ACPI_SIG_FADT, "HP ", 0x06040012, AQ_LTE, "HWPC20F ", | 98 | { ACPI_SIG_FADT, "HP ", 0x06040012, AQ_LTE, "HWPC20F ", | |
99 | ACPI_QUIRK_BROKEN }, | 99 | ACPI_QUIRK_BROKEN }, | |
100 | }; | 100 | }; | |
101 | 101 | |||
102 | static int | 102 | static int | |
103 | acpi_quirks_revcmp(uint32_t tabval, uint32_t wanted, int op) | 103 | acpi_quirks_revcmp(uint32_t tabval, uint32_t wanted, int op) | |
104 | { | 104 | { | |
105 | 105 | |||
106 | switch (op) { | 106 | switch (op) { | |
107 | 107 | |||
108 | case AQ_GT: | 108 | case AQ_GT: | |
109 | return (tabval > wanted) ? 0 : 1; | 109 | return (tabval > wanted) ? 0 : 1; | |
110 | 110 | |||
111 | case AQ_LT: | 111 | case AQ_LT: | |
112 | return (tabval < wanted) ? 0 : 1; | 112 | return (tabval < wanted) ? 0 : 1; | |
113 | 113 | |||
114 | case AQ_LTE: | 114 | case AQ_LTE: | |
115 | return (tabval <= wanted) ? 0 : 1; | 115 | return (tabval <= wanted) ? 0 : 1; | |
116 | 116 | |||
117 | case AQ_GTE: | 117 | case AQ_GTE: | |
118 | return (tabval >= wanted) ? 0 : 1; | 118 | return (tabval >= wanted) ? 0 : 1; | |
119 | 119 | |||
120 | case AQ_EQ: | 120 | case AQ_EQ: | |
121 | return (tabval == wanted) ? 0 : 1; | 121 | return (tabval == wanted) ? 0 : 1; | |
122 | 122 | |||
123 | default: | 123 | default: | |
124 | return 1; | 124 | return 1; | |
125 | } | 125 | } | |
126 | } | 126 | } | |
127 | 127 | |||
128 | #ifdef ACPI_BLACKLIST_YEAR | 128 | #ifdef ACPI_BLACKLIST_YEAR | |
129 | static int | 129 | static int | |
130 | acpi_quirks_bios_year(void) | 130 | acpi_quirks_bios_year(void) | |
131 | { | 131 | { | |
132 | const char *datestr = pmf_get_platform("firmware-date"); | 132 | const char *datestr = pmf_get_platform("bios-date"); | |
133 | unsigned long date; | 133 | unsigned long date; | |
134 | 134 | |||
135 | if (datestr == NULL) | 135 | if (datestr == NULL) | |
136 | return -1; | 136 | return -1; | |
137 | 137 | |||
138 | date = strtoul(datestr, NULL, 10); | 138 | date = strtoul(datestr, NULL, 10); | |
139 | if (date == 0 || date == ULONG_MAX) | 139 | if (date == 0 || date == ULONG_MAX) | |
140 | return -1; | 140 | return -1; | |
141 | if (date < 19000000 || date > 99999999) | 141 | if (date < 19000000 || date > 99999999) | |
142 | return -1; | 142 | return -1; | |
143 | return date / 10000; | 143 | return date / 10000; | |
144 | } | 144 | } | |
145 | #endif | 145 | #endif | |
146 | 146 | |||
147 | /* | 147 | /* | |
148 | * Simple function to search the quirk table. Only to be | 148 | * Simple function to search the quirk table. Only to be | |
149 | * used after AcpiLoadTables() has been successfully called. | 149 | * used after AcpiLoadTables() has been successfully called. | |
150 | */ | 150 | */ | |
151 | int | 151 | int | |
152 | acpi_find_quirks(void) | 152 | acpi_find_quirks(void) | |
153 | { | 153 | { | |
154 | ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr; | 154 | ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr; | |
155 | struct acpi_quirk *aq; | 155 | struct acpi_quirk *aq; | |
156 | ACPI_STATUS rv; | 156 | ACPI_STATUS rv; | |
157 | size_t i, len; | 157 | size_t i, len; | |
158 | 158 | |||
159 | #ifdef ACPI_BLACKLIST_YEAR | 159 | #ifdef ACPI_BLACKLIST_YEAR | |
160 | int year = acpi_quirks_bios_year(); | 160 | int year = acpi_quirks_bios_year(); | |
161 | 161 | |||
162 | if (year != -1 && year <= ACPI_BLACKLIST_YEAR) | 162 | if (year != -1 && year <= ACPI_BLACKLIST_YEAR) | |
163 | return ACPI_QUIRK_OLDBIOS; | 163 | return ACPI_QUIRK_OLDBIOS; | |
164 | #endif | 164 | #endif | |
165 | 165 | |||
166 | rv = AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt); | 166 | rv = AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt); | |
167 | 167 | |||
168 | if (ACPI_FAILURE(rv)) | 168 | if (ACPI_FAILURE(rv)) | |
169 | (void)memset(&fadt, 0, sizeof(fadt)); | 169 | (void)memset(&fadt, 0, sizeof(fadt)); | |
170 | 170 | |||
171 | rv = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt); | 171 | rv = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt); | |
172 | 172 | |||
173 | if (ACPI_FAILURE(rv)) | 173 | if (ACPI_FAILURE(rv)) | |
174 | (void)memset(&dsdt, 0, sizeof(dsdt)); | 174 | (void)memset(&dsdt, 0, sizeof(dsdt)); | |
175 | 175 | |||
176 | rv = AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt); | 176 | rv = AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt); | |
177 | 177 | |||
178 | if (ACPI_FAILURE(rv)) | 178 | if (ACPI_FAILURE(rv)) | |
179 | (void)memset(&xsdt, 0, sizeof(xsdt)); | 179 | (void)memset(&xsdt, 0, sizeof(xsdt)); | |
180 | 180 | |||
181 | for (i = 0; i < __arraycount(acpi_quirks); i++) { | 181 | for (i = 0; i < __arraycount(acpi_quirks); i++) { | |
182 | 182 | |||
183 | aq = &acpi_quirks[i]; | 183 | aq = &acpi_quirks[i]; | |
184 | 184 | |||
185 | if (strncmp(aq->aq_tabletype, ACPI_SIG_DSDT, 4) == 0) | 185 | if (strncmp(aq->aq_tabletype, ACPI_SIG_DSDT, 4) == 0) | |
186 | hdr = &dsdt; | 186 | hdr = &dsdt; | |
187 | else if (strncmp(aq->aq_tabletype, ACPI_SIG_XSDT, 4) == 0) | 187 | else if (strncmp(aq->aq_tabletype, ACPI_SIG_XSDT, 4) == 0) | |
188 | hdr = &xsdt; | 188 | hdr = &xsdt; | |
189 | else if (strncmp(aq->aq_tabletype, ACPI_SIG_FADT, 4) == 0) | 189 | else if (strncmp(aq->aq_tabletype, ACPI_SIG_FADT, 4) == 0) | |
190 | hdr = &fadt; | 190 | hdr = &fadt; | |
191 | else { | 191 | else { | |
192 | continue; | 192 | continue; | |
193 | } | 193 | } | |
194 | 194 | |||
195 | len = strlen(aq->aq_oemid); | 195 | len = strlen(aq->aq_oemid); | |
196 | 196 | |||
197 | if (strncmp(aq->aq_oemid, hdr->OemId, len) != 0) | 197 | if (strncmp(aq->aq_oemid, hdr->OemId, len) != 0) | |
198 | continue; | 198 | continue; | |
199 | 199 | |||
200 | if (acpi_quirks_revcmp(aq->aq_oemrev, | 200 | if (acpi_quirks_revcmp(aq->aq_oemrev, | |
201 | hdr->OemRevision, aq->aq_cmpop) != 0) | 201 | hdr->OemRevision, aq->aq_cmpop) != 0) | |
202 | continue; | 202 | continue; | |
203 | 203 | |||
204 | len = strlen(aq->aq_tabid); | 204 | len = strlen(aq->aq_tabid); | |
205 | 205 | |||
206 | if (strncmp(aq->aq_tabid, hdr->OemTableId, len) != 0) | 206 | if (strncmp(aq->aq_tabid, hdr->OemTableId, len) != 0) | |
207 | continue; | 207 | continue; | |
208 | 208 | |||
209 | return aq->aq_quirks; | 209 | return aq->aq_quirks; | |
210 | } | 210 | } | |
211 | 211 | |||
212 | return 0; | 212 | return 0; | |
213 | } | 213 | } | |
214 | 214 | |||
215 | /* | 215 | /* | |
216 | * Add or delete a string to the list that should return | 216 | * Add or delete a string to the list that should return | |
217 | * true when _OSI is being queried. The defaults are: | 217 | * true when _OSI is being queried. The defaults are: | |
218 | * | 218 | * | |
219 | * "Windows 2000" # Windows 2000 | 219 | * "Windows 2000" # Windows 2000 | |
220 | * "Windows 2001" # Windows XP | 220 | * "Windows 2001" # Windows XP | |
221 | * "Windows 2001 SP1" # Windows XP SP1 | 221 | * "Windows 2001 SP1" # Windows XP SP1 | |
222 | * "Windows 2001.1" # Windows Server 2003 | 222 | * "Windows 2001.1" # Windows Server 2003 | |
223 | * "Windows 2001 SP2" # Windows XP SP2 | 223 | * "Windows 2001 SP2" # Windows XP SP2 | |
224 | * "Windows 2001.1 SP1" # Windows Server 2003 SP1 | 224 | * "Windows 2001.1 SP1" # Windows Server 2003 SP1 | |
225 | * "Windows 2006" # Windows Vista | 225 | * "Windows 2006" # Windows Vista | |
226 | * "Windows 2006.1" # Windows Server 2008 | 226 | * "Windows 2006.1" # Windows Server 2008 | |
227 | * "Windows 2006 SP1" # Windows Vista SP1 | 227 | * "Windows 2006 SP1" # Windows Vista SP1 | |
228 | * "Windows 2006 SP2" # Windows Vista SP2 | 228 | * "Windows 2006 SP2" # Windows Vista SP2 | |
229 | * "Windows 2009" # Windows 7 and Server 2008 | 229 | * "Windows 2009" # Windows 7 and Server 2008 | |
230 | */ | 230 | */ | |
231 | int | 231 | int | |
232 | acpi_quirks_osi_add(const char *str) | 232 | acpi_quirks_osi_add(const char *str) | |
233 | { | 233 | { | |
234 | ACPI_STATUS rv; | 234 | ACPI_STATUS rv; | |
235 | 235 | |||
236 | if (str == NULL || *str == '\0') | 236 | if (str == NULL || *str == '\0') | |
237 | return EINVAL; | 237 | return EINVAL; | |
238 | 238 | |||
239 | rv = AcpiInstallInterface(__UNCONST(str)); | 239 | rv = AcpiInstallInterface(__UNCONST(str)); | |
240 | 240 | |||
241 | return (rv != AE_OK) ? EIO : 0; | 241 | return (rv != AE_OK) ? EIO : 0; | |
242 | } | 242 | } | |
243 | 243 | |||
244 | int | 244 | int | |
245 | acpi_quirks_osi_del(const char *str) | 245 | acpi_quirks_osi_del(const char *str) | |
246 | { | 246 | { | |
247 | ACPI_STATUS rv; | 247 | ACPI_STATUS rv; | |
248 | 248 | |||
249 | if (str == NULL || *str == '\0') | 249 | if (str == NULL || *str == '\0') | |
250 | return EINVAL; | 250 | return EINVAL; | |
251 | 251 | |||
252 | rv = AcpiRemoveInterface(__UNCONST(str)); | 252 | rv = AcpiRemoveInterface(__UNCONST(str)); | |
253 | 253 | |||
254 | return (rv != AE_OK) ? EIO : 0; | 254 | return (rv != AE_OK) ? EIO : 0; | |
255 | } | 255 | } | |
256 | 256 | |||
257 | #if 0 | 257 | #if 0 | |
258 | static void | 258 | static void | |
259 | acpi_quirks_osi_linux(void) | 259 | acpi_quirks_osi_linux(void) | |
260 | { | 260 | { | |
261 | (void)acpi_quirks_osi_add("Linux"); | 261 | (void)acpi_quirks_osi_add("Linux"); | |
262 | } | 262 | } | |
263 | 263 | |||
264 | static void | 264 | static void | |
265 | acpi_quirks_osi_vista(void) | 265 | acpi_quirks_osi_vista(void) | |
266 | { | 266 | { | |
267 | (void)acpi_quirks_osi_del("Windows 2006"); | 267 | (void)acpi_quirks_osi_del("Windows 2006"); | |
268 | (void)acpi_quirks_osi_del("Windows 2006 SP1"); | 268 | (void)acpi_quirks_osi_del("Windows 2006 SP1"); | |
269 | (void)acpi_quirks_osi_del("Windows 2006 SP2"); | 269 | (void)acpi_quirks_osi_del("Windows 2006 SP2"); | |
270 | } | 270 | } | |
271 | #endif | 271 | #endif |