hwregs.c revision 1.14 1 1.1 jruoho /*******************************************************************************
2 1.1 jruoho *
3 1.1 jruoho * Module Name: hwregs - Read/write access functions for the various ACPI
4 1.1 jruoho * control and status registers.
5 1.1 jruoho *
6 1.1 jruoho ******************************************************************************/
7 1.1 jruoho
8 1.13 christos /******************************************************************************
9 1.13 christos *
10 1.13 christos * 1. Copyright Notice
11 1.13 christos *
12 1.14 christos * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
13 1.1 jruoho * All rights reserved.
14 1.1 jruoho *
15 1.13 christos * 2. License
16 1.13 christos *
17 1.13 christos * 2.1. This is your license from Intel Corp. under its intellectual property
18 1.13 christos * rights. You may have additional license terms from the party that provided
19 1.13 christos * you this software, covering your right to use that party's intellectual
20 1.13 christos * property rights.
21 1.13 christos *
22 1.13 christos * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 1.13 christos * copy of the source code appearing in this file ("Covered Code") an
24 1.13 christos * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 1.13 christos * base code distributed originally by Intel ("Original Intel Code") to copy,
26 1.13 christos * make derivatives, distribute, use and display any portion of the Covered
27 1.13 christos * Code in any form, with the right to sublicense such rights; and
28 1.13 christos *
29 1.13 christos * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 1.13 christos * license (with the right to sublicense), under only those claims of Intel
31 1.13 christos * patents that are infringed by the Original Intel Code, to make, use, sell,
32 1.13 christos * offer to sell, and import the Covered Code and derivative works thereof
33 1.13 christos * solely to the minimum extent necessary to exercise the above copyright
34 1.13 christos * license, and in no event shall the patent license extend to any additions
35 1.13 christos * to or modifications of the Original Intel Code. No other license or right
36 1.13 christos * is granted directly or by implication, estoppel or otherwise;
37 1.13 christos *
38 1.13 christos * The above copyright and patent license is granted only if the following
39 1.13 christos * conditions are met:
40 1.13 christos *
41 1.13 christos * 3. Conditions
42 1.13 christos *
43 1.13 christos * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 1.13 christos * Redistribution of source code of any substantial portion of the Covered
45 1.13 christos * Code or modification with rights to further distribute source must include
46 1.13 christos * the above Copyright Notice, the above License, this list of Conditions,
47 1.13 christos * and the following Disclaimer and Export Compliance provision. In addition,
48 1.13 christos * Licensee must cause all Covered Code to which Licensee contributes to
49 1.13 christos * contain a file documenting the changes Licensee made to create that Covered
50 1.13 christos * Code and the date of any change. Licensee must include in that file the
51 1.13 christos * documentation of any changes made by any predecessor Licensee. Licensee
52 1.13 christos * must include a prominent statement that the modification is derived,
53 1.13 christos * directly or indirectly, from Original Intel Code.
54 1.13 christos *
55 1.13 christos * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 1.13 christos * Redistribution of source code of any substantial portion of the Covered
57 1.13 christos * Code or modification without rights to further distribute source must
58 1.13 christos * include the following Disclaimer and Export Compliance provision in the
59 1.13 christos * documentation and/or other materials provided with distribution. In
60 1.13 christos * addition, Licensee may not authorize further sublicense of source of any
61 1.13 christos * portion of the Covered Code, and must include terms to the effect that the
62 1.13 christos * license from Licensee to its licensee is limited to the intellectual
63 1.13 christos * property embodied in the software Licensee provides to its licensee, and
64 1.13 christos * not to intellectual property embodied in modifications its licensee may
65 1.13 christos * make.
66 1.13 christos *
67 1.13 christos * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 1.13 christos * substantial portion of the Covered Code or modification must reproduce the
69 1.13 christos * above Copyright Notice, and the following Disclaimer and Export Compliance
70 1.13 christos * provision in the documentation and/or other materials provided with the
71 1.13 christos * distribution.
72 1.13 christos *
73 1.13 christos * 3.4. Intel retains all right, title, and interest in and to the Original
74 1.13 christos * Intel Code.
75 1.13 christos *
76 1.13 christos * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 1.13 christos * Intel shall be used in advertising or otherwise to promote the sale, use or
78 1.13 christos * other dealings in products derived from or relating to the Covered Code
79 1.13 christos * without prior written authorization from Intel.
80 1.13 christos *
81 1.13 christos * 4. Disclaimer and Export Compliance
82 1.13 christos *
83 1.13 christos * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 1.13 christos * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 1.13 christos * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
86 1.13 christos * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
87 1.13 christos * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88 1.13 christos * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 1.13 christos * PARTICULAR PURPOSE.
90 1.13 christos *
91 1.13 christos * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 1.13 christos * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 1.13 christos * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 1.13 christos * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 1.13 christos * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 1.13 christos * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97 1.13 christos * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 1.13 christos * LIMITED REMEDY.
99 1.13 christos *
100 1.13 christos * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 1.13 christos * software or system incorporating such software without first obtaining any
102 1.13 christos * required license or other approval from the U. S. Department of Commerce or
103 1.13 christos * any other agency or department of the United States Government. In the
104 1.13 christos * event Licensee exports any such software from the United States or
105 1.13 christos * re-exports any such software from a foreign destination, Licensee shall
106 1.13 christos * ensure that the distribution and export/re-export of the software is in
107 1.13 christos * compliance with all laws, regulations, orders, or other restrictions of the
108 1.13 christos * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 1.13 christos * any of its subsidiaries will export/re-export any technical data, process,
110 1.13 christos * software, or service, directly or indirectly, to any country for which the
111 1.13 christos * United States government or any agency thereof requires an export license,
112 1.13 christos * other governmental approval, or letter of assurance, without first obtaining
113 1.13 christos * such license, approval or letter.
114 1.13 christos *
115 1.13 christos *****************************************************************************
116 1.13 christos *
117 1.13 christos * Alternatively, you may choose to be licensed under the terms of the
118 1.13 christos * following license:
119 1.13 christos *
120 1.2 christos * Redistribution and use in source and binary forms, with or without
121 1.2 christos * modification, are permitted provided that the following conditions
122 1.2 christos * are met:
123 1.2 christos * 1. Redistributions of source code must retain the above copyright
124 1.2 christos * notice, this list of conditions, and the following disclaimer,
125 1.2 christos * without modification.
126 1.2 christos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
127 1.2 christos * substantially similar to the "NO WARRANTY" disclaimer below
128 1.2 christos * ("Disclaimer") and any redistribution must be conditioned upon
129 1.2 christos * including a substantially similar Disclaimer requirement for further
130 1.2 christos * binary redistribution.
131 1.2 christos * 3. Neither the names of the above-listed copyright holders nor the names
132 1.2 christos * of any contributors may be used to endorse or promote products derived
133 1.2 christos * from this software without specific prior written permission.
134 1.2 christos *
135 1.2 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
136 1.2 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
137 1.10 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
138 1.2 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
139 1.13 christos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
140 1.13 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
141 1.13 christos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
142 1.13 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
143 1.13 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
144 1.13 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
145 1.13 christos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
146 1.13 christos *
147 1.13 christos * Alternatively, you may choose to be licensed under the terms of the
148 1.13 christos * GNU General Public License ("GPL") version 2 as published by the Free
149 1.13 christos * Software Foundation.
150 1.13 christos *
151 1.13 christos *****************************************************************************/
152 1.1 jruoho
153 1.1 jruoho #include "acpi.h"
154 1.1 jruoho #include "accommon.h"
155 1.1 jruoho #include "acevents.h"
156 1.1 jruoho
157 1.1 jruoho #define _COMPONENT ACPI_HARDWARE
158 1.1 jruoho ACPI_MODULE_NAME ("hwregs")
159 1.1 jruoho
160 1.1 jruoho
161 1.2 christos #if (!ACPI_REDUCED_HARDWARE)
162 1.2 christos
163 1.1 jruoho /* Local Prototypes */
164 1.1 jruoho
165 1.4 christos static UINT8
166 1.4 christos AcpiHwGetAccessBitWidth (
167 1.4 christos UINT64 Address,
168 1.4 christos ACPI_GENERIC_ADDRESS *Reg,
169 1.4 christos UINT8 MaxBitWidth);
170 1.4 christos
171 1.1 jruoho static ACPI_STATUS
172 1.1 jruoho AcpiHwReadMultiple (
173 1.1 jruoho UINT32 *Value,
174 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterA,
175 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterB);
176 1.1 jruoho
177 1.1 jruoho static ACPI_STATUS
178 1.1 jruoho AcpiHwWriteMultiple (
179 1.1 jruoho UINT32 Value,
180 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterA,
181 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterB);
182 1.1 jruoho
183 1.2 christos #endif /* !ACPI_REDUCED_HARDWARE */
184 1.2 christos
185 1.2 christos
186 1.2 christos /******************************************************************************
187 1.2 christos *
188 1.4 christos * FUNCTION: AcpiHwGetAccessBitWidth
189 1.4 christos *
190 1.4 christos * PARAMETERS: Address - GAS register address
191 1.4 christos * Reg - GAS register structure
192 1.4 christos * MaxBitWidth - Max BitWidth supported (32 or 64)
193 1.4 christos *
194 1.4 christos * RETURN: Status
195 1.4 christos *
196 1.4 christos * DESCRIPTION: Obtain optimal access bit width
197 1.4 christos *
198 1.4 christos ******************************************************************************/
199 1.4 christos
200 1.4 christos static UINT8
201 1.4 christos AcpiHwGetAccessBitWidth (
202 1.4 christos UINT64 Address,
203 1.4 christos ACPI_GENERIC_ADDRESS *Reg,
204 1.4 christos UINT8 MaxBitWidth)
205 1.4 christos {
206 1.4 christos UINT8 AccessBitWidth;
207 1.4 christos
208 1.4 christos
209 1.4 christos /*
210 1.4 christos * GAS format "register", used by FADT:
211 1.4 christos * 1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64;
212 1.4 christos * 2. AccessSize field is ignored and BitWidth field is used for
213 1.4 christos * determining the boundary of the IO accesses.
214 1.4 christos * GAS format "region", used by APEI registers:
215 1.4 christos * 1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64;
216 1.4 christos * 2. AccessSize field is used for determining the boundary of the
217 1.4 christos * IO accesses;
218 1.4 christos * 3. BitOffset/BitWidth fields are used to describe the "region".
219 1.4 christos *
220 1.4 christos * Note: This algorithm assumes that the "Address" fields should always
221 1.4 christos * contain aligned values.
222 1.4 christos */
223 1.4 christos if (!Reg->BitOffset && Reg->BitWidth &&
224 1.4 christos ACPI_IS_POWER_OF_TWO (Reg->BitWidth) &&
225 1.4 christos ACPI_IS_ALIGNED (Reg->BitWidth, 8))
226 1.4 christos {
227 1.4 christos AccessBitWidth = Reg->BitWidth;
228 1.4 christos }
229 1.4 christos else if (Reg->AccessWidth)
230 1.4 christos {
231 1.5 christos AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth);
232 1.4 christos }
233 1.4 christos else
234 1.4 christos {
235 1.4 christos AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 (
236 1.4 christos Reg->BitOffset + Reg->BitWidth);
237 1.4 christos if (AccessBitWidth <= 8)
238 1.4 christos {
239 1.4 christos AccessBitWidth = 8;
240 1.4 christos }
241 1.4 christos else
242 1.4 christos {
243 1.4 christos while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3))
244 1.4 christos {
245 1.4 christos AccessBitWidth >>= 1;
246 1.4 christos }
247 1.4 christos }
248 1.4 christos }
249 1.4 christos
250 1.4 christos /* Maximum IO port access bit width is 32 */
251 1.4 christos
252 1.4 christos if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
253 1.4 christos {
254 1.4 christos MaxBitWidth = 32;
255 1.4 christos }
256 1.4 christos
257 1.4 christos /*
258 1.4 christos * Return access width according to the requested maximum access bit width,
259 1.4 christos * as the caller should know the format of the register and may enforce
260 1.4 christos * a 32-bit accesses.
261 1.4 christos */
262 1.4 christos if (AccessBitWidth < MaxBitWidth)
263 1.4 christos {
264 1.4 christos return (AccessBitWidth);
265 1.4 christos }
266 1.4 christos return (MaxBitWidth);
267 1.4 christos }
268 1.4 christos
269 1.4 christos
270 1.4 christos /******************************************************************************
271 1.4 christos *
272 1.1 jruoho * FUNCTION: AcpiHwValidateRegister
273 1.1 jruoho *
274 1.1 jruoho * PARAMETERS: Reg - GAS register structure
275 1.1 jruoho * MaxBitWidth - Max BitWidth supported (32 or 64)
276 1.1 jruoho * Address - Pointer to where the gas->address
277 1.1 jruoho * is returned
278 1.1 jruoho *
279 1.1 jruoho * RETURN: Status
280 1.1 jruoho *
281 1.1 jruoho * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
282 1.1 jruoho * pointer, Address, SpaceId, BitWidth, and BitOffset.
283 1.1 jruoho *
284 1.1 jruoho ******************************************************************************/
285 1.1 jruoho
286 1.1 jruoho ACPI_STATUS
287 1.1 jruoho AcpiHwValidateRegister (
288 1.1 jruoho ACPI_GENERIC_ADDRESS *Reg,
289 1.1 jruoho UINT8 MaxBitWidth,
290 1.1 jruoho UINT64 *Address)
291 1.1 jruoho {
292 1.4 christos UINT8 BitWidth;
293 1.4 christos UINT8 AccessWidth;
294 1.4 christos
295 1.1 jruoho
296 1.1 jruoho /* Must have a valid pointer to a GAS structure */
297 1.1 jruoho
298 1.1 jruoho if (!Reg)
299 1.1 jruoho {
300 1.1 jruoho return (AE_BAD_PARAMETER);
301 1.1 jruoho }
302 1.1 jruoho
303 1.1 jruoho /*
304 1.1 jruoho * Copy the target address. This handles possible alignment issues.
305 1.1 jruoho * Address must not be null. A null address also indicates an optional
306 1.1 jruoho * ACPI register that is not supported, so no error message.
307 1.1 jruoho */
308 1.1 jruoho ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
309 1.1 jruoho if (!(*Address))
310 1.1 jruoho {
311 1.1 jruoho return (AE_BAD_ADDRESS);
312 1.1 jruoho }
313 1.1 jruoho
314 1.1 jruoho /* Validate the SpaceID */
315 1.1 jruoho
316 1.1 jruoho if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
317 1.1 jruoho (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
318 1.1 jruoho {
319 1.1 jruoho ACPI_ERROR ((AE_INFO,
320 1.1 jruoho "Unsupported address space: 0x%X", Reg->SpaceId));
321 1.1 jruoho return (AE_SUPPORT);
322 1.1 jruoho }
323 1.1 jruoho
324 1.4 christos /* Validate the AccessWidth */
325 1.1 jruoho
326 1.4 christos if (Reg->AccessWidth > 4)
327 1.1 jruoho {
328 1.1 jruoho ACPI_ERROR ((AE_INFO,
329 1.4 christos "Unsupported register access width: 0x%X", Reg->AccessWidth));
330 1.1 jruoho return (AE_SUPPORT);
331 1.1 jruoho }
332 1.1 jruoho
333 1.4 christos /* Validate the BitWidth, convert AccessWidth into number of bits */
334 1.1 jruoho
335 1.4 christos AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth);
336 1.4 christos BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth);
337 1.4 christos if (MaxBitWidth < BitWidth)
338 1.1 jruoho {
339 1.1 jruoho ACPI_WARNING ((AE_INFO,
340 1.4 christos "Requested bit width 0x%X is smaller than register bit width 0x%X",
341 1.4 christos MaxBitWidth, BitWidth));
342 1.4 christos return (AE_SUPPORT);
343 1.1 jruoho }
344 1.1 jruoho
345 1.1 jruoho return (AE_OK);
346 1.1 jruoho }
347 1.1 jruoho
348 1.1 jruoho
349 1.1 jruoho /******************************************************************************
350 1.1 jruoho *
351 1.1 jruoho * FUNCTION: AcpiHwRead
352 1.1 jruoho *
353 1.1 jruoho * PARAMETERS: Value - Where the value is returned
354 1.1 jruoho * Reg - GAS register structure
355 1.1 jruoho *
356 1.1 jruoho * RETURN: Status
357 1.1 jruoho *
358 1.5 christos * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max
359 1.5 christos * version of AcpiRead.
360 1.1 jruoho *
361 1.1 jruoho * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
362 1.1 jruoho * SpaceID must be SystemMemory or SystemIO.
363 1.1 jruoho *
364 1.1 jruoho ******************************************************************************/
365 1.1 jruoho
366 1.1 jruoho ACPI_STATUS
367 1.1 jruoho AcpiHwRead (
368 1.5 christos UINT64 *Value,
369 1.1 jruoho ACPI_GENERIC_ADDRESS *Reg)
370 1.1 jruoho {
371 1.1 jruoho UINT64 Address;
372 1.4 christos UINT8 AccessWidth;
373 1.4 christos UINT32 BitWidth;
374 1.4 christos UINT8 BitOffset;
375 1.2 christos UINT64 Value64;
376 1.4 christos UINT32 Value32;
377 1.4 christos UINT8 Index;
378 1.1 jruoho ACPI_STATUS Status;
379 1.1 jruoho
380 1.1 jruoho
381 1.1 jruoho ACPI_FUNCTION_NAME (HwRead);
382 1.1 jruoho
383 1.1 jruoho
384 1.1 jruoho /* Validate contents of the GAS register */
385 1.1 jruoho
386 1.5 christos Status = AcpiHwValidateRegister (Reg, 64, &Address);
387 1.1 jruoho if (ACPI_FAILURE (Status))
388 1.1 jruoho {
389 1.1 jruoho return (Status);
390 1.1 jruoho }
391 1.1 jruoho
392 1.4 christos /*
393 1.5 christos * Initialize entire 64-bit return value to zero, convert AccessWidth
394 1.4 christos * into number of bits based
395 1.4 christos */
396 1.1 jruoho *Value = 0;
397 1.5 christos AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
398 1.4 christos BitWidth = Reg->BitOffset + Reg->BitWidth;
399 1.4 christos BitOffset = Reg->BitOffset;
400 1.1 jruoho
401 1.1 jruoho /*
402 1.1 jruoho * Two address spaces supported: Memory or IO. PCI_Config is
403 1.1 jruoho * not supported here because the GAS structure is insufficient
404 1.1 jruoho */
405 1.4 christos Index = 0;
406 1.4 christos while (BitWidth)
407 1.1 jruoho {
408 1.4 christos if (BitOffset >= AccessWidth)
409 1.4 christos {
410 1.5 christos Value64 = 0;
411 1.4 christos BitOffset -= AccessWidth;
412 1.4 christos }
413 1.4 christos else
414 1.4 christos {
415 1.4 christos if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
416 1.4 christos {
417 1.4 christos Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
418 1.4 christos Address + Index * ACPI_DIV_8 (AccessWidth),
419 1.4 christos &Value64, AccessWidth);
420 1.4 christos }
421 1.4 christos else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
422 1.4 christos {
423 1.4 christos Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
424 1.4 christos Address + Index * ACPI_DIV_8 (AccessWidth),
425 1.4 christos &Value32, AccessWidth);
426 1.5 christos Value64 = (UINT64) Value32;
427 1.4 christos }
428 1.4 christos }
429 1.4 christos
430 1.4 christos /*
431 1.4 christos * Use offset style bit writes because "Index * AccessWidth" is
432 1.5 christos * ensured to be less than 64-bits by AcpiHwValidateRegister().
433 1.4 christos */
434 1.4 christos ACPI_SET_BITS (Value, Index * AccessWidth,
435 1.5 christos ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64);
436 1.2 christos
437 1.4 christos BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
438 1.4 christos Index++;
439 1.1 jruoho }
440 1.1 jruoho
441 1.1 jruoho ACPI_DEBUG_PRINT ((ACPI_DB_IO,
442 1.5 christos "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
443 1.5 christos ACPI_FORMAT_UINT64 (*Value), AccessWidth,
444 1.5 christos ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
445 1.1 jruoho
446 1.1 jruoho return (Status);
447 1.1 jruoho }
448 1.1 jruoho
449 1.1 jruoho
450 1.1 jruoho /******************************************************************************
451 1.1 jruoho *
452 1.1 jruoho * FUNCTION: AcpiHwWrite
453 1.1 jruoho *
454 1.1 jruoho * PARAMETERS: Value - Value to be written
455 1.1 jruoho * Reg - GAS register structure
456 1.1 jruoho *
457 1.1 jruoho * RETURN: Status
458 1.1 jruoho *
459 1.5 christos * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max
460 1.5 christos * version of AcpiWrite.
461 1.1 jruoho *
462 1.1 jruoho ******************************************************************************/
463 1.1 jruoho
464 1.1 jruoho ACPI_STATUS
465 1.1 jruoho AcpiHwWrite (
466 1.5 christos UINT64 Value,
467 1.1 jruoho ACPI_GENERIC_ADDRESS *Reg)
468 1.1 jruoho {
469 1.1 jruoho UINT64 Address;
470 1.4 christos UINT8 AccessWidth;
471 1.4 christos UINT32 BitWidth;
472 1.4 christos UINT8 BitOffset;
473 1.4 christos UINT64 Value64;
474 1.4 christos UINT8 Index;
475 1.1 jruoho ACPI_STATUS Status;
476 1.1 jruoho
477 1.1 jruoho
478 1.1 jruoho ACPI_FUNCTION_NAME (HwWrite);
479 1.1 jruoho
480 1.1 jruoho
481 1.1 jruoho /* Validate contents of the GAS register */
482 1.1 jruoho
483 1.5 christos Status = AcpiHwValidateRegister (Reg, 64, &Address);
484 1.1 jruoho if (ACPI_FAILURE (Status))
485 1.1 jruoho {
486 1.1 jruoho return (Status);
487 1.1 jruoho }
488 1.1 jruoho
489 1.4 christos /* Convert AccessWidth into number of bits based */
490 1.4 christos
491 1.5 christos AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
492 1.4 christos BitWidth = Reg->BitOffset + Reg->BitWidth;
493 1.4 christos BitOffset = Reg->BitOffset;
494 1.4 christos
495 1.1 jruoho /*
496 1.1 jruoho * Two address spaces supported: Memory or IO. PCI_Config is
497 1.1 jruoho * not supported here because the GAS structure is insufficient
498 1.1 jruoho */
499 1.4 christos Index = 0;
500 1.4 christos while (BitWidth)
501 1.3 christos {
502 1.4 christos /*
503 1.4 christos * Use offset style bit reads because "Index * AccessWidth" is
504 1.5 christos * ensured to be less than 64-bits by AcpiHwValidateRegister().
505 1.4 christos */
506 1.5 christos Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth,
507 1.5 christos ACPI_MASK_BITS_ABOVE_64 (AccessWidth));
508 1.4 christos
509 1.4 christos if (BitOffset >= AccessWidth)
510 1.4 christos {
511 1.4 christos BitOffset -= AccessWidth;
512 1.4 christos }
513 1.4 christos else
514 1.4 christos {
515 1.4 christos if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
516 1.4 christos {
517 1.4 christos Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
518 1.4 christos Address + Index * ACPI_DIV_8 (AccessWidth),
519 1.4 christos Value64, AccessWidth);
520 1.4 christos }
521 1.4 christos else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
522 1.4 christos {
523 1.4 christos Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
524 1.4 christos Address + Index * ACPI_DIV_8 (AccessWidth),
525 1.5 christos (UINT32) Value64, AccessWidth);
526 1.4 christos }
527 1.4 christos }
528 1.4 christos
529 1.4 christos /*
530 1.4 christos * Index * AccessWidth is ensured to be less than 32-bits by
531 1.4 christos * AcpiHwValidateRegister().
532 1.4 christos */
533 1.4 christos BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
534 1.4 christos Index++;
535 1.1 jruoho }
536 1.1 jruoho
537 1.1 jruoho ACPI_DEBUG_PRINT ((ACPI_DB_IO,
538 1.5 christos "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
539 1.5 christos ACPI_FORMAT_UINT64 (Value), AccessWidth,
540 1.5 christos ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
541 1.1 jruoho
542 1.1 jruoho return (Status);
543 1.1 jruoho }
544 1.1 jruoho
545 1.1 jruoho
546 1.2 christos #if (!ACPI_REDUCED_HARDWARE)
547 1.1 jruoho /*******************************************************************************
548 1.1 jruoho *
549 1.1 jruoho * FUNCTION: AcpiHwClearAcpiStatus
550 1.1 jruoho *
551 1.1 jruoho * PARAMETERS: None
552 1.1 jruoho *
553 1.1 jruoho * RETURN: Status
554 1.1 jruoho *
555 1.1 jruoho * DESCRIPTION: Clears all fixed and general purpose status bits
556 1.1 jruoho *
557 1.1 jruoho ******************************************************************************/
558 1.1 jruoho
559 1.1 jruoho ACPI_STATUS
560 1.1 jruoho AcpiHwClearAcpiStatus (
561 1.1 jruoho void)
562 1.1 jruoho {
563 1.1 jruoho ACPI_STATUS Status;
564 1.1 jruoho ACPI_CPU_FLAGS LockFlags = 0;
565 1.1 jruoho
566 1.1 jruoho
567 1.1 jruoho ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
568 1.1 jruoho
569 1.1 jruoho
570 1.1 jruoho ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
571 1.1 jruoho ACPI_BITMASK_ALL_FIXED_STATUS,
572 1.1 jruoho ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
573 1.1 jruoho
574 1.1 jruoho LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
575 1.1 jruoho
576 1.1 jruoho /* Clear the fixed events in PM1 A/B */
577 1.1 jruoho
578 1.1 jruoho Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
579 1.2 christos ACPI_BITMASK_ALL_FIXED_STATUS);
580 1.2 christos
581 1.2 christos AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
582 1.2 christos
583 1.1 jruoho if (ACPI_FAILURE (Status))
584 1.1 jruoho {
585 1.2 christos goto Exit;
586 1.1 jruoho }
587 1.1 jruoho
588 1.1 jruoho /* Clear the GPE Bits in all GPE registers in all GPE blocks */
589 1.1 jruoho
590 1.1 jruoho Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
591 1.1 jruoho
592 1.2 christos Exit:
593 1.1 jruoho return_ACPI_STATUS (Status);
594 1.1 jruoho }
595 1.1 jruoho
596 1.1 jruoho
597 1.1 jruoho /*******************************************************************************
598 1.1 jruoho *
599 1.2 christos * FUNCTION: AcpiHwGetBitRegisterInfo
600 1.1 jruoho *
601 1.1 jruoho * PARAMETERS: RegisterId - Index of ACPI Register to access
602 1.1 jruoho *
603 1.1 jruoho * RETURN: The bitmask to be used when accessing the register
604 1.1 jruoho *
605 1.1 jruoho * DESCRIPTION: Map RegisterId into a register bitmask.
606 1.1 jruoho *
607 1.1 jruoho ******************************************************************************/
608 1.1 jruoho
609 1.1 jruoho ACPI_BIT_REGISTER_INFO *
610 1.1 jruoho AcpiHwGetBitRegisterInfo (
611 1.1 jruoho UINT32 RegisterId)
612 1.1 jruoho {
613 1.1 jruoho ACPI_FUNCTION_ENTRY ();
614 1.1 jruoho
615 1.1 jruoho
616 1.1 jruoho if (RegisterId > ACPI_BITREG_MAX)
617 1.1 jruoho {
618 1.1 jruoho ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
619 1.1 jruoho return (NULL);
620 1.1 jruoho }
621 1.1 jruoho
622 1.1 jruoho return (&AcpiGbl_BitRegisterInfo[RegisterId]);
623 1.1 jruoho }
624 1.1 jruoho
625 1.1 jruoho
626 1.1 jruoho /******************************************************************************
627 1.1 jruoho *
628 1.1 jruoho * FUNCTION: AcpiHwWritePm1Control
629 1.1 jruoho *
630 1.1 jruoho * PARAMETERS: Pm1aControl - Value to be written to PM1A control
631 1.1 jruoho * Pm1bControl - Value to be written to PM1B control
632 1.1 jruoho *
633 1.1 jruoho * RETURN: Status
634 1.1 jruoho *
635 1.1 jruoho * DESCRIPTION: Write the PM1 A/B control registers. These registers are
636 1.11 christos * different than the PM1 A/B status and enable registers
637 1.1 jruoho * in that different values can be written to the A/B registers.
638 1.1 jruoho * Most notably, the SLP_TYP bits can be different, as per the
639 1.1 jruoho * values returned from the _Sx predefined methods.
640 1.1 jruoho *
641 1.1 jruoho ******************************************************************************/
642 1.1 jruoho
643 1.1 jruoho ACPI_STATUS
644 1.1 jruoho AcpiHwWritePm1Control (
645 1.1 jruoho UINT32 Pm1aControl,
646 1.1 jruoho UINT32 Pm1bControl)
647 1.1 jruoho {
648 1.1 jruoho ACPI_STATUS Status;
649 1.1 jruoho
650 1.1 jruoho
651 1.1 jruoho ACPI_FUNCTION_TRACE (HwWritePm1Control);
652 1.1 jruoho
653 1.1 jruoho
654 1.1 jruoho Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
655 1.1 jruoho if (ACPI_FAILURE (Status))
656 1.1 jruoho {
657 1.1 jruoho return_ACPI_STATUS (Status);
658 1.1 jruoho }
659 1.1 jruoho
660 1.1 jruoho if (AcpiGbl_FADT.XPm1bControlBlock.Address)
661 1.1 jruoho {
662 1.1 jruoho Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
663 1.1 jruoho }
664 1.1 jruoho return_ACPI_STATUS (Status);
665 1.1 jruoho }
666 1.1 jruoho
667 1.1 jruoho
668 1.1 jruoho /******************************************************************************
669 1.1 jruoho *
670 1.1 jruoho * FUNCTION: AcpiHwRegisterRead
671 1.1 jruoho *
672 1.1 jruoho * PARAMETERS: RegisterId - ACPI Register ID
673 1.1 jruoho * ReturnValue - Where the register value is returned
674 1.1 jruoho *
675 1.1 jruoho * RETURN: Status and the value read.
676 1.1 jruoho *
677 1.1 jruoho * DESCRIPTION: Read from the specified ACPI register
678 1.1 jruoho *
679 1.1 jruoho ******************************************************************************/
680 1.1 jruoho
681 1.1 jruoho ACPI_STATUS
682 1.1 jruoho AcpiHwRegisterRead (
683 1.1 jruoho UINT32 RegisterId,
684 1.1 jruoho UINT32 *ReturnValue)
685 1.1 jruoho {
686 1.1 jruoho UINT32 Value = 0;
687 1.5 christos UINT64 Value64;
688 1.1 jruoho ACPI_STATUS Status;
689 1.1 jruoho
690 1.1 jruoho
691 1.1 jruoho ACPI_FUNCTION_TRACE (HwRegisterRead);
692 1.1 jruoho
693 1.1 jruoho
694 1.1 jruoho switch (RegisterId)
695 1.1 jruoho {
696 1.1 jruoho case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
697 1.1 jruoho
698 1.1 jruoho Status = AcpiHwReadMultiple (&Value,
699 1.2 christos &AcpiGbl_XPm1aStatus,
700 1.2 christos &AcpiGbl_XPm1bStatus);
701 1.1 jruoho break;
702 1.1 jruoho
703 1.1 jruoho case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
704 1.1 jruoho
705 1.1 jruoho Status = AcpiHwReadMultiple (&Value,
706 1.2 christos &AcpiGbl_XPm1aEnable,
707 1.2 christos &AcpiGbl_XPm1bEnable);
708 1.1 jruoho break;
709 1.1 jruoho
710 1.1 jruoho case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
711 1.1 jruoho
712 1.1 jruoho Status = AcpiHwReadMultiple (&Value,
713 1.2 christos &AcpiGbl_FADT.XPm1aControlBlock,
714 1.2 christos &AcpiGbl_FADT.XPm1bControlBlock);
715 1.1 jruoho
716 1.1 jruoho /*
717 1.1 jruoho * Zero the write-only bits. From the ACPI specification, "Hardware
718 1.1 jruoho * Write-Only Bits": "Upon reads to registers with write-only bits,
719 1.1 jruoho * software masks out all write-only bits."
720 1.1 jruoho */
721 1.1 jruoho Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
722 1.1 jruoho break;
723 1.1 jruoho
724 1.1 jruoho case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
725 1.1 jruoho
726 1.5 christos Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock);
727 1.7 christos if (ACPI_SUCCESS (Status))
728 1.7 christos {
729 1.7 christos Value = (UINT32) Value64;
730 1.7 christos }
731 1.1 jruoho break;
732 1.1 jruoho
733 1.1 jruoho case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
734 1.1 jruoho
735 1.5 christos Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock);
736 1.7 christos if (ACPI_SUCCESS (Status))
737 1.7 christos {
738 1.7 christos Value = (UINT32) Value64;
739 1.7 christos }
740 1.7 christos
741 1.1 jruoho break;
742 1.1 jruoho
743 1.1 jruoho case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
744 1.1 jruoho
745 1.1 jruoho Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
746 1.1 jruoho break;
747 1.1 jruoho
748 1.2 christos default:
749 1.1 jruoho
750 1.1 jruoho ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
751 1.1 jruoho RegisterId));
752 1.1 jruoho Status = AE_BAD_PARAMETER;
753 1.1 jruoho break;
754 1.1 jruoho }
755 1.1 jruoho
756 1.1 jruoho if (ACPI_SUCCESS (Status))
757 1.1 jruoho {
758 1.5 christos *ReturnValue = (UINT32) Value;
759 1.1 jruoho }
760 1.1 jruoho
761 1.1 jruoho return_ACPI_STATUS (Status);
762 1.1 jruoho }
763 1.1 jruoho
764 1.1 jruoho
765 1.1 jruoho /******************************************************************************
766 1.1 jruoho *
767 1.1 jruoho * FUNCTION: AcpiHwRegisterWrite
768 1.1 jruoho *
769 1.1 jruoho * PARAMETERS: RegisterId - ACPI Register ID
770 1.1 jruoho * Value - The value to write
771 1.1 jruoho *
772 1.1 jruoho * RETURN: Status
773 1.1 jruoho *
774 1.1 jruoho * DESCRIPTION: Write to the specified ACPI register
775 1.1 jruoho *
776 1.1 jruoho * NOTE: In accordance with the ACPI specification, this function automatically
777 1.1 jruoho * preserves the value of the following bits, meaning that these bits cannot be
778 1.1 jruoho * changed via this interface:
779 1.1 jruoho *
780 1.1 jruoho * PM1_CONTROL[0] = SCI_EN
781 1.1 jruoho * PM1_CONTROL[9]
782 1.1 jruoho * PM1_STATUS[11]
783 1.1 jruoho *
784 1.1 jruoho * ACPI References:
785 1.1 jruoho * 1) Hardware Ignored Bits: When software writes to a register with ignored
786 1.1 jruoho * bit fields, it preserves the ignored bit fields
787 1.1 jruoho * 2) SCI_EN: OSPM always preserves this bit position
788 1.1 jruoho *
789 1.1 jruoho ******************************************************************************/
790 1.1 jruoho
791 1.1 jruoho ACPI_STATUS
792 1.1 jruoho AcpiHwRegisterWrite (
793 1.1 jruoho UINT32 RegisterId,
794 1.1 jruoho UINT32 Value)
795 1.1 jruoho {
796 1.1 jruoho ACPI_STATUS Status;
797 1.1 jruoho UINT32 ReadValue;
798 1.5 christos UINT64 ReadValue64;
799 1.1 jruoho
800 1.1 jruoho
801 1.1 jruoho ACPI_FUNCTION_TRACE (HwRegisterWrite);
802 1.1 jruoho
803 1.1 jruoho
804 1.1 jruoho switch (RegisterId)
805 1.1 jruoho {
806 1.1 jruoho case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
807 1.1 jruoho /*
808 1.1 jruoho * Handle the "ignored" bit in PM1 Status. According to the ACPI
809 1.1 jruoho * specification, ignored bits are to be preserved when writing.
810 1.1 jruoho * Normally, this would mean a read/modify/write sequence. However,
811 1.1 jruoho * preserving a bit in the status register is different. Writing a
812 1.1 jruoho * one clears the status, and writing a zero preserves the status.
813 1.1 jruoho * Therefore, we must always write zero to the ignored bit.
814 1.1 jruoho *
815 1.1 jruoho * This behavior is clarified in the ACPI 4.0 specification.
816 1.1 jruoho */
817 1.1 jruoho Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
818 1.1 jruoho
819 1.1 jruoho Status = AcpiHwWriteMultiple (Value,
820 1.2 christos &AcpiGbl_XPm1aStatus,
821 1.2 christos &AcpiGbl_XPm1bStatus);
822 1.1 jruoho break;
823 1.1 jruoho
824 1.1 jruoho case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
825 1.1 jruoho
826 1.1 jruoho Status = AcpiHwWriteMultiple (Value,
827 1.2 christos &AcpiGbl_XPm1aEnable,
828 1.2 christos &AcpiGbl_XPm1bEnable);
829 1.1 jruoho break;
830 1.1 jruoho
831 1.1 jruoho case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
832 1.1 jruoho /*
833 1.1 jruoho * Perform a read first to preserve certain bits (per ACPI spec)
834 1.1 jruoho * Note: This includes SCI_EN, we never want to change this bit
835 1.1 jruoho */
836 1.1 jruoho Status = AcpiHwReadMultiple (&ReadValue,
837 1.2 christos &AcpiGbl_FADT.XPm1aControlBlock,
838 1.2 christos &AcpiGbl_FADT.XPm1bControlBlock);
839 1.1 jruoho if (ACPI_FAILURE (Status))
840 1.1 jruoho {
841 1.1 jruoho goto Exit;
842 1.1 jruoho }
843 1.1 jruoho
844 1.1 jruoho /* Insert the bits to be preserved */
845 1.1 jruoho
846 1.1 jruoho ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
847 1.1 jruoho
848 1.1 jruoho /* Now we can write the data */
849 1.1 jruoho
850 1.1 jruoho Status = AcpiHwWriteMultiple (Value,
851 1.2 christos &AcpiGbl_FADT.XPm1aControlBlock,
852 1.2 christos &AcpiGbl_FADT.XPm1bControlBlock);
853 1.1 jruoho break;
854 1.1 jruoho
855 1.1 jruoho case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
856 1.1 jruoho /*
857 1.1 jruoho * For control registers, all reserved bits must be preserved,
858 1.1 jruoho * as per the ACPI spec.
859 1.1 jruoho */
860 1.5 christos Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock);
861 1.1 jruoho if (ACPI_FAILURE (Status))
862 1.1 jruoho {
863 1.1 jruoho goto Exit;
864 1.1 jruoho }
865 1.5 christos ReadValue = (UINT32) ReadValue64;
866 1.1 jruoho
867 1.1 jruoho /* Insert the bits to be preserved */
868 1.1 jruoho
869 1.1 jruoho ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
870 1.1 jruoho
871 1.1 jruoho Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
872 1.1 jruoho break;
873 1.1 jruoho
874 1.1 jruoho case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
875 1.1 jruoho
876 1.1 jruoho Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
877 1.1 jruoho break;
878 1.1 jruoho
879 1.1 jruoho case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
880 1.1 jruoho
881 1.1 jruoho /* SMI_CMD is currently always in IO space */
882 1.1 jruoho
883 1.1 jruoho Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
884 1.1 jruoho break;
885 1.1 jruoho
886 1.2 christos default:
887 1.1 jruoho
888 1.1 jruoho ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
889 1.1 jruoho RegisterId));
890 1.1 jruoho Status = AE_BAD_PARAMETER;
891 1.1 jruoho break;
892 1.1 jruoho }
893 1.1 jruoho
894 1.1 jruoho Exit:
895 1.1 jruoho return_ACPI_STATUS (Status);
896 1.1 jruoho }
897 1.1 jruoho
898 1.1 jruoho
899 1.1 jruoho /******************************************************************************
900 1.1 jruoho *
901 1.1 jruoho * FUNCTION: AcpiHwReadMultiple
902 1.1 jruoho *
903 1.1 jruoho * PARAMETERS: Value - Where the register value is returned
904 1.1 jruoho * RegisterA - First ACPI register (required)
905 1.1 jruoho * RegisterB - Second ACPI register (optional)
906 1.1 jruoho *
907 1.1 jruoho * RETURN: Status
908 1.1 jruoho *
909 1.1 jruoho * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
910 1.1 jruoho *
911 1.1 jruoho ******************************************************************************/
912 1.1 jruoho
913 1.1 jruoho static ACPI_STATUS
914 1.1 jruoho AcpiHwReadMultiple (
915 1.1 jruoho UINT32 *Value,
916 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterA,
917 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterB)
918 1.1 jruoho {
919 1.1 jruoho UINT32 ValueA = 0;
920 1.1 jruoho UINT32 ValueB = 0;
921 1.5 christos UINT64 Value64;
922 1.1 jruoho ACPI_STATUS Status;
923 1.1 jruoho
924 1.1 jruoho
925 1.1 jruoho /* The first register is always required */
926 1.1 jruoho
927 1.5 christos Status = AcpiHwRead (&Value64, RegisterA);
928 1.1 jruoho if (ACPI_FAILURE (Status))
929 1.1 jruoho {
930 1.1 jruoho return (Status);
931 1.1 jruoho }
932 1.5 christos ValueA = (UINT32) Value64;
933 1.1 jruoho
934 1.1 jruoho /* Second register is optional */
935 1.1 jruoho
936 1.1 jruoho if (RegisterB->Address)
937 1.1 jruoho {
938 1.5 christos Status = AcpiHwRead (&Value64, RegisterB);
939 1.1 jruoho if (ACPI_FAILURE (Status))
940 1.1 jruoho {
941 1.1 jruoho return (Status);
942 1.1 jruoho }
943 1.5 christos ValueB = (UINT32) Value64;
944 1.1 jruoho }
945 1.1 jruoho
946 1.1 jruoho /*
947 1.1 jruoho * OR the two return values together. No shifting or masking is necessary,
948 1.1 jruoho * because of how the PM1 registers are defined in the ACPI specification:
949 1.1 jruoho *
950 1.1 jruoho * "Although the bits can be split between the two register blocks (each
951 1.1 jruoho * register block has a unique pointer within the FADT), the bit positions
952 1.1 jruoho * are maintained. The register block with unimplemented bits (that is,
953 1.1 jruoho * those implemented in the other register block) always returns zeros,
954 1.1 jruoho * and writes have no side effects"
955 1.1 jruoho */
956 1.1 jruoho *Value = (ValueA | ValueB);
957 1.1 jruoho return (AE_OK);
958 1.1 jruoho }
959 1.1 jruoho
960 1.1 jruoho
961 1.1 jruoho /******************************************************************************
962 1.1 jruoho *
963 1.1 jruoho * FUNCTION: AcpiHwWriteMultiple
964 1.1 jruoho *
965 1.1 jruoho * PARAMETERS: Value - The value to write
966 1.1 jruoho * RegisterA - First ACPI register (required)
967 1.1 jruoho * RegisterB - Second ACPI register (optional)
968 1.1 jruoho *
969 1.1 jruoho * RETURN: Status
970 1.1 jruoho *
971 1.1 jruoho * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
972 1.1 jruoho *
973 1.1 jruoho ******************************************************************************/
974 1.1 jruoho
975 1.1 jruoho static ACPI_STATUS
976 1.1 jruoho AcpiHwWriteMultiple (
977 1.1 jruoho UINT32 Value,
978 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterA,
979 1.1 jruoho ACPI_GENERIC_ADDRESS *RegisterB)
980 1.1 jruoho {
981 1.1 jruoho ACPI_STATUS Status;
982 1.1 jruoho
983 1.1 jruoho
984 1.1 jruoho /* The first register is always required */
985 1.1 jruoho
986 1.1 jruoho Status = AcpiHwWrite (Value, RegisterA);
987 1.1 jruoho if (ACPI_FAILURE (Status))
988 1.1 jruoho {
989 1.1 jruoho return (Status);
990 1.1 jruoho }
991 1.1 jruoho
992 1.1 jruoho /*
993 1.1 jruoho * Second register is optional
994 1.1 jruoho *
995 1.1 jruoho * No bit shifting or clearing is necessary, because of how the PM1
996 1.1 jruoho * registers are defined in the ACPI specification:
997 1.1 jruoho *
998 1.1 jruoho * "Although the bits can be split between the two register blocks (each
999 1.1 jruoho * register block has a unique pointer within the FADT), the bit positions
1000 1.1 jruoho * are maintained. The register block with unimplemented bits (that is,
1001 1.1 jruoho * those implemented in the other register block) always returns zeros,
1002 1.1 jruoho * and writes have no side effects"
1003 1.1 jruoho */
1004 1.1 jruoho if (RegisterB->Address)
1005 1.1 jruoho {
1006 1.1 jruoho Status = AcpiHwWrite (Value, RegisterB);
1007 1.1 jruoho }
1008 1.1 jruoho
1009 1.1 jruoho return (Status);
1010 1.1 jruoho }
1011 1.1 jruoho
1012 1.2 christos #endif /* !ACPI_REDUCED_HARDWARE */
1013