hwxface.c revision 193529
1
2/******************************************************************************
3 *
4 * Module Name: hwxface - Public ACPICA hardware interfaces
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117#include <contrib/dev/acpica/include/acpi.h>
118#include <contrib/dev/acpica/include/accommon.h>
119#include <contrib/dev/acpica/include/acnamesp.h>
120
121#define _COMPONENT          ACPI_HARDWARE
122        ACPI_MODULE_NAME    ("hwxface")
123
124
125/******************************************************************************
126 *
127 * FUNCTION:    AcpiReset
128 *
129 * PARAMETERS:  None
130 *
131 * RETURN:      Status
132 *
133 * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
134 *              support reset register in PCI config space, this must be
135 *              handled separately.
136 *
137 ******************************************************************************/
138
139ACPI_STATUS
140AcpiReset (
141    void)
142{
143    ACPI_GENERIC_ADDRESS    *ResetReg;
144    ACPI_STATUS             Status;
145
146
147    ACPI_FUNCTION_TRACE (AcpiReset);
148
149
150    ResetReg = &AcpiGbl_FADT.ResetRegister;
151
152    /* Check if the reset register is supported */
153
154    if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
155        !ResetReg->Address)
156    {
157        return_ACPI_STATUS (AE_NOT_EXIST);
158    }
159
160    /* Write the reset value to the reset register */
161
162    Status = AcpiWrite (AcpiGbl_FADT.ResetValue, ResetReg);
163    return_ACPI_STATUS (Status);
164}
165
166ACPI_EXPORT_SYMBOL (AcpiReset)
167
168
169/******************************************************************************
170 *
171 * FUNCTION:    AcpiRead
172 *
173 * PARAMETERS:  Value               - Where the value is returned
174 *              Reg                 - GAS register structure
175 *
176 * RETURN:      Status
177 *
178 * DESCRIPTION: Read from either memory or IO space.
179 *
180 ******************************************************************************/
181
182ACPI_STATUS
183AcpiRead (
184    UINT32                  *Value,
185    ACPI_GENERIC_ADDRESS    *Reg)
186{
187    UINT32                  Width;
188    UINT64                  Address;
189    ACPI_STATUS             Status;
190
191
192    ACPI_FUNCTION_NAME (AcpiRead);
193
194
195    /*
196     * Must have a valid pointer to a GAS structure, and a non-zero address
197     * within.
198     */
199    if (!Reg)
200    {
201        return (AE_BAD_PARAMETER);
202    }
203
204    /* Get a local copy of the address. Handles possible alignment issues */
205
206    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
207    if (!Address)
208    {
209        return (AE_BAD_ADDRESS);
210    }
211
212    /* Supported widths are 8/16/32 */
213
214    Width = Reg->BitWidth;
215    if ((Width != 8) && (Width != 16) && (Width != 32))
216    {
217        return (AE_SUPPORT);
218    }
219
220    /* Initialize entire 32-bit return value to zero */
221
222    *Value = 0;
223
224    /*
225     * Two address spaces supported: Memory or IO. PCI_Config is
226     * not supported here because the GAS structure is insufficient
227     */
228    switch (Reg->SpaceId)
229    {
230    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
231
232        Status = AcpiOsReadMemory (
233                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
234        break;
235
236
237    case ACPI_ADR_SPACE_SYSTEM_IO:
238
239        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address, Value, Width);
240        break;
241
242
243    default:
244        ACPI_ERROR ((AE_INFO,
245            "Unsupported address space: %X", Reg->SpaceId));
246        return (AE_BAD_PARAMETER);
247    }
248
249    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
250        "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
251        *Value, Width, ACPI_FORMAT_UINT64 (Address),
252        AcpiUtGetRegionName (Reg->SpaceId)));
253
254    return (Status);
255}
256
257ACPI_EXPORT_SYMBOL (AcpiRead)
258
259
260/******************************************************************************
261 *
262 * FUNCTION:    AcpiWrite
263 *
264 * PARAMETERS:  Value               - To be written
265 *              Reg                 - GAS register structure
266 *
267 * RETURN:      Status
268 *
269 * DESCRIPTION: Write to either memory or IO space.
270 *
271 ******************************************************************************/
272
273ACPI_STATUS
274AcpiWrite (
275    UINT32                  Value,
276    ACPI_GENERIC_ADDRESS    *Reg)
277{
278    UINT32                  Width;
279    UINT64                  Address;
280    ACPI_STATUS             Status;
281
282
283    ACPI_FUNCTION_NAME (AcpiWrite);
284
285
286    /*
287     * Must have a valid pointer to a GAS structure, and a non-zero address
288     * within.
289     */
290    if (!Reg)
291    {
292        return (AE_BAD_PARAMETER);
293    }
294
295    /* Get a local copy of the address. Handles possible alignment issues */
296
297    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
298    if (!Address)
299    {
300        return (AE_BAD_ADDRESS);
301    }
302
303    /* Supported widths are 8/16/32 */
304
305    Width = Reg->BitWidth;
306    if ((Width != 8) && (Width != 16) && (Width != 32))
307    {
308        return (AE_SUPPORT);
309    }
310
311    /*
312     * Two address spaces supported: Memory or IO.
313     * PCI_Config is not supported here because the GAS struct is insufficient
314     */
315    switch (Reg->SpaceId)
316    {
317    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
318
319        Status = AcpiOsWriteMemory (
320                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
321        break;
322
323
324    case ACPI_ADR_SPACE_SYSTEM_IO:
325
326        Status = AcpiHwWritePort (
327                    (ACPI_IO_ADDRESS) Address, Value, Width);
328        break;
329
330
331    default:
332        ACPI_ERROR ((AE_INFO,
333            "Unsupported address space: %X", Reg->SpaceId));
334        return (AE_BAD_PARAMETER);
335    }
336
337    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
338        "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
339        Value, Width, ACPI_FORMAT_UINT64 (Address),
340        AcpiUtGetRegionName (Reg->SpaceId)));
341
342    return (Status);
343}
344
345ACPI_EXPORT_SYMBOL (AcpiWrite)
346
347
348/*******************************************************************************
349 *
350 * FUNCTION:    AcpiReadBitRegister
351 *
352 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
353 *              ReturnValue     - Value that was read from the register,
354 *                                normalized to bit position zero.
355 *
356 * RETURN:      Status and the value read from the specified Register. Value
357 *              returned is normalized to bit0 (is shifted all the way right)
358 *
359 * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
360 *
361 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
362 *              PM2 Control.
363 *
364 * Note: The hardware lock is not required when reading the ACPI bit registers
365 *       since almost all of them are single bit and it does not matter that
366 *       the parent hardware register can be split across two physical
367 *       registers. The only multi-bit field is SLP_TYP in the PM1 control
368 *       register, but this field does not cross an 8-bit boundary (nor does
369 *       it make much sense to actually read this field.)
370 *
371 ******************************************************************************/
372
373ACPI_STATUS
374AcpiReadBitRegister (
375    UINT32                  RegisterId,
376    UINT32                  *ReturnValue)
377{
378    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
379    UINT32                  RegisterValue;
380    UINT32                  Value;
381    ACPI_STATUS             Status;
382
383
384    ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
385
386
387    /* Get the info structure corresponding to the requested ACPI Register */
388
389    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
390    if (!BitRegInfo)
391    {
392        return_ACPI_STATUS (AE_BAD_PARAMETER);
393    }
394
395    /* Read the entire parent register */
396
397    Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
398                &RegisterValue);
399    if (ACPI_FAILURE (Status))
400    {
401        return_ACPI_STATUS (Status);
402    }
403
404    /* Normalize the value that was read, mask off other bits */
405
406    Value = ((RegisterValue & BitRegInfo->AccessBitMask)
407                >> BitRegInfo->BitPosition);
408
409    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
410        "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
411        RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
412
413    *ReturnValue = Value;
414    return_ACPI_STATUS (AE_OK);
415}
416
417ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
418
419
420/*******************************************************************************
421 *
422 * FUNCTION:    AcpiWriteBitRegister
423 *
424 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
425 *              Value           - Value to write to the register, in bit
426 *                                position zero. The bit is automaticallly
427 *                                shifted to the correct position.
428 *
429 * RETURN:      Status
430 *
431 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
432 *              since most operations require a read/modify/write sequence.
433 *
434 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
435 *              PM2 Control.
436 *
437 * Note that at this level, the fact that there may be actually two
438 * hardware registers (A and B - and B may not exist) is abstracted.
439 *
440 ******************************************************************************/
441
442ACPI_STATUS
443AcpiWriteBitRegister (
444    UINT32                  RegisterId,
445    UINT32                  Value)
446{
447    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
448    ACPI_CPU_FLAGS          LockFlags;
449    UINT32                  RegisterValue;
450    ACPI_STATUS             Status = AE_OK;
451
452
453    ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
454
455
456    /* Get the info structure corresponding to the requested ACPI Register */
457
458    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
459    if (!BitRegInfo)
460    {
461        return_ACPI_STATUS (AE_BAD_PARAMETER);
462    }
463
464    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
465
466    /*
467     * At this point, we know that the parent register is one of the
468     * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
469     */
470    if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
471    {
472        /*
473         * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
474         *
475         * Perform a register read to preserve the bits that we are not
476         * interested in
477         */
478        Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
479                    &RegisterValue);
480        if (ACPI_FAILURE (Status))
481        {
482            goto UnlockAndExit;
483        }
484
485        /*
486         * Insert the input bit into the value that was just read
487         * and write the register
488         */
489        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
490            BitRegInfo->AccessBitMask, Value);
491
492        Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
493                    RegisterValue);
494    }
495    else
496    {
497        /*
498         * 2) Case for PM1 Status
499         *
500         * The Status register is different from the rest. Clear an event
501         * by writing 1, writing 0 has no effect. So, the only relevant
502         * information is the single bit we're interested in, all others
503         * should be written as 0 so they will be left unchanged.
504         */
505        RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
506            BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
507
508        /* No need to write the register if value is all zeros */
509
510        if (RegisterValue)
511        {
512            Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
513                        RegisterValue);
514        }
515    }
516
517    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
518        "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
519        RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
520
521
522UnlockAndExit:
523
524    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
525    return_ACPI_STATUS (Status);
526}
527
528ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
529
530
531/*******************************************************************************
532 *
533 * FUNCTION:    AcpiGetSleepTypeData
534 *
535 * PARAMETERS:  SleepState          - Numeric sleep state
536 *              *SleepTypeA         - Where SLP_TYPa is returned
537 *              *SleepTypeB         - Where SLP_TYPb is returned
538 *
539 * RETURN:      Status - ACPI status
540 *
541 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
542 *              state.
543 *
544 ******************************************************************************/
545
546ACPI_STATUS
547AcpiGetSleepTypeData (
548    UINT8                   SleepState,
549    UINT8                   *SleepTypeA,
550    UINT8                   *SleepTypeB)
551{
552    ACPI_STATUS             Status = AE_OK;
553    ACPI_EVALUATE_INFO      *Info;
554
555
556    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
557
558
559    /* Validate parameters */
560
561    if ((SleepState > ACPI_S_STATES_MAX) ||
562        !SleepTypeA ||
563        !SleepTypeB)
564    {
565        return_ACPI_STATUS (AE_BAD_PARAMETER);
566    }
567
568    /* Allocate the evaluation information block */
569
570    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
571    if (!Info)
572    {
573        return_ACPI_STATUS (AE_NO_MEMORY);
574    }
575
576    Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
577
578    /* Evaluate the namespace object containing the values for this state */
579
580    Status = AcpiNsEvaluate (Info);
581    if (ACPI_FAILURE (Status))
582    {
583        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
584            "%s while evaluating SleepState [%s]\n",
585            AcpiFormatException (Status), Info->Pathname));
586
587        goto Cleanup;
588    }
589
590    /* Must have a return object */
591
592    if (!Info->ReturnObject)
593    {
594        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
595            Info->Pathname));
596        Status = AE_NOT_EXIST;
597    }
598
599    /* It must be of type Package */
600
601    else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
602    {
603        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
604        Status = AE_AML_OPERAND_TYPE;
605    }
606
607    /*
608     * The package must have at least two elements. NOTE (March 2005): This
609     * goes against the current ACPI spec which defines this object as a
610     * package with one encoded DWORD element. However, existing practice
611     * by BIOS vendors seems to be to have 2 or more elements, at least
612     * one per sleep type (A/B).
613     */
614    else if (Info->ReturnObject->Package.Count < 2)
615    {
616        ACPI_ERROR ((AE_INFO,
617            "Sleep State return package does not have at least two elements"));
618        Status = AE_AML_NO_OPERAND;
619    }
620
621    /* The first two elements must both be of type Integer */
622
623    else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
624                != ACPI_TYPE_INTEGER) ||
625             ((Info->ReturnObject->Package.Elements[1])->Common.Type
626                != ACPI_TYPE_INTEGER))
627    {
628        ACPI_ERROR ((AE_INFO,
629            "Sleep State return package elements are not both Integers "
630            "(%s, %s)",
631            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
632            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
633        Status = AE_AML_OPERAND_TYPE;
634    }
635    else
636    {
637        /* Valid _Sx_ package size, type, and value */
638
639        *SleepTypeA = (UINT8)
640            (Info->ReturnObject->Package.Elements[0])->Integer.Value;
641        *SleepTypeB = (UINT8)
642            (Info->ReturnObject->Package.Elements[1])->Integer.Value;
643    }
644
645    if (ACPI_FAILURE (Status))
646    {
647        ACPI_EXCEPTION ((AE_INFO, Status,
648            "While evaluating SleepState [%s], bad Sleep object %p type %s",
649            Info->Pathname, Info->ReturnObject,
650            AcpiUtGetObjectTypeName (Info->ReturnObject)));
651    }
652
653    AcpiUtRemoveReference (Info->ReturnObject);
654
655Cleanup:
656    ACPI_FREE (Info);
657    return_ACPI_STATUS (Status);
658}
659
660ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
661