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