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