]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/contrib/dev/acpica/hwregs.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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: 1.187 $
7  *
8  ******************************************************************************/
9
10 /******************************************************************************
11  *
12  * 1. Copyright Notice
13  *
14  * Some or all of this work - Copyright (c) 1999 - 2007, 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:  None
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     void)
145 {
146     ACPI_STATUS             Status;
147     ACPI_CPU_FLAGS          LockFlags = 0;
148
149
150     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
151
152
153     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
154         ACPI_BITMASK_ALL_FIXED_STATUS,
155         (UINT16) AcpiGbl_FADT.XPm1aEventBlock.Address));
156
157     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
158
159     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
160                 ACPI_REGISTER_PM1_STATUS,
161                 ACPI_BITMASK_ALL_FIXED_STATUS);
162     if (ACPI_FAILURE (Status))
163     {
164         goto UnlockAndExit;
165     }
166
167     /* Clear the fixed events */
168
169     if (AcpiGbl_FADT.XPm1bEventBlock.Address)
170     {
171         Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
172                     &AcpiGbl_FADT.XPm1bEventBlock);
173         if (ACPI_FAILURE (Status))
174         {
175             goto UnlockAndExit;
176         }
177     }
178
179     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
180
181     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
182
183 UnlockAndExit:
184     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
185     return_ACPI_STATUS (Status);
186 }
187
188
189 /*******************************************************************************
190  *
191  * FUNCTION:    AcpiGetSleepTypeData
192  *
193  * PARAMETERS:  SleepState          - Numeric sleep state
194  *              *SleepTypeA         - Where SLP_TYPa is returned
195  *              *SleepTypeB         - Where SLP_TYPb is returned
196  *
197  * RETURN:      Status - ACPI status
198  *
199  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
200  *              state.
201  *
202  ******************************************************************************/
203
204 ACPI_STATUS
205 AcpiGetSleepTypeData (
206     UINT8                   SleepState,
207     UINT8                   *SleepTypeA,
208     UINT8                   *SleepTypeB)
209 {
210     ACPI_STATUS             Status = AE_OK;
211     ACPI_EVALUATE_INFO      *Info;
212
213
214     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
215
216
217     /* Validate parameters */
218
219     if ((SleepState > ACPI_S_STATES_MAX) ||
220         !SleepTypeA || !SleepTypeB)
221     {
222         return_ACPI_STATUS (AE_BAD_PARAMETER);
223     }
224
225     /* Allocate the evaluation information block */
226
227     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
228     if (!Info)
229     {
230         return_ACPI_STATUS (AE_NO_MEMORY);
231     }
232
233     Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
234
235     /* Evaluate the namespace object containing the values for this state */
236
237     Status = AcpiNsEvaluate (Info);
238     if (ACPI_FAILURE (Status))
239     {
240         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
241             "%s while evaluating SleepState [%s]\n",
242             AcpiFormatException (Status), Info->Pathname));
243
244         goto Cleanup;
245     }
246
247     /* Must have a return object */
248
249     if (!Info->ReturnObject)
250     {
251         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
252             Info->Pathname));
253         Status = AE_NOT_EXIST;
254     }
255
256     /* It must be of type Package */
257
258     else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE)
259     {
260         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
261         Status = AE_AML_OPERAND_TYPE;
262     }
263
264     /*
265      * The package must have at least two elements. NOTE (March 2005): This
266      * goes against the current ACPI spec which defines this object as a
267      * package with one encoded DWORD element. However, existing practice
268      * by BIOS vendors seems to be to have 2 or more elements, at least
269      * one per sleep type (A/B).
270      */
271     else if (Info->ReturnObject->Package.Count < 2)
272     {
273         ACPI_ERROR ((AE_INFO,
274             "Sleep State return package does not have at least two elements"));
275         Status = AE_AML_NO_OPERAND;
276     }
277
278     /* The first two elements must both be of type Integer */
279
280     else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0])
281                 != ACPI_TYPE_INTEGER) ||
282              (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1])
283                 != ACPI_TYPE_INTEGER))
284     {
285         ACPI_ERROR ((AE_INFO,
286             "Sleep State return package elements are not both Integers (%s, %s)",
287             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
288             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
289         Status = AE_AML_OPERAND_TYPE;
290     }
291     else
292     {
293         /* Valid _Sx_ package size, type, and value */
294
295         *SleepTypeA = (UINT8)
296             (Info->ReturnObject->Package.Elements[0])->Integer.Value;
297         *SleepTypeB = (UINT8)
298             (Info->ReturnObject->Package.Elements[1])->Integer.Value;
299     }
300
301     if (ACPI_FAILURE (Status))
302     {
303         ACPI_EXCEPTION ((AE_INFO, Status,
304             "While evaluating SleepState [%s], bad Sleep object %p type %s",
305             Info->Pathname, Info->ReturnObject,
306             AcpiUtGetObjectTypeName (Info->ReturnObject)));
307     }
308
309     AcpiUtRemoveReference (Info->ReturnObject);
310
311 Cleanup:
312     ACPI_FREE (Info);
313     return_ACPI_STATUS (Status);
314 }
315
316 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
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_ENTRY ();
336
337
338     if (RegisterId > ACPI_BITREG_MAX)
339     {
340         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", 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  *
355  * RETURN:      Status and the value read from specified Register. Value
356  *              returned is normalized to bit0 (is shifted all the way right)
357  *
358  * DESCRIPTION: ACPI BitRegister read function.
359  *
360  ******************************************************************************/
361
362 ACPI_STATUS
363 AcpiGetRegister (
364     UINT32                  RegisterId,
365     UINT32                  *ReturnValue)
366 {
367     UINT32                  RegisterValue = 0;
368     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
369     ACPI_STATUS             Status;
370
371
372     ACPI_FUNCTION_TRACE (AcpiGetRegister);
373
374
375     /* Get the info structure corresponding to the requested ACPI Register */
376
377     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
378     if (!BitRegInfo)
379     {
380         return_ACPI_STATUS (AE_BAD_PARAMETER);
381     }
382
383     /* Read from the register */
384
385     Status = AcpiHwRegisterRead (ACPI_MTX_LOCK,
386                 BitRegInfo->ParentRegister, &RegisterValue);
387
388     if (ACPI_SUCCESS (Status))
389     {
390         /* Normalize the value that was read */
391
392         RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
393                             >> BitRegInfo->BitPosition);
394
395         *ReturnValue = RegisterValue;
396
397         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
398             RegisterValue, BitRegInfo->ParentRegister));
399     }
400
401     return_ACPI_STATUS (Status);
402 }
403
404 ACPI_EXPORT_SYMBOL (AcpiGetRegister)
405
406
407 /*******************************************************************************
408  *
409  * FUNCTION:    AcpiSetRegister
410  *
411  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
412  *              Value           - (only used on write) value to write to the
413  *                                Register, NOT pre-normalized to the bit pos
414  *
415  * RETURN:      Status
416  *
417  * DESCRIPTION: ACPI Bit Register write function.
418  *
419  ******************************************************************************/
420
421 ACPI_STATUS
422 AcpiSetRegister (
423     UINT32                  RegisterId,
424     UINT32                  Value)
425 {
426     UINT32                  RegisterValue = 0;
427     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
428     ACPI_STATUS             Status;
429     ACPI_CPU_FLAGS          LockFlags;
430
431
432     ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId);
433
434
435     /* Get the info structure corresponding to the requested ACPI Register */
436
437     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
438     if (!BitRegInfo)
439     {
440         ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId));
441         return_ACPI_STATUS (AE_BAD_PARAMETER);
442     }
443
444     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
445
446     /* Always do a register read first so we can insert the new bits  */
447
448     Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
449                 BitRegInfo->ParentRegister, &RegisterValue);
450     if (ACPI_FAILURE (Status))
451     {
452         goto UnlockAndExit;
453     }
454
455     /*
456      * Decode the Register ID
457      * Register ID = [Register block ID] | [bit ID]
458      *
459      * Check bit ID to fine locate Register offset.
460      * Check Mask to determine Register offset, and then read-write.
461      */
462     switch (BitRegInfo->ParentRegister)
463     {
464     case ACPI_REGISTER_PM1_STATUS:
465
466         /*
467          * Status Registers are different from the rest. Clear by
468          * writing 1, and writing 0 has no effect. So, the only relevant
469          * information is the single bit we're interested in, all others should
470          * be written as 0 so they will be left unchanged.
471          */
472         Value = ACPI_REGISTER_PREPARE_BITS (Value,
473                     BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
474         if (Value)
475         {
476             Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
477                         ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
478             RegisterValue = 0;
479         }
480         break;
481
482
483     case ACPI_REGISTER_PM1_ENABLE:
484
485         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
486             BitRegInfo->AccessBitMask, Value);
487
488         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
489                     ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
490         break;
491
492
493     case ACPI_REGISTER_PM1_CONTROL:
494
495         /*
496          * Write the PM1 Control register.
497          * Note that at this level, the fact that there are actually TWO
498          * registers (A and B - and B may not exist) is abstracted.
499          */
500         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n",
501             RegisterValue));
502
503         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
504             BitRegInfo->AccessBitMask, Value);
505
506         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
507                     ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue);
508         break;
509
510
511     case ACPI_REGISTER_PM2_CONTROL:
512
513         Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
514                     ACPI_REGISTER_PM2_CONTROL, &RegisterValue);
515         if (ACPI_FAILURE (Status))
516         {
517             goto UnlockAndExit;
518         }
519
520         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
521             RegisterValue,
522             ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
523
524         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
525                 BitRegInfo->AccessBitMask, Value);
526
527         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
528             RegisterValue,
529             ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
530
531         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
532                     ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
533         break;
534
535
536     default:
537         break;
538     }
539
540
541 UnlockAndExit:
542
543     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
544
545     /* Normalize the value that was read */
546
547     ACPI_DEBUG_EXEC (RegisterValue =
548         ((RegisterValue & BitRegInfo->AccessBitMask) >>
549             BitRegInfo->BitPosition));
550
551     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
552         Value, RegisterValue, BitRegInfo->ParentRegister));
553     return_ACPI_STATUS (Status);
554 }
555
556 ACPI_EXPORT_SYMBOL (AcpiSetRegister)
557
558
559 /******************************************************************************
560  *
561  * FUNCTION:    AcpiHwRegisterRead
562  *
563  * PARAMETERS:  UseLock             - Lock hardware? True/False
564  *              RegisterId          - ACPI Register ID
565  *              ReturnValue         - Where the register value is returned
566  *
567  * RETURN:      Status and the value read.
568  *
569  * DESCRIPTION: Read from the specified ACPI register
570  *
571  ******************************************************************************/
572
573 ACPI_STATUS
574 AcpiHwRegisterRead (
575     BOOLEAN                 UseLock,
576     UINT32                  RegisterId,
577     UINT32                  *ReturnValue)
578 {
579     UINT32                  Value1 = 0;
580     UINT32                  Value2 = 0;
581     ACPI_STATUS             Status;
582     ACPI_CPU_FLAGS          LockFlags = 0;
583
584
585     ACPI_FUNCTION_TRACE (HwRegisterRead);
586
587
588     if (ACPI_MTX_LOCK == UseLock)
589     {
590         LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
591     }
592
593     switch (RegisterId)
594     {
595     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
596
597         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aEventBlock);
598         if (ACPI_FAILURE (Status))
599         {
600             goto UnlockAndExit;
601         }
602
603         /* PM1B is optional */
604
605         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bEventBlock);
606         Value1 |= Value2;
607         break;
608
609
610     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
611
612         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
613         if (ACPI_FAILURE (Status))
614         {
615             goto UnlockAndExit;
616         }
617
618         /* PM1B is optional */
619
620         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
621         Value1 |= Value2;
622         break;
623
624
625     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
626
627         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aControlBlock);
628         if (ACPI_FAILURE (Status))
629         {
630             goto UnlockAndExit;
631         }
632
633         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bControlBlock);
634         Value1 |= Value2;
635         break;
636
637
638     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
639
640         Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT.XPm2ControlBlock);
641         break;
642
643
644     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
645
646         Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT.XPmTimerBlock);
647         break;
648
649     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
650
651         Status = AcpiOsReadPort (AcpiGbl_FADT.SmiCommand, &Value1, 8);
652         break;
653
654     default:
655         ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X",
656             RegisterId));
657         Status = AE_BAD_PARAMETER;
658         break;
659     }
660
661 UnlockAndExit:
662     if (ACPI_MTX_LOCK == UseLock)
663     {
664         AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
665     }
666
667     if (ACPI_SUCCESS (Status))
668     {
669         *ReturnValue = Value1;
670     }
671
672     return_ACPI_STATUS (Status);
673 }
674
675
676 /******************************************************************************
677  *
678  * FUNCTION:    AcpiHwRegisterWrite
679  *
680  * PARAMETERS:  UseLock             - Lock hardware? True/False
681  *              RegisterId          - ACPI Register ID
682  *              Value               - The value to write
683  *
684  * RETURN:      Status
685  *
686  * DESCRIPTION: Write to the specified ACPI register
687  *
688  * NOTE: In accordance with the ACPI specification, this function automatically
689  * preserves the value of the following bits, meaning that these bits cannot be
690  * changed via this interface:
691  *
692  * PM1_CONTROL[0] = SCI_EN
693  * PM1_CONTROL[9]
694  * PM1_STATUS[11]
695  *
696  * ACPI References:
697  * 1) Hardware Ignored Bits: When software writes to a register with ignored
698  *      bit fields, it preserves the ignored bit fields
699  * 2) SCI_EN: OSPM always preserves this bit position
700  *
701  ******************************************************************************/
702
703 ACPI_STATUS
704 AcpiHwRegisterWrite (
705     BOOLEAN                 UseLock,
706     UINT32                  RegisterId,
707     UINT32                  Value)
708 {
709     ACPI_STATUS             Status;
710     ACPI_CPU_FLAGS          LockFlags = 0;
711     UINT32                  ReadValue;
712
713
714     ACPI_FUNCTION_TRACE (HwRegisterWrite);
715
716
717     if (ACPI_MTX_LOCK == UseLock)
718     {
719         LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
720     }
721
722     switch (RegisterId)
723     {
724     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
725
726         /* Perform a read first to preserve certain bits (per ACPI spec) */
727
728         Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
729                     ACPI_REGISTER_PM1_STATUS, &ReadValue);
730         if (ACPI_FAILURE (Status))
731         {
732             goto UnlockAndExit;
733         }
734
735         /* Insert the bits to be preserved */
736
737         ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue);
738
739         /* Now we can write the data */
740
741         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aEventBlock);
742         if (ACPI_FAILURE (Status))
743         {
744             goto UnlockAndExit;
745         }
746
747         /* PM1B is optional */
748
749         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bEventBlock);
750         break;
751
752
753     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
754
755         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
756         if (ACPI_FAILURE (Status))
757         {
758             goto UnlockAndExit;
759         }
760
761         /* PM1B is optional */
762
763         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
764         break;
765
766
767     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
768
769         /*
770          * Perform a read first to preserve certain bits (per ACPI spec)
771          *
772          * Note: This includes SCI_EN, we never want to change this bit
773          */
774         Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
775                     ACPI_REGISTER_PM1_CONTROL, &ReadValue);
776         if (ACPI_FAILURE (Status))
777         {
778             goto UnlockAndExit;
779         }
780
781         /* Insert the bits to be preserved */
782
783         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
784
785         /* Now we can write the data */
786
787         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
788         if (ACPI_FAILURE (Status))
789         {
790             goto UnlockAndExit;
791         }
792
793         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
794         break;
795
796
797     case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
798
799         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
800         break;
801
802
803     case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
804
805         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
806         break;
807
808
809     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
810
811         Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT.XPm2ControlBlock);
812         break;
813
814
815     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
816
817         Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT.XPmTimerBlock);
818         break;
819
820
821     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
822
823         /* SMI_CMD is currently always in IO space */
824
825         Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
826         break;
827
828
829     default:
830         Status = AE_BAD_PARAMETER;
831         break;
832     }
833
834 UnlockAndExit:
835     if (ACPI_MTX_LOCK == UseLock)
836     {
837         AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
838     }
839
840     return_ACPI_STATUS (Status);
841 }
842
843
844 /******************************************************************************
845  *
846  * FUNCTION:    AcpiHwLowLevelRead
847  *
848  * PARAMETERS:  Width               - 8, 16, or 32
849  *              Value               - Where the value is returned
850  *              Reg                 - GAS register structure
851  *
852  * RETURN:      Status
853  *
854  * DESCRIPTION: Read from either memory or IO space.
855  *
856  ******************************************************************************/
857
858 ACPI_STATUS
859 AcpiHwLowLevelRead (
860     UINT32                  Width,
861     UINT32                  *Value,
862     ACPI_GENERIC_ADDRESS    *Reg)
863 {
864     UINT64                  Address;
865     ACPI_STATUS             Status;
866
867
868     ACPI_FUNCTION_NAME (HwLowLevelRead);
869
870
871     /*
872      * Must have a valid pointer to a GAS structure, and
873      * a non-zero address within. However, don't return an error
874      * because the PM1A/B code must not fail if B isn't present.
875      */
876     if (!Reg)
877     {
878         return (AE_OK);
879     }
880
881     /* Get a local copy of the address. Handles possible alignment issues */
882
883     ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
884     if (!Address)
885     {
886         return (AE_OK);
887     }
888     *Value = 0;
889
890     /*
891      * Two address spaces supported: Memory or IO.
892      * PCI_Config is not supported here because the GAS struct is insufficient
893      */
894     switch (Reg->SpaceId)
895     {
896     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
897
898         Status = AcpiOsReadMemory (
899                     (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
900         break;
901
902
903     case ACPI_ADR_SPACE_SYSTEM_IO:
904
905         Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) Address, Value, Width);
906         break;
907
908
909     default:
910         ACPI_ERROR ((AE_INFO,
911             "Unsupported address space: %X", Reg->SpaceId));
912         return (AE_BAD_PARAMETER);
913     }
914
915     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
916         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
917         *Value, Width, ACPI_FORMAT_UINT64 (Address),
918         AcpiUtGetRegionName (Reg->SpaceId)));
919
920     return (Status);
921 }
922
923
924 /******************************************************************************
925  *
926  * FUNCTION:    AcpiHwLowLevelWrite
927  *
928  * PARAMETERS:  Width               - 8, 16, or 32
929  *              Value               - To be written
930  *              Reg                 - GAS register structure
931  *
932  * RETURN:      Status
933  *
934  * DESCRIPTION: Write to either memory or IO space.
935  *
936  ******************************************************************************/
937
938 ACPI_STATUS
939 AcpiHwLowLevelWrite (
940     UINT32                  Width,
941     UINT32                  Value,
942     ACPI_GENERIC_ADDRESS    *Reg)
943 {
944     UINT64                  Address;
945     ACPI_STATUS             Status;
946
947
948     ACPI_FUNCTION_NAME (HwLowLevelWrite);
949
950
951     /*
952      * Must have a valid pointer to a GAS structure, and
953      * a non-zero address within. However, don't return an error
954      * because the PM1A/B code must not fail if B isn't present.
955      */
956     if (!Reg)
957     {
958         return (AE_OK);
959     }
960
961     /* Get a local copy of the address. Handles possible alignment issues */
962
963     ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
964     if (!Address)
965     {
966         return (AE_OK);
967     }
968
969     /*
970      * Two address spaces supported: Memory or IO.
971      * PCI_Config is not supported here because the GAS struct is insufficient
972      */
973     switch (Reg->SpaceId)
974     {
975     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
976
977         Status = AcpiOsWriteMemory (
978                     (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
979         break;
980
981
982     case ACPI_ADR_SPACE_SYSTEM_IO:
983
984         Status = AcpiOsWritePort (
985                     (ACPI_IO_ADDRESS) Address, Value, Width);
986         break;
987
988
989     default:
990         ACPI_ERROR ((AE_INFO,
991             "Unsupported address space: %X", Reg->SpaceId));
992         return (AE_BAD_PARAMETER);
993     }
994
995     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
996         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
997         Value, Width, ACPI_FORMAT_UINT64 (Address),
998         AcpiUtGetRegionName (Reg->SpaceId)));
999
1000     return (Status);
1001 }