Commit | Line | Data |
---|---|---|
7db5d82d BM |
1 | |
2 | /****************************************************************************** | |
3 | * | |
4 | * Module Name: hwxface - Public ACPICA hardware interfaces | |
5 | * | |
6 | *****************************************************************************/ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2000 - 2008, Intel Corp. | |
10 | * All rights reserved. | |
11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | |
16 | * notice, this list of conditions, and the following disclaimer, | |
17 | * without modification. | |
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
19 | * substantially similar to the "NO WARRANTY" disclaimer below | |
20 | * ("Disclaimer") and any redistribution must be conditioned upon | |
21 | * including a substantially similar Disclaimer requirement for further | |
22 | * binary redistribution. | |
23 | * 3. Neither the names of the above-listed copyright holders nor the names | |
24 | * of any contributors may be used to endorse or promote products derived | |
25 | * from this software without specific prior written permission. | |
26 | * | |
27 | * Alternatively, this software may be distributed under the terms of the | |
28 | * GNU General Public License ("GPL") version 2 as published by the Free | |
29 | * Software Foundation. | |
30 | * | |
31 | * NO WARRANTY | |
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
42 | * POSSIBILITY OF SUCH DAMAGES. | |
43 | */ | |
44 | ||
45 | #include <acpi/acpi.h> | |
e2f7a777 LB |
46 | #include "accommon.h" |
47 | #include "acnamesp.h" | |
7db5d82d BM |
48 | |
49 | #define _COMPONENT ACPI_HARDWARE | |
50 | ACPI_MODULE_NAME("hwxface") | |
51 | ||
d3fd902d BM |
52 | /****************************************************************************** |
53 | * | |
54 | * FUNCTION: acpi_reset | |
55 | * | |
56 | * PARAMETERS: None | |
57 | * | |
58 | * RETURN: Status | |
59 | * | |
60 | * DESCRIPTION: Set reset register in memory or IO space. Note: Does not | |
61 | * support reset register in PCI config space, this must be | |
62 | * handled separately. | |
63 | * | |
64 | ******************************************************************************/ | |
65 | acpi_status acpi_reset(void) | |
66 | { | |
67 | struct acpi_generic_address *reset_reg; | |
68 | acpi_status status; | |
69 | ||
70 | ACPI_FUNCTION_TRACE(acpi_reset); | |
71 | ||
72 | reset_reg = &acpi_gbl_FADT.reset_register; | |
73 | ||
74 | /* Check if the reset register is supported */ | |
75 | ||
76 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || | |
77 | !reset_reg->address) { | |
78 | return_ACPI_STATUS(AE_NOT_EXIST); | |
79 | } | |
80 | ||
81 | /* Write the reset value to the reset register */ | |
82 | ||
83 | status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); | |
84 | return_ACPI_STATUS(status); | |
85 | } | |
86 | ||
87 | ACPI_EXPORT_SYMBOL(acpi_reset) | |
88 | ||
7db5d82d BM |
89 | /****************************************************************************** |
90 | * | |
91 | * FUNCTION: acpi_read | |
92 | * | |
93 | * PARAMETERS: Value - Where the value is returned | |
94 | * Reg - GAS register structure | |
95 | * | |
96 | * RETURN: Status | |
97 | * | |
98 | * DESCRIPTION: Read from either memory or IO space. | |
99 | * | |
100 | ******************************************************************************/ | |
101 | acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) | |
102 | { | |
103 | u32 width; | |
104 | u64 address; | |
105 | acpi_status status; | |
106 | ||
107 | ACPI_FUNCTION_NAME(acpi_read); | |
108 | ||
109 | /* | |
ac0c8450 BM |
110 | * Must have a valid pointer to a GAS structure, and a non-zero address |
111 | * within. | |
7db5d82d BM |
112 | */ |
113 | if (!reg) { | |
ac0c8450 | 114 | return (AE_BAD_PARAMETER); |
7db5d82d BM |
115 | } |
116 | ||
117 | /* Get a local copy of the address. Handles possible alignment issues */ | |
118 | ||
119 | ACPI_MOVE_64_TO_64(&address, ®->address); | |
120 | if (!address) { | |
ac0c8450 | 121 | return (AE_BAD_ADDRESS); |
7db5d82d BM |
122 | } |
123 | ||
124 | /* Supported widths are 8/16/32 */ | |
125 | ||
126 | width = reg->bit_width; | |
127 | if ((width != 8) && (width != 16) && (width != 32)) { | |
128 | return (AE_SUPPORT); | |
129 | } | |
130 | ||
131 | /* Initialize entire 32-bit return value to zero */ | |
132 | ||
133 | *value = 0; | |
134 | ||
135 | /* | |
136 | * Two address spaces supported: Memory or IO. | |
137 | * PCI_Config is not supported here because the GAS struct is insufficient | |
138 | */ | |
139 | switch (reg->space_id) { | |
140 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | |
141 | ||
142 | status = acpi_os_read_memory((acpi_physical_address) address, | |
143 | value, width); | |
144 | break; | |
145 | ||
146 | case ACPI_ADR_SPACE_SYSTEM_IO: | |
147 | ||
148 | status = | |
149 | acpi_os_read_port((acpi_io_address) address, value, width); | |
150 | break; | |
151 | ||
152 | default: | |
153 | ACPI_ERROR((AE_INFO, | |
154 | "Unsupported address space: %X", reg->space_id)); | |
155 | return (AE_BAD_PARAMETER); | |
156 | } | |
157 | ||
158 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | |
159 | "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", | |
160 | *value, width, ACPI_FORMAT_UINT64(address), | |
161 | acpi_ut_get_region_name(reg->space_id))); | |
162 | ||
163 | return (status); | |
164 | } | |
165 | ||
166 | ACPI_EXPORT_SYMBOL(acpi_read) | |
167 | ||
168 | /****************************************************************************** | |
169 | * | |
170 | * FUNCTION: acpi_write | |
171 | * | |
172 | * PARAMETERS: Value - To be written | |
173 | * Reg - GAS register structure | |
174 | * | |
175 | * RETURN: Status | |
176 | * | |
177 | * DESCRIPTION: Write to either memory or IO space. | |
178 | * | |
179 | ******************************************************************************/ | |
180 | acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) | |
181 | { | |
182 | u32 width; | |
183 | u64 address; | |
184 | acpi_status status; | |
185 | ||
186 | ACPI_FUNCTION_NAME(acpi_write); | |
187 | ||
188 | /* | |
ac0c8450 BM |
189 | * Must have a valid pointer to a GAS structure, and a non-zero address |
190 | * within. | |
7db5d82d BM |
191 | */ |
192 | if (!reg) { | |
ac0c8450 | 193 | return (AE_BAD_PARAMETER); |
7db5d82d BM |
194 | } |
195 | ||
196 | /* Get a local copy of the address. Handles possible alignment issues */ | |
197 | ||
198 | ACPI_MOVE_64_TO_64(&address, ®->address); | |
199 | if (!address) { | |
ac0c8450 | 200 | return (AE_BAD_ADDRESS); |
7db5d82d BM |
201 | } |
202 | ||
203 | /* Supported widths are 8/16/32 */ | |
204 | ||
205 | width = reg->bit_width; | |
206 | if ((width != 8) && (width != 16) && (width != 32)) { | |
207 | return (AE_SUPPORT); | |
208 | } | |
209 | ||
210 | /* | |
211 | * Two address spaces supported: Memory or IO. | |
212 | * PCI_Config is not supported here because the GAS struct is insufficient | |
213 | */ | |
214 | switch (reg->space_id) { | |
215 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | |
216 | ||
217 | status = acpi_os_write_memory((acpi_physical_address) address, | |
218 | value, width); | |
219 | break; | |
220 | ||
221 | case ACPI_ADR_SPACE_SYSTEM_IO: | |
222 | ||
223 | status = acpi_os_write_port((acpi_io_address) address, value, | |
224 | width); | |
225 | break; | |
226 | ||
227 | default: | |
228 | ACPI_ERROR((AE_INFO, | |
229 | "Unsupported address space: %X", reg->space_id)); | |
230 | return (AE_BAD_PARAMETER); | |
231 | } | |
232 | ||
233 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | |
234 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", | |
235 | value, width, ACPI_FORMAT_UINT64(address), | |
236 | acpi_ut_get_region_name(reg->space_id))); | |
237 | ||
238 | return (status); | |
239 | } | |
240 | ||
241 | ACPI_EXPORT_SYMBOL(acpi_write) | |
242 | ||
243 | /******************************************************************************* | |
244 | * | |
50ffba1b | 245 | * FUNCTION: acpi_read_bit_register |
7db5d82d | 246 | * |
9892dd23 BM |
247 | * PARAMETERS: register_id - ID of ACPI Bit Register to access |
248 | * return_value - Value that was read from the register, | |
249 | * normalized to bit position zero. | |
7db5d82d | 250 | * |
9892dd23 | 251 | * RETURN: Status and the value read from the specified Register. Value |
7db5d82d BM |
252 | * returned is normalized to bit0 (is shifted all the way right) |
253 | * | |
254 | * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock. | |
255 | * | |
9892dd23 BM |
256 | * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and |
257 | * PM2 Control. | |
258 | * | |
259 | * Note: The hardware lock is not required when reading the ACPI bit registers | |
260 | * since almost all of them are single bit and it does not matter that | |
261 | * the parent hardware register can be split across two physical | |
262 | * registers. The only multi-bit field is SLP_TYP in the PM1 control | |
263 | * register, but this field does not cross an 8-bit boundary (nor does | |
264 | * it make much sense to actually read this field.) | |
265 | * | |
7db5d82d | 266 | ******************************************************************************/ |
50ffba1b | 267 | acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) |
7db5d82d BM |
268 | { |
269 | u32 register_value = 0; | |
270 | struct acpi_bit_register_info *bit_reg_info; | |
271 | acpi_status status; | |
272 | ||
50ffba1b | 273 | ACPI_FUNCTION_TRACE(acpi_read_bit_register); |
7db5d82d BM |
274 | |
275 | /* Get the info structure corresponding to the requested ACPI Register */ | |
276 | ||
277 | bit_reg_info = acpi_hw_get_bit_register_info(register_id); | |
278 | if (!bit_reg_info) { | |
279 | return_ACPI_STATUS(AE_BAD_PARAMETER); | |
280 | } | |
281 | ||
9892dd23 | 282 | /* Read the entire parent register */ |
7db5d82d BM |
283 | |
284 | status = acpi_hw_register_read(bit_reg_info->parent_register, | |
285 | ®ister_value); | |
286 | ||
287 | if (ACPI_SUCCESS(status)) { | |
288 | ||
289 | /* Normalize the value that was read */ | |
290 | ||
291 | register_value = | |
292 | ((register_value & bit_reg_info->access_bit_mask) | |
293 | >> bit_reg_info->bit_position); | |
294 | ||
295 | *return_value = register_value; | |
296 | ||
297 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n", | |
298 | register_value, | |
299 | bit_reg_info->parent_register)); | |
300 | } | |
301 | ||
302 | return_ACPI_STATUS(status); | |
303 | } | |
304 | ||
50ffba1b | 305 | ACPI_EXPORT_SYMBOL(acpi_read_bit_register) |
7db5d82d BM |
306 | |
307 | /******************************************************************************* | |
308 | * | |
50ffba1b | 309 | * FUNCTION: acpi_write_bit_register |
7db5d82d | 310 | * |
9892dd23 BM |
311 | * PARAMETERS: register_id - ID of ACPI Bit Register to access |
312 | * Value - Value to write to the register, in bit | |
313 | * position zero. The bit is automaticallly | |
314 | * shifted to the correct position. | |
7db5d82d BM |
315 | * |
316 | * RETURN: Status | |
317 | * | |
9892dd23 BM |
318 | * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock |
319 | * since most operations require a read/modify/write sequence. | |
320 | * | |
321 | * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and | |
322 | * PM2 Control. | |
7db5d82d BM |
323 | * |
324 | ******************************************************************************/ | |
50ffba1b | 325 | acpi_status acpi_write_bit_register(u32 register_id, u32 value) |
7db5d82d BM |
326 | { |
327 | u32 register_value = 0; | |
328 | struct acpi_bit_register_info *bit_reg_info; | |
329 | acpi_status status; | |
330 | acpi_cpu_flags lock_flags; | |
331 | ||
50ffba1b | 332 | ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id); |
7db5d82d BM |
333 | |
334 | /* Get the info structure corresponding to the requested ACPI Register */ | |
335 | ||
336 | bit_reg_info = acpi_hw_get_bit_register_info(register_id); | |
337 | if (!bit_reg_info) { | |
338 | ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", | |
339 | register_id)); | |
340 | return_ACPI_STATUS(AE_BAD_PARAMETER); | |
341 | } | |
342 | ||
343 | lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); | |
344 | ||
345 | /* Always do a register read first so we can insert the new bits */ | |
346 | ||
347 | status = acpi_hw_register_read(bit_reg_info->parent_register, | |
348 | ®ister_value); | |
349 | if (ACPI_FAILURE(status)) { | |
350 | goto unlock_and_exit; | |
351 | } | |
352 | ||
353 | /* | |
354 | * Decode the Register ID | |
355 | * Register ID = [Register block ID] | [bit ID] | |
356 | * | |
357 | * Check bit ID to fine locate Register offset. | |
358 | * Check Mask to determine Register offset, and then read-write. | |
359 | */ | |
360 | switch (bit_reg_info->parent_register) { | |
361 | case ACPI_REGISTER_PM1_STATUS: | |
362 | ||
363 | /* | |
364 | * Status Registers are different from the rest. Clear by | |
365 | * writing 1, and writing 0 has no effect. So, the only relevant | |
366 | * information is the single bit we're interested in, all others should | |
367 | * be written as 0 so they will be left unchanged. | |
368 | */ | |
369 | value = ACPI_REGISTER_PREPARE_BITS(value, | |
370 | bit_reg_info->bit_position, | |
371 | bit_reg_info-> | |
372 | access_bit_mask); | |
373 | if (value) { | |
374 | status = | |
375 | acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, | |
376 | (u16) value); | |
377 | register_value = 0; | |
378 | } | |
379 | break; | |
380 | ||
381 | case ACPI_REGISTER_PM1_ENABLE: | |
382 | ||
383 | ACPI_REGISTER_INSERT_VALUE(register_value, | |
384 | bit_reg_info->bit_position, | |
385 | bit_reg_info->access_bit_mask, | |
386 | value); | |
387 | ||
388 | status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE, | |
389 | (u16) register_value); | |
390 | break; | |
391 | ||
392 | case ACPI_REGISTER_PM1_CONTROL: | |
393 | ||
394 | /* | |
395 | * Write the PM1 Control register. | |
396 | * Note that at this level, the fact that there are actually TWO | |
397 | * registers (A and B - and B may not exist) is abstracted. | |
398 | */ | |
399 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n", | |
400 | register_value)); | |
401 | ||
402 | ACPI_REGISTER_INSERT_VALUE(register_value, | |
403 | bit_reg_info->bit_position, | |
404 | bit_reg_info->access_bit_mask, | |
405 | value); | |
406 | ||
407 | status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, | |
408 | (u16) register_value); | |
409 | break; | |
410 | ||
411 | case ACPI_REGISTER_PM2_CONTROL: | |
412 | ||
413 | status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL, | |
414 | ®ister_value); | |
415 | if (ACPI_FAILURE(status)) { | |
416 | goto unlock_and_exit; | |
417 | } | |
418 | ||
419 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | |
420 | "PM2 control: Read %X from %8.8X%8.8X\n", | |
421 | register_value, | |
422 | ACPI_FORMAT_UINT64(acpi_gbl_FADT. | |
423 | xpm2_control_block. | |
424 | address))); | |
425 | ||
426 | ACPI_REGISTER_INSERT_VALUE(register_value, | |
427 | bit_reg_info->bit_position, | |
428 | bit_reg_info->access_bit_mask, | |
429 | value); | |
430 | ||
431 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | |
432 | "About to write %4.4X to %8.8X%8.8X\n", | |
433 | register_value, | |
434 | ACPI_FORMAT_UINT64(acpi_gbl_FADT. | |
435 | xpm2_control_block. | |
436 | address))); | |
437 | ||
438 | status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL, | |
439 | (u8) (register_value)); | |
440 | break; | |
441 | ||
442 | default: | |
443 | break; | |
444 | } | |
445 | ||
446 | unlock_and_exit: | |
447 | ||
448 | acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); | |
449 | ||
450 | /* Normalize the value that was read */ | |
451 | ||
452 | ACPI_DEBUG_EXEC(register_value = | |
453 | ((register_value & bit_reg_info->access_bit_mask) >> | |
454 | bit_reg_info->bit_position)); | |
455 | ||
456 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | |
457 | "Set bits: %8.8X actual %8.8X register %X\n", value, | |
458 | register_value, bit_reg_info->parent_register)); | |
459 | return_ACPI_STATUS(status); | |
460 | } | |
461 | ||
50ffba1b | 462 | ACPI_EXPORT_SYMBOL(acpi_write_bit_register) |
7db5d82d BM |
463 | |
464 | /******************************************************************************* | |
465 | * | |
466 | * FUNCTION: acpi_get_sleep_type_data | |
467 | * | |
468 | * PARAMETERS: sleep_state - Numeric sleep state | |
469 | * *sleep_type_a - Where SLP_TYPa is returned | |
470 | * *sleep_type_b - Where SLP_TYPb is returned | |
471 | * | |
472 | * RETURN: Status - ACPI status | |
473 | * | |
474 | * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep | |
475 | * state. | |
476 | * | |
477 | ******************************************************************************/ | |
478 | acpi_status | |
479 | acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) | |
480 | { | |
481 | acpi_status status = AE_OK; | |
482 | struct acpi_evaluate_info *info; | |
483 | ||
484 | ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); | |
485 | ||
486 | /* Validate parameters */ | |
487 | ||
488 | if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) { | |
489 | return_ACPI_STATUS(AE_BAD_PARAMETER); | |
490 | } | |
491 | ||
492 | /* Allocate the evaluation information block */ | |
493 | ||
494 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); | |
495 | if (!info) { | |
496 | return_ACPI_STATUS(AE_NO_MEMORY); | |
497 | } | |
498 | ||
499 | info->pathname = | |
500 | ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); | |
501 | ||
502 | /* Evaluate the namespace object containing the values for this state */ | |
503 | ||
504 | status = acpi_ns_evaluate(info); | |
505 | if (ACPI_FAILURE(status)) { | |
506 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | |
507 | "%s while evaluating SleepState [%s]\n", | |
508 | acpi_format_exception(status), | |
509 | info->pathname)); | |
510 | ||
511 | goto cleanup; | |
512 | } | |
513 | ||
514 | /* Must have a return object */ | |
515 | ||
516 | if (!info->return_object) { | |
517 | ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", | |
518 | info->pathname)); | |
519 | status = AE_NOT_EXIST; | |
520 | } | |
521 | ||
522 | /* It must be of type Package */ | |
523 | ||
3371c19c | 524 | else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { |
7db5d82d BM |
525 | ACPI_ERROR((AE_INFO, |
526 | "Sleep State return object is not a Package")); | |
527 | status = AE_AML_OPERAND_TYPE; | |
528 | } | |
529 | ||
530 | /* | |
531 | * The package must have at least two elements. NOTE (March 2005): This | |
532 | * goes against the current ACPI spec which defines this object as a | |
533 | * package with one encoded DWORD element. However, existing practice | |
534 | * by BIOS vendors seems to be to have 2 or more elements, at least | |
535 | * one per sleep type (A/B). | |
536 | */ | |
537 | else if (info->return_object->package.count < 2) { | |
538 | ACPI_ERROR((AE_INFO, | |
539 | "Sleep State return package does not have at least two elements")); | |
540 | status = AE_AML_NO_OPERAND; | |
541 | } | |
542 | ||
543 | /* The first two elements must both be of type Integer */ | |
544 | ||
3371c19c | 545 | else if (((info->return_object->package.elements[0])->common.type |
7db5d82d | 546 | != ACPI_TYPE_INTEGER) || |
3371c19c | 547 | ((info->return_object->package.elements[1])->common.type |
7db5d82d BM |
548 | != ACPI_TYPE_INTEGER)) { |
549 | ACPI_ERROR((AE_INFO, | |
550 | "Sleep State return package elements are not both Integers (%s, %s)", | |
551 | acpi_ut_get_object_type_name(info->return_object-> | |
552 | package.elements[0]), | |
553 | acpi_ut_get_object_type_name(info->return_object-> | |
554 | package.elements[1]))); | |
555 | status = AE_AML_OPERAND_TYPE; | |
556 | } else { | |
557 | /* Valid _Sx_ package size, type, and value */ | |
558 | ||
559 | *sleep_type_a = (u8) | |
560 | (info->return_object->package.elements[0])->integer.value; | |
561 | *sleep_type_b = (u8) | |
562 | (info->return_object->package.elements[1])->integer.value; | |
563 | } | |
564 | ||
565 | if (ACPI_FAILURE(status)) { | |
566 | ACPI_EXCEPTION((AE_INFO, status, | |
567 | "While evaluating SleepState [%s], bad Sleep object %p type %s", | |
568 | info->pathname, info->return_object, | |
569 | acpi_ut_get_object_type_name(info-> | |
570 | return_object))); | |
571 | } | |
572 | ||
573 | acpi_ut_remove_reference(info->return_object); | |
574 | ||
575 | cleanup: | |
576 | ACPI_FREE(info); | |
577 | return_ACPI_STATUS(status); | |
578 | } | |
579 | ||
580 | ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data) |