]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/hwregs.c
This commit was generated by cvs2svn to compensate for changes in r167802,
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / hwregs.c
1
2 /*******************************************************************************
3  *
4  * Module Name: hwregs - Read/write access functions for the various ACPI
5  *                       control and status registers.
6  *              $Revision: 162 $
7  *
8  ******************************************************************************/
9
10 /******************************************************************************
11  *
12  * 1. Copyright Notice
13  *
14  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
15  * All rights reserved.
16  *
17  * 2. License
18  *
19  * 2.1. This is your license from Intel Corp. under its intellectual property
20  * rights.  You may have additional license terms from the party that provided
21  * you this software, covering your right to use that party's intellectual
22  * property rights.
23  *
24  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
25  * copy of the source code appearing in this file ("Covered Code") an
26  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
27  * base code distributed originally by Intel ("Original Intel Code") to copy,
28  * make derivatives, distribute, use and display any portion of the Covered
29  * Code in any form, with the right to sublicense such rights; and
30  *
31  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
32  * license (with the right to sublicense), under only those claims of Intel
33  * patents that are infringed by the Original Intel Code, to make, use, sell,
34  * offer to sell, and import the Covered Code and derivative works thereof
35  * solely to the minimum extent necessary to exercise the above copyright
36  * license, and in no event shall the patent license extend to any additions
37  * to or modifications of the Original Intel Code.  No other license or right
38  * is granted directly or by implication, estoppel or otherwise;
39  *
40  * The above copyright and patent license is granted only if the following
41  * conditions are met:
42  *
43  * 3. Conditions
44  *
45  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
46  * Redistribution of source code of any substantial portion of the Covered
47  * Code or modification with rights to further distribute source must include
48  * the above Copyright Notice, the above License, this list of Conditions,
49  * and the following Disclaimer and Export Compliance provision.  In addition,
50  * Licensee must cause all Covered Code to which Licensee contributes to
51  * contain a file documenting the changes Licensee made to create that Covered
52  * Code and the date of any change.  Licensee must include in that file the
53  * documentation of any changes made by any predecessor Licensee.  Licensee
54  * must include a prominent statement that the modification is derived,
55  * directly or indirectly, from Original Intel Code.
56  *
57  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
58  * Redistribution of source code of any substantial portion of the Covered
59  * Code or modification without rights to further distribute source must
60  * include the following Disclaimer and Export Compliance provision in the
61  * documentation and/or other materials provided with distribution.  In
62  * addition, Licensee may not authorize further sublicense of source of any
63  * portion of the Covered Code, and must include terms to the effect that the
64  * license from Licensee to its licensee is limited to the intellectual
65  * property embodied in the software Licensee provides to its licensee, and
66  * not to intellectual property embodied in modifications its licensee may
67  * make.
68  *
69  * 3.3. Redistribution of Executable. Redistribution in executable form of any
70  * substantial portion of the Covered Code or modification must reproduce the
71  * above Copyright Notice, and the following Disclaimer and Export Compliance
72  * provision in the documentation and/or other materials provided with the
73  * distribution.
74  *
75  * 3.4. Intel retains all right, title, and interest in and to the Original
76  * Intel Code.
77  *
78  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
79  * Intel shall be used in advertising or otherwise to promote the sale, use or
80  * other dealings in products derived from or relating to the Covered Code
81  * without prior written authorization from Intel.
82  *
83  * 4. Disclaimer and Export Compliance
84  *
85  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
86  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
87  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
88  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
89  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
90  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
91  * PARTICULAR PURPOSE.
92  *
93  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
94  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
95  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
96  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
97  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
98  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
99  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
100  * LIMITED REMEDY.
101  *
102  * 4.3. Licensee shall not export, either directly or indirectly, any of this
103  * software or system incorporating such software without first obtaining any
104  * required license or other approval from the U. S. Department of Commerce or
105  * any other agency or department of the United States Government.  In the
106  * event Licensee exports any such software from the United States or
107  * re-exports any such software from a foreign destination, Licensee shall
108  * ensure that the distribution and export/re-export of the software is in
109  * compliance with all laws, regulations, orders, or other restrictions of the
110  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
111  * any of its subsidiaries will export/re-export any technical data, process,
112  * software, or service, directly or indirectly, to any country for which the
113  * United States government or any agency thereof requires an export license,
114  * other governmental approval, or letter of assurance, without first obtaining
115  * such license, approval or letter.
116  *
117  *****************************************************************************/
118
119 #define __HWREGS_C__
120
121 #include <contrib/dev/acpica/acpi.h>
122 #include <contrib/dev/acpica/acnamesp.h>
123 #include <contrib/dev/acpica/acevents.h>
124
125 #define _COMPONENT          ACPI_HARDWARE
126         ACPI_MODULE_NAME    ("hwregs")
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiHwClearAcpiStatus
132  *
133  * PARAMETERS:  Flags           - Lock the hardware or not
134  *
135  * RETURN:      none
136  *
137  * DESCRIPTION: Clears all fixed and general purpose status bits
138  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
139  *
140  ******************************************************************************/
141
142 ACPI_STATUS
143 AcpiHwClearAcpiStatus (
144     UINT32                  Flags)
145 {
146     ACPI_STATUS             Status;
147
148
149     ACPI_FUNCTION_TRACE ("HwClearAcpiStatus");
150
151
152     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
153         ACPI_BITMASK_ALL_FIXED_STATUS,
154         (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
155
156     if (Flags & ACPI_MTX_LOCK)
157     {
158         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
159         if (ACPI_FAILURE (Status))
160         {
161             return_ACPI_STATUS (Status);
162         }
163     }
164
165     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
166                 ACPI_REGISTER_PM1_STATUS,
167                 ACPI_BITMASK_ALL_FIXED_STATUS);
168     if (ACPI_FAILURE (Status))
169     {
170         goto UnlockAndExit;
171     }
172
173     /* Clear the fixed events */
174
175     if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
176     {
177         Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
178                     &AcpiGbl_FADT->XPm1bEvtBlk);
179         if (ACPI_FAILURE (Status))
180         {
181             goto UnlockAndExit;
182         }
183     }
184
185     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
186
187     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
188
189 UnlockAndExit:
190     if (Flags & ACPI_MTX_LOCK)
191     {
192         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
193     }
194     return_ACPI_STATUS (Status);
195 }
196
197
198 /*******************************************************************************
199  *
200  * FUNCTION:    AcpiGetSleepTypeData
201  *
202  * PARAMETERS:  SleepState          - Numeric sleep state
203  *              *SleepTypeA         - Where SLP_TYPa is returned
204  *              *SleepTypeB         - Where SLP_TYPb is returned
205  *
206  * RETURN:      Status - ACPI status
207  *
208  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
209  *              state.
210  *
211  ******************************************************************************/
212
213 ACPI_STATUS
214 AcpiGetSleepTypeData (
215     UINT8                   SleepState,
216     UINT8                   *SleepTypeA,
217     UINT8                   *SleepTypeB)
218 {
219     ACPI_STATUS             Status = AE_OK;
220     ACPI_PARAMETER_INFO     Info;
221     char                    *SleepStateName;
222
223
224     ACPI_FUNCTION_TRACE ("AcpiGetSleepTypeData");
225
226
227     /* Validate parameters */
228
229     if ((SleepState > ACPI_S_STATES_MAX) ||
230         !SleepTypeA || !SleepTypeB)
231     {
232         return_ACPI_STATUS (AE_BAD_PARAMETER);
233     }
234
235     /* Evaluate the namespace object containing the values for this state */
236
237     Info.Parameters = NULL;
238     Info.ReturnObject = NULL;
239     SleepStateName = (char *) (uintptr_t) AcpiGbl_SleepStateNames[SleepState];
240
241     Status = AcpiNsEvaluateByName (SleepStateName, &Info);
242     if (ACPI_FAILURE (Status))
243     {
244         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
245             "%s while evaluating SleepState [%s]\n",
246             AcpiFormatException (Status), SleepStateName));
247
248         return_ACPI_STATUS (Status);
249     }
250
251     /* Must have a return object */
252
253     if (!Info.ReturnObject)
254     {
255         ACPI_REPORT_ERROR (("No Sleep State object returned from [%s]\n",
256             SleepStateName));
257         Status = AE_NOT_EXIST;
258     }
259
260     /* It must be of type Package */
261
262     else if (ACPI_GET_OBJECT_TYPE (Info.ReturnObject) != ACPI_TYPE_PACKAGE)
263     {
264         ACPI_REPORT_ERROR (("Sleep State return object is not a Package\n"));
265         Status = AE_AML_OPERAND_TYPE;
266     }
267
268     /*
269      * The package must have at least two elements.  NOTE (March 2005): This
270      * goes against the current ACPI spec which defines this object as a
271      * package with one encoded DWORD element.  However, existing practice
272      * by BIOS vendors seems to be to have 2 or more elements, at least
273      * one per sleep type (A/B).
274      */
275     else if (Info.ReturnObject->Package.Count < 2)
276     {
277         ACPI_REPORT_ERROR ((
278             "Sleep State return package does not have at least two elements\n"));
279         Status = AE_AML_NO_OPERAND;
280     }
281
282     /* The first two elements must both be of type Integer */
283
284     else if ((ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[0])
285                 != ACPI_TYPE_INTEGER) ||
286              (ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[1])
287                 != ACPI_TYPE_INTEGER))
288     {
289         ACPI_REPORT_ERROR ((
290             "Sleep State return package elements are not both Integers (%s, %s)\n",
291             AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[0]),
292             AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[1])));
293         Status = AE_AML_OPERAND_TYPE;
294     }
295     else
296     {
297         /* Valid _Sx_ package size, type, and value */
298
299         *SleepTypeA = (UINT8)
300             (Info.ReturnObject->Package.Elements[0])->Integer.Value;
301         *SleepTypeB = (UINT8)
302             (Info.ReturnObject->Package.Elements[1])->Integer.Value;
303     }
304
305     if (ACPI_FAILURE (Status))
306     {
307         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
308             "%s While evaluating SleepState [%s], bad Sleep object %p type %s\n",
309             AcpiFormatException (Status),
310             SleepStateName, Info.ReturnObject,
311             AcpiUtGetObjectTypeName (Info.ReturnObject)));
312     }
313
314     AcpiUtRemoveReference (Info.ReturnObject);
315     return_ACPI_STATUS (Status);
316 }
317
318
319 /*******************************************************************************
320  *
321  * FUNCTION:    AcpiHwGetRegisterBitMask
322  *
323  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
324  *
325  * RETURN:      The bitmask to be used when accessing the register
326  *
327  * DESCRIPTION: Map RegisterId into a register bitmask.
328  *
329  ******************************************************************************/
330
331 ACPI_BIT_REGISTER_INFO *
332 AcpiHwGetBitRegisterInfo (
333     UINT32                  RegisterId)
334 {
335     ACPI_FUNCTION_NAME ("HwGetBitRegisterInfo");
336
337
338     if (RegisterId > ACPI_BITREG_MAX)
339     {
340         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid BitRegister ID: %X\n", RegisterId));
341         return (NULL);
342     }
343
344     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
345 }
346
347
348 /*******************************************************************************
349  *
350  * FUNCTION:    AcpiGetRegister
351  *
352  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
353  *              ReturnValue     - Value that was read from the register
354  *              Flags           - Lock the hardware or not
355  *
356  * RETURN:      Status and the value read from specified Register.  Value
357  *              returned is normalized to bit0 (is shifted all the way right)
358  *
359  * DESCRIPTION: ACPI BitRegister read function.
360  *
361  ******************************************************************************/
362
363 ACPI_STATUS
364 AcpiGetRegister (
365     UINT32                  RegisterId,
366     UINT32                  *ReturnValue,
367     UINT32                  Flags)
368 {
369     UINT32                  RegisterValue = 0;
370     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
371     ACPI_STATUS             Status;
372
373
374     ACPI_FUNCTION_TRACE ("AcpiGetRegister");
375
376
377     /* Get the info structure corresponding to the requested ACPI Register */
378
379     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
380     if (!BitRegInfo)
381     {
382         return_ACPI_STATUS (AE_BAD_PARAMETER);
383     }
384
385     if (Flags & ACPI_MTX_LOCK)
386     {
387         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
388         if (ACPI_FAILURE (Status))
389         {
390             return_ACPI_STATUS (Status);
391         }
392     }
393
394     /* Read from the register */
395
396     Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
397                     BitRegInfo->ParentRegister, &RegisterValue);
398
399     if (Flags & ACPI_MTX_LOCK)
400     {
401         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
402     }
403
404     if (ACPI_SUCCESS (Status))
405     {
406         /* Normalize the value that was read */
407
408         RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
409                             >> BitRegInfo->BitPosition);
410
411         *ReturnValue = RegisterValue;
412
413         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
414                 RegisterValue, BitRegInfo->ParentRegister));
415     }
416
417     return_ACPI_STATUS (Status);
418 }
419
420
421 /*******************************************************************************
422  *
423  * FUNCTION:    AcpiSetRegister
424  *
425  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
426  *              Value           - (only used on write) value to write to the
427  *                                Register, NOT pre-normalized to the bit pos
428  *              Flags           - Lock the hardware or not
429  *
430  * RETURN:      Status
431  *
432  * DESCRIPTION: ACPI Bit Register write function.
433  *
434  ******************************************************************************/
435
436 ACPI_STATUS
437 AcpiSetRegister (
438     UINT32                  RegisterId,
439     UINT32                  Value,
440     UINT32                  Flags)
441 {
442     UINT32                  RegisterValue = 0;
443     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
444     ACPI_STATUS             Status;
445
446
447     ACPI_FUNCTION_TRACE_U32 ("AcpiSetRegister", RegisterId);
448
449
450     /* Get the info structure corresponding to the requested ACPI Register */
451
452     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
453     if (!BitRegInfo)
454     {
455         ACPI_REPORT_ERROR (("Bad ACPI HW RegisterId: %X\n", RegisterId));
456         return_ACPI_STATUS (AE_BAD_PARAMETER);
457     }
458
459     if (Flags & ACPI_MTX_LOCK)
460     {
461         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
462         if (ACPI_FAILURE (Status))
463         {
464             return_ACPI_STATUS (Status);
465         }
466     }
467
468     /* Always do a register read first so we can insert the new bits  */
469
470     Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
471                 BitRegInfo->ParentRegister, &RegisterValue);
472     if (ACPI_FAILURE (Status))
473     {
474         goto UnlockAndExit;
475     }
476
477     /*
478      * Decode the Register ID
479      * Register ID = [Register block ID] | [bit ID]
480      *
481      * Check bit ID to fine locate Register offset.
482      * Check Mask to determine Register offset, and then read-write.
483      */
484     switch (BitRegInfo->ParentRegister)
485     {
486     case ACPI_REGISTER_PM1_STATUS:
487
488         /*
489          * Status Registers are different from the rest.  Clear by
490          * writing 1, and writing 0 has no effect.  So, the only relevant
491          * information is the single bit we're interested in, all others should
492          * be written as 0 so they will be left unchanged.
493          */
494         Value = ACPI_REGISTER_PREPARE_BITS (Value,
495                     BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
496         if (Value)
497         {
498             Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
499                         ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
500             RegisterValue = 0;
501         }
502         break;
503
504
505     case ACPI_REGISTER_PM1_ENABLE:
506
507         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
508                 BitRegInfo->AccessBitMask, Value);
509
510         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
511                     ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
512         break;
513
514
515     case ACPI_REGISTER_PM1_CONTROL:
516
517         /*
518          * Write the PM1 Control register.
519          * Note that at this level, the fact that there are actually TWO
520          * registers (A and B - and B may not exist) is abstracted.
521          */
522         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", RegisterValue));
523
524         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
525                 BitRegInfo->AccessBitMask, Value);
526
527         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
528                     ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue);
529         break;
530
531
532     case ACPI_REGISTER_PM2_CONTROL:
533
534         Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
535                     ACPI_REGISTER_PM2_CONTROL, &RegisterValue);
536         if (ACPI_FAILURE (Status))
537         {
538             goto UnlockAndExit;
539         }
540
541         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
542             RegisterValue,
543             ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (
544                 AcpiGbl_FADT->XPm2CntBlk.Address))));
545
546         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
547                 BitRegInfo->AccessBitMask, Value);
548
549         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
550             RegisterValue,
551             ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (
552                 AcpiGbl_FADT->XPm2CntBlk.Address))));
553
554         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
555                     ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
556         break;
557
558
559     default:
560         break;
561     }
562
563
564 UnlockAndExit:
565
566     if (Flags & ACPI_MTX_LOCK)
567     {
568         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
569     }
570
571     /* Normalize the value that was read */
572
573     ACPI_DEBUG_EXEC (RegisterValue =
574         ((RegisterValue & BitRegInfo->AccessBitMask) >>
575             BitRegInfo->BitPosition));
576
577     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
578             Value, RegisterValue, BitRegInfo->ParentRegister));
579     return_ACPI_STATUS (Status);
580 }
581
582
583 /******************************************************************************
584  *
585  * FUNCTION:    AcpiHwRegisterRead
586  *
587  * PARAMETERS:  UseLock             - Mutex hw access
588  *              RegisterId          - RegisterID + Offset
589  *              ReturnValue         - Where the register value is returned
590  *
591  * RETURN:      Status and the value read.
592  *
593  * DESCRIPTION: Acpi register read function.  Registers are read at the
594  *              given offset.
595  *
596  ******************************************************************************/
597
598 ACPI_STATUS
599 AcpiHwRegisterRead (
600     BOOLEAN                 UseLock,
601     UINT32                  RegisterId,
602     UINT32                  *ReturnValue)
603 {
604     UINT32                  Value1 = 0;
605     UINT32                  Value2 = 0;
606     ACPI_STATUS             Status;
607
608
609     ACPI_FUNCTION_TRACE ("HwRegisterRead");
610
611
612     if (ACPI_MTX_LOCK == UseLock)
613     {
614         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
615         if (ACPI_FAILURE (Status))
616         {
617             return_ACPI_STATUS (Status);
618         }
619     }
620
621     switch (RegisterId)
622     {
623     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
624
625         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aEvtBlk);
626         if (ACPI_FAILURE (Status))
627         {
628             goto UnlockAndExit;
629         }
630
631         /* PM1B is optional */
632
633         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bEvtBlk);
634         Value1 |= Value2;
635         break;
636
637
638     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
639
640         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
641         if (ACPI_FAILURE (Status))
642         {
643             goto UnlockAndExit;
644         }
645
646         /* PM1B is optional */
647
648         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
649         Value1 |= Value2;
650         break;
651
652
653     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
654
655         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aCntBlk);
656         if (ACPI_FAILURE (Status))
657         {
658             goto UnlockAndExit;
659         }
660
661         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bCntBlk);
662         Value1 |= Value2;
663         break;
664
665
666     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
667
668         Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT->XPm2CntBlk);
669         break;
670
671
672     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
673
674         Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT->XPmTmrBlk);
675         break;
676
677     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
678
679         Status = AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value1, 8);
680         break;
681
682     default:
683         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
684             RegisterId));
685         Status = AE_BAD_PARAMETER;
686         break;
687     }
688
689 UnlockAndExit:
690     if (ACPI_MTX_LOCK == UseLock)
691     {
692         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
693     }
694
695     if (ACPI_SUCCESS (Status))
696     {
697         *ReturnValue = Value1;
698     }
699
700     return_ACPI_STATUS (Status);
701 }
702
703
704 /******************************************************************************
705  *
706  * FUNCTION:    AcpiHwRegisterWrite
707  *
708  * PARAMETERS:  UseLock             - Mutex hw access
709  *              RegisterId          - RegisterID + Offset
710  *              Value               - The value to write
711  *
712  * RETURN:      Status
713  *
714  * DESCRIPTION: Acpi register Write function.  Registers are written at the
715  *              given offset.
716  *
717  ******************************************************************************/
718
719 ACPI_STATUS
720 AcpiHwRegisterWrite (
721     BOOLEAN                 UseLock,
722     UINT32                  RegisterId,
723     UINT32                  Value)
724 {
725     ACPI_STATUS             Status;
726
727
728     ACPI_FUNCTION_TRACE ("HwRegisterWrite");
729
730
731     if (ACPI_MTX_LOCK == UseLock)
732     {
733         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
734         if (ACPI_FAILURE (Status))
735         {
736             return_ACPI_STATUS (Status);
737         }
738     }
739
740     switch (RegisterId)
741     {
742     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
743
744         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk);
745         if (ACPI_FAILURE (Status))
746         {
747             goto UnlockAndExit;
748         }
749
750         /* PM1B is optional */
751
752         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk);
753         break;
754
755
756     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
757
758         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
759         if (ACPI_FAILURE (Status))
760         {
761             goto UnlockAndExit;
762         }
763
764         /* PM1B is optional */
765
766         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
767         break;
768
769
770     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
771
772         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
773         if (ACPI_FAILURE (Status))
774         {
775             goto UnlockAndExit;
776         }
777
778         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
779         break;
780
781
782     case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
783
784         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
785         break;
786
787
788     case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
789
790         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
791         break;
792
793
794     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
795
796         Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk);
797         break;
798
799
800     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
801
802         Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk);
803         break;
804
805
806     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
807
808         /* SMI_CMD is currently always in IO space */
809
810         Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
811         break;
812
813
814     default:
815         Status = AE_BAD_PARAMETER;
816         break;
817     }
818
819 UnlockAndExit:
820     if (ACPI_MTX_LOCK == UseLock)
821     {
822         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
823     }
824
825     return_ACPI_STATUS (Status);
826 }
827
828
829 /******************************************************************************
830  *
831  * FUNCTION:    AcpiHwLowLevelRead
832  *
833  * PARAMETERS:  Width               - 8, 16, or 32
834  *              Value               - Where the value is returned
835  *              Reg                 - GAS register structure
836  *
837  * RETURN:      Status
838  *
839  * DESCRIPTION: Read from either memory or IO space.
840  *
841  ******************************************************************************/
842
843 ACPI_STATUS
844 AcpiHwLowLevelRead (
845     UINT32                  Width,
846     UINT32                  *Value,
847     ACPI_GENERIC_ADDRESS    *Reg)
848 {
849     UINT64                  Address;
850     ACPI_STATUS             Status;
851
852
853     ACPI_FUNCTION_NAME ("HwLowLevelRead");
854
855
856     /*
857      * Must have a valid pointer to a GAS structure, and
858      * a non-zero address within. However, don't return an error
859      * because the PM1A/B code must not fail if B isn't present.
860      */
861     if (!Reg)
862     {
863         return (AE_OK);
864     }
865
866     /* Get a local copy of the address.  Handles possible alignment issues */
867
868     ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
869     if (!ACPI_VALID_ADDRESS (Address))
870     {
871         return (AE_OK);
872     }
873     *Value = 0;
874
875     /*
876      * Two address spaces supported: Memory or IO.
877      * PCI_Config is not supported here because the GAS struct is insufficient
878      */
879     switch (Reg->AddressSpaceId)
880     {
881     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
882
883         Status = AcpiOsReadMemory (
884                     (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Address),
885                     Value, Width);
886         break;
887
888
889     case ACPI_ADR_SPACE_SYSTEM_IO:
890
891         Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Address),
892                     Value, Width);
893         break;
894
895
896     default:
897         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
898             "Unsupported address space: %X\n", Reg->AddressSpaceId));
899         return (AE_BAD_PARAMETER);
900     }
901
902     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
903         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
904         *Value, Width,
905         ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Address)),
906         AcpiUtGetRegionName (Reg->AddressSpaceId)));
907
908     return (Status);
909 }
910
911
912 /******************************************************************************
913  *
914  * FUNCTION:    AcpiHwLowLevelWrite
915  *
916  * PARAMETERS:  Width               - 8, 16, or 32
917  *              Value               - To be written
918  *              Reg                 - GAS register structure
919  *
920  * RETURN:      Status
921  *
922  * DESCRIPTION: Write to either memory or IO space.
923  *
924  ******************************************************************************/
925
926 ACPI_STATUS
927 AcpiHwLowLevelWrite (
928     UINT32                  Width,
929     UINT32                  Value,
930     ACPI_GENERIC_ADDRESS    *Reg)
931 {
932     UINT64                  Address;
933     ACPI_STATUS             Status;
934
935
936     ACPI_FUNCTION_NAME ("HwLowLevelWrite");
937
938
939     /*
940      * Must have a valid pointer to a GAS structure, and
941      * a non-zero address within. However, don't return an error
942      * because the PM1A/B code must not fail if B isn't present.
943      */
944     if (!Reg)
945     {
946         return (AE_OK);
947     }
948
949     /* Get a local copy of the address.  Handles possible alignment issues */
950
951     ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
952     if (!ACPI_VALID_ADDRESS (Address))
953     {
954         return (AE_OK);
955     }
956
957     /*
958      * Two address spaces supported: Memory or IO.
959      * PCI_Config is not supported here because the GAS struct is insufficient
960      */
961     switch (Reg->AddressSpaceId)
962     {
963     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
964
965         Status = AcpiOsWriteMemory (
966                     (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Address),
967                     Value, Width);
968         break;
969
970
971     case ACPI_ADR_SPACE_SYSTEM_IO:
972
973         Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Address),
974                     Value, Width);
975         break;
976
977
978     default:
979         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
980             "Unsupported address space: %X\n", Reg->AddressSpaceId));
981         return (AE_BAD_PARAMETER);
982     }
983
984     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
985         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
986         Value, Width,
987         ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Address)),
988         AcpiUtGetRegionName (Reg->AddressSpaceId)));
989
990     return (Status);
991 }