Pull bay into test branch
[linux-2.6] / drivers / acpi / hardware / hwregs.c
1
2 /*******************************************************************************
3  *
4  * Module Name: hwregs - Read/write access functions for the various ACPI
5  *                       control and status registers.
6  *
7  ******************************************************************************/
8
9 /*
10  * Copyright (C) 2000 - 2007, 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  */
45
46 #include <acpi/acpi.h>
47 #include <acpi/acnamesp.h>
48 #include <acpi/acevents.h>
49
50 #define _COMPONENT          ACPI_HARDWARE
51 ACPI_MODULE_NAME("hwregs")
52
53 /*******************************************************************************
54  *
55  * FUNCTION:    acpi_hw_clear_acpi_status
56  *
57  * PARAMETERS:  None
58  *
59  * RETURN:      None
60  *
61  * DESCRIPTION: Clears all fixed and general purpose status bits
62  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
63  *
64  ******************************************************************************/
65 acpi_status acpi_hw_clear_acpi_status(void)
66 {
67         acpi_status status;
68         acpi_cpu_flags lock_flags = 0;
69
70         ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
71
72         ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
73                           ACPI_BITMASK_ALL_FIXED_STATUS,
74                           (u16) acpi_gbl_FADT.xpm1a_event_block.address));
75
76         lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
77
78         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
79                                         ACPI_REGISTER_PM1_STATUS,
80                                         ACPI_BITMASK_ALL_FIXED_STATUS);
81         if (ACPI_FAILURE(status)) {
82                 goto unlock_and_exit;
83         }
84
85         /* Clear the fixed events */
86
87         if (acpi_gbl_FADT.xpm1b_event_block.address) {
88                 status =
89                     acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
90                                             &acpi_gbl_FADT.xpm1b_event_block);
91                 if (ACPI_FAILURE(status)) {
92                         goto unlock_and_exit;
93                 }
94         }
95
96         /* Clear the GPE Bits in all GPE registers in all GPE blocks */
97
98         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
99
100       unlock_and_exit:
101         acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
102         return_ACPI_STATUS(status);
103 }
104
105 /*******************************************************************************
106  *
107  * FUNCTION:    acpi_get_sleep_type_data
108  *
109  * PARAMETERS:  sleep_state         - Numeric sleep state
110  *              *sleep_type_a        - Where SLP_TYPa is returned
111  *              *sleep_type_b        - Where SLP_TYPb is returned
112  *
113  * RETURN:      Status - ACPI status
114  *
115  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
116  *              state.
117  *
118  ******************************************************************************/
119
120 acpi_status
121 acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
122 {
123         acpi_status status = AE_OK;
124         struct acpi_evaluate_info *info;
125
126         ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
127
128         /* Validate parameters */
129
130         if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
131                 return_ACPI_STATUS(AE_BAD_PARAMETER);
132         }
133
134         /* Allocate the evaluation information block */
135
136         info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
137         if (!info) {
138                 return_ACPI_STATUS(AE_NO_MEMORY);
139         }
140
141         info->pathname =
142             ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
143
144         /* Evaluate the namespace object containing the values for this state */
145
146         status = acpi_ns_evaluate(info);
147         if (ACPI_FAILURE(status)) {
148                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
149                                   "%s while evaluating SleepState [%s]\n",
150                                   acpi_format_exception(status),
151                                   info->pathname));
152
153                 goto cleanup;
154         }
155
156         /* Must have a return object */
157
158         if (!info->return_object) {
159                 ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
160                             info->pathname));
161                 status = AE_NOT_EXIST;
162         }
163
164         /* It must be of type Package */
165
166         else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
167                 ACPI_ERROR((AE_INFO,
168                             "Sleep State return object is not a Package"));
169                 status = AE_AML_OPERAND_TYPE;
170         }
171
172         /*
173          * The package must have at least two elements. NOTE (March 2005): This
174          * goes against the current ACPI spec which defines this object as a
175          * package with one encoded DWORD element. However, existing practice
176          * by BIOS vendors seems to be to have 2 or more elements, at least
177          * one per sleep type (A/B).
178          */
179         else if (info->return_object->package.count < 2) {
180                 ACPI_ERROR((AE_INFO,
181                             "Sleep State return package does not have at least two elements"));
182                 status = AE_AML_NO_OPERAND;
183         }
184
185         /* The first two elements must both be of type Integer */
186
187         else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
188                   != ACPI_TYPE_INTEGER) ||
189                  (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
190                   != ACPI_TYPE_INTEGER)) {
191                 ACPI_ERROR((AE_INFO,
192                             "Sleep State return package elements are not both Integers (%s, %s)",
193                             acpi_ut_get_object_type_name(info->return_object->
194                                                          package.elements[0]),
195                             acpi_ut_get_object_type_name(info->return_object->
196                                                          package.elements[1])));
197                 status = AE_AML_OPERAND_TYPE;
198         } else {
199                 /* Valid _Sx_ package size, type, and value */
200
201                 *sleep_type_a = (u8)
202                     (info->return_object->package.elements[0])->integer.value;
203                 *sleep_type_b = (u8)
204                     (info->return_object->package.elements[1])->integer.value;
205         }
206
207         if (ACPI_FAILURE(status)) {
208                 ACPI_EXCEPTION((AE_INFO, status,
209                                 "While evaluating SleepState [%s], bad Sleep object %p type %s",
210                                 info->pathname, info->return_object,
211                                 acpi_ut_get_object_type_name(info->
212                                                              return_object)));
213         }
214
215         acpi_ut_remove_reference(info->return_object);
216
217       cleanup:
218         ACPI_FREE(info);
219         return_ACPI_STATUS(status);
220 }
221
222 ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
223
224 /*******************************************************************************
225  *
226  * FUNCTION:    acpi_hw_get_register_bit_mask
227  *
228  * PARAMETERS:  register_id         - Index of ACPI Register to access
229  *
230  * RETURN:      The bitmask to be used when accessing the register
231  *
232  * DESCRIPTION: Map register_id into a register bitmask.
233  *
234  ******************************************************************************/
235 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
236 {
237         ACPI_FUNCTION_ENTRY();
238
239         if (register_id > ACPI_BITREG_MAX) {
240                 ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
241                             register_id));
242                 return (NULL);
243         }
244
245         return (&acpi_gbl_bit_register_info[register_id]);
246 }
247
248 /*******************************************************************************
249  *
250  * FUNCTION:    acpi_get_register
251  *
252  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
253  *              return_value    - Value that was read from the register
254  *
255  * RETURN:      Status and the value read from specified Register. Value
256  *              returned is normalized to bit0 (is shifted all the way right)
257  *
258  * DESCRIPTION: ACPI bit_register read function.
259  *
260  ******************************************************************************/
261
262 acpi_status acpi_get_register(u32 register_id, u32 * return_value)
263 {
264         u32 register_value = 0;
265         struct acpi_bit_register_info *bit_reg_info;
266         acpi_status status;
267
268         ACPI_FUNCTION_TRACE(acpi_get_register);
269
270         /* Get the info structure corresponding to the requested ACPI Register */
271
272         bit_reg_info = acpi_hw_get_bit_register_info(register_id);
273         if (!bit_reg_info) {
274                 return_ACPI_STATUS(AE_BAD_PARAMETER);
275         }
276
277         /* Read from the register */
278
279         status = acpi_hw_register_read(ACPI_MTX_LOCK,
280                                        bit_reg_info->parent_register,
281                                        &register_value);
282
283         if (ACPI_SUCCESS(status)) {
284
285                 /* Normalize the value that was read */
286
287                 register_value =
288                     ((register_value & bit_reg_info->access_bit_mask)
289                      >> bit_reg_info->bit_position);
290
291                 *return_value = register_value;
292
293                 ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n",
294                                   register_value,
295                                   bit_reg_info->parent_register));
296         }
297
298         return_ACPI_STATUS(status);
299 }
300
301 ACPI_EXPORT_SYMBOL(acpi_get_register)
302
303 /*******************************************************************************
304  *
305  * FUNCTION:    acpi_set_register
306  *
307  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
308  *              Value           - (only used on write) value to write to the
309  *                                Register, NOT pre-normalized to the bit pos
310  *
311  * RETURN:      Status
312  *
313  * DESCRIPTION: ACPI Bit Register write function.
314  *
315  ******************************************************************************/
316 acpi_status acpi_set_register(u32 register_id, u32 value)
317 {
318         u32 register_value = 0;
319         struct acpi_bit_register_info *bit_reg_info;
320         acpi_status status;
321         acpi_cpu_flags lock_flags;
322
323         ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id);
324
325         /* Get the info structure corresponding to the requested ACPI Register */
326
327         bit_reg_info = acpi_hw_get_bit_register_info(register_id);
328         if (!bit_reg_info) {
329                 ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X",
330                             register_id));
331                 return_ACPI_STATUS(AE_BAD_PARAMETER);
332         }
333
334         lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
335
336         /* Always do a register read first so we can insert the new bits  */
337
338         status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
339                                        bit_reg_info->parent_register,
340                                        &register_value);
341         if (ACPI_FAILURE(status)) {
342                 goto unlock_and_exit;
343         }
344
345         /*
346          * Decode the Register ID
347          * Register ID = [Register block ID] | [bit ID]
348          *
349          * Check bit ID to fine locate Register offset.
350          * Check Mask to determine Register offset, and then read-write.
351          */
352         switch (bit_reg_info->parent_register) {
353         case ACPI_REGISTER_PM1_STATUS:
354
355                 /*
356                  * Status Registers are different from the rest. Clear by
357                  * writing 1, and writing 0 has no effect. So, the only relevant
358                  * information is the single bit we're interested in, all others should
359                  * be written as 0 so they will be left unchanged.
360                  */
361                 value = ACPI_REGISTER_PREPARE_BITS(value,
362                                                    bit_reg_info->bit_position,
363                                                    bit_reg_info->
364                                                    access_bit_mask);
365                 if (value) {
366                         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
367                                                         ACPI_REGISTER_PM1_STATUS,
368                                                         (u16) value);
369                         register_value = 0;
370                 }
371                 break;
372
373         case ACPI_REGISTER_PM1_ENABLE:
374
375                 ACPI_REGISTER_INSERT_VALUE(register_value,
376                                            bit_reg_info->bit_position,
377                                            bit_reg_info->access_bit_mask,
378                                            value);
379
380                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
381                                                 ACPI_REGISTER_PM1_ENABLE,
382                                                 (u16) register_value);
383                 break;
384
385         case ACPI_REGISTER_PM1_CONTROL:
386
387                 /*
388                  * Write the PM1 Control register.
389                  * Note that at this level, the fact that there are actually TWO
390                  * registers (A and B - and B may not exist) is abstracted.
391                  */
392                 ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n",
393                                   register_value));
394
395                 ACPI_REGISTER_INSERT_VALUE(register_value,
396                                            bit_reg_info->bit_position,
397                                            bit_reg_info->access_bit_mask,
398                                            value);
399
400                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
401                                                 ACPI_REGISTER_PM1_CONTROL,
402                                                 (u16) register_value);
403                 break;
404
405         case ACPI_REGISTER_PM2_CONTROL:
406
407                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
408                                                ACPI_REGISTER_PM2_CONTROL,
409                                                &register_value);
410                 if (ACPI_FAILURE(status)) {
411                         goto unlock_and_exit;
412                 }
413
414                 ACPI_DEBUG_PRINT((ACPI_DB_IO,
415                                   "PM2 control: Read %X from %8.8X%8.8X\n",
416                                   register_value,
417                                   ACPI_FORMAT_UINT64(acpi_gbl_FADT.
418                                                      xpm2_control_block.
419                                                      address)));
420
421                 ACPI_REGISTER_INSERT_VALUE(register_value,
422                                            bit_reg_info->bit_position,
423                                            bit_reg_info->access_bit_mask,
424                                            value);
425
426                 ACPI_DEBUG_PRINT((ACPI_DB_IO,
427                                   "About to write %4.4X to %8.8X%8.8X\n",
428                                   register_value,
429                                   ACPI_FORMAT_UINT64(acpi_gbl_FADT.
430                                                      xpm2_control_block.
431                                                      address)));
432
433                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
434                                                 ACPI_REGISTER_PM2_CONTROL,
435                                                 (u8) (register_value));
436                 break;
437
438         default:
439                 break;
440         }
441
442       unlock_and_exit:
443
444         acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
445
446         /* Normalize the value that was read */
447
448         ACPI_DEBUG_EXEC(register_value =
449                         ((register_value & bit_reg_info->access_bit_mask) >>
450                          bit_reg_info->bit_position));
451
452         ACPI_DEBUG_PRINT((ACPI_DB_IO,
453                           "Set bits: %8.8X actual %8.8X register %X\n", value,
454                           register_value, bit_reg_info->parent_register));
455         return_ACPI_STATUS(status);
456 }
457
458 ACPI_EXPORT_SYMBOL(acpi_set_register)
459
460 /******************************************************************************
461  *
462  * FUNCTION:    acpi_hw_register_read
463  *
464  * PARAMETERS:  use_lock            - Lock hardware? True/False
465  *              register_id         - ACPI Register ID
466  *              return_value        - Where the register value is returned
467  *
468  * RETURN:      Status and the value read.
469  *
470  * DESCRIPTION: Read from the specified ACPI register
471  *
472  ******************************************************************************/
473 acpi_status
474 acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
475 {
476         u32 value1 = 0;
477         u32 value2 = 0;
478         acpi_status status;
479         acpi_cpu_flags lock_flags = 0;
480
481         ACPI_FUNCTION_TRACE(hw_register_read);
482
483         if (ACPI_MTX_LOCK == use_lock) {
484                 lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
485         }
486
487         switch (register_id) {
488         case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
489
490                 status =
491                     acpi_hw_low_level_read(16, &value1,
492                                            &acpi_gbl_FADT.xpm1a_event_block);
493                 if (ACPI_FAILURE(status)) {
494                         goto unlock_and_exit;
495                 }
496
497                 /* PM1B is optional */
498
499                 status =
500                     acpi_hw_low_level_read(16, &value2,
501                                            &acpi_gbl_FADT.xpm1b_event_block);
502                 value1 |= value2;
503                 break;
504
505         case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
506
507                 status =
508                     acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
509                 if (ACPI_FAILURE(status)) {
510                         goto unlock_and_exit;
511                 }
512
513                 /* PM1B is optional */
514
515                 status =
516                     acpi_hw_low_level_read(16, &value2, &acpi_gbl_xpm1b_enable);
517                 value1 |= value2;
518                 break;
519
520         case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
521
522                 status =
523                     acpi_hw_low_level_read(16, &value1,
524                                            &acpi_gbl_FADT.xpm1a_control_block);
525                 if (ACPI_FAILURE(status)) {
526                         goto unlock_and_exit;
527                 }
528
529                 status =
530                     acpi_hw_low_level_read(16, &value2,
531                                            &acpi_gbl_FADT.xpm1b_control_block);
532                 value1 |= value2;
533                 break;
534
535         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
536
537                 status =
538                     acpi_hw_low_level_read(8, &value1,
539                                            &acpi_gbl_FADT.xpm2_control_block);
540                 break;
541
542         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
543
544                 status =
545                     acpi_hw_low_level_read(32, &value1,
546                                            &acpi_gbl_FADT.xpm_timer_block);
547                 break;
548
549         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
550
551                 status =
552                     acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
553                 break;
554
555         default:
556                 ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
557                 status = AE_BAD_PARAMETER;
558                 break;
559         }
560
561       unlock_and_exit:
562         if (ACPI_MTX_LOCK == use_lock) {
563                 acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
564         }
565
566         if (ACPI_SUCCESS(status)) {
567                 *return_value = value1;
568         }
569
570         return_ACPI_STATUS(status);
571 }
572
573 /******************************************************************************
574  *
575  * FUNCTION:    acpi_hw_register_write
576  *
577  * PARAMETERS:  use_lock            - Lock hardware? True/False
578  *              register_id         - ACPI Register ID
579  *              Value               - The value to write
580  *
581  * RETURN:      Status
582  *
583  * DESCRIPTION: Write to the specified ACPI register
584  *
585  * NOTE: In accordance with the ACPI specification, this function automatically
586  * preserves the value of the following bits, meaning that these bits cannot be
587  * changed via this interface:
588  *
589  * PM1_CONTROL[0] = SCI_EN
590  * PM1_CONTROL[9]
591  * PM1_STATUS[11]
592  *
593  * ACPI References:
594  * 1) Hardware Ignored Bits: When software writes to a register with ignored
595  *      bit fields, it preserves the ignored bit fields
596  * 2) SCI_EN: OSPM always preserves this bit position
597  *
598  ******************************************************************************/
599
600 acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
601 {
602         acpi_status status;
603         acpi_cpu_flags lock_flags = 0;
604         u32 read_value;
605
606         ACPI_FUNCTION_TRACE(hw_register_write);
607
608         if (ACPI_MTX_LOCK == use_lock) {
609                 lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
610         }
611
612         switch (register_id) {
613         case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
614
615                 /* Perform a read first to preserve certain bits (per ACPI spec) */
616
617                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
618                                                ACPI_REGISTER_PM1_STATUS,
619                                                &read_value);
620                 if (ACPI_FAILURE(status)) {
621                         goto unlock_and_exit;
622                 }
623
624                 /* Insert the bits to be preserved */
625
626                 ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
627                                  read_value);
628
629                 /* Now we can write the data */
630
631                 status =
632                     acpi_hw_low_level_write(16, value,
633                                             &acpi_gbl_FADT.xpm1a_event_block);
634                 if (ACPI_FAILURE(status)) {
635                         goto unlock_and_exit;
636                 }
637
638                 /* PM1B is optional */
639
640                 status =
641                     acpi_hw_low_level_write(16, value,
642                                             &acpi_gbl_FADT.xpm1b_event_block);
643                 break;
644
645         case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
646
647                 status =
648                     acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
649                 if (ACPI_FAILURE(status)) {
650                         goto unlock_and_exit;
651                 }
652
653                 /* PM1B is optional */
654
655                 status =
656                     acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1b_enable);
657                 break;
658
659         case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
660
661                 /*
662                  * Perform a read first to preserve certain bits (per ACPI spec)
663                  */
664                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
665                                                ACPI_REGISTER_PM1_CONTROL,
666                                                &read_value);
667                 if (ACPI_FAILURE(status)) {
668                         goto unlock_and_exit;
669                 }
670
671                 /* Insert the bits to be preserved */
672
673                 ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
674                                  read_value);
675
676                 /* Now we can write the data */
677
678                 status =
679                     acpi_hw_low_level_write(16, value,
680                                             &acpi_gbl_FADT.xpm1a_control_block);
681                 if (ACPI_FAILURE(status)) {
682                         goto unlock_and_exit;
683                 }
684
685                 status =
686                     acpi_hw_low_level_write(16, value,
687                                             &acpi_gbl_FADT.xpm1b_control_block);
688                 break;
689
690         case ACPI_REGISTER_PM1A_CONTROL:        /* 16-bit access */
691
692                 status =
693                     acpi_hw_low_level_write(16, value,
694                                             &acpi_gbl_FADT.xpm1a_control_block);
695                 break;
696
697         case ACPI_REGISTER_PM1B_CONTROL:        /* 16-bit access */
698
699                 status =
700                     acpi_hw_low_level_write(16, value,
701                                             &acpi_gbl_FADT.xpm1b_control_block);
702                 break;
703
704         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
705
706                 status =
707                     acpi_hw_low_level_write(8, value,
708                                             &acpi_gbl_FADT.xpm2_control_block);
709                 break;
710
711         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
712
713                 status =
714                     acpi_hw_low_level_write(32, value,
715                                             &acpi_gbl_FADT.xpm_timer_block);
716                 break;
717
718         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
719
720                 /* SMI_CMD is currently always in IO space */
721
722                 status =
723                     acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
724                 break;
725
726         default:
727                 status = AE_BAD_PARAMETER;
728                 break;
729         }
730
731       unlock_and_exit:
732         if (ACPI_MTX_LOCK == use_lock) {
733                 acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
734         }
735
736         return_ACPI_STATUS(status);
737 }
738
739 /******************************************************************************
740  *
741  * FUNCTION:    acpi_hw_low_level_read
742  *
743  * PARAMETERS:  Width               - 8, 16, or 32
744  *              Value               - Where the value is returned
745  *              Reg                 - GAS register structure
746  *
747  * RETURN:      Status
748  *
749  * DESCRIPTION: Read from either memory or IO space.
750  *
751  ******************************************************************************/
752
753 acpi_status
754 acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
755 {
756         u64 address;
757         acpi_status status;
758
759         ACPI_FUNCTION_NAME(hw_low_level_read);
760
761         /*
762          * Must have a valid pointer to a GAS structure, and
763          * a non-zero address within. However, don't return an error
764          * because the PM1A/B code must not fail if B isn't present.
765          */
766         if (!reg) {
767                 return (AE_OK);
768         }
769
770         /* Get a local copy of the address. Handles possible alignment issues */
771
772         ACPI_MOVE_64_TO_64(&address, &reg->address);
773         if (!address) {
774                 return (AE_OK);
775         }
776         *value = 0;
777
778         /*
779          * Two address spaces supported: Memory or IO.
780          * PCI_Config is not supported here because the GAS struct is insufficient
781          */
782         switch (reg->space_id) {
783         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
784
785                 status = acpi_os_read_memory((acpi_physical_address) address,
786                                              value, width);
787                 break;
788
789         case ACPI_ADR_SPACE_SYSTEM_IO:
790
791                 status =
792                     acpi_os_read_port((acpi_io_address) address, value, width);
793                 break;
794
795         default:
796                 ACPI_ERROR((AE_INFO,
797                             "Unsupported address space: %X", reg->space_id));
798                 return (AE_BAD_PARAMETER);
799         }
800
801         ACPI_DEBUG_PRINT((ACPI_DB_IO,
802                           "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
803                           *value, width, ACPI_FORMAT_UINT64(address),
804                           acpi_ut_get_region_name(reg->space_id)));
805
806         return (status);
807 }
808
809 /******************************************************************************
810  *
811  * FUNCTION:    acpi_hw_low_level_write
812  *
813  * PARAMETERS:  Width               - 8, 16, or 32
814  *              Value               - To be written
815  *              Reg                 - GAS register structure
816  *
817  * RETURN:      Status
818  *
819  * DESCRIPTION: Write to either memory or IO space.
820  *
821  ******************************************************************************/
822
823 acpi_status
824 acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
825 {
826         u64 address;
827         acpi_status status;
828
829         ACPI_FUNCTION_NAME(hw_low_level_write);
830
831         /*
832          * Must have a valid pointer to a GAS structure, and
833          * a non-zero address within. However, don't return an error
834          * because the PM1A/B code must not fail if B isn't present.
835          */
836         if (!reg) {
837                 return (AE_OK);
838         }
839
840         /* Get a local copy of the address. Handles possible alignment issues */
841
842         ACPI_MOVE_64_TO_64(&address, &reg->address);
843         if (!address) {
844                 return (AE_OK);
845         }
846
847         /*
848          * Two address spaces supported: Memory or IO.
849          * PCI_Config is not supported here because the GAS struct is insufficient
850          */
851         switch (reg->space_id) {
852         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
853
854                 status = acpi_os_write_memory((acpi_physical_address) address,
855                                               value, width);
856                 break;
857
858         case ACPI_ADR_SPACE_SYSTEM_IO:
859
860                 status = acpi_os_write_port((acpi_io_address) address, value,
861                                             width);
862                 break;
863
864         default:
865                 ACPI_ERROR((AE_INFO,
866                             "Unsupported address space: %X", reg->space_id));
867                 return (AE_BAD_PARAMETER);
868         }
869
870         ACPI_DEBUG_PRINT((ACPI_DB_IO,
871                           "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
872                           value, width, ACPI_FORMAT_UINT64(address),
873                           acpi_ut_get_region_name(reg->space_id)));
874
875         return (status);
876 }