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