Merge from vendor branch LESS:
[dragonfly.git] / sys / contrib / dev / acpica-unix-20031203 / hardware / hwregs.c
1
2 /*******************************************************************************
3  *
4  * Module Name: hwregs - Read/write access functions for the various ACPI
5  *                       control and status registers.
6  *              $Revision: 152 $
7  *
8  ******************************************************************************/
9
10 /******************************************************************************
11  *
12  * 1. Copyright Notice
13  *
14  * Some or all of this work - Copyright (c) 1999 - 2003, 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 "acpi.h"
122 #include "acnamesp.h"
123 #include "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  *
139  ******************************************************************************/
140
141 ACPI_STATUS
142 AcpiHwClearAcpiStatus (
143     UINT32                  Flags)
144 {
145     ACPI_STATUS             Status;
146
147
148     ACPI_FUNCTION_TRACE ("HwClearAcpiStatus");
149
150
151     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
152         ACPI_BITMASK_ALL_FIXED_STATUS,
153         (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
154
155     if (Flags & ACPI_MTX_LOCK)
156     {
157         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
158         if (ACPI_FAILURE (Status))
159         {
160             return_ACPI_STATUS (Status);
161         }
162     }
163
164     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
165                     ACPI_BITMASK_ALL_FIXED_STATUS);
166     if (ACPI_FAILURE (Status))
167     {
168         goto UnlockAndExit;
169     }
170
171     /* Clear the fixed events */
172
173     if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
174     {
175         Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
176                     &AcpiGbl_FADT->XPm1bEvtBlk);
177         if (ACPI_FAILURE (Status))
178         {
179             goto UnlockAndExit;
180         }
181     }
182
183     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
184
185     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
186
187 UnlockAndExit:
188     if (Flags & ACPI_MTX_LOCK)
189     {
190         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
191     }
192     return_ACPI_STATUS (Status);
193 }
194
195
196 /*******************************************************************************
197  *
198  * FUNCTION:    AcpiGetSleepTypeData
199  *
200  * PARAMETERS:  SleepState          - Numeric sleep state
201  *              *SleepTypeA         - Where SLP_TYPa is returned
202  *              *SleepTypeB         - Where SLP_TYPb is returned
203  *
204  * RETURN:      Status - ACPI status
205  *
206  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
207  *              state.
208  *
209  ******************************************************************************/
210
211 ACPI_STATUS
212 AcpiGetSleepTypeData (
213     UINT8                   SleepState,
214     UINT8                   *SleepTypeA,
215     UINT8                   *SleepTypeB)
216 {
217     ACPI_STATUS             Status = AE_OK;
218     ACPI_OPERAND_OBJECT     *ObjDesc;
219
220
221     ACPI_FUNCTION_TRACE ("AcpiGetSleepTypeData");
222
223
224     /*
225      * Validate parameters
226      */
227     if ((SleepState > ACPI_S_STATES_MAX) ||
228         !SleepTypeA || !SleepTypeB)
229     {
230         return_ACPI_STATUS (AE_BAD_PARAMETER);
231     }
232
233     /*
234      * Evaluate the namespace object containing the values for this state
235      */
236     Status = AcpiNsEvaluateByName ((char *) AcpiGbl_DbSleepStates[SleepState],
237                     NULL, &ObjDesc);
238     if (ACPI_FAILURE (Status))
239     {
240         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating SleepState [%s]\n",
241             AcpiFormatException (Status), AcpiGbl_DbSleepStates[SleepState]));
242
243         return_ACPI_STATUS (Status);
244     }
245
246     /* Must have a return object */
247
248     if (!ObjDesc)
249     {
250         ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
251         Status = AE_NOT_EXIST;
252     }
253
254     /* It must be of type Package */
255
256     else if (ACPI_GET_OBJECT_TYPE (ObjDesc) != ACPI_TYPE_PACKAGE)
257     {
258         ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
259         Status = AE_AML_OPERAND_TYPE;
260     }
261
262     /* The package must have at least two elements */
263
264     else if (ObjDesc->Package.Count < 2)
265     {
266         ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
267         Status = AE_AML_NO_OPERAND;
268     }
269
270     /* The first two elements must both be of type Integer */
271
272     else if ((ACPI_GET_OBJECT_TYPE (ObjDesc->Package.Elements[0]) != ACPI_TYPE_INTEGER) ||
273              (ACPI_GET_OBJECT_TYPE (ObjDesc->Package.Elements[1]) != ACPI_TYPE_INTEGER))
274     {
275         ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
276             AcpiUtGetObjectTypeName (ObjDesc->Package.Elements[0]),
277             AcpiUtGetObjectTypeName (ObjDesc->Package.Elements[1])));
278         Status = AE_AML_OPERAND_TYPE;
279     }
280     else
281     {
282         /*
283          * Valid _Sx_ package size, type, and value
284          */
285         *SleepTypeA = (UINT8) (ObjDesc->Package.Elements[0])->Integer.Value;
286         *SleepTypeB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.Value;
287     }
288
289     if (ACPI_FAILURE (Status))
290     {
291         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating SleepState [%s], bad Sleep object %p type %s\n",
292             AcpiGbl_DbSleepStates[SleepState], ObjDesc, AcpiUtGetObjectTypeName (ObjDesc)));
293     }
294
295     AcpiUtRemoveReference (ObjDesc);
296     return_ACPI_STATUS (Status);
297 }
298
299
300 /*******************************************************************************
301  *
302  * FUNCTION:    AcpiHwGetRegisterBitMask
303  *
304  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
305  *
306  * RETURN:      The bit mask to be used when accessing the register
307  *
308  * DESCRIPTION: Map RegisterId into a register bit mask.
309  *
310  ******************************************************************************/
311
312 ACPI_BIT_REGISTER_INFO *
313 AcpiHwGetBitRegisterInfo (
314     UINT32                  RegisterId)
315 {
316     ACPI_FUNCTION_NAME ("HwGetBitRegisterInfo");
317
318
319     if (RegisterId > ACPI_BITREG_MAX)
320     {
321         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid BitRegister ID: %X\n", RegisterId));
322         return (NULL);
323     }
324
325     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
326 }
327
328
329 /*******************************************************************************
330  *
331  * FUNCTION:    AcpiGetRegister
332  *
333  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
334  *              ReturnValue     - Value that was read from the register
335  *              Flags           - Lock the hardware or not
336  *
337  * RETURN:      Value is read from specified Register.  Value returned is
338  *              normalized to bit0 (is shifted all the way right)
339  *
340  * DESCRIPTION: ACPI BitRegister read function.
341  *
342  ******************************************************************************/
343
344 ACPI_STATUS
345 AcpiGetRegister (
346     UINT32                  RegisterId,
347     UINT32                  *ReturnValue,
348     UINT32                  Flags)
349 {
350     UINT32                  RegisterValue = 0;
351     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
352     ACPI_STATUS             Status;
353
354
355     ACPI_FUNCTION_TRACE ("AcpiGetRegister");
356
357
358     /* Get the info structure corresponding to the requested ACPI Register */
359
360     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
361     if (!BitRegInfo)
362     {
363         return_ACPI_STATUS (AE_BAD_PARAMETER);
364     }
365
366     if (Flags & ACPI_MTX_LOCK)
367     {
368         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
369         if (ACPI_FAILURE (Status))
370         {
371             return_ACPI_STATUS (Status);
372         }
373     }
374
375     Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
376                     BitRegInfo->ParentRegister, &RegisterValue);
377
378     if (Flags & ACPI_MTX_LOCK)
379     {
380         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
381     }
382
383     if (ACPI_SUCCESS (Status))
384     {
385         /* Normalize the value that was read */
386
387         RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
388                             >> BitRegInfo->BitPosition);
389
390         *ReturnValue = RegisterValue;
391
392         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
393                 RegisterValue, BitRegInfo->ParentRegister));
394     }
395
396     return_ACPI_STATUS (Status);
397 }
398
399
400 /*******************************************************************************
401  *
402  * FUNCTION:    AcpiSetRegister
403  *
404  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
405  *              Value           - (only used on write) value to write to the
406  *                                Register, NOT pre-normalized to the bit pos.
407  *              Flags           - Lock the hardware or not
408  *
409  * RETURN:      None
410  *
411  * DESCRIPTION: ACPI Bit Register write function.
412  *
413  ******************************************************************************/
414
415 ACPI_STATUS
416 AcpiSetRegister (
417     UINT32                  RegisterId,
418     UINT32                  Value,
419     UINT32                  Flags)
420 {
421     UINT32                  RegisterValue = 0;
422     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
423     ACPI_STATUS             Status;
424
425
426     ACPI_FUNCTION_TRACE_U32 ("AcpiSetRegister", RegisterId);
427
428
429     /* Get the info structure corresponding to the requested ACPI Register */
430
431     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
432     if (!BitRegInfo)
433     {
434         ACPI_REPORT_ERROR (("Bad ACPI HW RegisterId: %X\n", RegisterId));
435         return_ACPI_STATUS (AE_BAD_PARAMETER);
436     }
437
438     if (Flags & ACPI_MTX_LOCK)
439     {
440         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
441         if (ACPI_FAILURE (Status))
442         {
443             return_ACPI_STATUS (Status);
444         }
445     }
446
447     /* Always do a register read first so we can insert the new bits  */
448
449     Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
450                     BitRegInfo->ParentRegister, &RegisterValue);
451     if (ACPI_FAILURE (Status))
452     {
453         goto UnlockAndExit;
454     }
455
456     /*
457      * Decode the Register ID
458      * Register ID = [Register block ID] | [bit ID]
459      *
460      * Check bit ID to fine locate Register offset.
461      * Check Mask to determine Register offset, and then read-write.
462      */
463     switch (BitRegInfo->ParentRegister)
464     {
465     case ACPI_REGISTER_PM1_STATUS:
466
467         /*
468          * Status Registers are different from the rest.  Clear by
469          * writing 1, and writing 0 has no effect.  So, the only relevant
470          * information is the single bit we're interested in, all others should
471          * be written as 0 so they will be left unchanged.
472          */
473         Value = ACPI_REGISTER_PREPARE_BITS (Value,
474                     BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
475         if (Value)
476         {
477             Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
478                         ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
479             RegisterValue = 0;
480         }
481         break;
482
483
484     case ACPI_REGISTER_PM1_ENABLE:
485
486         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
487                 BitRegInfo->AccessBitMask, Value);
488
489         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
490                         ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
491         break;
492
493
494     case ACPI_REGISTER_PM1_CONTROL:
495
496         /*
497          * Write the PM1 Control register.
498          * Note that at this level, the fact that there are actually TWO
499          * registers (A and B - and B may not exist) is abstracted.
500          */
501         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", 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 (ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.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 (ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.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     if (Flags & ACPI_MTX_LOCK)
544     {
545         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
546     }
547
548     /* Normalize the value that was read */
549
550     ACPI_DEBUG_EXEC (RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) >> BitRegInfo->BitPosition));
551
552     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
553             Value, RegisterValue, BitRegInfo->ParentRegister));
554     return_ACPI_STATUS (Status);
555 }
556
557
558 /******************************************************************************
559  *
560  * FUNCTION:    AcpiHwRegisterRead
561  *
562  * PARAMETERS:  UseLock                - Mutex hw access.
563  *              RegisterId             - RegisterID + Offset.
564  *
565  * RETURN:      Value read or written.
566  *
567  * DESCRIPTION: Acpi register read function.  Registers are read at the
568  *              given offset.
569  *
570  ******************************************************************************/
571
572 ACPI_STATUS
573 AcpiHwRegisterRead (
574     BOOLEAN                 UseLock,
575     UINT32                  RegisterId,
576     UINT32                  *ReturnValue)
577 {
578     UINT32                  Value1 = 0;
579     UINT32                  Value2 = 0;
580     ACPI_STATUS             Status;
581
582
583     ACPI_FUNCTION_TRACE ("HwRegisterRead");
584
585
586     if (ACPI_MTX_LOCK == UseLock)
587     {
588         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
589         if (ACPI_FAILURE (Status))
590         {
591             return_ACPI_STATUS (Status);
592         }
593     }
594
595     switch (RegisterId)
596     {
597     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
598
599         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aEvtBlk);
600         if (ACPI_FAILURE (Status))
601         {
602             goto UnlockAndExit;
603         }
604
605         /* PM1B is optional */
606
607         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bEvtBlk);
608         Value1 |= Value2;
609         break;
610
611
612     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
613
614         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
615         if (ACPI_FAILURE (Status))
616         {
617             goto UnlockAndExit;
618         }
619
620         /* PM1B is optional */
621
622         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
623         Value1 |= Value2;
624         break;
625
626
627     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
628
629         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aCntBlk);
630         if (ACPI_FAILURE (Status))
631         {
632             goto UnlockAndExit;
633         }
634
635         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bCntBlk);
636         Value1 |= Value2;
637         break;
638
639
640     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
641
642         Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT->XPm2CntBlk);
643         break;
644
645
646     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
647
648         Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT->XPmTmrBlk);
649         break;
650
651     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
652
653         Status = AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value1, 8);
654         break;
655
656     default:
657         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n", RegisterId));
658         Status = AE_BAD_PARAMETER;
659         break;
660     }
661
662 UnlockAndExit:
663     if (ACPI_MTX_LOCK == UseLock)
664     {
665         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
666     }
667
668     if (ACPI_SUCCESS (Status))
669     {
670         *ReturnValue = Value1;
671     }
672
673     return_ACPI_STATUS (Status);
674 }
675
676
677 /******************************************************************************
678  *
679  * FUNCTION:    AcpiHwRegisterWrite
680  *
681  * PARAMETERS:  UseLock                - Mutex hw access.
682  *              RegisterId             - RegisterID + Offset.
683  *
684  * RETURN:      Value read or written.
685  *
686  * DESCRIPTION: Acpi register Write function.  Registers are written at the
687  *              given offset.
688  *
689  ******************************************************************************/
690
691 ACPI_STATUS
692 AcpiHwRegisterWrite (
693     BOOLEAN                 UseLock,
694     UINT32                  RegisterId,
695     UINT32                  Value)
696 {
697     ACPI_STATUS             Status;
698
699
700     ACPI_FUNCTION_TRACE ("HwRegisterWrite");
701
702
703     if (ACPI_MTX_LOCK == UseLock)
704     {
705         Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
706         if (ACPI_FAILURE (Status))
707         {
708             return_ACPI_STATUS (Status);
709         }
710     }
711
712     switch (RegisterId)
713     {
714     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
715
716         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk);
717         if (ACPI_FAILURE (Status))
718         {
719             goto UnlockAndExit;
720         }
721
722         /* PM1B is optional */
723
724         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk);
725         break;
726
727
728     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
729
730         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
731         if (ACPI_FAILURE (Status))
732         {
733             goto UnlockAndExit;
734         }
735
736         /* PM1B is optional */
737
738         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
739         break;
740
741
742     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
743
744         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
745         if (ACPI_FAILURE (Status))
746         {
747             goto UnlockAndExit;
748         }
749
750         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
751         break;
752
753
754     case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
755
756         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
757         break;
758
759
760     case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
761
762         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
763         break;
764
765
766     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
767
768         Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk);
769         break;
770
771
772     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
773
774         Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk);
775         break;
776
777
778     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
779
780         /* SMI_CMD is currently always in IO space */
781
782         Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
783         break;
784
785
786     default:
787         Status = AE_BAD_PARAMETER;
788         break;
789     }
790
791 UnlockAndExit:
792     if (ACPI_MTX_LOCK == UseLock)
793     {
794         (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
795     }
796
797     return_ACPI_STATUS (Status);
798 }
799
800
801 /******************************************************************************
802  *
803  * FUNCTION:    AcpiHwLowLevelRead
804  *
805  * PARAMETERS:  Width               - 8, 16, or 32
806  *              Value               - Where the value is returned
807  *              Register            - GAS register structure
808  *
809  * RETURN:      Status
810  *
811  * DESCRIPTION: Read from either memory, IO, or PCI config space.
812  *
813  ******************************************************************************/
814
815 ACPI_STATUS
816 AcpiHwLowLevelRead (
817     UINT32                  Width,
818     UINT32                  *Value,
819     ACPI_GENERIC_ADDRESS    *Reg)
820 {
821     ACPI_PCI_ID             PciId;
822     UINT16                  PciRegister;
823     ACPI_STATUS             Status;
824
825
826     ACPI_FUNCTION_NAME ("HwLowLevelRead");
827
828
829     /*
830      * Must have a valid pointer to a GAS structure, and
831      * a non-zero address within. However, don't return an error
832      * because the PM1A/B code must not fail if B isn't present.
833      */
834     if ((!Reg) ||
835         (!ACPI_VALID_ADDRESS (Reg->Address)))
836     {
837         return (AE_OK);
838     }
839     *Value = 0;
840
841     /*
842      * Three address spaces supported:
843      * Memory, IO, or PCI_Config.
844      */
845     switch (Reg->AddressSpaceId)
846     {
847     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
848
849         Status = AcpiOsReadMemory (
850                     (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
851                     Value, Width);
852         break;
853
854
855     case ACPI_ADR_SPACE_SYSTEM_IO:
856
857         Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
858                     Value, Width);
859         break;
860
861
862     case ACPI_ADR_SPACE_PCI_CONFIG:
863
864         PciId.Segment  = 0;
865         PciId.Bus      = 0;
866         PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
867         PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
868         PciRegister    = (UINT16) ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address));
869
870         Status = AcpiOsReadPciConfiguration  (&PciId, PciRegister,
871                     Value, Width);
872         break;
873
874
875     default:
876         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
877             "Unsupported address space: %X\n", Reg->AddressSpaceId));
878         return (AE_BAD_PARAMETER);
879     }
880
881     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
882             *Value, Width,
883             ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Reg->Address)),
884             AcpiUtGetRegionName (Reg->AddressSpaceId)));
885
886     return (Status);
887 }
888
889
890 /******************************************************************************
891  *
892  * FUNCTION:    AcpiHwLowLevelWrite
893  *
894  * PARAMETERS:  Width               - 8, 16, or 32
895  *              Value               - To be written
896  *              Register            - GAS register structure
897  *
898  * RETURN:      Status
899  *
900  * DESCRIPTION: Write to either memory, IO, or PCI config space.
901  *
902  ******************************************************************************/
903
904 ACPI_STATUS
905 AcpiHwLowLevelWrite (
906     UINT32                  Width,
907     UINT32                  Value,
908     ACPI_GENERIC_ADDRESS    *Reg)
909 {
910     ACPI_PCI_ID             PciId;
911     UINT16                  PciRegister;
912     ACPI_STATUS             Status;
913
914
915     ACPI_FUNCTION_NAME ("HwLowLevelWrite");
916
917
918     /*
919      * Must have a valid pointer to a GAS structure, and
920      * a non-zero address within. However, don't return an error
921      * because the PM1A/B code must not fail if B isn't present.
922      */
923     if ((!Reg) ||
924         (!ACPI_VALID_ADDRESS (Reg->Address)))
925     {
926         return (AE_OK);
927     }
928
929     /*
930      * Three address spaces supported:
931      * Memory, IO, or PCI_Config.
932      */
933     switch (Reg->AddressSpaceId)
934     {
935     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
936
937         Status = AcpiOsWriteMemory (
938                     (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
939                     Value, Width);
940         break;
941
942
943     case ACPI_ADR_SPACE_SYSTEM_IO:
944
945         Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Reg->Address),
946                     Value, Width);
947         break;
948
949
950     case ACPI_ADR_SPACE_PCI_CONFIG:
951
952         PciId.Segment  = 0;
953         PciId.Bus      = 0;
954         PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
955         PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
956         PciRegister    = (UINT16) ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address));
957
958         Status = AcpiOsWritePciConfiguration (&PciId, PciRegister,
959                     (ACPI_INTEGER) Value, Width);
960         break;
961
962
963     default:
964         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
965             "Unsupported address space: %X\n", Reg->AddressSpaceId));
966         return (AE_BAD_PARAMETER);
967     }
968
969     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
970             Value, Width,
971             ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Reg->Address)),
972             AcpiUtGetRegionName (Reg->AddressSpaceId)));
973
974     return (Status);
975 }