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