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