time.c
来自「一个类似windows」· C语言 代码 · 共 357 行
C
357 行
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/time.c
* PURPOSE: Getting time information
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* MACROS and CONSTANTS ******************************************************/
/* macro BCD_INT : convert bcd to int */
#define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f))
/* macro INT_BCD : convert int to bcd */
#define INT_BCD(int) (((int / 10) << 4) + (int % 10))
#define RTC_REGISTER_A 0x0A
#define RTC_REG_A_UIP 0x80 /* Update In Progress bit */
#define RTC_REGISTER_B 0x0B
#define RTC_REGISTER_CENTURY 0x32
/* GLOBALS ******************************************************************/
static KSPIN_LOCK CmosLock = {0};
/* FUNCTIONS *****************************************************************/
static UCHAR
HalpQueryCMOS(UCHAR Reg)
{
UCHAR Val;
ULONG Flags;
Reg |= 0x80;
/* save flags and disable interrupts */
Ki386SaveFlags(Flags);
Ki386DisableInterrupts();
WRITE_PORT_UCHAR((PUCHAR)0x70, Reg);
Val = READ_PORT_UCHAR((PUCHAR)0x71);
WRITE_PORT_UCHAR((PUCHAR)0x70, 0);
/* restore flags */
Ki386RestoreFlags(Flags);
return(Val);
}
static VOID
HalpSetCMOS(UCHAR Reg,
UCHAR Val)
{
ULONG Flags;
Reg |= 0x80;
/* save flags and disable interrupts */
Ki386SaveFlags(Flags);
Ki386DisableInterrupts();
WRITE_PORT_UCHAR((PUCHAR)0x70, Reg);
WRITE_PORT_UCHAR((PUCHAR)0x71, Val);
WRITE_PORT_UCHAR((PUCHAR)0x70, 0);
/* restore flags */
Ki386RestoreFlags(Flags);
}
static UCHAR
HalpQueryECMOS(USHORT Reg)
{
UCHAR Val;
ULONG Flags;
/* save flags and disable interrupts */
Ki386SaveFlags(Flags);
Ki386DisableInterrupts();
WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF));
WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8));
Val = READ_PORT_UCHAR((PUCHAR)0x76);
/* restore flags */
Ki386RestoreFlags(Flags);
return(Val);
}
static VOID
HalpSetECMOS(USHORT Reg,
UCHAR Val)
{
ULONG Flags;
/* save flags and disable interrupts */
Ki386SaveFlags(Flags);
Ki386DisableInterrupts();
WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF));
WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8));
WRITE_PORT_UCHAR((PUCHAR)0x76, Val);
/* restore flags */
Ki386RestoreFlags(Flags);
}
VOID STDCALL
HalQueryRealTimeClock(PTIME_FIELDS Time)
{
KIRQL oldIrql;
KeAcquireSpinLock(&CmosLock, &oldIrql);
/* check 'Update In Progress' bit */
while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP);
Time->Second = BCD_INT(HalpQueryCMOS (0));
Time->Minute = BCD_INT(HalpQueryCMOS (2));
Time->Hour = BCD_INT(HalpQueryCMOS (4));
Time->Weekday = BCD_INT(HalpQueryCMOS (6));
Time->Day = BCD_INT(HalpQueryCMOS (7));
Time->Month = BCD_INT(HalpQueryCMOS (8));
Time->Year = BCD_INT(HalpQueryCMOS (9));
if (Time->Year > 80)
Time->Year += 1900;
else
Time->Year += 2000;
#if 0
/* Century */
Time->Year += BCD_INT(HalpQueryCMOS (RTC_REGISTER_CENTURY)) * 100;
#endif
KeReleaseSpinLock(&CmosLock, oldIrql);
#ifndef NDEBUG
DbgPrint ("HalQueryRealTimeClock() %d:%d:%d %d/%d/%d\n",
Time->Hour,
Time->Minute,
Time->Second,
Time->Day,
Time->Month,
Time->Year
);
#endif
Time->Milliseconds = 0;
}
VOID STDCALL
HalSetRealTimeClock(PTIME_FIELDS Time)
{
KIRQL oldIrql;
KeAcquireSpinLock(&CmosLock, &oldIrql);
/* check 'Update In Progress' bit */
while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP);
HalpSetCMOS (0, (UCHAR)INT_BCD(Time->Second));
HalpSetCMOS (2, (UCHAR)INT_BCD(Time->Minute));
HalpSetCMOS (4, (UCHAR)INT_BCD(Time->Hour));
HalpSetCMOS (6, (UCHAR)INT_BCD(Time->Weekday));
HalpSetCMOS (7, (UCHAR)INT_BCD(Time->Day));
HalpSetCMOS (8, (UCHAR)INT_BCD(Time->Month));
HalpSetCMOS (9, (UCHAR)INT_BCD(Time->Year % 100));
#if 0
/* Century */
HalpSetCMOS (RTC_REGISTER_CENTURY, INT_BCD(Time->Year / 100));
#endif
KeReleaseSpinLock(&CmosLock, oldIrql);
}
BOOLEAN STDCALL
HalGetEnvironmentVariable(PCH Name,
PCH Value,
USHORT ValueLength)
{
KIRQL oldIrql;
if (_stricmp(Name, "LastKnownGood") != 0)
{
return FALSE;
}
KeAcquireSpinLock(&CmosLock, &oldIrql);
if (HalpQueryCMOS(RTC_REGISTER_B) & 0x01)
{
strncpy(Value, "FALSE", ValueLength);
}
else
{
strncpy(Value, "TRUE", ValueLength);
}
KeReleaseSpinLock(&CmosLock, oldIrql);
return TRUE;
}
BOOLEAN STDCALL
HalSetEnvironmentVariable(PCH Name,
PCH Value)
{
UCHAR Val;
KIRQL oldIrql;
BOOLEAN result = TRUE;
if (_stricmp(Name, "LastKnownGood") != 0)
return FALSE;
KeAcquireSpinLock(&CmosLock, &oldIrql);
Val = HalpQueryCMOS(RTC_REGISTER_B);
if (_stricmp(Value, "TRUE") == 0)
HalpSetCMOS(RTC_REGISTER_B, (UCHAR)(Val | 0x01));
else if (_stricmp(Value, "FALSE") == 0)
HalpSetCMOS(RTC_REGISTER_B, (UCHAR)(Val & ~0x01));
else
result = FALSE;
KeReleaseSpinLock(&CmosLock, oldIrql);
return result;
}
ULONG STDCALL
HalpGetCmosData(PBUS_HANDLER BusHandler,
ULONG BusNumber,
ULONG SlotNumber,
PVOID Buffer,
ULONG Offset,
ULONG Length)
{
PUCHAR Ptr = Buffer;
ULONG Address = SlotNumber;
ULONG Len = Length;
KIRQL oldIrql;
DPRINT("HalpGetCmosData() called.\n");
DPRINT(" BusNumber %lu\n", BusNumber);
DPRINT(" SlotNumber %lu\n", SlotNumber);
DPRINT(" Offset 0x%lx\n", Offset);
DPRINT(" Length 0x%lx\n", Length);
if (Length == 0)
return 0;
if (BusNumber == 0)
{
/* CMOS */
KeAcquireSpinLock(&CmosLock, &oldIrql);
while ((Len > 0) && (Address < 0x100))
{
*Ptr = HalpQueryCMOS((UCHAR)Address);
Ptr = Ptr + 1;
Address++;
Len--;
}
KeReleaseSpinLock(&CmosLock, oldIrql);
}
else if (BusNumber == 1)
{
/* Extended CMOS */
KeAcquireSpinLock(&CmosLock, &oldIrql);
while ((Len > 0) && (Address < 0x1000))
{
*Ptr = HalpQueryECMOS((USHORT)Address);
Ptr = Ptr + 1;
Address++;
Len--;
}
KeReleaseSpinLock(&CmosLock, oldIrql);
}
return(Length - Len);
}
ULONG STDCALL
HalpSetCmosData(PBUS_HANDLER BusHandler,
ULONG BusNumber,
ULONG SlotNumber,
PVOID Buffer,
ULONG Offset,
ULONG Length)
{
PUCHAR Ptr = (PUCHAR)Buffer;
ULONG Address = SlotNumber;
ULONG Len = Length;
KIRQL oldIrql;
DPRINT("HalpSetCmosData() called.\n");
DPRINT(" BusNumber %lu\n", BusNumber);
DPRINT(" SlotNumber %lu\n", SlotNumber);
DPRINT(" Offset 0x%lx\n", Offset);
DPRINT(" Length 0x%lx\n", Length);
if (Length == 0)
return 0;
if (BusNumber == 0)
{
/* CMOS */
KeAcquireSpinLock(&CmosLock, &oldIrql);
while ((Len > 0) && (Address < 0x100))
{
HalpSetCMOS((UCHAR)Address, *Ptr);
Ptr = Ptr + 1;
Address++;
Len--;
}
KeReleaseSpinLock(&CmosLock, oldIrql);
}
else if (BusNumber == 1)
{
/* Extended CMOS */
KeAcquireSpinLock(&CmosLock, &oldIrql);
while ((Len > 0) && (Address < 0x1000))
{
HalpSetECMOS((USHORT)Address, *Ptr);
Ptr = Ptr + 1;
Address++;
Len--;
}
KeReleaseSpinLock(&CmosLock, oldIrql);
}
return(Length - Len);
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?