blob: 4ead85f29215d9d6294961c78c1f972f8c991c5f [file] [log] [blame]
Bob Moore7db5d822008-12-30 11:04:48 +08001
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>
Len Browne2f7a772009-01-09 00:30:03 -050046#include "accommon.h"
47#include "acnamesp.h"
Bob Moore7db5d822008-12-30 11:04:48 +080048
49#define _COMPONENT ACPI_HARDWARE
50ACPI_MODULE_NAME("hwxface")
51
52/******************************************************************************
53 *
Bob Moored3fd9022008-12-30 11:11:57 +080054 * 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 ******************************************************************************/
65acpi_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
Bob Moorec6b57742009-06-24 09:44:06 +080083 status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg);
Bob Moored3fd9022008-12-30 11:11:57 +080084 return_ACPI_STATUS(status);
85}
86
87ACPI_EXPORT_SYMBOL(acpi_reset)
88
89/******************************************************************************
90 *
Bob Moore7db5d822008-12-30 11:04:48 +080091 * 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 *
Bob Moorec6b57742009-06-24 09:44:06 +0800100 * LIMITATIONS: <These limitations also apply to acpi_write>
101 * bit_width must be exactly 8, 16, 32, or 64.
102 * space_iD must be system_memory or system_iO.
103 * bit_offset and access_width are currently ignored, as there has
104 * not been a need to implement these.
105 *
Bob Moore7db5d822008-12-30 11:04:48 +0800106 ******************************************************************************/
Bob Moorec6b57742009-06-24 09:44:06 +0800107acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
Bob Moore7db5d822008-12-30 11:04:48 +0800108{
Bob Moorec6b57742009-06-24 09:44:06 +0800109 u32 value;
Bob Moore7db5d822008-12-30 11:04:48 +0800110 u32 width;
111 u64 address;
112 acpi_status status;
113
114 ACPI_FUNCTION_NAME(acpi_read);
115
Bob Moorec6b57742009-06-24 09:44:06 +0800116 if (!return_value) {
Bob Mooreac0c8452009-02-18 14:28:02 +0800117 return (AE_BAD_PARAMETER);
Bob Moore7db5d822008-12-30 11:04:48 +0800118 }
119
Bob Moorec6b57742009-06-24 09:44:06 +0800120 /* Validate contents of the GAS register. Allow 64-bit transfers */
Bob Moore7db5d822008-12-30 11:04:48 +0800121
Bob Moorec6b57742009-06-24 09:44:06 +0800122 status = acpi_hw_validate_register(reg, 64, &address);
123 if (ACPI_FAILURE(status)) {
124 return (status);
Bob Moore7db5d822008-12-30 11:04:48 +0800125 }
126
Bob Moore7db5d822008-12-30 11:04:48 +0800127 width = reg->bit_width;
Bob Moorec6b57742009-06-24 09:44:06 +0800128 if (width == 64) {
129 width = 32; /* Break into two 32-bit transfers */
Bob Moore7db5d822008-12-30 11:04:48 +0800130 }
131
Bob Moorec6b57742009-06-24 09:44:06 +0800132 /* Initialize entire 64-bit return value to zero */
Bob Moore7db5d822008-12-30 11:04:48 +0800133
Bob Moorec6b57742009-06-24 09:44:06 +0800134 *return_value = 0;
135 value = 0;
Bob Moore7db5d822008-12-30 11:04:48 +0800136
137 /*
Bob Moore88dcb042009-02-18 16:01:04 +0800138 * Two address spaces supported: Memory or IO. PCI_Config is
139 * not supported here because the GAS structure is insufficient
Bob Moore7db5d822008-12-30 11:04:48 +0800140 */
Bob Moorec6b57742009-06-24 09:44:06 +0800141 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
142 status = acpi_os_read_memory((acpi_physical_address)
143 address, &value, width);
144 if (ACPI_FAILURE(status)) {
145 return (status);
146 }
147 *return_value = value;
Bob Moore7db5d822008-12-30 11:04:48 +0800148
Bob Moorec6b57742009-06-24 09:44:06 +0800149 if (reg->bit_width == 64) {
Bob Moore7db5d822008-12-30 11:04:48 +0800150
Bob Moorec6b57742009-06-24 09:44:06 +0800151 /* Read the top 32 bits */
Bob Moore7db5d822008-12-30 11:04:48 +0800152
Bob Moorec6b57742009-06-24 09:44:06 +0800153 status = acpi_os_read_memory((acpi_physical_address)
154 (address + 4), &value, 32);
155 if (ACPI_FAILURE(status)) {
156 return (status);
157 }
158 *return_value |= ((u64)value << 32);
159 }
160 } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
Bob Moore7db5d822008-12-30 11:04:48 +0800161
Bob Moorec6b57742009-06-24 09:44:06 +0800162 status = acpi_hw_read_port((acpi_io_address)
163 address, &value, width);
164 if (ACPI_FAILURE(status)) {
165 return (status);
166 }
167 *return_value = value;
168
169 if (reg->bit_width == 64) {
170
171 /* Read the top 32 bits */
172
173 status = acpi_hw_read_port((acpi_io_address)
174 (address + 4), &value, 32);
175 if (ACPI_FAILURE(status)) {
176 return (status);
177 }
178 *return_value |= ((u64)value << 32);
179 }
Bob Moore7db5d822008-12-30 11:04:48 +0800180 }
181
182 ACPI_DEBUG_PRINT((ACPI_DB_IO,
Bob Moorec6b57742009-06-24 09:44:06 +0800183 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
184 ACPI_FORMAT_UINT64(*return_value), reg->bit_width,
185 ACPI_FORMAT_UINT64(address),
Bob Moore7db5d822008-12-30 11:04:48 +0800186 acpi_ut_get_region_name(reg->space_id)));
187
188 return (status);
189}
190
191ACPI_EXPORT_SYMBOL(acpi_read)
192
193/******************************************************************************
194 *
195 * FUNCTION: acpi_write
196 *
Bob Moorec6b57742009-06-24 09:44:06 +0800197 * PARAMETERS: Value - Value to be written
Bob Moore7db5d822008-12-30 11:04:48 +0800198 * Reg - GAS register structure
199 *
200 * RETURN: Status
201 *
202 * DESCRIPTION: Write to either memory or IO space.
203 *
204 ******************************************************************************/
Bob Moorec6b57742009-06-24 09:44:06 +0800205acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
Bob Moore7db5d822008-12-30 11:04:48 +0800206{
207 u32 width;
208 u64 address;
209 acpi_status status;
210
211 ACPI_FUNCTION_NAME(acpi_write);
212
Bob Moorec6b57742009-06-24 09:44:06 +0800213 /* Validate contents of the GAS register. Allow 64-bit transfers */
214
215 status = acpi_hw_validate_register(reg, 64, &address);
216 if (ACPI_FAILURE(status)) {
217 return (status);
Bob Moore7db5d822008-12-30 11:04:48 +0800218 }
219
Bob Moore7db5d822008-12-30 11:04:48 +0800220 width = reg->bit_width;
Bob Moorec6b57742009-06-24 09:44:06 +0800221 if (width == 64) {
222 width = 32; /* Break into two 32-bit transfers */
Bob Moore7db5d822008-12-30 11:04:48 +0800223 }
224
225 /*
Bob Moorec6b57742009-06-24 09:44:06 +0800226 * Two address spaces supported: Memory or IO. PCI_Config is
227 * not supported here because the GAS structure is insufficient
Bob Moore7db5d822008-12-30 11:04:48 +0800228 */
Bob Moorec6b57742009-06-24 09:44:06 +0800229 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
230 status = acpi_os_write_memory((acpi_physical_address)
231 address, ACPI_LODWORD(value),
232 width);
233 if (ACPI_FAILURE(status)) {
234 return (status);
235 }
Bob Moore7db5d822008-12-30 11:04:48 +0800236
Bob Moorec6b57742009-06-24 09:44:06 +0800237 if (reg->bit_width == 64) {
238 status = acpi_os_write_memory((acpi_physical_address)
239 (address + 4),
240 ACPI_HIDWORD(value), 32);
241 if (ACPI_FAILURE(status)) {
242 return (status);
243 }
244 }
245 } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
Bob Moore7db5d822008-12-30 11:04:48 +0800246
Bob Moorec6b57742009-06-24 09:44:06 +0800247 status = acpi_hw_write_port((acpi_io_address)
248 address, ACPI_LODWORD(value),
Bob Moore7db5d822008-12-30 11:04:48 +0800249 width);
Bob Moorec6b57742009-06-24 09:44:06 +0800250 if (ACPI_FAILURE(status)) {
251 return (status);
252 }
Bob Moore7db5d822008-12-30 11:04:48 +0800253
Bob Moorec6b57742009-06-24 09:44:06 +0800254 if (reg->bit_width == 64) {
255 status = acpi_hw_write_port((acpi_io_address)
256 (address + 4),
257 ACPI_HIDWORD(value), 32);
258 if (ACPI_FAILURE(status)) {
259 return (status);
260 }
261 }
Bob Moore7db5d822008-12-30 11:04:48 +0800262 }
263
264 ACPI_DEBUG_PRINT((ACPI_DB_IO,
Bob Moorec6b57742009-06-24 09:44:06 +0800265 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
266 ACPI_FORMAT_UINT64(value), reg->bit_width,
267 ACPI_FORMAT_UINT64(address),
Bob Moore7db5d822008-12-30 11:04:48 +0800268 acpi_ut_get_region_name(reg->space_id)));
269
270 return (status);
271}
272
273ACPI_EXPORT_SYMBOL(acpi_write)
274
275/*******************************************************************************
276 *
Bob Moore50ffba12009-02-23 15:02:07 +0800277 * FUNCTION: acpi_read_bit_register
Bob Moore7db5d822008-12-30 11:04:48 +0800278 *
Bob Moore9892dd22009-02-18 15:10:07 +0800279 * PARAMETERS: register_id - ID of ACPI Bit Register to access
280 * return_value - Value that was read from the register,
281 * normalized to bit position zero.
Bob Moore7db5d822008-12-30 11:04:48 +0800282 *
Bob Moore9892dd22009-02-18 15:10:07 +0800283 * RETURN: Status and the value read from the specified Register. Value
Bob Moore7db5d822008-12-30 11:04:48 +0800284 * returned is normalized to bit0 (is shifted all the way right)
285 *
286 * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock.
287 *
Bob Moore9892dd22009-02-18 15:10:07 +0800288 * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
289 * PM2 Control.
290 *
291 * Note: The hardware lock is not required when reading the ACPI bit registers
292 * since almost all of them are single bit and it does not matter that
293 * the parent hardware register can be split across two physical
294 * registers. The only multi-bit field is SLP_TYP in the PM1 control
295 * register, but this field does not cross an 8-bit boundary (nor does
296 * it make much sense to actually read this field.)
297 *
Bob Moore7db5d822008-12-30 11:04:48 +0800298 ******************************************************************************/
Bob Moore50ffba12009-02-23 15:02:07 +0800299acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value)
Bob Moore7db5d822008-12-30 11:04:48 +0800300{
Bob Moore7db5d822008-12-30 11:04:48 +0800301 struct acpi_bit_register_info *bit_reg_info;
Bob Moore88dcb042009-02-18 16:01:04 +0800302 u32 register_value;
303 u32 value;
Bob Moore7db5d822008-12-30 11:04:48 +0800304 acpi_status status;
305
Bob Moore88dcb042009-02-18 16:01:04 +0800306 ACPI_FUNCTION_TRACE_U32(acpi_read_bit_register, register_id);
Bob Moore7db5d822008-12-30 11:04:48 +0800307
308 /* Get the info structure corresponding to the requested ACPI Register */
309
310 bit_reg_info = acpi_hw_get_bit_register_info(register_id);
311 if (!bit_reg_info) {
312 return_ACPI_STATUS(AE_BAD_PARAMETER);
313 }
314
Bob Moore9892dd22009-02-18 15:10:07 +0800315 /* Read the entire parent register */
Bob Moore7db5d822008-12-30 11:04:48 +0800316
317 status = acpi_hw_register_read(bit_reg_info->parent_register,
318 &register_value);
Bob Moore88dcb042009-02-18 16:01:04 +0800319 if (ACPI_FAILURE(status)) {
320 return_ACPI_STATUS(status);
Bob Moore7db5d822008-12-30 11:04:48 +0800321 }
322
Bob Moore88dcb042009-02-18 16:01:04 +0800323 /* Normalize the value that was read, mask off other bits */
324
325 value = ((register_value & bit_reg_info->access_bit_mask)
326 >> bit_reg_info->bit_position);
327
328 ACPI_DEBUG_PRINT((ACPI_DB_IO,
329 "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
330 register_id, bit_reg_info->parent_register,
331 register_value, value));
332
333 *return_value = value;
334 return_ACPI_STATUS(AE_OK);
Bob Moore7db5d822008-12-30 11:04:48 +0800335}
336
Bob Moore50ffba12009-02-23 15:02:07 +0800337ACPI_EXPORT_SYMBOL(acpi_read_bit_register)
Bob Moore7db5d822008-12-30 11:04:48 +0800338
339/*******************************************************************************
340 *
Bob Moore50ffba12009-02-23 15:02:07 +0800341 * FUNCTION: acpi_write_bit_register
Bob Moore7db5d822008-12-30 11:04:48 +0800342 *
Bob Moore9892dd22009-02-18 15:10:07 +0800343 * PARAMETERS: register_id - ID of ACPI Bit Register to access
344 * Value - Value to write to the register, in bit
345 * position zero. The bit is automaticallly
346 * shifted to the correct position.
Bob Moore7db5d822008-12-30 11:04:48 +0800347 *
348 * RETURN: Status
349 *
Bob Moore9892dd22009-02-18 15:10:07 +0800350 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
351 * since most operations require a read/modify/write sequence.
352 *
353 * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
354 * PM2 Control.
Bob Moore7db5d822008-12-30 11:04:48 +0800355 *
Bob Moore88dcb042009-02-18 16:01:04 +0800356 * Note that at this level, the fact that there may be actually two
357 * hardware registers (A and B - and B may not exist) is abstracted.
358 *
Bob Moore7db5d822008-12-30 11:04:48 +0800359 ******************************************************************************/
Bob Moore50ffba12009-02-23 15:02:07 +0800360acpi_status acpi_write_bit_register(u32 register_id, u32 value)
Bob Moore7db5d822008-12-30 11:04:48 +0800361{
Bob Moore7db5d822008-12-30 11:04:48 +0800362 struct acpi_bit_register_info *bit_reg_info;
Bob Moore7db5d822008-12-30 11:04:48 +0800363 acpi_cpu_flags lock_flags;
Bob Moore88dcb042009-02-18 16:01:04 +0800364 u32 register_value;
365 acpi_status status = AE_OK;
Bob Moore7db5d822008-12-30 11:04:48 +0800366
Bob Moore50ffba12009-02-23 15:02:07 +0800367 ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id);
Bob Moore7db5d822008-12-30 11:04:48 +0800368
369 /* Get the info structure corresponding to the requested ACPI Register */
370
371 bit_reg_info = acpi_hw_get_bit_register_info(register_id);
372 if (!bit_reg_info) {
Bob Moore7db5d822008-12-30 11:04:48 +0800373 return_ACPI_STATUS(AE_BAD_PARAMETER);
374 }
375
376 lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
377
Bob Moore7db5d822008-12-30 11:04:48 +0800378 /*
Bob Moore88dcb042009-02-18 16:01:04 +0800379 * At this point, we know that the parent register is one of the
380 * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
Bob Moore7db5d822008-12-30 11:04:48 +0800381 */
Bob Moore88dcb042009-02-18 16:01:04 +0800382 if (bit_reg_info->parent_register != ACPI_REGISTER_PM1_STATUS) {
Bob Moore7db5d822008-12-30 11:04:48 +0800383 /*
Bob Moore88dcb042009-02-18 16:01:04 +0800384 * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
385 *
386 * Perform a register read to preserve the bits that we are not
387 * interested in
Bob Moore7db5d822008-12-30 11:04:48 +0800388 */
Bob Moore88dcb042009-02-18 16:01:04 +0800389 status = acpi_hw_register_read(bit_reg_info->parent_register,
Bob Moore7db5d822008-12-30 11:04:48 +0800390 &register_value);
391 if (ACPI_FAILURE(status)) {
392 goto unlock_and_exit;
393 }
394
Bob Moore88dcb042009-02-18 16:01:04 +0800395 /*
396 * Insert the input bit into the value that was just read
397 * and write the register
398 */
Bob Moore7db5d822008-12-30 11:04:48 +0800399 ACPI_REGISTER_INSERT_VALUE(register_value,
400 bit_reg_info->bit_position,
401 bit_reg_info->access_bit_mask,
402 value);
403
Bob Moore88dcb042009-02-18 16:01:04 +0800404 status = acpi_hw_register_write(bit_reg_info->parent_register,
405 register_value);
406 } else {
407 /*
408 * 2) Case for PM1 Status
409 *
410 * The Status register is different from the rest. Clear an event
411 * by writing 1, writing 0 has no effect. So, the only relevant
412 * information is the single bit we're interested in, all others
413 * should be written as 0 so they will be left unchanged.
414 */
415 register_value = ACPI_REGISTER_PREPARE_BITS(value,
416 bit_reg_info->
417 bit_position,
418 bit_reg_info->
419 access_bit_mask);
Bob Moore7db5d822008-12-30 11:04:48 +0800420
Bob Moore88dcb042009-02-18 16:01:04 +0800421 /* No need to write the register if value is all zeros */
Bob Moore7db5d822008-12-30 11:04:48 +0800422
Bob Moore88dcb042009-02-18 16:01:04 +0800423 if (register_value) {
424 status =
425 acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
426 register_value);
427 }
Bob Moore7db5d822008-12-30 11:04:48 +0800428 }
429
Bob Moore88dcb042009-02-18 16:01:04 +0800430 ACPI_DEBUG_PRINT((ACPI_DB_IO,
431 "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
432 register_id, bit_reg_info->parent_register, value,
433 register_value));
434
435unlock_and_exit:
Bob Moore7db5d822008-12-30 11:04:48 +0800436
437 acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
Bob Moore7db5d822008-12-30 11:04:48 +0800438 return_ACPI_STATUS(status);
439}
440
Bob Moore50ffba12009-02-23 15:02:07 +0800441ACPI_EXPORT_SYMBOL(acpi_write_bit_register)
Bob Moore7db5d822008-12-30 11:04:48 +0800442
443/*******************************************************************************
444 *
445 * FUNCTION: acpi_get_sleep_type_data
446 *
447 * PARAMETERS: sleep_state - Numeric sleep state
448 * *sleep_type_a - Where SLP_TYPa is returned
449 * *sleep_type_b - Where SLP_TYPb is returned
450 *
451 * RETURN: Status - ACPI status
452 *
453 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
454 * state.
455 *
456 ******************************************************************************/
457acpi_status
458acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
459{
460 acpi_status status = AE_OK;
461 struct acpi_evaluate_info *info;
462
463 ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
464
465 /* Validate parameters */
466
467 if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
468 return_ACPI_STATUS(AE_BAD_PARAMETER);
469 }
470
471 /* Allocate the evaluation information block */
472
473 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
474 if (!info) {
475 return_ACPI_STATUS(AE_NO_MEMORY);
476 }
477
478 info->pathname =
479 ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
480
481 /* Evaluate the namespace object containing the values for this state */
482
483 status = acpi_ns_evaluate(info);
484 if (ACPI_FAILURE(status)) {
485 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
486 "%s while evaluating SleepState [%s]\n",
487 acpi_format_exception(status),
488 info->pathname));
489
490 goto cleanup;
491 }
492
493 /* Must have a return object */
494
495 if (!info->return_object) {
496 ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
497 info->pathname));
498 status = AE_NOT_EXIST;
499 }
500
501 /* It must be of type Package */
502
Bob Moore3371c192009-02-18 14:44:03 +0800503 else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) {
Bob Moore7db5d822008-12-30 11:04:48 +0800504 ACPI_ERROR((AE_INFO,
505 "Sleep State return object is not a Package"));
506 status = AE_AML_OPERAND_TYPE;
507 }
508
509 /*
510 * The package must have at least two elements. NOTE (March 2005): This
511 * goes against the current ACPI spec which defines this object as a
512 * package with one encoded DWORD element. However, existing practice
513 * by BIOS vendors seems to be to have 2 or more elements, at least
514 * one per sleep type (A/B).
515 */
516 else if (info->return_object->package.count < 2) {
517 ACPI_ERROR((AE_INFO,
518 "Sleep State return package does not have at least two elements"));
519 status = AE_AML_NO_OPERAND;
520 }
521
522 /* The first two elements must both be of type Integer */
523
Bob Moore3371c192009-02-18 14:44:03 +0800524 else if (((info->return_object->package.elements[0])->common.type
Bob Moore7db5d822008-12-30 11:04:48 +0800525 != ACPI_TYPE_INTEGER) ||
Bob Moore3371c192009-02-18 14:44:03 +0800526 ((info->return_object->package.elements[1])->common.type
Bob Moore7db5d822008-12-30 11:04:48 +0800527 != ACPI_TYPE_INTEGER)) {
528 ACPI_ERROR((AE_INFO,
Bob Moored4913dc2009-03-06 10:05:18 +0800529 "Sleep State return package elements are not both Integers "
530 "(%s, %s)",
Bob Moore7db5d822008-12-30 11:04:48 +0800531 acpi_ut_get_object_type_name(info->return_object->
532 package.elements[0]),
533 acpi_ut_get_object_type_name(info->return_object->
534 package.elements[1])));
535 status = AE_AML_OPERAND_TYPE;
536 } else {
537 /* Valid _Sx_ package size, type, and value */
538
539 *sleep_type_a = (u8)
540 (info->return_object->package.elements[0])->integer.value;
541 *sleep_type_b = (u8)
542 (info->return_object->package.elements[1])->integer.value;
543 }
544
545 if (ACPI_FAILURE(status)) {
546 ACPI_EXCEPTION((AE_INFO, status,
547 "While evaluating SleepState [%s], bad Sleep object %p type %s",
548 info->pathname, info->return_object,
549 acpi_ut_get_object_type_name(info->
550 return_object)));
551 }
552
553 acpi_ut_remove_reference(info->return_object);
554
555 cleanup:
556 ACPI_FREE(info);
557 return_ACPI_STATUS(status);
558}
559
560ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)