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