ia64/xen-unstable

view xen/drivers/acpi/hwregs.c @ 18896:f7f8f44b9292

tools: Fix a few error-path memory leaks.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 09 12:53:19 2008 +0000 (2008-12-09)
parents a4cf79209a28
children
line source
2 /*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 * control and status registers.
6 *
7 ******************************************************************************/
9 /*
10 * Copyright (C) 2000 - 2006, R. Byron Moore
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions, and the following disclaimer,
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20 * substantially similar to the "NO WARRANTY" disclaimer below
21 * ("Disclaimer") and any redistribution must be conditioned upon
22 * including a substantially similar Disclaimer requirement for further
23 * binary redistribution.
24 * 3. Neither the names of the above-listed copyright holders nor the names
25 * of any contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * Alternatively, this software may be distributed under the terms of the
29 * GNU General Public License ("GPL") version 2 as published by the Free
30 * Software Foundation.
31 *
32 * NO WARRANTY
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGES.
44 */
46 #include <asm/io.h>
47 #include <xen/config.h>
48 #include <xen/init.h>
49 #include <xen/types.h>
50 #include <xen/errno.h>
51 #include <acpi/acpi.h>
53 #define _COMPONENT ACPI_HARDWARE
54 ACPI_MODULE_NAME("hwregs")
56 /*******************************************************************************
57 *
58 * FUNCTION: acpi_hw_get_register_bit_mask
59 *
60 * PARAMETERS: register_id - Index of ACPI Register to access
61 *
62 * RETURN: The bitmask to be used when accessing the register
63 *
64 * DESCRIPTION: Map register_id into a register bitmask.
65 *
66 ******************************************************************************/
67 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
68 {
69 ACPI_FUNCTION_ENTRY();
71 if (register_id > ACPI_BITREG_MAX) {
72 ACPI_DEBUG_PRINT((AE_INFO, "Invalid BitRegister ID: %X",
73 register_id));
74 return (NULL);
75 }
77 return (&acpi_gbl_bit_register_info[register_id]);
78 }
80 /*******************************************************************************
81 *
82 * FUNCTION: acpi_get_register
83 *
84 * PARAMETERS: register_id - ID of ACPI bit_register to access
85 * return_value - Value that was read from the register
86 *
87 * RETURN: Status and the value read from specified Register. Value
88 * returned is normalized to bit0 (is shifted all the way right)
89 *
90 * DESCRIPTION: ACPI bit_register read function.
91 *
92 ******************************************************************************/
94 acpi_status acpi_get_register_unlocked(u32 register_id, u32 * return_value)
95 {
96 u32 register_value = 0;
97 struct acpi_bit_register_info *bit_reg_info;
98 acpi_status status;
100 ACPI_FUNCTION_TRACE(acpi_get_register);
102 /* Get the info structure corresponding to the requested ACPI Register */
104 bit_reg_info = acpi_hw_get_bit_register_info(register_id);
105 if (!bit_reg_info) {
106 return_ACPI_STATUS(AE_BAD_PARAMETER);
107 }
109 /* Read from the register */
111 status = acpi_hw_register_read(bit_reg_info->parent_register,
112 &register_value);
114 if (ACPI_SUCCESS(status)) {
116 /* Normalize the value that was read */
118 register_value =
119 ((register_value & bit_reg_info->access_bit_mask)
120 >> bit_reg_info->bit_position);
122 *return_value = register_value;
124 ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n",
125 register_value,
126 bit_reg_info->parent_register));
127 }
129 return_ACPI_STATUS(status);
130 }
132 acpi_status acpi_get_register(u32 register_id, u32 * return_value)
133 {
134 acpi_status status;
135 //acpi_cpu_flags flags;
136 //flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
137 status = acpi_get_register_unlocked(register_id, return_value);
138 //acpi_os_release_lock(acpi_gbl_hardware_lock, flags);
139 return status;
140 }
142 /*******************************************************************************
143 *
144 * FUNCTION: acpi_set_register
145 *
146 * PARAMETERS: register_id - ID of ACPI bit_register to access
147 * Value - (only used on write) value to write to the
148 * Register, NOT pre-normalized to the bit pos
149 *
150 * RETURN: Status
151 *
152 * DESCRIPTION: ACPI Bit Register write function.
153 *
154 ******************************************************************************/
155 acpi_status acpi_set_register(u32 register_id, u32 value)
156 {
157 u32 register_value = 0;
158 struct acpi_bit_register_info *bit_reg_info;
159 acpi_status status;
160 //acpi_cpu_flags lock_flags;
162 ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id);
164 /* Get the info structure corresponding to the requested ACPI Register */
166 bit_reg_info = acpi_hw_get_bit_register_info(register_id);
167 if (!bit_reg_info) {
168 ACPI_DEBUG_PRINT((AE_INFO, "Bad ACPI HW RegisterId: %X",
169 register_id));
170 return_ACPI_STATUS(AE_BAD_PARAMETER);
171 }
173 //lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
175 /* Always do a register read first so we can insert the new bits */
177 status = acpi_hw_register_read(bit_reg_info->parent_register,
178 &register_value);
179 if (ACPI_FAILURE(status)) {
180 goto unlock_and_exit;
181 }
183 /*
184 * Decode the Register ID
185 * Register ID = [Register block ID] | [bit ID]
186 *
187 * Check bit ID to fine locate Register offset.
188 * Check Mask to determine Register offset, and then read-write.
189 */
190 switch (bit_reg_info->parent_register) {
191 case ACPI_REGISTER_PM1_STATUS:
193 /*
194 * Status Registers are different from the rest. Clear by
195 * writing 1, and writing 0 has no effect. So, the only relevant
196 * information is the single bit we're interested in, all others should
197 * be written as 0 so they will be left unchanged.
198 */
199 value = ACPI_REGISTER_PREPARE_BITS(value,
200 bit_reg_info->bit_position,
201 bit_reg_info->
202 access_bit_mask);
203 if (value) {
204 status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
205 (u16) value);
206 register_value = 0;
207 }
208 break;
210 case ACPI_REGISTER_PM1_ENABLE:
212 ACPI_REGISTER_INSERT_VALUE(register_value,
213 bit_reg_info->bit_position,
214 bit_reg_info->access_bit_mask,
215 value);
217 status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE,
218 (u16) register_value);
219 break;
221 case ACPI_REGISTER_PM1_CONTROL:
223 /*
224 * Write the PM1 Control register.
225 * Note that at this level, the fact that there are actually TWO
226 * registers (A and B - and B may not exist) is abstracted.
227 */
228 ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n",
229 register_value));
231 ACPI_REGISTER_INSERT_VALUE(register_value,
232 bit_reg_info->bit_position,
233 bit_reg_info->access_bit_mask,
234 value);
236 status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
237 (u16) register_value);
238 break;
240 case ACPI_REGISTER_PM2_CONTROL:
242 #if 0 /* Redundant read in original Linux code. */
243 status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL,
244 &register_value);
245 if (ACPI_FAILURE(status)) {
246 goto unlock_and_exit;
247 }
248 #endif
250 ACPI_DEBUG_PRINT((ACPI_DB_IO,
251 "PM2 control: Read %X from %8.8X%8.8X\n",
252 register_value,
253 ACPI_FORMAT_UINT64(acpi_gbl_FADT.
254 xpm2_control_block.
255 address)));
257 ACPI_REGISTER_INSERT_VALUE(register_value,
258 bit_reg_info->bit_position,
259 bit_reg_info->access_bit_mask,
260 value);
262 ACPI_DEBUG_PRINT((ACPI_DB_IO,
263 "About to write %4.4X to %8.8X%8.8X\n",
264 register_value,
265 ACPI_FORMAT_UINT64(acpi_gbl_FADT.
266 xpm2_control_block.
267 address)));
269 status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL,
270 (u8) (register_value));
271 break;
273 default:
274 break;
275 }
277 unlock_and_exit:
279 //acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
281 /* Normalize the value that was read */
283 ACPI_DEBUG_EXEC(register_value =
284 ((register_value & bit_reg_info->access_bit_mask) >>
285 bit_reg_info->bit_position));
287 ACPI_DEBUG_PRINT((ACPI_DB_IO,
288 "Set bits: %8.8X actual %8.8X register %X\n", value,
289 register_value, bit_reg_info->parent_register));
290 return_ACPI_STATUS(status);
291 }
293 /******************************************************************************
294 *
295 * FUNCTION: acpi_hw_register_read
296 *
297 * PARAMETERS: register_id - ACPI Register ID
298 * return_value - Where the register value is returned
299 *
300 * RETURN: Status and the value read.
301 *
302 * DESCRIPTION: Read from the specified ACPI register
303 *
304 ******************************************************************************/
305 acpi_status
306 acpi_hw_register_read(u32 register_id, u32 * return_value)
307 {
308 u32 value1 = 0;
309 u32 value2 = 0;
310 acpi_status status;
312 ACPI_FUNCTION_TRACE(hw_register_read);
314 switch (register_id) {
315 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
317 status =
318 acpi_hw_low_level_read(16, &value1,
319 &acpi_gbl_FADT.xpm1a_event_block);
320 if (ACPI_FAILURE(status)) {
321 goto exit;
322 }
324 /* PM1B is optional */
326 status =
327 acpi_hw_low_level_read(16, &value2,
328 &acpi_gbl_FADT.xpm1b_event_block);
329 value1 |= value2;
330 break;
332 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
334 status =
335 acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
336 if (ACPI_FAILURE(status)) {
337 goto exit;
338 }
340 /* PM1B is optional */
342 status =
343 acpi_hw_low_level_read(16, &value2, &acpi_gbl_xpm1b_enable);
344 value1 |= value2;
345 break;
347 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
349 status =
350 acpi_hw_low_level_read(16, &value1,
351 &acpi_gbl_FADT.xpm1a_control_block);
352 if (ACPI_FAILURE(status)) {
353 goto exit;
354 }
356 status =
357 acpi_hw_low_level_read(16, &value2,
358 &acpi_gbl_FADT.xpm1b_control_block);
359 value1 |= value2;
360 break;
362 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
364 status =
365 acpi_hw_low_level_read(8, &value1,
366 &acpi_gbl_FADT.xpm2_control_block);
367 break;
369 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
371 status =
372 acpi_hw_low_level_read(32, &value1,
373 &acpi_gbl_FADT.xpm_timer_block);
374 break;
376 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
378 status =
379 acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
380 break;
382 default:
383 ACPI_DEBUG_PRINT((AE_INFO, "Unknown Register ID: %X", register_id));
384 status = AE_BAD_PARAMETER;
385 break;
386 }
388 exit:
390 if (ACPI_SUCCESS(status)) {
391 *return_value = value1;
392 }
394 return_ACPI_STATUS(status);
395 }
397 /******************************************************************************
398 *
399 * FUNCTION: acpi_hw_register_write
400 *
401 * PARAMETERS: register_id - ACPI Register ID
402 * Value - The value to write
403 *
404 * RETURN: Status
405 *
406 * DESCRIPTION: Write to the specified ACPI register
407 *
408 * NOTE: In accordance with the ACPI specification, this function automatically
409 * preserves the value of the following bits, meaning that these bits cannot be
410 * changed via this interface:
411 *
412 * PM1_CONTROL[0] = SCI_EN
413 * PM1_CONTROL[9]
414 * PM1_STATUS[11]
415 *
416 * ACPI References:
417 * 1) Hardware Ignored Bits: When software writes to a register with ignored
418 * bit fields, it preserves the ignored bit fields
419 * 2) SCI_EN: OSPM always preserves this bit position
420 *
421 ******************************************************************************/
423 acpi_status acpi_hw_register_write(u32 register_id, u32 value)
424 {
425 acpi_status status;
426 u32 read_value;
428 ACPI_FUNCTION_TRACE(hw_register_write);
430 switch (register_id) {
431 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
433 /* Perform a read first to preserve certain bits (per ACPI spec) */
435 status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
436 &read_value);
437 if (ACPI_FAILURE(status)) {
438 goto exit;
439 }
441 /* Insert the bits to be preserved */
443 ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
444 read_value);
446 /* Now we can write the data */
448 status =
449 acpi_hw_low_level_write(16, value,
450 &acpi_gbl_FADT.xpm1a_event_block);
451 if (ACPI_FAILURE(status)) {
452 goto exit;
453 }
455 /* PM1B is optional */
457 status =
458 acpi_hw_low_level_write(16, value,
459 &acpi_gbl_FADT.xpm1b_event_block);
460 break;
462 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
464 status =
465 acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
466 if (ACPI_FAILURE(status)) {
467 goto exit;
468 }
470 /* PM1B is optional */
472 status =
473 acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1b_enable);
474 break;
476 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
478 /*
479 * Perform a read first to preserve certain bits (per ACPI spec)
480 */
481 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
482 &read_value);
483 if (ACPI_FAILURE(status)) {
484 goto exit;
485 }
487 /* Insert the bits to be preserved */
489 ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
490 read_value);
492 /* Now we can write the data */
494 status =
495 acpi_hw_low_level_write(16, value,
496 &acpi_gbl_FADT.xpm1a_control_block);
497 if (ACPI_FAILURE(status)) {
498 goto exit;
499 }
501 status =
502 acpi_hw_low_level_write(16, value,
503 &acpi_gbl_FADT.xpm1b_control_block);
504 break;
506 case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
508 status =
509 acpi_hw_low_level_write(16, value,
510 &acpi_gbl_FADT.xpm1a_control_block);
511 break;
513 case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
515 status =
516 acpi_hw_low_level_write(16, value,
517 &acpi_gbl_FADT.xpm1b_control_block);
518 break;
520 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
522 status =
523 acpi_hw_low_level_write(8, value,
524 &acpi_gbl_FADT.xpm2_control_block);
525 break;
527 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
529 status =
530 acpi_hw_low_level_write(32, value,
531 &acpi_gbl_FADT.xpm_timer_block);
532 break;
534 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
536 /* SMI_CMD is currently always in IO space */
538 status =
539 acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
540 break;
542 default:
543 status = AE_BAD_PARAMETER;
544 break;
545 }
547 exit:
548 return_ACPI_STATUS(status);
549 }
551 /******************************************************************************
552 *
553 * FUNCTION: acpi_hw_low_level_read
554 *
555 * PARAMETERS: Width - 8, 16, or 32
556 * Value - Where the value is returned
557 * Reg - GAS register structure
558 *
559 * RETURN: Status
560 *
561 * DESCRIPTION: Read from either memory or IO space.
562 *
563 ******************************************************************************/
565 acpi_status
566 acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
567 {
568 u64 address;
569 acpi_status status;
571 ACPI_FUNCTION_NAME(hw_low_level_read);
573 /*
574 * Must have a valid pointer to a GAS structure, and
575 * a non-zero address within. However, don't return an error
576 * because the PM1A/B code must not fail if B isn't present.
577 */
578 if (!reg) {
579 return (AE_OK);
580 }
582 /* Get a local copy of the address. Handles possible alignment issues */
584 ACPI_MOVE_64_TO_64(&address, &reg->address);
585 if (!address) {
586 return (AE_OK);
587 }
588 *value = 0;
590 /*
591 * Two address spaces supported: Memory or IO.
592 * PCI_Config is not supported here because the GAS struct is insufficient
593 */
594 switch (reg->space_id) {
595 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
597 status = acpi_os_read_memory((acpi_physical_address) address,
598 value, width);
599 break;
601 case ACPI_ADR_SPACE_SYSTEM_IO:
603 status = acpi_os_read_port((acpi_io_address) address,
604 value, width);
605 break;
607 default:
609 return (AE_BAD_PARAMETER);
610 }
612 ACPI_DEBUG_PRINT((ACPI_DB_IO,
613 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
614 *value, width,
615 ACPI_FORMAT_UINT64(address),
616 acpi_ut_get_region_name(reg->address_space_id)));
618 return (status);
619 }
621 /******************************************************************************
622 *
623 * FUNCTION: acpi_hw_low_level_write
624 *
625 * PARAMETERS: Width - 8, 16, or 32
626 * Value - To be written
627 * Reg - GAS register structure
628 *
629 * RETURN: Status
630 *
631 * DESCRIPTION: Write to either memory or IO space.
632 *
633 ******************************************************************************/
635 acpi_status
636 acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
637 {
638 u64 address;
639 acpi_status status;
641 ACPI_FUNCTION_NAME(hw_low_level_write);
643 /*
644 * Must have a valid pointer to a GAS structure, and
645 * a non-zero address within. However, don't return an error
646 * because the PM1A/B code must not fail if B isn't present.
647 */
648 if (!reg) {
649 return (AE_OK);
650 }
652 /* Get a local copy of the address. Handles possible alignment issues */
654 ACPI_MOVE_64_TO_64(&address, &reg->address);
655 if (!address) {
656 return (AE_OK);
657 }
659 /*
660 * Two address spaces supported: Memory or IO.
661 * PCI_Config is not supported here because the GAS struct is insufficient
662 */
663 switch (reg->space_id) {
664 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
666 status = acpi_os_write_memory((acpi_physical_address) address,
667 value, width);
668 break;
670 case ACPI_ADR_SPACE_SYSTEM_IO:
672 status = acpi_os_write_port((acpi_io_address) address,
673 value, width);
674 break;
676 default:
677 return (AE_BAD_PARAMETER);
678 }
680 ACPI_DEBUG_PRINT((ACPI_DB_IO,
681 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
682 value, width,
683 ACPI_FORMAT_UINT64(address),
684 acpi_ut_get_region_name(reg->address_space_id)));
686 return (status);
687 }