2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/time.c
5 * PURPOSE: Getting time information
9 /* INCLUDES *****************************************************************/
11 #include <ddk/ntddk.h>
17 #include <internal/debug.h>
19 /* MACROS and CONSTANTS ******************************************************/
21 /* macro BCD_INT : convert bcd to int */
22 #define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f))
24 /* macro INT_BCD : convert int to bcd */
25 #define INT_BCD(int) (((int / 10) << 4) + (int % 10))
28 #define RTC_REGISTER_A 0x0A
29 #define RTC_REG_A_UIP 0x80 /* Update In Progress bit */
31 #define RTC_REGISTER_B 0x0B
33 #define RTC_REGISTER_CENTURY 0x32
35 /* GLOBALS ******************************************************************/
37 static KSPIN_LOCK CmosLock = {0};
39 /* FUNCTIONS *****************************************************************/
43 HalpQueryCMOS(UCHAR Reg)
50 __asm__("cli\n"); // AP unsure as to whether to do this here
51 WRITE_PORT_UCHAR((PUCHAR)0x70, Reg);
52 Val = READ_PORT_UCHAR((PUCHAR)0x71);
53 WRITE_PORT_UCHAR((PUCHAR)0x70, 0);
61 HalpSetCMOS(UCHAR Reg,
68 __asm__("cli\n"); // AP unsure as to whether to do this here
69 WRITE_PORT_UCHAR((PUCHAR)0x70, Reg);
70 WRITE_PORT_UCHAR((PUCHAR)0x71, Val);
71 WRITE_PORT_UCHAR((PUCHAR)0x70, 0);
77 HalpQueryECMOS(USHORT Reg)
83 __asm__("cli\n"); // AP unsure as to whether to do this here
84 WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF));
85 WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8));
86 Val = READ_PORT_UCHAR((PUCHAR)0x76);
94 HalpSetECMOS(USHORT Reg,
100 __asm__("cli\n"); // AP unsure as to whether to do this here
101 WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF));
102 WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8));
103 WRITE_PORT_UCHAR((PUCHAR)0x76, Val);
109 HalQueryRealTimeClock(PTIME_FIELDS Time)
113 KeAcquireSpinLock(&CmosLock, &oldIrql);
115 /* check 'Update In Progress' bit */
116 while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP);
118 Time->Second = BCD_INT(HalpQueryCMOS (0));
119 Time->Minute = BCD_INT(HalpQueryCMOS (2));
120 Time->Hour = BCD_INT(HalpQueryCMOS (4));
121 Time->Weekday = BCD_INT(HalpQueryCMOS (6));
122 Time->Day = BCD_INT(HalpQueryCMOS (7));
123 Time->Month = BCD_INT(HalpQueryCMOS (8));
124 Time->Year = BCD_INT(HalpQueryCMOS (9));
133 Time->Year += BCD_INT(HalpQueryCMOS (RTC_REGISTER_CENTURY)) * 100;
136 KeReleaseSpinLock(&CmosLock, oldIrql);
139 DbgPrint ("HalQueryRealTimeClock() %d:%d:%d %d/%d/%d\n",
149 Time->Milliseconds = 0;
154 HalSetRealTimeClock(PTIME_FIELDS Time)
158 KeAcquireSpinLock(&CmosLock, &oldIrql);
160 /* check 'Update In Progress' bit */
161 while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP);
163 HalpSetCMOS (0, INT_BCD(Time->Second));
164 HalpSetCMOS (2, INT_BCD(Time->Minute));
165 HalpSetCMOS (4, INT_BCD(Time->Hour));
166 HalpSetCMOS (6, INT_BCD(Time->Weekday));
167 HalpSetCMOS (7, INT_BCD(Time->Day));
168 HalpSetCMOS (8, INT_BCD(Time->Month));
169 HalpSetCMOS (9, INT_BCD(Time->Year % 100));
173 HalpSetCMOS (RTC_REGISTER_CENTURY, INT_BCD(Time->Year / 100));
175 KeReleaseSpinLock(&CmosLock, oldIrql);
181 HalGetEnvironmentVariable(PCH Name,
188 if (_stricmp(Name, "LastKnownGood") != 0)
193 KeAcquireSpinLock(&CmosLock, &oldIrql);
194 if (HalpQueryCMOS(RTC_REGISTER_B) & 0x01)
196 strncpy(Value, "FALSE", ValueLength);
200 strncpy(Value, "TRUE", ValueLength);
202 KeReleaseSpinLock(&CmosLock, oldIrql);
209 HalSetEnvironmentVariable(PCH Name,
214 BOOLEAN result = TRUE;
216 if (_stricmp(Name, "LastKnownGood") != 0)
219 KeAcquireSpinLock(&CmosLock, &oldIrql);
221 Val = HalpQueryCMOS(RTC_REGISTER_B);
223 if (_stricmp(Value, "TRUE") == 0)
224 HalpSetCMOS(RTC_REGISTER_B, Val | 0x01);
225 else if (_stricmp(Value, "FALSE") == 0)
226 HalpSetCMOS(RTC_REGISTER_B, Val & ~0x01);
230 KeReleaseSpinLock(&CmosLock, oldIrql);
237 HalpGetCmosData(PBUS_HANDLER BusHandler,
245 ULONG Address = SlotNumber;
249 DPRINT("HalpGetCmosData() called.\n");
250 DPRINT(" BusNumber %lu\n", BusNumber);
251 DPRINT(" SlotNumber %lu\n", SlotNumber);
252 DPRINT(" Offset 0x%lx\n", Offset);
253 DPRINT(" Length 0x%lx\n", Length);
261 KeAcquireSpinLock(&CmosLock, &oldIrql);
262 while ((Len > 0) && (Address < 0x100))
264 *Ptr = HalpQueryCMOS((UCHAR)Address);
269 KeReleaseSpinLock(&CmosLock, oldIrql);
271 else if (BusNumber == 1)
274 KeAcquireSpinLock(&CmosLock, &oldIrql);
275 while ((Len > 0) && (Address < 0x1000))
277 *Ptr = HalpQueryECMOS((USHORT)Address);
282 KeReleaseSpinLock(&CmosLock, oldIrql);
285 return(Length - Len);
290 HalpSetCmosData(PBUS_HANDLER BusHandler,
297 PUCHAR Ptr = (PUCHAR)Buffer;
298 ULONG Address = SlotNumber;
302 DPRINT("HalpSetCmosData() called.\n");
303 DPRINT(" BusNumber %lu\n", BusNumber);
304 DPRINT(" SlotNumber %lu\n", SlotNumber);
305 DPRINT(" Offset 0x%lx\n", Offset);
306 DPRINT(" Length 0x%lx\n", Length);
314 KeAcquireSpinLock(&CmosLock, &oldIrql);
315 while ((Len > 0) && (Address < 0x100))
317 HalpSetCMOS((UCHAR)Address, *Ptr);
322 KeReleaseSpinLock(&CmosLock, oldIrql);
324 else if (BusNumber == 1)
327 KeAcquireSpinLock(&CmosLock, &oldIrql);
328 while ((Len > 0) && (Address < 0x1000))
330 HalpSetECMOS((USHORT)Address, *Ptr);
335 KeReleaseSpinLock(&CmosLock, oldIrql);
338 return(Length - Len);