3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 This is a generic template for a child of the IchSmm driver.
25 #include "SmmPlatform.h"
26 #include <Protocol/CpuIo2.h>
37 EFI_PCI_BUS_MASTER mPciBm
[] = {
38 { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS
, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1
},
39 { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS
, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2
},
40 { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS
, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3
},
41 { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS
, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4
},
42 { PCI_DEVICE_NUMBER_PCH_USB
, PCI_FUNCTION_NUMBER_PCH_EHCI
}
47 SYSTEM_CONFIGURATION mSystemConfiguration
;
48 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
;
49 EFI_GLOBAL_NVS_AREA_PROTOCOL
*mGlobalNvsAreaPtr
;
51 UINT16 mPM1_SaveState16
;
52 UINT32 mGPE_SaveState32
;
54 BOOLEAN mSetSmmVariableProtocolSmiAllowed
= TRUE
;
58 // Variables. Need to initialize this from Setup
60 BOOLEAN mWakeOnLanS5Variable
;
61 BOOLEAN mWakeOnRtcVariable
;
68 // Use an enum. 0 is Stay Off, 1 is Last State, 2 is Stay On
70 UINT8 mAcLossVariable
;
74 UINT8 mTco1Sources
[] = {
80 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
87 InitRuntimeScriptTable (
88 IN EFI_SYSTEM_TABLE
*SystemTable
92 S5SleepWakeOnRtcCallBack (
93 IN EFI_HANDLE DispatchHandle
,
94 IN EFI_SMM_SX_DISPATCH_CONTEXT
*DispatchContext
117 Initializes the SMM Handler Driver
127 InitializePlatformSmm (
128 IN EFI_HANDLE ImageHandle
,
129 IN EFI_SYSTEM_TABLE
*SystemTable
135 EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT PowerButtonContext
;
136 EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL
*PowerButtonDispatch
;
137 EFI_SMM_ICHN_DISPATCH_CONTEXT IchnContext
;
138 EFI_SMM_ICHN_DISPATCH_PROTOCOL
*IchnDispatch
;
139 EFI_SMM_SX_DISPATCH_PROTOCOL
*SxDispatch
;
140 EFI_SMM_SX_DISPATCH_CONTEXT EntryDispatchContext
;
141 EFI_SMM_SW_DISPATCH_PROTOCOL
*SwDispatch
;
142 EFI_SMM_SW_DISPATCH_CONTEXT SwContext
;
144 EFI_BOOT_MODE BootMode
;
149 // Locate the Global NVS Protocol.
151 Status
= gBS
->LocateProtocol (
152 &gEfiGlobalNvsAreaProtocolGuid
,
154 (void **)&mGlobalNvsAreaPtr
156 ASSERT_EFI_ERROR (Status
);
160 // Get the ACPI Base Address
163 mAcpiBaseAddr
= PchLpcPciCfg16( R_PCH_LPC_ACPI_BASE
) & B_PCH_LPC_ACPI_BASE_BAR
;
165 VarSize
= sizeof(SYSTEM_CONFIGURATION
);
166 Status
= SystemTable
->RuntimeServices
->GetVariable(
168 &gEfiSetupVariableGuid
,
171 &mSystemConfiguration
173 if (!EFI_ERROR(Status
)) {
174 mAcLossVariable
= mSystemConfiguration
.StateAfterG3
;
177 // If LAN is disabled, WOL function should be disabled too.
179 if (mSystemConfiguration
.Lan
== 0x01){
180 mWakeOnLanS5Variable
= mSystemConfiguration
.WakeOnLanS5
;
182 mWakeOnLanS5Variable
= FALSE
;
185 mWakeOnRtcVariable
= mSystemConfiguration
.WakeOnRtcS5
;
188 BootMode
= GetBootModeHob ();
191 // Get the Power Button protocol
193 Status
= gBS
->LocateProtocol(
194 &gEfiSmmPowerButtonDispatchProtocolGuid
,
196 (void **)&PowerButtonDispatch
198 ASSERT_EFI_ERROR(Status
);
200 if (BootMode
!= BOOT_ON_FLASH_UPDATE
) {
202 // Register for the power button event
204 PowerButtonContext
.Phase
= PowerButtonEntry
;
205 Status
= PowerButtonDispatch
->Register(
211 ASSERT_EFI_ERROR(Status
);
214 // Get the Sx dispatch protocol
216 Status
= gBS
->LocateProtocol (
217 &gEfiSmmSxDispatchProtocolGuid
,
221 ASSERT_EFI_ERROR(Status
);
224 // Register entry phase call back function
226 EntryDispatchContext
.Type
= SxS3
;
227 EntryDispatchContext
.Phase
= SxEntry
;
229 Status
= SxDispatch
->Register (
231 (EFI_SMM_SX_DISPATCH
)SxSleepEntryCallBack
,
232 &EntryDispatchContext
,
237 EntryDispatchContext
.Type
= SxS4
;
239 Status
= SxDispatch
->Register (
242 &EntryDispatchContext
,
245 ASSERT_EFI_ERROR(Status
);
248 EntryDispatchContext
.Type
= SxS5
;
250 Status
= SxDispatch
->Register (
253 &EntryDispatchContext
,
256 ASSERT_EFI_ERROR(Status
);
258 Status
= SxDispatch
->Register (
260 S5SleepAcLossCallBack
,
261 &EntryDispatchContext
,
264 ASSERT_EFI_ERROR(Status
);
267 // Get the Sw dispatch protocol
269 Status
= gBS
->LocateProtocol (
270 &gEfiSmmSwDispatchProtocolGuid
,
274 ASSERT_EFI_ERROR(Status
);
277 // Register ACPI enable handler
279 SwContext
.SwSmiInputValue
= ACPI_ENABLE
;
280 Status
= SwDispatch
->Register (
286 ASSERT_EFI_ERROR(Status
);
289 // Register ACPI disable handler
291 SwContext
.SwSmiInputValue
= ACPI_DISABLE
;
292 Status
= SwDispatch
->Register (
298 ASSERT_EFI_ERROR(Status
);
302 // Register for SmmReadyToBootCallback
304 SwContext
.SwSmiInputValue
= SMI_SET_SMMVARIABLE_PROTOCOL
;
305 Status
= SwDispatch
->Register(
307 SmmReadyToBootCallback
,
311 ASSERT_EFI_ERROR(Status
);
314 // Get the ICHn protocol
316 Status
= gBS
->LocateProtocol(
317 &gEfiSmmIchnDispatchProtocolGuid
,
319 (void **)&IchnDispatch
321 ASSERT_EFI_ERROR(Status
);
324 // Register for the events that may happen that we do not care.
325 // This is true for SMI related to TCO since TCO is enabled by BIOS WP
327 for (Index
= 0; Index
< sizeof(mTco1Sources
)/sizeof(UINT8
); Index
++) {
328 IchnContext
.Type
= mTco1Sources
[Index
];
329 Status
= IchnDispatch
->Register(
331 (EFI_SMM_ICHN_DISPATCH
)DummyTco1Callback
,
335 ASSERT_EFI_ERROR( Status
);
341 IoWrite16( mAcpiBaseAddr
+ R_PCH_TCO_CNT
, IoRead16( mAcpiBaseAddr
+ R_PCH_TCO_CNT
) | B_PCH_TCO_CNT_LOCK
);
344 // Set to power on from G3 dependent on WOL instead of AC Loss variable in order to support WOL from G3 feature.
347 // Set wake from G3 dependent on AC Loss variable and Wake On LAN variable.
348 // This is because no matter how, if WOL enabled or AC Loss variable not disabled, the board needs to wake from G3 to program the LAN WOL settings.
349 // This needs to be done after LAN enable/disable so that the PWR_FLR state clear not impacted the WOL from G3 feature.
351 if (mAcLossVariable
!= 0x00) {
354 SetAfterG3On (FALSE
);
365 SmmReadyToBootCallback (
366 IN EFI_HANDLE DispatchHandle
,
367 IN EFI_SMM_SW_DISPATCH_CONTEXT
*DispatchContext
372 if (mSetSmmVariableProtocolSmiAllowed
)
375 // It is okay to use gBS->LocateProtocol here because
376 // we are still in trusted execution.
378 Status
= gBS
->LocateProtocol(
379 &gEfiSmmVariableProtocolGuid
,
381 (void **)&mSmmVariable
384 ASSERT_EFI_ERROR(Status
);
387 // mSetSmmVariableProtocolSmiAllowed will prevent this function from
388 // being executed more than 1 time.
390 mSetSmmVariableProtocolSmiAllowed
= FALSE
;
397 @param DispatchHandle The handle of this callback, obtained when registering
398 @param DispatchContext The predefined context which contained sleep type and phase
401 @retval EFI_SUCCESS Operation successfully performed
406 SxSleepEntryCallBack (
407 IN EFI_HANDLE DispatchHandle
,
408 IN EFI_SMM_SX_DISPATCH_CONTEXT
*DispatchContext
413 Status
= SaveRuntimeScriptTable ();
414 if (EFI_ERROR(Status
)) {
419 // Workaround for S3 wake hang if C State is enabled
421 CpuSmmSxWorkAround();
432 MsrValue
= AsmReadMsr64 (0xE2);
434 if (MsrValue
& BIT15
) {
438 if (MsrValue
& BIT10
) {
440 AsmWriteMsr64 (0xE2, MsrValue
);
451 for (Index
= 0; Index
< sizeof(mPciBm
)/sizeof(EFI_PCI_BUS_MASTER
); Index
++) {
452 Command
= MmioRead8 (
454 DEFAULT_PCI_BUS_NUMBER_PCH
,
455 mPciBm
[Index
].Device
,
456 mPciBm
[Index
].Function
,
460 Command
&= ~EFI_PCI_COMMAND_BUS_MASTER
;
463 DEFAULT_PCI_BUS_NUMBER_PCH
,
464 mPciBm
[Index
].Device
,
465 mPciBm
[Index
].Function
,
475 Set the AC Loss to turn on or off.
486 // ICH handling portion
488 PmCon1
= MmioRead8 ( PMC_BASE_ADDRESS
+ R_PCH_PMC_GEN_PMCON_1
);
489 PmCon1
&= ~B_PCH_PMC_GEN_PMCON_AFTERG3_EN
;
491 PmCon1
|= B_PCH_PMC_GEN_PMCON_AFTERG3_EN
;
493 MmioWrite8 (PMC_BASE_ADDRESS
+ R_PCH_PMC_GEN_PMCON_1
, PmCon1
);
498 When a power button event happens, it shuts off the machine
503 PowerButtonCallback (
504 IN EFI_HANDLE DispatchHandle
,
505 IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT
*DispatchContext
509 // Check what the state to return to after AC Loss. If Last State, then
514 if (mWakeOnRtcVariable
) {
518 if (mAcLossVariable
== 1) {
525 // Program clock chip
530 data16
= (UINT16
)(IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_EN
));
531 data16
&= B_PCH_ACPI_GPE0a_EN_PCI_EXP
;
535 // Clear Sleep SMI Status
537 IoWrite16 (mAcpiBaseAddr
+ R_PCH_SMI_STS
,
538 (UINT16
)(IoRead16 (mAcpiBaseAddr
+ R_PCH_SMI_STS
) | B_PCH_SMI_STS_ON_SLP_EN
));
540 // Clear Sleep Type Enable
542 IoWrite16 (mAcpiBaseAddr
+ R_PCH_SMI_EN
,
543 (UINT16
)(IoRead16 (mAcpiBaseAddr
+ R_PCH_SMI_EN
) & (~B_PCH_SMI_EN_ON_SLP_EN
)));
546 // Clear Power Button Status
548 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_STS
, B_PCH_ACPI_PM1_STS_PWRBTN
);
553 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_CNT
, V_PCH_ACPI_PM1_CNT_S5
);
554 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_CNT
, B_PCH_ACPI_PM1_CNT_SLP_EN
| V_PCH_ACPI_PM1_CNT_S5
);
564 @param DispatchHandle - The handle of this callback, obtained when registering
566 @param DispatchContext - The predefined context which contained sleep type and phase
571 S5SleepAcLossCallBack (
572 IN EFI_HANDLE DispatchHandle
,
573 IN EFI_SMM_SX_DISPATCH_CONTEXT
*DispatchContext
577 // Check what the state to return to after AC Loss. If Last State, then
580 if (mAcLossVariable
== 1) {
587 @param DispatchHandle The handle of this callback, obtained when registering
588 @param DispatchContext The predefined context which contained sleep type and phase
590 @retval Clears the Save State bit in the clock.
596 IN EFI_HANDLE DispatchHandle
,
597 IN EFI_SMM_SX_DISPATCH_CONTEXT
*DispatchContext
604 // Enable/Disable USB Charging
606 if (mSystemConfiguration
.UsbCharging
== 0x01) {
607 Data32
= IoRead32 (GPIO_BASE_ADDRESS
+ R_PCH_GPIO_SC_LVL
);
609 IoWrite32(GPIO_BASE_ADDRESS
+ R_PCH_GPIO_SC_LVL
, Data32
);
621 SMI handler to enable ACPI mode
623 Dispatched on reads from APM port with value 0xA0
625 Disables the SW SMI Timer.
626 ACPI events are disabled and ACPI event status is cleared.
627 SCI mode is then enabled.
631 Clear all ACPI event status and disable all ACPI events
632 Disable PM sources except power button
641 Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm")
645 @param DispatchHandle - EFI Handle
646 @param DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
654 IN EFI_HANDLE DispatchHandle
,
655 IN EFI_SMM_SW_DISPATCH_CONTEXT
*DispatchContext
664 // Disable SW SMI Timer
666 SmiEn
= IoRead32(mAcpiBaseAddr
+ R_PCH_SMI_EN
);
667 SmiEn
&= ~B_PCH_SMI_STS_SWSMI_TMR
;
668 IoWrite32(mAcpiBaseAddr
+ R_PCH_SMI_EN
, SmiEn
);
670 wordValue
= IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_STS
);
671 if(wordValue
& B_PCH_ACPI_PM1_STS_WAK
) {
672 IoWrite32((mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_EN
), 0x0000);
673 IoWrite32((mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_STS
), 0xffffffff);
676 mPM1_SaveState16
= IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_EN
);
679 // Disable PM sources except power button
681 // power button is enabled only for PCAT. Disabled it on Tablet platform
683 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_EN
, B_PCH_ACPI_PM1_EN_PWRBTN
);
684 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_STS
, 0xffff);
686 mGPE_SaveState32
= IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_EN
);
687 IoWrite32(mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_EN
, 0x0000);
688 IoWrite32(mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_STS
, 0xffffffff);
693 // Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm")
694 // Clear Status D reg VM bit, Date of month Alarm to make Data in CMOS RAM is no longer Valid
696 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_D
);
697 IoWrite8 (PCAT_RTC_DATA_REGISTER
, 0x0);
700 RegData32
= IoRead32(ACPI_BASE_ADDRESS
+ R_PCH_ALT_GP_SMI_EN
);
701 RegData32
&= ~(BIT7
);
702 IoWrite32((ACPI_BASE_ADDRESS
+ R_PCH_ALT_GP_SMI_EN
), RegData32
);
708 Pm1Cnt
= IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_CNT
);
709 Pm1Cnt
|= B_PCH_ACPI_PM1_CNT_SCI_EN
;
710 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_CNT
, Pm1Cnt
);
716 SMI handler to disable ACPI mode
718 Dispatched on reads from APM port with value 0xA1
720 ACPI events are disabled and ACPI event status is cleared.
721 SCI mode is then disabled.
722 Clear all ACPI event status and disable all ACPI events
723 Disable PM sources except power button
731 @param DispatchHandle - EFI Handle
732 @param DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
739 DisableAcpiCallback (
740 IN EFI_HANDLE DispatchHandle
,
741 IN EFI_SMM_SW_DISPATCH_CONTEXT
*DispatchContext
746 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_STS
, 0xffff);
747 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_EN
, mPM1_SaveState16
);
749 IoWrite32(mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_STS
, 0xffffffff);
750 IoWrite32(mAcpiBaseAddr
+ R_PCH_ACPI_GPE0a_EN
, mGPE_SaveState32
);
755 Pm1Cnt
= IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_CNT
);
756 Pm1Cnt
&= ~B_PCH_ACPI_PM1_CNT_SCI_EN
;
757 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_CNT
, Pm1Cnt
);
762 When an unknown event happen.
769 IN EFI_HANDLE DispatchHandle
,
770 IN EFI_SMM_ICHN_DISPATCH_CONTEXT
*DispatchContext
777 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
780 EFI_DEVICE_PATH_PROTOCOL
*Start
;
782 if (DevicePath
== NULL
) {
787 // Search for the end of the device path structure
790 while (!IsDevicePathEnd (DevicePath
)) {
791 DevicePath
= NextDevicePathNode (DevicePath
);
795 // Compute the size and add back in the size of the end device path structure
797 return ((UINTN
)DevicePath
- (UINTN
)Start
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
);
802 @param DispatchHandle The handle of this callback, obtained when registering
803 @param DispatchContext The predefined context which contained sleep type and phase
807 S5SleepWakeOnRtcCallBack (
808 IN EFI_HANDLE DispatchHandle
,
809 IN EFI_SMM_SX_DISPATCH_CONTEXT
*DispatchContext
817 @retval 1. Check Alarm interrupt is not set.
818 2. Clear Alarm interrupt.
819 2. Set RTC wake up date and time.
820 2. Enable RTC wake up alarm.
821 3. Enable ICH PM1 EN Bit 10(RTC_EN)
833 // make sure EFI_SMM_VARIABLE_PROTOCOL is available
839 VarSize
= sizeof(SYSTEM_CONFIGURATION
);
842 // read the variable into the buffer
844 Status
= mSmmVariable
->SmmGetVariable(
846 &gEfiSetupVariableGuid
,
849 &mSystemConfiguration
851 if (EFI_ERROR(Status
) || (!mSystemConfiguration
.WakeOnRtcS5
)) {
854 mWakeupDay
= HexToBcd((UINT8
)mSystemConfiguration
.RTCWakeupDate
);
855 mWakeupHour
= HexToBcd((UINT8
)mSystemConfiguration
.RTCWakeupTimeHour
);
856 mWakeupMinute
= HexToBcd((UINT8
)mSystemConfiguration
.RTCWakeupTimeMinute
);
857 mWakeupSecond
= HexToBcd((UINT8
)mSystemConfiguration
.RTCWakeupTimeSecond
);
860 // Check RTC alarm interrupt is enabled. If enabled, someone already
861 // grabbed RTC alarm. Just return.
863 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_B
);
864 if(IoRead8(PCAT_RTC_DATA_REGISTER
) & B_RTC_ALARM_INT_ENABLE
){
871 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_D
);
872 CmosData
= IoRead8(PCAT_RTC_DATA_REGISTER
);
873 CmosData
&= ~(B_RTC_DATE_ALARM_MASK
);
874 CmosData
|= mWakeupDay
;
875 for(i
= 0 ; i
< 0xffff ; i
++){
876 IoWrite8(PCAT_RTC_DATA_REGISTER
, CmosData
);
878 if(((CmosData
= IoRead8(PCAT_RTC_DATA_REGISTER
)) & B_RTC_DATE_ALARM_MASK
)
887 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_SECOND_ALARM
);
888 for(i
= 0 ; i
< 0xffff ; i
++){
889 IoWrite8(PCAT_RTC_DATA_REGISTER
, mWakeupSecond
);
891 if(IoRead8(PCAT_RTC_DATA_REGISTER
) == mWakeupSecond
){
899 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_MINUTE_ALARM
);
900 for(i
= 0 ; i
< 0xffff ; i
++){
901 IoWrite8(PCAT_RTC_DATA_REGISTER
, mWakeupMinute
);
903 if(IoRead8(PCAT_RTC_DATA_REGISTER
) == mWakeupMinute
){
911 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_HOUR_ALARM
);
912 for(i
= 0 ; i
< 0xffff ; i
++){
913 IoWrite8(PCAT_RTC_DATA_REGISTER
, mWakeupHour
);
915 if(IoRead8(PCAT_RTC_DATA_REGISTER
) == mWakeupHour
){
921 // Wait for UIP to arm RTC alarm
923 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_A
);
924 while (IoRead8(PCAT_RTC_DATA_REGISTER
) & 0x80);
927 // Read RTC register 0C to clear pending RTC interrupts
929 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_C
);
930 IoRead8(PCAT_RTC_DATA_REGISTER
);
933 // Enable RTC Alarm Interrupt
935 IoWrite8(PCAT_RTC_ADDRESS_REGISTER
, RTC_ADDRESS_REGISTER_B
);
936 IoWrite8(PCAT_RTC_DATA_REGISTER
, IoRead8(PCAT_RTC_DATA_REGISTER
) | B_RTC_ALARM_INT_ENABLE
);
939 // Clear ICH RTC Status
941 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_STS
, B_PCH_ACPI_PM1_STS_RTC
);
944 // Enable ICH RTC event
946 IoWrite16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_EN
,
947 (UINT16
)(IoRead16(mAcpiBaseAddr
+ R_PCH_ACPI_PM1_EN
) | B_PCH_ACPI_PM1_EN_RTC
));
958 HighByte
= (UINTN
)HexValue
/ 10;
959 LowByte
= (UINTN
)HexValue
% 10;
961 return ((UINT8
)(LowByte
+ (HighByte
<< 4)));
972 HighByte
= (UINTN
)((BcdValue
>> 4) * 10);
973 LowByte
= (UINTN
)(BcdValue
& 0x0F);
975 return ((UINT8
)(LowByte
+ HighByte
));