Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320/* * PROJECT: ReactOS HAL * LICENSE: GPL - See COPYING in the top level directory * PURPOSE: CMOS Access Routines (Real Time Clock and LastKnownGood) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * Eric Kohl */
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG#include <debug.h>
/* GLOBALS *******************************************************************/
UCHAR HalpCmosCenturyOffset;
/* PRIVATE FUNCTIONS *********************************************************/
_Requires_lock_held_(HalpSystemHardwareLock)UCHARNTAPIHalpReadCmos(IN UCHAR Reg){ /* Select the register (0x80 to disable NMIs) */ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, 0x80 | Reg);
/* Query the value */ return READ_PORT_UCHAR(CMOS_DATA_PORT);}
_Requires_lock_held_(HalpSystemHardwareLock)VOIDNTAPIHalpWriteCmos(IN UCHAR Reg, IN UCHAR Value){ /* Select the register (0x80 to disable NMIs) */ WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, 0x80 | Reg);
/* Write the value */ WRITE_PORT_UCHAR(CMOS_DATA_PORT, Value);}
ULONGNTAPIHalpGetCmosData( _In_ ULONG BusNumber, _In_ ULONG SlotNumber, _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length){ PUCHAR Ptr = (PUCHAR)Buffer; ULONG Address = SlotNumber; ULONG Len = Length;
/* Do nothing if we don't have a length */ if (!Length) return 0;
/* Acquire CMOS Lock */ HalpAcquireCmosSpinLock();
/* Check if this is simple CMOS */ if (BusNumber == 0) { /* Loop the buffer up to 0xFF */ while ((Len > 0) && (Address < 0x100)) { /* Read the data */ *Ptr = HalpReadCmos((UCHAR)Address);
/* Update position and length */ Ptr++; Address++; Len--; } } else if (BusNumber == 1) { /* Loop the buffer up to 0xFFFF */ while ((Len > 0) && (Address < 0x10000)) { /* Write the data */ *Ptr = HalpReadCmos((UCHAR)Address);
/* Update position and length */ Ptr++; Address++; Len--; } }
/* Release CMOS Lock */ HalpReleaseCmosSpinLock();
/* Return length read */ return Length - Len;}
ULONGNTAPIHalpSetCmosData( _In_ ULONG BusNumber, _In_ ULONG SlotNumber, _In_reads_bytes_(Length) PVOID Buffer, _In_ ULONG Length){ PUCHAR Ptr = (PUCHAR)Buffer; ULONG Address = SlotNumber; ULONG Len = Length;
/* Do nothing if we don't have a length */ if (!Length) return 0;
/* Acquire CMOS Lock */ HalpAcquireCmosSpinLock();
/* Check if this is simple CMOS */ if (BusNumber == 0) { /* Loop the buffer up to 0xFF */ while ((Len > 0) && (Address < 0x100)) { /* Write the data */ HalpWriteCmos((UCHAR)Address, *Ptr);
/* Update position and length */ Ptr++; Address++; Len--; } } else if (BusNumber == 1) { /* Loop the buffer up to 0xFFFF */ while ((Len > 0) && (Address < 0x10000)) { /* Write the data */ HalpWriteCmos((UCHAR)Address, *Ptr);
/* Update position and length */ Ptr++; Address++; Len--; } }
/* Release CMOS Lock */ HalpReleaseCmosSpinLock();
/* Return length read */ return Length - Len;}
CODE_SEG("INIT")VOIDNTAPIHalpInitializeCmos(VOID){ /* Set default century offset byte */ HalpCmosCenturyOffset = 50;
/* No support for EISA or MCA */ ASSERT(HalpBusType == MACHINE_TYPE_ISA);}
/* PUBLIC FUNCTIONS **********************************************************/
/* * @implemented */ARC_STATUSNTAPIHalGetEnvironmentVariable( _In_ PCH Name, _In_ USHORT ValueLength, _Out_writes_z_(ValueLength) PCH Value){ UCHAR Val;
/* Only variable supported on x86 */ if (_stricmp(Name, "LastKnownGood")) return ENOENT;
/* Acquire CMOS Lock */ HalpAcquireCmosSpinLock();
/* Query the current value */ Val = HalpReadCmos(RTC_REGISTER_B) & 0x01;
/* Release CMOS lock */ HalpReleaseCmosSpinLock();
/* Check the flag */ if (Val) { /* Return false */ strncpy(Value, "FALSE", ValueLength); } else { /* Return true */ strncpy(Value, "TRUE", ValueLength); }
/* Return success */ return ESUCCESS;}
/* * @implemented */ARC_STATUSNTAPIHalSetEnvironmentVariable(IN PCH Name, IN PCH Value){ UCHAR Val;
/* Only variable supported on x86 */ if (_stricmp(Name, "LastKnownGood")) return ENOMEM;
/* Check if this is true or false */ if (!_stricmp(Value, "TRUE")) { /* It's true, acquire CMOS lock */ HalpAcquireCmosSpinLock();
/* Read the current value and add the flag */ Val = HalpReadCmos(RTC_REGISTER_B) | 1; } else if (!_stricmp(Value, "FALSE")) { /* It's false, acquire CMOS lock */ HalpAcquireCmosSpinLock();
/* Read the current value and mask out the flag */ Val = HalpReadCmos(RTC_REGISTER_B) & ~1; } else { /* Fail */ return ENOMEM; }
/* Write new value */ HalpWriteCmos(RTC_REGISTER_B, Val);
/* Release the lock and return success */ HalpReleaseCmosSpinLock(); return ESUCCESS;}
/* * @implemented */BOOLEANNTAPIHalQueryRealTimeClock(OUT PTIME_FIELDS Time){ /* Acquire CMOS Lock */ HalpAcquireCmosSpinLock();
/* Loop while update is in progress */ while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);
/* Set the time data */ Time->Second = BCD_INT(HalpReadCmos(0)); Time->Minute = BCD_INT(HalpReadCmos(2)); Time->Hour = BCD_INT(HalpReadCmos(4)); Time->Weekday = BCD_INT(HalpReadCmos(6)); Time->Day = BCD_INT(HalpReadCmos(7)); Time->Month = BCD_INT(HalpReadCmos(8)); Time->Year = BCD_INT(HalpReadCmos(9)); Time->Milliseconds = 0;
/* FIXME: Check century byte */
/* Compensate for the century field */ Time->Year += (Time->Year > 80) ? 1900: 2000;
/* Release CMOS lock */ HalpReleaseCmosSpinLock();
/* Always return TRUE */ return TRUE;}
/* * @implemented */BOOLEANNTAPIHalSetRealTimeClock(IN PTIME_FIELDS Time){ /* Acquire CMOS Lock */ HalpAcquireCmosSpinLock();
/* Loop while update is in progress */ while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);
/* Write time fields to CMOS RTC */ HalpWriteCmos(0, INT_BCD(Time->Second)); HalpWriteCmos(2, INT_BCD(Time->Minute)); HalpWriteCmos(4, INT_BCD(Time->Hour)); HalpWriteCmos(6, INT_BCD(Time->Weekday)); HalpWriteCmos(7, INT_BCD(Time->Day)); HalpWriteCmos(8, INT_BCD(Time->Month)); HalpWriteCmos(9, INT_BCD(Time->Year % 100));
/* FIXME: Set the century byte */
/* Release CMOS lock */ HalpReleaseCmosSpinLock();
/* Always return TRUE */ return TRUE;}