| @@ -1,689 +1,717 @@ | | | @@ -1,689 +1,717 @@ |
1 | /* $NetBSD: acpi_util.c,v 1.16 2019/12/22 15:57:07 thorpej Exp $ */ | | 1 | /* $NetBSD: acpi_util.c,v 1.17 2019/12/29 13:45:11 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 2001, 2003 Wasabi Systems, Inc. | | 33 | * Copyright 2001, 2003 Wasabi Systems, Inc. |
34 | * All rights reserved. | | 34 | * All rights reserved. |
35 | * | | 35 | * |
36 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | | 36 | * Written by Jason R. Thorpe 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 | #include <sys/cdefs.h> | | 67 | #include <sys/cdefs.h> |
68 | __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.16 2019/12/22 15:57:07 thorpej Exp $"); | | 68 | __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.17 2019/12/29 13:45:11 jmcneill Exp $"); |
69 | | | 69 | |
70 | #include <sys/param.h> | | 70 | #include <sys/param.h> |
71 | #include <sys/kmem.h> | | 71 | #include <sys/kmem.h> |
72 | #include <sys/cpu.h> | | 72 | #include <sys/cpu.h> |
73 | | | 73 | |
74 | #include <dev/acpi/acpireg.h> | | 74 | #include <dev/acpi/acpireg.h> |
75 | #include <dev/acpi/acpivar.h> | | 75 | #include <dev/acpi/acpivar.h> |
76 | #include <dev/acpi/acpi_intr.h> | | 76 | #include <dev/acpi/acpi_intr.h> |
77 | | | 77 | |
78 | #include <machine/acpi_machdep.h> | | 78 | #include <machine/acpi_machdep.h> |
79 | | | 79 | |
80 | #define _COMPONENT ACPI_BUS_COMPONENT | | 80 | #define _COMPONENT ACPI_BUS_COMPONENT |
81 | ACPI_MODULE_NAME ("acpi_util") | | 81 | ACPI_MODULE_NAME ("acpi_util") |
82 | | | 82 | |
83 | static void acpi_clean_node(ACPI_HANDLE, void *); | | 83 | static void acpi_clean_node(ACPI_HANDLE, void *); |
84 | | | 84 | |
85 | static const char * const acpicpu_ids[] = { | | 85 | static const char * const acpicpu_ids[] = { |
86 | "ACPI0007", | | 86 | "ACPI0007", |
87 | NULL | | 87 | NULL |
88 | }; | | 88 | }; |
89 | | | 89 | |
90 | /* | | 90 | /* |
91 | * Evaluate an integer object. | | 91 | * Evaluate an integer object. |
92 | */ | | 92 | */ |
93 | ACPI_STATUS | | 93 | ACPI_STATUS |
94 | acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) | | 94 | acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp) |
95 | { | | 95 | { |
96 | ACPI_OBJECT obj; | | 96 | ACPI_OBJECT obj; |
97 | ACPI_BUFFER buf; | | 97 | ACPI_BUFFER buf; |
98 | ACPI_STATUS rv; | | 98 | ACPI_STATUS rv; |
99 | | | 99 | |
100 | if (handle == NULL) | | 100 | if (handle == NULL) |
101 | handle = ACPI_ROOT_OBJECT; | | 101 | handle = ACPI_ROOT_OBJECT; |
102 | | | 102 | |
103 | (void)memset(&obj, 0, sizeof(obj)); | | 103 | (void)memset(&obj, 0, sizeof(obj)); |
104 | buf.Pointer = &obj; | | 104 | buf.Pointer = &obj; |
105 | buf.Length = sizeof(obj); | | 105 | buf.Length = sizeof(obj); |
106 | | | 106 | |
107 | rv = AcpiEvaluateObject(handle, path, NULL, &buf); | | 107 | rv = AcpiEvaluateObject(handle, path, NULL, &buf); |
108 | | | 108 | |
109 | if (ACPI_FAILURE(rv)) | | 109 | if (ACPI_FAILURE(rv)) |
110 | return rv; | | 110 | return rv; |
111 | | | 111 | |
112 | /* Check that evaluation produced a return value. */ | | 112 | /* Check that evaluation produced a return value. */ |
113 | if (buf.Length == 0) | | 113 | if (buf.Length == 0) |
114 | return AE_NULL_OBJECT; | | 114 | return AE_NULL_OBJECT; |
115 | | | 115 | |
116 | if (obj.Type != ACPI_TYPE_INTEGER) | | 116 | if (obj.Type != ACPI_TYPE_INTEGER) |
117 | return AE_TYPE; | | 117 | return AE_TYPE; |
118 | | | 118 | |
119 | if (valp != NULL) | | 119 | if (valp != NULL) |
120 | *valp = obj.Integer.Value; | | 120 | *valp = obj.Integer.Value; |
121 | | | 121 | |
122 | return AE_OK; | | 122 | return AE_OK; |
123 | } | | 123 | } |
124 | | | 124 | |
125 | /* | | 125 | /* |
126 | * Evaluate an integer object with a single integer input parameter. | | 126 | * Evaluate an integer object with a single integer input parameter. |
127 | */ | | 127 | */ |
128 | ACPI_STATUS | | 128 | ACPI_STATUS |
129 | acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) | | 129 | acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER val) |
130 | { | | 130 | { |
131 | ACPI_OBJECT_LIST arg; | | 131 | ACPI_OBJECT_LIST arg; |
132 | ACPI_OBJECT obj; | | 132 | ACPI_OBJECT obj; |
133 | | | 133 | |
134 | if (handle == NULL) | | 134 | if (handle == NULL) |
135 | handle = ACPI_ROOT_OBJECT; | | 135 | handle = ACPI_ROOT_OBJECT; |
136 | | | 136 | |
137 | obj.Type = ACPI_TYPE_INTEGER; | | 137 | obj.Type = ACPI_TYPE_INTEGER; |
138 | obj.Integer.Value = val; | | 138 | obj.Integer.Value = val; |
139 | | | 139 | |
140 | arg.Count = 1; | | 140 | arg.Count = 1; |
141 | arg.Pointer = &obj; | | 141 | arg.Pointer = &obj; |
142 | | | 142 | |
143 | return AcpiEvaluateObject(handle, path, &arg, NULL); | | 143 | return AcpiEvaluateObject(handle, path, &arg, NULL); |
144 | } | | 144 | } |
145 | | | 145 | |
146 | /* | | 146 | /* |
147 | * Evaluate a (Unicode) string object. | | 147 | * Evaluate a (Unicode) string object. |
148 | */ | | 148 | */ |
149 | ACPI_STATUS | | 149 | ACPI_STATUS |
150 | acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) | | 150 | acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp) |
151 | { | | 151 | { |
152 | ACPI_OBJECT *obj; | | 152 | ACPI_OBJECT *obj; |
153 | ACPI_BUFFER buf; | | 153 | ACPI_BUFFER buf; |
154 | ACPI_STATUS rv; | | 154 | ACPI_STATUS rv; |
155 | | | 155 | |
156 | rv = acpi_eval_struct(handle, path, &buf); | | 156 | rv = acpi_eval_struct(handle, path, &buf); |
157 | | | 157 | |
158 | if (ACPI_FAILURE(rv)) | | 158 | if (ACPI_FAILURE(rv)) |
159 | return rv; | | 159 | return rv; |
160 | | | 160 | |
161 | obj = buf.Pointer; | | 161 | obj = buf.Pointer; |
162 | | | 162 | |
163 | if (obj->Type != ACPI_TYPE_STRING) { | | 163 | if (obj->Type != ACPI_TYPE_STRING) { |
164 | rv = AE_TYPE; | | 164 | rv = AE_TYPE; |
165 | goto out; | | 165 | goto out; |
166 | } | | 166 | } |
167 | | | 167 | |
168 | if (obj->String.Length == 0) { | | 168 | if (obj->String.Length == 0) { |
169 | rv = AE_BAD_DATA; | | 169 | rv = AE_BAD_DATA; |
170 | goto out; | | 170 | goto out; |
171 | } | | 171 | } |
172 | | | 172 | |
173 | *stringp = ACPI_ALLOCATE(obj->String.Length + 1); | | 173 | *stringp = ACPI_ALLOCATE(obj->String.Length + 1); |
174 | | | 174 | |
175 | if (*stringp == NULL) { | | 175 | if (*stringp == NULL) { |
176 | rv = AE_NO_MEMORY; | | 176 | rv = AE_NO_MEMORY; |
177 | goto out; | | 177 | goto out; |
178 | } | | 178 | } |
179 | | | 179 | |
180 | (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); | | 180 | (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length); |
181 | | | 181 | |
182 | (*stringp)[obj->String.Length] = '\0'; | | 182 | (*stringp)[obj->String.Length] = '\0'; |
183 | | | 183 | |
184 | out: | | 184 | out: |
185 | ACPI_FREE(buf.Pointer); | | 185 | ACPI_FREE(buf.Pointer); |
186 | | | 186 | |
187 | return rv; | | 187 | return rv; |
188 | } | | 188 | } |
189 | | | 189 | |
190 | /* | | 190 | /* |
191 | * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). | | 191 | * Evaluate a structure. Caller must free buf.Pointer by ACPI_FREE(). |
192 | */ | | 192 | */ |
193 | ACPI_STATUS | | 193 | ACPI_STATUS |
194 | acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) | | 194 | acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *buf) |
195 | { | | 195 | { |
196 | | | 196 | |
197 | if (handle == NULL) | | 197 | if (handle == NULL) |
198 | handle = ACPI_ROOT_OBJECT; | | 198 | handle = ACPI_ROOT_OBJECT; |
199 | | | 199 | |
200 | buf->Pointer = NULL; | | 200 | buf->Pointer = NULL; |
201 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; | | 201 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; |
202 | | | 202 | |
203 | return AcpiEvaluateObject(handle, path, NULL, buf); | | 203 | return AcpiEvaluateObject(handle, path, NULL, buf); |
204 | } | | 204 | } |
205 | | | 205 | |
206 | /* | | 206 | /* |
207 | * Evaluate a reference handle from an element in a package. | | 207 | * Evaluate a reference handle from an element in a package. |
208 | */ | | 208 | */ |
209 | ACPI_STATUS | | 209 | ACPI_STATUS |
210 | acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) | | 210 | acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle) |
211 | { | | 211 | { |
212 | | | 212 | |
213 | if (elm == NULL || handle == NULL) | | 213 | if (elm == NULL || handle == NULL) |
214 | return AE_BAD_PARAMETER; | | 214 | return AE_BAD_PARAMETER; |
215 | | | 215 | |
216 | switch (elm->Type) { | | 216 | switch (elm->Type) { |
217 | | | 217 | |
218 | case ACPI_TYPE_ANY: | | 218 | case ACPI_TYPE_ANY: |
219 | case ACPI_TYPE_LOCAL_REFERENCE: | | 219 | case ACPI_TYPE_LOCAL_REFERENCE: |
220 | | | 220 | |
221 | if (elm->Reference.Handle == NULL) | | 221 | if (elm->Reference.Handle == NULL) |
222 | return AE_NULL_ENTRY; | | 222 | return AE_NULL_ENTRY; |
223 | | | 223 | |
224 | *handle = elm->Reference.Handle; | | 224 | *handle = elm->Reference.Handle; |
225 | | | 225 | |
226 | return AE_OK; | | 226 | return AE_OK; |
227 | | | 227 | |
228 | case ACPI_TYPE_STRING: | | 228 | case ACPI_TYPE_STRING: |
229 | return AcpiGetHandle(NULL, elm->String.Pointer, handle); | | 229 | return AcpiGetHandle(NULL, elm->String.Pointer, handle); |
230 | | | 230 | |
231 | default: | | 231 | default: |
232 | return AE_TYPE; | | 232 | return AE_TYPE; |
233 | } | | 233 | } |
234 | } | | 234 | } |
235 | | | 235 | |
236 | /* | | 236 | /* |
237 | * Iterate over all objects in a package, and pass them all | | 237 | * Iterate over all objects in a package, and pass them all |
238 | * to a function. If the called function returns non-AE_OK, | | 238 | * to a function. If the called function returns non-AE_OK, |
239 | * the iteration is stopped and that value is returned. | | 239 | * the iteration is stopped and that value is returned. |
240 | */ | | 240 | */ |
241 | ACPI_STATUS | | 241 | ACPI_STATUS |
242 | acpi_foreach_package_object(ACPI_OBJECT *pkg, | | 242 | acpi_foreach_package_object(ACPI_OBJECT *pkg, |
243 | ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) | | 243 | ACPI_STATUS (*func)(ACPI_OBJECT *, void *), void *arg) |
244 | { | | 244 | { |
245 | ACPI_STATUS rv = AE_OK; | | 245 | ACPI_STATUS rv = AE_OK; |
246 | uint32_t i; | | 246 | uint32_t i; |
247 | | | 247 | |
248 | if (pkg == NULL) | | 248 | if (pkg == NULL) |
249 | return AE_BAD_PARAMETER; | | 249 | return AE_BAD_PARAMETER; |
250 | | | 250 | |
251 | if (pkg->Type != ACPI_TYPE_PACKAGE) | | 251 | if (pkg->Type != ACPI_TYPE_PACKAGE) |
252 | return AE_TYPE; | | 252 | return AE_TYPE; |
253 | | | 253 | |
254 | for (i = 0; i < pkg->Package.Count; i++) { | | 254 | for (i = 0; i < pkg->Package.Count; i++) { |
255 | | | 255 | |
256 | rv = (*func)(&pkg->Package.Elements[i], arg); | | 256 | rv = (*func)(&pkg->Package.Elements[i], arg); |
257 | | | 257 | |
258 | if (ACPI_FAILURE(rv)) | | 258 | if (ACPI_FAILURE(rv)) |
259 | break; | | 259 | break; |
260 | } | | 260 | } |
261 | | | 261 | |
262 | return rv; | | 262 | return rv; |
263 | } | | 263 | } |
264 | | | 264 | |
265 | /* | | 265 | /* |
266 | * Fetch data info the specified (empty) ACPI buffer. | | 266 | * Fetch data info the specified (empty) ACPI buffer. |
267 | * Caller must free buf.Pointer by ACPI_FREE(). | | 267 | * Caller must free buf.Pointer by ACPI_FREE(). |
268 | */ | | 268 | */ |
269 | ACPI_STATUS | | 269 | ACPI_STATUS |
270 | acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, | | 270 | acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf, |
271 | ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) | | 271 | ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *)) |
272 | { | | 272 | { |
273 | | | 273 | |
274 | buf->Pointer = NULL; | | 274 | buf->Pointer = NULL; |
275 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; | | 275 | buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER; |
276 | | | 276 | |
277 | return (*getit)(handle, buf); | | 277 | return (*getit)(handle, buf); |
278 | } | | 278 | } |
279 | | | 279 | |
280 | /* | | 280 | /* |
281 | * Return a complete pathname from a handle. | | 281 | * Return a complete pathname from a handle. |
282 | * | | 282 | * |
283 | * Note that the function uses static data storage; | | 283 | * Note that the function uses static data storage; |
284 | * if the data is needed for future use, it should be | | 284 | * if the data is needed for future use, it should be |
285 | * copied before any subsequent calls overwrite it. | | 285 | * copied before any subsequent calls overwrite it. |
286 | */ | | 286 | */ |
287 | const char * | | 287 | const char * |
288 | acpi_name(ACPI_HANDLE handle) | | 288 | acpi_name(ACPI_HANDLE handle) |
289 | { | | 289 | { |
290 | static char name[80]; | | 290 | static char name[80]; |
291 | ACPI_BUFFER buf; | | 291 | ACPI_BUFFER buf; |
292 | ACPI_STATUS rv; | | 292 | ACPI_STATUS rv; |
293 | | | 293 | |
294 | if (handle == NULL) | | 294 | if (handle == NULL) |
295 | handle = ACPI_ROOT_OBJECT; | | 295 | handle = ACPI_ROOT_OBJECT; |
296 | | | 296 | |
297 | buf.Pointer = name; | | 297 | buf.Pointer = name; |
298 | buf.Length = sizeof(name); | | 298 | buf.Length = sizeof(name); |
299 | | | 299 | |
300 | rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); | | 300 | rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf); |
301 | | | 301 | |
302 | if (ACPI_FAILURE(rv)) | | 302 | if (ACPI_FAILURE(rv)) |
303 | return "UNKNOWN"; | | 303 | return "UNKNOWN"; |
304 | | | 304 | |
305 | return name; | | 305 | return name; |
306 | } | | 306 | } |
307 | | | 307 | |
308 | /* | | 308 | /* |
309 | * Match given IDs against _HID and _CIDs. | | 309 | * Match given IDs against _HID and _CIDs. |
310 | */ | | 310 | */ |
311 | int | | 311 | int |
312 | acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) | | 312 | acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids) |
313 | { | | 313 | { |
314 | uint32_t i, n; | | 314 | uint32_t i, n; |
315 | char *id; | | 315 | char *id; |
316 | | | 316 | |
317 | while (*ids) { | | 317 | while (*ids) { |
318 | | | 318 | |
319 | if ((ad->Valid & ACPI_VALID_HID) != 0) { | | 319 | if ((ad->Valid & ACPI_VALID_HID) != 0) { |
320 | | | 320 | |
321 | if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) | | 321 | if (pmatch(ad->HardwareId.String, *ids, NULL) == 2) |
322 | return 1; | | 322 | return 1; |
323 | } | | 323 | } |
324 | | | 324 | |
325 | if ((ad->Valid & ACPI_VALID_CID) != 0) { | | 325 | if ((ad->Valid & ACPI_VALID_CID) != 0) { |
326 | | | 326 | |
327 | n = ad->CompatibleIdList.Count; | | 327 | n = ad->CompatibleIdList.Count; |
328 | | | 328 | |
329 | for (i = 0; i < n; i++) { | | 329 | for (i = 0; i < n; i++) { |
330 | | | 330 | |
331 | id = ad->CompatibleIdList.Ids[i].String; | | 331 | id = ad->CompatibleIdList.Ids[i].String; |
332 | | | 332 | |
333 | if (pmatch(id, *ids, NULL) == 2) | | 333 | if (pmatch(id, *ids, NULL) == 2) |
334 | return 1; | | 334 | return 1; |
335 | } | | 335 | } |
336 | } | | 336 | } |
337 | | | 337 | |
338 | ids++; | | 338 | ids++; |
339 | } | | 339 | } |
340 | | | 340 | |
341 | return 0; | | 341 | return 0; |
342 | } | | 342 | } |
343 | | | 343 | |
344 | /* | | 344 | /* |
345 | * Match a PCI-defined bass-class, sub-class, and programming interface | | 345 | * Match a PCI-defined bass-class, sub-class, and programming interface |
346 | * against a handle's _CLS object. | | 346 | * against a handle's _CLS object. |
347 | */ | | 347 | */ |
348 | int | | 348 | int |
349 | acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass, | | 349 | acpi_match_class(ACPI_HANDLE handle, uint8_t pci_class, uint8_t pci_subclass, |
350 | uint8_t pci_interface) | | 350 | uint8_t pci_interface) |
351 | { | | 351 | { |
352 | ACPI_BUFFER buf; | | 352 | ACPI_BUFFER buf; |
353 | ACPI_OBJECT *obj; | | 353 | ACPI_OBJECT *obj; |
354 | ACPI_STATUS rv; | | 354 | ACPI_STATUS rv; |
355 | int match = 0; | | 355 | int match = 0; |
356 | | | 356 | |
357 | rv = acpi_eval_struct(handle, "_CLS", &buf); | | 357 | rv = acpi_eval_struct(handle, "_CLS", &buf); |
358 | if (ACPI_FAILURE(rv)) | | 358 | if (ACPI_FAILURE(rv)) |
359 | goto done; | | 359 | goto done; |
360 | | | 360 | |
361 | obj = buf.Pointer; | | 361 | obj = buf.Pointer; |
362 | if (obj->Type != ACPI_TYPE_PACKAGE) | | 362 | if (obj->Type != ACPI_TYPE_PACKAGE) |
363 | goto done; | | 363 | goto done; |
364 | if (obj->Package.Count != 3) | | 364 | if (obj->Package.Count != 3) |
365 | goto done; | | 365 | goto done; |
366 | if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER || | | 366 | if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER || |
367 | obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER || | | 367 | obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER || |
368 | obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER) | | 368 | obj->Package.Elements[2].Type != ACPI_TYPE_INTEGER) |
369 | goto done; | | 369 | goto done; |
370 | | | 370 | |
371 | match = obj->Package.Elements[0].Integer.Value == pci_class && | | 371 | match = obj->Package.Elements[0].Integer.Value == pci_class && |
372 | obj->Package.Elements[1].Integer.Value == pci_subclass && | | 372 | obj->Package.Elements[1].Integer.Value == pci_subclass && |
373 | obj->Package.Elements[2].Integer.Value == pci_interface; | | 373 | obj->Package.Elements[2].Integer.Value == pci_interface; |
374 | | | 374 | |
375 | done: | | 375 | done: |
376 | if (buf.Pointer) | | 376 | if (buf.Pointer) |
377 | ACPI_FREE(buf.Pointer); | | 377 | ACPI_FREE(buf.Pointer); |
378 | return match; | | 378 | return match; |
379 | } | | 379 | } |
380 | | | 380 | |
381 | /* | | 381 | /* |
382 | * Match a device node from a handle. | | 382 | * Match a device node from a handle. |
383 | */ | | 383 | */ |
384 | struct acpi_devnode * | | 384 | struct acpi_devnode * |
385 | acpi_match_node(ACPI_HANDLE handle) | | 385 | acpi_match_node(ACPI_HANDLE handle) |
386 | { | | 386 | { |
387 | struct acpi_devnode *ad; | | 387 | struct acpi_devnode *ad; |
388 | ACPI_STATUS rv; | | 388 | ACPI_STATUS rv; |
389 | | | 389 | |
390 | if (handle == NULL) | | 390 | if (handle == NULL) |
391 | return NULL; | | 391 | return NULL; |
392 | | | 392 | |
393 | rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); | | 393 | rv = AcpiGetData(handle, acpi_clean_node, (void **)&ad); |
394 | | | 394 | |
395 | if (ACPI_FAILURE(rv)) | | 395 | if (ACPI_FAILURE(rv)) |
396 | return NULL; | | 396 | return NULL; |
397 | | | 397 | |
398 | return ad; | | 398 | return ad; |
399 | } | | 399 | } |
400 | | | 400 | |
401 | /* | | 401 | /* |
402 | * Permanently associate a device node with a handle. | | 402 | * Permanently associate a device node with a handle. |
403 | */ | | 403 | */ |
404 | void | | 404 | void |
405 | acpi_match_node_init(struct acpi_devnode *ad) | | 405 | acpi_match_node_init(struct acpi_devnode *ad) |
406 | { | | 406 | { |
407 | (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); | | 407 | (void)AcpiAttachData(ad->ad_handle, acpi_clean_node, ad); |
408 | } | | 408 | } |
409 | | | 409 | |
410 | static void | | 410 | static void |
411 | acpi_clean_node(ACPI_HANDLE handle, void *aux) | | 411 | acpi_clean_node(ACPI_HANDLE handle, void *aux) |
412 | { | | 412 | { |
413 | /* Nothing. */ | | 413 | /* Nothing. */ |
414 | } | | 414 | } |
415 | | | 415 | |
416 | /* | | 416 | /* |
417 | * Match a handle from a cpu_info. Returns NULL on failure. | | 417 | * Match a handle from a cpu_info. Returns NULL on failure. |
418 | * | | 418 | * |
419 | * Note that acpi_match_node() can be used if the device node | | 419 | * Note that acpi_match_node() can be used if the device node |
420 | * is also required. | | 420 | * is also required. |
421 | */ | | 421 | */ |
422 | ACPI_HANDLE | | 422 | ACPI_HANDLE |
423 | acpi_match_cpu_info(struct cpu_info *ci) | | 423 | acpi_match_cpu_info(struct cpu_info *ci) |
424 | { | | 424 | { |
425 | struct acpi_softc *sc = acpi_softc; | | 425 | struct acpi_softc *sc = acpi_softc; |
426 | struct acpi_devnode *ad; | | 426 | struct acpi_devnode *ad; |
427 | ACPI_INTEGER val; | | 427 | ACPI_INTEGER val; |
428 | ACPI_OBJECT *obj; | | 428 | ACPI_OBJECT *obj; |
429 | ACPI_BUFFER buf; | | 429 | ACPI_BUFFER buf; |
430 | ACPI_HANDLE hdl; | | 430 | ACPI_HANDLE hdl; |
431 | ACPI_STATUS rv; | | 431 | ACPI_STATUS rv; |
432 | | | 432 | |
433 | if (sc == NULL || acpi_active == 0) | | 433 | if (sc == NULL || acpi_active == 0) |
434 | return NULL; | | 434 | return NULL; |
435 | | | 435 | |
436 | /* | | 436 | /* |
437 | * CPUs are declared in the ACPI namespace | | 437 | * CPUs are declared in the ACPI namespace |
438 | * either as a Processor() or as a Device(). | | 438 | * either as a Processor() or as a Device(). |
439 | * In both cases the MADT entries are used | | 439 | * In both cases the MADT entries are used |
440 | * for the match (see ACPI 4.0, section 8.4). | | 440 | * for the match (see ACPI 4.0, section 8.4). |
441 | */ | | 441 | */ |
442 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { | | 442 | SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) { |
443 | | | 443 | |
444 | hdl = ad->ad_handle; | | 444 | hdl = ad->ad_handle; |
445 | | | 445 | |
446 | switch (ad->ad_type) { | | 446 | switch (ad->ad_type) { |
447 | | | 447 | |
448 | case ACPI_TYPE_DEVICE: | | 448 | case ACPI_TYPE_DEVICE: |
449 | | | 449 | |
450 | if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0) | | 450 | if (acpi_match_hid(ad->ad_devinfo, acpicpu_ids) == 0) |
451 | break; | | 451 | break; |
452 | | | 452 | |
453 | rv = acpi_eval_integer(hdl, "_UID", &val); | | 453 | rv = acpi_eval_integer(hdl, "_UID", &val); |
454 | | | 454 | |
455 | if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid) | | 455 | if (ACPI_SUCCESS(rv) && val == ci->ci_acpiid) |
456 | return hdl; | | 456 | return hdl; |
457 | | | 457 | |
458 | break; | | 458 | break; |
459 | | | 459 | |
460 | case ACPI_TYPE_PROCESSOR: | | 460 | case ACPI_TYPE_PROCESSOR: |
461 | | | 461 | |
462 | rv = acpi_eval_struct(hdl, NULL, &buf); | | 462 | rv = acpi_eval_struct(hdl, NULL, &buf); |
463 | | | 463 | |
464 | if (ACPI_FAILURE(rv)) | | 464 | if (ACPI_FAILURE(rv)) |
465 | break; | | 465 | break; |
466 | | | 466 | |
467 | obj = buf.Pointer; | | 467 | obj = buf.Pointer; |
468 | | | 468 | |
469 | if (obj->Processor.ProcId == ci->ci_acpiid) { | | 469 | if (obj->Processor.ProcId == ci->ci_acpiid) { |
470 | ACPI_FREE(buf.Pointer); | | 470 | ACPI_FREE(buf.Pointer); |
471 | return hdl; | | 471 | return hdl; |
472 | } | | 472 | } |
473 | | | 473 | |
474 | ACPI_FREE(buf.Pointer); | | 474 | ACPI_FREE(buf.Pointer); |
475 | break; | | 475 | break; |
476 | } | | 476 | } |
477 | } | | 477 | } |
478 | | | 478 | |
479 | return NULL; | | 479 | return NULL; |
480 | } | | 480 | } |
481 | | | 481 | |
482 | /* | | 482 | /* |
483 | * Match a CPU from a handle. Returns NULL on failure. | | 483 | * Match a CPU from a handle. Returns NULL on failure. |
484 | */ | | 484 | */ |
485 | struct cpu_info * | | 485 | struct cpu_info * |
486 | acpi_match_cpu_handle(ACPI_HANDLE hdl) | | 486 | acpi_match_cpu_handle(ACPI_HANDLE hdl) |
487 | { | | 487 | { |
488 | struct cpu_info *ci; | | 488 | struct cpu_info *ci; |
489 | ACPI_DEVICE_INFO *di; | | 489 | ACPI_DEVICE_INFO *di; |
490 | CPU_INFO_ITERATOR cii; | | 490 | CPU_INFO_ITERATOR cii; |
491 | ACPI_INTEGER val; | | 491 | ACPI_INTEGER val; |
492 | ACPI_OBJECT *obj; | | 492 | ACPI_OBJECT *obj; |
493 | ACPI_BUFFER buf; | | 493 | ACPI_BUFFER buf; |
494 | ACPI_STATUS rv; | | 494 | ACPI_STATUS rv; |
495 | | | 495 | |
496 | ci = NULL; | | 496 | ci = NULL; |
497 | di = NULL; | | 497 | di = NULL; |
498 | buf.Pointer = NULL; | | 498 | buf.Pointer = NULL; |
499 | | | 499 | |
500 | rv = AcpiGetObjectInfo(hdl, &di); | | 500 | rv = AcpiGetObjectInfo(hdl, &di); |
501 | | | 501 | |
502 | if (ACPI_FAILURE(rv)) | | 502 | if (ACPI_FAILURE(rv)) |
503 | return NULL; | | 503 | return NULL; |
504 | | | 504 | |
505 | switch (di->Type) { | | 505 | switch (di->Type) { |
506 | | | 506 | |
507 | case ACPI_TYPE_DEVICE: | | 507 | case ACPI_TYPE_DEVICE: |
508 | | | 508 | |
509 | if (acpi_match_hid(di, acpicpu_ids) == 0) | | 509 | if (acpi_match_hid(di, acpicpu_ids) == 0) |
510 | goto out; | | 510 | goto out; |
511 | | | 511 | |
512 | rv = acpi_eval_integer(hdl, "_UID", &val); | | 512 | rv = acpi_eval_integer(hdl, "_UID", &val); |
513 | | | 513 | |
514 | if (ACPI_FAILURE(rv)) | | 514 | if (ACPI_FAILURE(rv)) |
515 | goto out; | | 515 | goto out; |
516 | | | 516 | |
517 | break; | | 517 | break; |
518 | | | 518 | |
519 | case ACPI_TYPE_PROCESSOR: | | 519 | case ACPI_TYPE_PROCESSOR: |
520 | | | 520 | |
521 | rv = acpi_eval_struct(hdl, NULL, &buf); | | 521 | rv = acpi_eval_struct(hdl, NULL, &buf); |
522 | | | 522 | |
523 | if (ACPI_FAILURE(rv)) | | 523 | if (ACPI_FAILURE(rv)) |
524 | goto out; | | 524 | goto out; |
525 | | | 525 | |
526 | obj = buf.Pointer; | | 526 | obj = buf.Pointer; |
527 | val = obj->Processor.ProcId; | | 527 | val = obj->Processor.ProcId; |
528 | break; | | 528 | break; |
529 | | | 529 | |
530 | default: | | 530 | default: |
531 | goto out; | | 531 | goto out; |
532 | } | | 532 | } |
533 | | | 533 | |
534 | for (CPU_INFO_FOREACH(cii, ci)) { | | 534 | for (CPU_INFO_FOREACH(cii, ci)) { |
535 | | | 535 | |
536 | if (ci->ci_acpiid == val) | | 536 | if (ci->ci_acpiid == val) |
537 | goto out; | | 537 | goto out; |
538 | } | | 538 | } |
539 | | | 539 | |
540 | ci = NULL; | | 540 | ci = NULL; |
541 | | | 541 | |
542 | out: | | 542 | out: |
543 | if (di != NULL) | | 543 | if (di != NULL) |
544 | ACPI_FREE(di); | | 544 | ACPI_FREE(di); |
545 | | | 545 | |
546 | if (buf.Pointer != NULL) | | 546 | if (buf.Pointer != NULL) |
547 | ACPI_FREE(buf.Pointer); | | 547 | ACPI_FREE(buf.Pointer); |
548 | | | 548 | |
549 | return ci; | | 549 | return ci; |
550 | } | | 550 | } |
551 | | | 551 | |
552 | struct acpi_irq_handler { | | 552 | struct acpi_irq_handler { |
553 | ACPI_HANDLE aih_hdl; | | 553 | ACPI_HANDLE aih_hdl; |
554 | uint32_t aih_irq; | | 554 | uint32_t aih_irq; |
555 | void *aih_ih; | | 555 | void *aih_ih; |
556 | }; | | 556 | }; |
557 | | | 557 | |
558 | void * | | 558 | void * |
559 | acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe, | | 559 | acpi_intr_establish(device_t dev, uint64_t c, int ipl, bool mpsafe, |
560 | int (*intr)(void *), void *iarg, const char *xname) | | 560 | int (*intr)(void *), void *iarg, const char *xname) |
561 | { | | 561 | { |
562 | ACPI_STATUS rv; | | 562 | ACPI_STATUS rv; |
563 | ACPI_HANDLE hdl = (void *)(uintptr_t)c; | | 563 | ACPI_HANDLE hdl = (void *)(uintptr_t)c; |
564 | struct acpi_resources res; | | 564 | struct acpi_resources res; |
565 | struct acpi_irq *irq; | | 565 | struct acpi_irq *irq; |
566 | struct acpi_irq_handler *aih = NULL; | | 566 | struct acpi_irq_handler *aih = NULL; |
567 | void *ih; | | 567 | void *ih; |
568 | | | 568 | |
569 | rv = acpi_resource_parse(dev, hdl, "_CRS", &res, | | 569 | rv = acpi_resource_parse(dev, hdl, "_CRS", &res, |
570 | &acpi_resource_parse_ops_quiet); | | 570 | &acpi_resource_parse_ops_quiet); |
571 | if (ACPI_FAILURE(rv)) | | 571 | if (ACPI_FAILURE(rv)) |
572 | return NULL; | | 572 | return NULL; |
573 | | | 573 | |
574 | irq = acpi_res_irq(&res, 0); | | 574 | irq = acpi_res_irq(&res, 0); |
575 | if (irq == NULL) | | 575 | if (irq == NULL) |
576 | goto end; | | 576 | goto end; |
577 | | | 577 | |
578 | const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL; | | 578 | const int type = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL; |
579 | ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname); | | 579 | ih = acpi_md_intr_establish(irq->ar_irq, ipl, type, intr, iarg, mpsafe, xname); |
580 | if (ih == NULL) | | 580 | if (ih == NULL) |
581 | goto end; | | 581 | goto end; |
582 | | | 582 | |
583 | aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP); | | 583 | aih = kmem_alloc(sizeof(struct acpi_irq_handler), KM_SLEEP); |
584 | aih->aih_hdl = hdl; | | 584 | aih->aih_hdl = hdl; |
585 | aih->aih_irq = irq->ar_irq; | | 585 | aih->aih_irq = irq->ar_irq; |
586 | aih->aih_ih = ih; | | 586 | aih->aih_ih = ih; |
587 | | | 587 | |
588 | end: | | 588 | end: |
589 | acpi_resource_cleanup(&res); | | 589 | acpi_resource_cleanup(&res); |
590 | return aih; | | 590 | return aih; |
591 | } | | 591 | } |
592 | | | 592 | |
593 | void | | 593 | void |
594 | acpi_intr_mask(void *c) | | 594 | acpi_intr_mask(void *c) |
595 | { | | 595 | { |
596 | struct acpi_irq_handler * const aih = c; | | 596 | struct acpi_irq_handler * const aih = c; |
597 | | | 597 | |
598 | acpi_md_intr_mask(aih->aih_ih); | | 598 | acpi_md_intr_mask(aih->aih_ih); |
599 | } | | 599 | } |
600 | | | 600 | |
601 | void | | 601 | void |
602 | acpi_intr_unmask(void *c) | | 602 | acpi_intr_unmask(void *c) |
603 | { | | 603 | { |
604 | struct acpi_irq_handler * const aih = c; | | 604 | struct acpi_irq_handler * const aih = c; |
605 | | | 605 | |
606 | acpi_md_intr_unmask(aih->aih_ih); | | 606 | acpi_md_intr_unmask(aih->aih_ih); |
607 | } | | 607 | } |
608 | | | 608 | |
609 | void | | 609 | void |
610 | acpi_intr_disestablish(void *c) | | 610 | acpi_intr_disestablish(void *c) |
611 | { | | 611 | { |
612 | struct acpi_irq_handler *aih = c; | | 612 | struct acpi_irq_handler *aih = c; |
613 | | | 613 | |
614 | acpi_md_intr_disestablish(aih->aih_ih); | | 614 | acpi_md_intr_disestablish(aih->aih_ih); |
615 | kmem_free(aih, sizeof(struct acpi_irq_handler)); | | 615 | kmem_free(aih, sizeof(struct acpi_irq_handler)); |
616 | } | | 616 | } |
617 | | | 617 | |
618 | const char * | | 618 | const char * |
619 | acpi_intr_string(void *c, char *buf, size_t size) | | 619 | acpi_intr_string(void *c, char *buf, size_t size) |
620 | { | | 620 | { |
621 | struct acpi_irq_handler *aih = c; | | 621 | struct acpi_irq_handler *aih = c; |
622 | intr_handle_t ih = aih->aih_irq; | | 622 | intr_handle_t ih = aih->aih_irq; |
623 | | | 623 | |
624 | return intr_string(ih, buf, size); | | 624 | return intr_string(ih, buf, size); |
625 | } | | 625 | } |
626 | | | 626 | |
627 | /* | | 627 | /* |
628 | * USB Device-Specific Data (_DSD) support | | 628 | * USB Device-Specific Data (_DSD) support |
629 | */ | | 629 | */ |
630 | | | 630 | |
631 | static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = { | | 631 | static UINT8 acpi_dsd_uuid[ACPI_UUID_LENGTH] = { |
632 | 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, | | 632 | 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, |
633 | 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 | | 633 | 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 |
634 | }; | | 634 | }; |
635 | | | 635 | |
636 | ACPI_STATUS | | 636 | static ACPI_STATUS |
637 | acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val) | | 637 | acpi_dsd_property(ACPI_HANDLE handle, const char *prop, ACPI_BUFFER *pbuf, ACPI_OBJECT_TYPE type, ACPI_OBJECT **ret) |
638 | { | | 638 | { |
639 | ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval; | | 639 | ACPI_OBJECT *obj, *uuid, *props, *pobj, *propkey, *propval; |
640 | ACPI_STATUS rv; | | 640 | ACPI_STATUS rv; |
641 | ACPI_BUFFER buf; | | | |
642 | int n; | | 641 | int n; |
643 | | | 642 | |
644 | buf.Pointer = NULL; | | 643 | rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, pbuf, ACPI_TYPE_PACKAGE); |
645 | buf.Length = ACPI_ALLOCATE_BUFFER; | | | |
646 | | | | |
647 | rv = AcpiEvaluateObjectTyped(handle, "_DSD", NULL, &buf, ACPI_TYPE_PACKAGE); | | | |
648 | if (ACPI_FAILURE(rv)) | | 644 | if (ACPI_FAILURE(rv)) |
649 | return rv; | | 645 | return rv; |
650 | | | 646 | |
651 | props = NULL; | | 647 | props = NULL; |
652 | obj = (ACPI_OBJECT *)buf.Pointer; | | 648 | obj = (ACPI_OBJECT *)pbuf->Pointer; |
653 | for (n = 0; (n + 1) < obj->Package.Count; n += 2) { | | 649 | for (n = 0; (n + 1) < obj->Package.Count; n += 2) { |
654 | uuid = &obj->Package.Elements[n]; | | 650 | uuid = &obj->Package.Elements[n]; |
655 | if (uuid->Buffer.Length == ACPI_UUID_LENGTH && | | 651 | if (uuid->Buffer.Length == ACPI_UUID_LENGTH && |
656 | memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) { | | 652 | memcmp(uuid->Buffer.Pointer, acpi_dsd_uuid, ACPI_UUID_LENGTH) == 0) { |
657 | props = &obj->Package.Elements[n + 1]; | | 653 | props = &obj->Package.Elements[n + 1]; |
658 | break; | | 654 | break; |
659 | } | | 655 | } |
660 | } | | 656 | } |
661 | if (props == NULL) { | | 657 | if (props == NULL) |
662 | rv = AE_NOT_FOUND; | | 658 | return AE_NOT_FOUND; |
663 | goto done; | | | |
664 | } | | | |
665 | | | 659 | |
666 | for (n = 0; n < props->Package.Count; n++) { | | 660 | for (n = 0; n < props->Package.Count; n++) { |
667 | pobj = &props->Package.Elements[n]; | | 661 | pobj = &props->Package.Elements[n]; |
668 | if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2) | | 662 | if (pobj->Type != ACPI_TYPE_PACKAGE || pobj->Package.Count != 2) |
669 | continue; | | 663 | continue; |
670 | propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0]; | | 664 | propkey = (ACPI_OBJECT *)&pobj->Package.Elements[0]; |
671 | propval = (ACPI_OBJECT *)&pobj->Package.Elements[1]; | | 665 | propval = (ACPI_OBJECT *)&pobj->Package.Elements[1]; |
672 | if (propkey->Type != ACPI_TYPE_STRING) | | 666 | if (propkey->Type != ACPI_TYPE_STRING) |
673 | continue; | | 667 | continue; |
674 | if (strcmp(propkey->String.Pointer, prop) != 0) | | 668 | if (strcmp(propkey->String.Pointer, prop) != 0) |
675 | continue; | | 669 | continue; |
676 | | | 670 | |
677 | if (propval->Type != ACPI_TYPE_INTEGER) { | | 671 | if (propval->Type != type) { |
678 | rv = AE_TYPE; | | 672 | return AE_TYPE; |
679 | } else { | | 673 | } else { |
680 | *val = propval->Integer.Value; | | 674 | *ret = propval; |
681 | rv = AE_OK; | | 675 | return AE_OK; |
682 | } | | 676 | } |
683 | break; | | 677 | break; |
684 | } | | 678 | } |
685 | | | 679 | |
686 | done: | | 680 | return AE_NOT_FOUND; |
| | | 681 | } |
| | | 682 | |
| | | 683 | ACPI_STATUS |
| | | 684 | acpi_dsd_integer(ACPI_HANDLE handle, const char *prop, ACPI_INTEGER *val) |
| | | 685 | { |
| | | 686 | ACPI_OBJECT *propval; |
| | | 687 | ACPI_STATUS rv; |
| | | 688 | ACPI_BUFFER buf; |
| | | 689 | |
| | | 690 | buf.Pointer = NULL; |
| | | 691 | buf.Length = ACPI_ALLOCATE_BUFFER; |
| | | 692 | |
| | | 693 | rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_INTEGER, &propval); |
| | | 694 | if (ACPI_SUCCESS(rv)) |
| | | 695 | *val = propval->Integer.Value; |
| | | 696 | |
| | | 697 | ACPI_FREE(buf.Pointer); |
| | | 698 | return rv; |
| | | 699 | } |
| | | 700 | |
| | | 701 | ACPI_STATUS |
| | | 702 | acpi_dsd_string(ACPI_HANDLE handle, const char *prop, char **val) |
| | | 703 | { |
| | | 704 | ACPI_OBJECT *propval; |
| | | 705 | ACPI_STATUS rv; |
| | | 706 | ACPI_BUFFER buf; |
| | | 707 | |
| | | 708 | buf.Pointer = NULL; |
| | | 709 | buf.Length = ACPI_ALLOCATE_BUFFER; |
| | | 710 | |
| | | 711 | rv = acpi_dsd_property(handle, prop, &buf, ACPI_TYPE_STRING, &propval); |
| | | 712 | if (ACPI_SUCCESS(rv)) |
| | | 713 | *val = kmem_strdup(propval->String.Pointer, KM_SLEEP); |
| | | 714 | |
687 | ACPI_FREE(buf.Pointer); | | 715 | ACPI_FREE(buf.Pointer); |
688 | return rv; | | 716 | return rv; |
689 | } | | 717 | } |