1
2 /*******************************************************************************
3 *
4 * Module Name: hwregs - Read/write access functions for the various ACPI
5 * control and status registers.
6 *
7 ******************************************************************************/
8
9 /*
10 * Copyright (C) 2000 - 2011, Intel Corp.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions, and the following disclaimer,
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20 * substantially similar to the "NO WARRANTY" disclaimer below
21 * ("Disclaimer") and any redistribution must be conditioned upon
22 * including a substantially similar Disclaimer requirement for further
23 * binary redistribution.
24 * 3. Neither the names of the above-listed copyright holders nor the names
25 * of any contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * Alternatively, this software may be distributed under the terms of the
29 * GNU General Public License ("GPL") version 2 as published by the Free
30 * Software Foundation.
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGES.
44 */
45
46 #define __HWREGS_C__
47
48 #include "acpi.h"
49 #include "accommon.h"
50 #include "acevents.h"
51
52 #define _COMPONENT ACPI_HARDWARE
53 ACPI_MODULE_NAME ("hwregs")
54
55
56 /* Local Prototypes */
57
58 static ACPI_STATUS
59 AcpiHwReadMultiple (
60 UINT32 *Value,
61 ACPI_GENERIC_ADDRESS *RegisterA,
62 ACPI_GENERIC_ADDRESS *RegisterB);
63
64 static ACPI_STATUS
65 AcpiHwWriteMultiple (
66 UINT32 Value,
67 ACPI_GENERIC_ADDRESS *RegisterA,
68 ACPI_GENERIC_ADDRESS *RegisterB);
69
70
71 /******************************************************************************
72 *
73 * FUNCTION: AcpiHwValidateRegister
74 *
75 * PARAMETERS: Reg - GAS register structure
76 * MaxBitWidth - Max BitWidth supported (32 or 64)
77 * Address - Pointer to where the gas->address
78 * is returned
79 *
80 * RETURN: Status
81 *
82 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
83 * pointer, Address, SpaceId, BitWidth, and BitOffset.
84 *
85 ******************************************************************************/
86
87 ACPI_STATUS
88 AcpiHwValidateRegister (
89 ACPI_GENERIC_ADDRESS *Reg,
153 * RETURN: Status
154 *
155 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
156 * version of AcpiRead, used internally since the overhead of
157 * 64-bit values is not needed.
158 *
159 * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
160 * BitWidth must be exactly 8, 16, or 32.
161 * SpaceID must be SystemMemory or SystemIO.
162 * BitOffset and AccessWidth are currently ignored, as there has
163 * not been a need to implement these.
164 *
165 ******************************************************************************/
166
167 ACPI_STATUS
168 AcpiHwRead (
169 UINT32 *Value,
170 ACPI_GENERIC_ADDRESS *Reg)
171 {
172 UINT64 Address;
173 ACPI_STATUS Status;
174
175
176 ACPI_FUNCTION_NAME (HwRead);
177
178
179 /* Validate contents of the GAS register */
180
181 Status = AcpiHwValidateRegister (Reg, 32, &Address);
182 if (ACPI_FAILURE (Status))
183 {
184 return (Status);
185 }
186
187 /* Initialize entire 32-bit return value to zero */
188
189 *Value = 0;
190
191 /*
192 * Two address spaces supported: Memory or IO. PCI_Config is
193 * not supported here because the GAS structure is insufficient
194 */
195 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
196 {
197 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
198 Address, Value, Reg->BitWidth);
199 }
200 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
201 {
202 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
203 Address, Value, Reg->BitWidth);
204 }
205
206 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
207 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
208 *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
209 AcpiUtGetRegionName (Reg->SpaceId)));
210
211 return (Status);
212 }
213
214
215 /******************************************************************************
216 *
217 * FUNCTION: AcpiHwWrite
218 *
237
238
239 ACPI_FUNCTION_NAME (HwWrite);
240
241
242 /* Validate contents of the GAS register */
243
244 Status = AcpiHwValidateRegister (Reg, 32, &Address);
245 if (ACPI_FAILURE (Status))
246 {
247 return (Status);
248 }
249
250 /*
251 * Two address spaces supported: Memory or IO. PCI_Config is
252 * not supported here because the GAS structure is insufficient
253 */
254 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
255 {
256 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
257 Address, Value, Reg->BitWidth);
258 }
259 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
260 {
261 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
262 Address, Value, Reg->BitWidth);
263 }
264
265 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
266 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
267 Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
268 AcpiUtGetRegionName (Reg->SpaceId)));
269
270 return (Status);
271 }
272
273
274 /*******************************************************************************
275 *
276 * FUNCTION: AcpiHwClearAcpiStatus
277 *
278 * PARAMETERS: None
279 *
280 * RETURN: Status
281 *
282 * DESCRIPTION: Clears all fixed and general purpose status bits
283 *
284 ******************************************************************************/
285
286 ACPI_STATUS
287 AcpiHwClearAcpiStatus (
288 void)
289 {
290 ACPI_STATUS Status;
291 ACPI_CPU_FLAGS LockFlags = 0;
292
293
304
305 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
306 ACPI_BITMASK_ALL_FIXED_STATUS);
307 if (ACPI_FAILURE (Status))
308 {
309 goto UnlockAndExit;
310 }
311
312 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
313
314 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
315
316 UnlockAndExit:
317 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
318 return_ACPI_STATUS (Status);
319 }
320
321
322 /*******************************************************************************
323 *
324 * FUNCTION: AcpiHwGetRegisterBitMask
325 *
326 * PARAMETERS: RegisterId - Index of ACPI Register to access
327 *
328 * RETURN: The bitmask to be used when accessing the register
329 *
330 * DESCRIPTION: Map RegisterId into a register bitmask.
331 *
332 ******************************************************************************/
333
334 ACPI_BIT_REGISTER_INFO *
335 AcpiHwGetBitRegisterInfo (
336 UINT32 RegisterId)
337 {
338 ACPI_FUNCTION_ENTRY ();
339
340
341 if (RegisterId > ACPI_BITREG_MAX)
342 {
343 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
344 return (NULL);
407 AcpiHwRegisterRead (
408 UINT32 RegisterId,
409 UINT32 *ReturnValue)
410 {
411 UINT32 Value = 0;
412 ACPI_STATUS Status;
413
414
415 ACPI_FUNCTION_TRACE (HwRegisterRead);
416
417
418 switch (RegisterId)
419 {
420 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
421
422 Status = AcpiHwReadMultiple (&Value,
423 &AcpiGbl_XPm1aStatus,
424 &AcpiGbl_XPm1bStatus);
425 break;
426
427
428 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
429
430 Status = AcpiHwReadMultiple (&Value,
431 &AcpiGbl_XPm1aEnable,
432 &AcpiGbl_XPm1bEnable);
433 break;
434
435
436 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
437
438 Status = AcpiHwReadMultiple (&Value,
439 &AcpiGbl_FADT.XPm1aControlBlock,
440 &AcpiGbl_FADT.XPm1bControlBlock);
441
442 /*
443 * Zero the write-only bits. From the ACPI specification, "Hardware
444 * Write-Only Bits": "Upon reads to registers with write-only bits,
445 * software masks out all write-only bits."
446 */
447 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
448 break;
449
450
451 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
452
453 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
454 break;
455
456
457 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
458
459 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
460 break;
461
462
463 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
464
465 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
466 break;
467
468
469 default:
470 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
471 RegisterId));
472 Status = AE_BAD_PARAMETER;
473 break;
474 }
475
476 if (ACPI_SUCCESS (Status))
477 {
478 *ReturnValue = Value;
479 }
480
481 return_ACPI_STATUS (Status);
482 }
483
484
485 /******************************************************************************
486 *
487 * FUNCTION: AcpiHwRegisterWrite
488 *
489 * PARAMETERS: RegisterId - ACPI Register ID
523 switch (RegisterId)
524 {
525 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
526 /*
527 * Handle the "ignored" bit in PM1 Status. According to the ACPI
528 * specification, ignored bits are to be preserved when writing.
529 * Normally, this would mean a read/modify/write sequence. However,
530 * preserving a bit in the status register is different. Writing a
531 * one clears the status, and writing a zero preserves the status.
532 * Therefore, we must always write zero to the ignored bit.
533 *
534 * This behavior is clarified in the ACPI 4.0 specification.
535 */
536 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
537
538 Status = AcpiHwWriteMultiple (Value,
539 &AcpiGbl_XPm1aStatus,
540 &AcpiGbl_XPm1bStatus);
541 break;
542
543
544 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
545
546 Status = AcpiHwWriteMultiple (Value,
547 &AcpiGbl_XPm1aEnable,
548 &AcpiGbl_XPm1bEnable);
549 break;
550
551
552 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
553
554 /*
555 * Perform a read first to preserve certain bits (per ACPI spec)
556 * Note: This includes SCI_EN, we never want to change this bit
557 */
558 Status = AcpiHwReadMultiple (&ReadValue,
559 &AcpiGbl_FADT.XPm1aControlBlock,
560 &AcpiGbl_FADT.XPm1bControlBlock);
561 if (ACPI_FAILURE (Status))
562 {
563 goto Exit;
564 }
565
566 /* Insert the bits to be preserved */
567
568 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
569
570 /* Now we can write the data */
571
572 Status = AcpiHwWriteMultiple (Value,
573 &AcpiGbl_FADT.XPm1aControlBlock,
574 &AcpiGbl_FADT.XPm1bControlBlock);
575 break;
576
577
578 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
579
580 /*
581 * For control registers, all reserved bits must be preserved,
582 * as per the ACPI spec.
583 */
584 Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
585 if (ACPI_FAILURE (Status))
586 {
587 goto Exit;
588 }
589
590 /* Insert the bits to be preserved */
591
592 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
593
594 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
595 break;
596
597
598 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
599
600 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
601 break;
602
603
604 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
605
606 /* SMI_CMD is currently always in IO space */
607
608 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
609 break;
610
611
612 default:
613 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
614 RegisterId));
615 Status = AE_BAD_PARAMETER;
616 break;
617 }
618
619 Exit:
620 return_ACPI_STATUS (Status);
621 }
622
623
624 /******************************************************************************
625 *
626 * FUNCTION: AcpiHwReadMultiple
627 *
628 * PARAMETERS: Value - Where the register value is returned
629 * RegisterA - First ACPI register (required)
630 * RegisterB - Second ACPI register (optional)
631 *
632 * RETURN: Status
714 /*
715 * Second register is optional
716 *
717 * No bit shifting or clearing is necessary, because of how the PM1
718 * registers are defined in the ACPI specification:
719 *
720 * "Although the bits can be split between the two register blocks (each
721 * register block has a unique pointer within the FADT), the bit positions
722 * are maintained. The register block with unimplemented bits (that is,
723 * those implemented in the other register block) always returns zeros,
724 * and writes have no side effects"
725 */
726 if (RegisterB->Address)
727 {
728 Status = AcpiHwWrite (Value, RegisterB);
729 }
730
731 return (Status);
732 }
733
|
1 /*******************************************************************************
2 *
3 * Module Name: hwregs - Read/write access functions for the various ACPI
4 * control and status registers.
5 *
6 ******************************************************************************/
7
8 /*
9 * Copyright (C) 2000 - 2014, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45 #define __HWREGS_C__
46
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acevents.h"
50
51 #define _COMPONENT ACPI_HARDWARE
52 ACPI_MODULE_NAME ("hwregs")
53
54
55 #if (!ACPI_REDUCED_HARDWARE)
56
57 /* Local Prototypes */
58
59 static ACPI_STATUS
60 AcpiHwReadMultiple (
61 UINT32 *Value,
62 ACPI_GENERIC_ADDRESS *RegisterA,
63 ACPI_GENERIC_ADDRESS *RegisterB);
64
65 static ACPI_STATUS
66 AcpiHwWriteMultiple (
67 UINT32 Value,
68 ACPI_GENERIC_ADDRESS *RegisterA,
69 ACPI_GENERIC_ADDRESS *RegisterB);
70
71 #endif /* !ACPI_REDUCED_HARDWARE */
72
73 /******************************************************************************
74 *
75 * FUNCTION: AcpiHwValidateRegister
76 *
77 * PARAMETERS: Reg - GAS register structure
78 * MaxBitWidth - Max BitWidth supported (32 or 64)
79 * Address - Pointer to where the gas->address
80 * is returned
81 *
82 * RETURN: Status
83 *
84 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
85 * pointer, Address, SpaceId, BitWidth, and BitOffset.
86 *
87 ******************************************************************************/
88
89 ACPI_STATUS
90 AcpiHwValidateRegister (
91 ACPI_GENERIC_ADDRESS *Reg,
155 * RETURN: Status
156 *
157 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
158 * version of AcpiRead, used internally since the overhead of
159 * 64-bit values is not needed.
160 *
161 * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
162 * BitWidth must be exactly 8, 16, or 32.
163 * SpaceID must be SystemMemory or SystemIO.
164 * BitOffset and AccessWidth are currently ignored, as there has
165 * not been a need to implement these.
166 *
167 ******************************************************************************/
168
169 ACPI_STATUS
170 AcpiHwRead (
171 UINT32 *Value,
172 ACPI_GENERIC_ADDRESS *Reg)
173 {
174 UINT64 Address;
175 UINT64 Value64;
176 ACPI_STATUS Status;
177
178
179 ACPI_FUNCTION_NAME (HwRead);
180
181
182 /* Validate contents of the GAS register */
183
184 Status = AcpiHwValidateRegister (Reg, 32, &Address);
185 if (ACPI_FAILURE (Status))
186 {
187 return (Status);
188 }
189
190 /* Initialize entire 32-bit return value to zero */
191
192 *Value = 0;
193
194 /*
195 * Two address spaces supported: Memory or IO. PCI_Config is
196 * not supported here because the GAS structure is insufficient
197 */
198 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
199 {
200 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
201 Address, &Value64, Reg->BitWidth);
202
203 *Value = (UINT32) Value64;
204 }
205 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
206 {
207 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
208 Address, Value, Reg->BitWidth);
209 }
210
211 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
212 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
213 *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
214 AcpiUtGetRegionName (Reg->SpaceId)));
215
216 return (Status);
217 }
218
219
220 /******************************************************************************
221 *
222 * FUNCTION: AcpiHwWrite
223 *
242
243
244 ACPI_FUNCTION_NAME (HwWrite);
245
246
247 /* Validate contents of the GAS register */
248
249 Status = AcpiHwValidateRegister (Reg, 32, &Address);
250 if (ACPI_FAILURE (Status))
251 {
252 return (Status);
253 }
254
255 /*
256 * Two address spaces supported: Memory or IO. PCI_Config is
257 * not supported here because the GAS structure is insufficient
258 */
259 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
260 {
261 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
262 Address, (UINT64) Value, Reg->BitWidth);
263 }
264 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
265 {
266 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
267 Address, Value, Reg->BitWidth);
268 }
269
270 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
271 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
272 Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
273 AcpiUtGetRegionName (Reg->SpaceId)));
274
275 return (Status);
276 }
277
278
279 #if (!ACPI_REDUCED_HARDWARE)
280 /*******************************************************************************
281 *
282 * FUNCTION: AcpiHwClearAcpiStatus
283 *
284 * PARAMETERS: None
285 *
286 * RETURN: Status
287 *
288 * DESCRIPTION: Clears all fixed and general purpose status bits
289 *
290 ******************************************************************************/
291
292 ACPI_STATUS
293 AcpiHwClearAcpiStatus (
294 void)
295 {
296 ACPI_STATUS Status;
297 ACPI_CPU_FLAGS LockFlags = 0;
298
299
310
311 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
312 ACPI_BITMASK_ALL_FIXED_STATUS);
313 if (ACPI_FAILURE (Status))
314 {
315 goto UnlockAndExit;
316 }
317
318 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
319
320 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
321
322 UnlockAndExit:
323 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
324 return_ACPI_STATUS (Status);
325 }
326
327
328 /*******************************************************************************
329 *
330 * FUNCTION: AcpiHwGetBitRegisterInfo
331 *
332 * PARAMETERS: RegisterId - Index of ACPI Register to access
333 *
334 * RETURN: The bitmask to be used when accessing the register
335 *
336 * DESCRIPTION: Map RegisterId into a register bitmask.
337 *
338 ******************************************************************************/
339
340 ACPI_BIT_REGISTER_INFO *
341 AcpiHwGetBitRegisterInfo (
342 UINT32 RegisterId)
343 {
344 ACPI_FUNCTION_ENTRY ();
345
346
347 if (RegisterId > ACPI_BITREG_MAX)
348 {
349 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
350 return (NULL);
413 AcpiHwRegisterRead (
414 UINT32 RegisterId,
415 UINT32 *ReturnValue)
416 {
417 UINT32 Value = 0;
418 ACPI_STATUS Status;
419
420
421 ACPI_FUNCTION_TRACE (HwRegisterRead);
422
423
424 switch (RegisterId)
425 {
426 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
427
428 Status = AcpiHwReadMultiple (&Value,
429 &AcpiGbl_XPm1aStatus,
430 &AcpiGbl_XPm1bStatus);
431 break;
432
433 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
434
435 Status = AcpiHwReadMultiple (&Value,
436 &AcpiGbl_XPm1aEnable,
437 &AcpiGbl_XPm1bEnable);
438 break;
439
440 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
441
442 Status = AcpiHwReadMultiple (&Value,
443 &AcpiGbl_FADT.XPm1aControlBlock,
444 &AcpiGbl_FADT.XPm1bControlBlock);
445
446 /*
447 * Zero the write-only bits. From the ACPI specification, "Hardware
448 * Write-Only Bits": "Upon reads to registers with write-only bits,
449 * software masks out all write-only bits."
450 */
451 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
452 break;
453
454 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
455
456 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
457 break;
458
459 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
460
461 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
462 break;
463
464 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
465
466 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
467 break;
468
469 default:
470
471 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
472 RegisterId));
473 Status = AE_BAD_PARAMETER;
474 break;
475 }
476
477 if (ACPI_SUCCESS (Status))
478 {
479 *ReturnValue = Value;
480 }
481
482 return_ACPI_STATUS (Status);
483 }
484
485
486 /******************************************************************************
487 *
488 * FUNCTION: AcpiHwRegisterWrite
489 *
490 * PARAMETERS: RegisterId - ACPI Register ID
524 switch (RegisterId)
525 {
526 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
527 /*
528 * Handle the "ignored" bit in PM1 Status. According to the ACPI
529 * specification, ignored bits are to be preserved when writing.
530 * Normally, this would mean a read/modify/write sequence. However,
531 * preserving a bit in the status register is different. Writing a
532 * one clears the status, and writing a zero preserves the status.
533 * Therefore, we must always write zero to the ignored bit.
534 *
535 * This behavior is clarified in the ACPI 4.0 specification.
536 */
537 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
538
539 Status = AcpiHwWriteMultiple (Value,
540 &AcpiGbl_XPm1aStatus,
541 &AcpiGbl_XPm1bStatus);
542 break;
543
544 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
545
546 Status = AcpiHwWriteMultiple (Value,
547 &AcpiGbl_XPm1aEnable,
548 &AcpiGbl_XPm1bEnable);
549 break;
550
551 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
552 /*
553 * Perform a read first to preserve certain bits (per ACPI spec)
554 * Note: This includes SCI_EN, we never want to change this bit
555 */
556 Status = AcpiHwReadMultiple (&ReadValue,
557 &AcpiGbl_FADT.XPm1aControlBlock,
558 &AcpiGbl_FADT.XPm1bControlBlock);
559 if (ACPI_FAILURE (Status))
560 {
561 goto Exit;
562 }
563
564 /* Insert the bits to be preserved */
565
566 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
567
568 /* Now we can write the data */
569
570 Status = AcpiHwWriteMultiple (Value,
571 &AcpiGbl_FADT.XPm1aControlBlock,
572 &AcpiGbl_FADT.XPm1bControlBlock);
573 break;
574
575 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
576 /*
577 * For control registers, all reserved bits must be preserved,
578 * as per the ACPI spec.
579 */
580 Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
581 if (ACPI_FAILURE (Status))
582 {
583 goto Exit;
584 }
585
586 /* Insert the bits to be preserved */
587
588 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
589
590 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
591 break;
592
593 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
594
595 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
596 break;
597
598 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
599
600 /* SMI_CMD is currently always in IO space */
601
602 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
603 break;
604
605 default:
606
607 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
608 RegisterId));
609 Status = AE_BAD_PARAMETER;
610 break;
611 }
612
613 Exit:
614 return_ACPI_STATUS (Status);
615 }
616
617
618 /******************************************************************************
619 *
620 * FUNCTION: AcpiHwReadMultiple
621 *
622 * PARAMETERS: Value - Where the register value is returned
623 * RegisterA - First ACPI register (required)
624 * RegisterB - Second ACPI register (optional)
625 *
626 * RETURN: Status
708 /*
709 * Second register is optional
710 *
711 * No bit shifting or clearing is necessary, because of how the PM1
712 * registers are defined in the ACPI specification:
713 *
714 * "Although the bits can be split between the two register blocks (each
715 * register block has a unique pointer within the FADT), the bit positions
716 * are maintained. The register block with unimplemented bits (that is,
717 * those implemented in the other register block) always returns zeros,
718 * and writes have no side effects"
719 */
720 if (RegisterB->Address)
721 {
722 Status = AcpiHwWrite (Value, RegisterB);
723 }
724
725 return (Status);
726 }
727
728 #endif /* !ACPI_REDUCED_HARDWARE */
|