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 *****************************************************************/
16 /* MACROS and CONSTANTS ******************************************************/
18 /* macro BCD_INT : convert bcd to int */
19 #define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f))
21 /* macro INT_BCD : convert int to bcd */
22 #define INT_BCD(int) (((int / 10) << 4) + (int % 10))
25 #define RTC_REGISTER_A 0x0A
26 #define RTC_REG_A_UIP 0x80 /* Update In Progress bit */
28 #define RTC_REGISTER_B 0x0B
30 #define RTC_REGISTER_CENTURY 0x32
32 /* GLOBALS ******************************************************************/
34 static KSPIN_LOCK CmosLock
= {0};
36 /* FUNCTIONS *****************************************************************/
40 HalpQueryCMOS(UCHAR Reg
)
47 /* save flags and disable interrupts */
48 Ki386SaveFlags(Flags
);
49 Ki386DisableInterrupts();
51 WRITE_PORT_UCHAR((PUCHAR
)0x70, Reg
);
52 Val
= READ_PORT_UCHAR((PUCHAR
)0x71);
53 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0);
56 Ki386RestoreFlags(Flags
);
63 HalpSetCMOS(UCHAR Reg
,
70 /* save flags and disable interrupts */
71 Ki386SaveFlags(Flags
);
72 Ki386DisableInterrupts();
74 WRITE_PORT_UCHAR((PUCHAR
)0x70, Reg
);
75 WRITE_PORT_UCHAR((PUCHAR
)0x71, Val
);
76 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0);
79 Ki386RestoreFlags(Flags
);
84 HalpQueryECMOS(USHORT Reg
)
89 /* save flags and disable interrupts */
90 Ki386SaveFlags(Flags
);
91 Ki386DisableInterrupts();
93 WRITE_PORT_UCHAR((PUCHAR
)0x74, (UCHAR
)(Reg
& 0x00FF));
94 WRITE_PORT_UCHAR((PUCHAR
)0x75, (UCHAR
)(Reg
>>8));
95 Val
= READ_PORT_UCHAR((PUCHAR
)0x76);
98 Ki386RestoreFlags(Flags
);
105 HalpSetECMOS(USHORT Reg
,
110 /* save flags and disable interrupts */
111 Ki386SaveFlags(Flags
);
112 Ki386DisableInterrupts();
114 WRITE_PORT_UCHAR((PUCHAR
)0x74, (UCHAR
)(Reg
& 0x00FF));
115 WRITE_PORT_UCHAR((PUCHAR
)0x75, (UCHAR
)(Reg
>>8));
116 WRITE_PORT_UCHAR((PUCHAR
)0x76, Val
);
119 Ki386RestoreFlags(Flags
);
124 HalQueryRealTimeClock(PTIME_FIELDS Time
)
128 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
130 /* check 'Update In Progress' bit */
131 while (HalpQueryCMOS (RTC_REGISTER_A
) & RTC_REG_A_UIP
);
133 Time
->Second
= BCD_INT(HalpQueryCMOS (0));
134 Time
->Minute
= BCD_INT(HalpQueryCMOS (2));
135 Time
->Hour
= BCD_INT(HalpQueryCMOS (4));
136 Time
->Weekday
= BCD_INT(HalpQueryCMOS (6));
137 Time
->Day
= BCD_INT(HalpQueryCMOS (7));
138 Time
->Month
= BCD_INT(HalpQueryCMOS (8));
139 Time
->Year
= BCD_INT(HalpQueryCMOS (9));
148 Time
->Year
+= BCD_INT(HalpQueryCMOS (RTC_REGISTER_CENTURY
)) * 100;
151 KeReleaseSpinLock(&CmosLock
, oldIrql
);
154 DbgPrint ("HalQueryRealTimeClock() %d:%d:%d %d/%d/%d\n",
164 Time
->Milliseconds
= 0;
169 HalSetRealTimeClock(PTIME_FIELDS Time
)
173 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
175 /* check 'Update In Progress' bit */
176 while (HalpQueryCMOS (RTC_REGISTER_A
) & RTC_REG_A_UIP
);
178 HalpSetCMOS (0, (UCHAR
)INT_BCD(Time
->Second
));
179 HalpSetCMOS (2, (UCHAR
)INT_BCD(Time
->Minute
));
180 HalpSetCMOS (4, (UCHAR
)INT_BCD(Time
->Hour
));
181 HalpSetCMOS (6, (UCHAR
)INT_BCD(Time
->Weekday
));
182 HalpSetCMOS (7, (UCHAR
)INT_BCD(Time
->Day
));
183 HalpSetCMOS (8, (UCHAR
)INT_BCD(Time
->Month
));
184 HalpSetCMOS (9, (UCHAR
)INT_BCD(Time
->Year
% 100));
188 HalpSetCMOS (RTC_REGISTER_CENTURY
, INT_BCD(Time
->Year
/ 100));
190 KeReleaseSpinLock(&CmosLock
, oldIrql
);
196 HalGetEnvironmentVariable(PCH Name
,
203 if (_stricmp(Name
, "LastKnownGood") != 0)
208 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
209 if (HalpQueryCMOS(RTC_REGISTER_B
) & 0x01)
211 strncpy(Value
, "FALSE", ValueLength
);
215 strncpy(Value
, "TRUE", ValueLength
);
217 KeReleaseSpinLock(&CmosLock
, oldIrql
);
224 HalSetEnvironmentVariable(PCH Name
,
229 BOOLEAN result
= TRUE
;
231 if (_stricmp(Name
, "LastKnownGood") != 0)
234 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
236 Val
= HalpQueryCMOS(RTC_REGISTER_B
);
238 if (_stricmp(Value
, "TRUE") == 0)
239 HalpSetCMOS(RTC_REGISTER_B
, (UCHAR
)(Val
| 0x01));
240 else if (_stricmp(Value
, "FALSE") == 0)
241 HalpSetCMOS(RTC_REGISTER_B
, (UCHAR
)(Val
& ~0x01));
245 KeReleaseSpinLock(&CmosLock
, oldIrql
);
252 HalpGetCmosData(PBUS_HANDLER BusHandler
,
260 ULONG Address
= SlotNumber
;
264 DPRINT("HalpGetCmosData() called.\n");
265 DPRINT(" BusNumber %lu\n", BusNumber
);
266 DPRINT(" SlotNumber %lu\n", SlotNumber
);
267 DPRINT(" Offset 0x%lx\n", Offset
);
268 DPRINT(" Length 0x%lx\n", Length
);
276 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
277 while ((Len
> 0) && (Address
< 0x100))
279 *Ptr
= HalpQueryCMOS((UCHAR
)Address
);
284 KeReleaseSpinLock(&CmosLock
, oldIrql
);
286 else if (BusNumber
== 1)
289 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
290 while ((Len
> 0) && (Address
< 0x1000))
292 *Ptr
= HalpQueryECMOS((USHORT
)Address
);
297 KeReleaseSpinLock(&CmosLock
, oldIrql
);
300 return(Length
- Len
);
305 HalpSetCmosData(PBUS_HANDLER BusHandler
,
312 PUCHAR Ptr
= (PUCHAR
)Buffer
;
313 ULONG Address
= SlotNumber
;
317 DPRINT("HalpSetCmosData() called.\n");
318 DPRINT(" BusNumber %lu\n", BusNumber
);
319 DPRINT(" SlotNumber %lu\n", SlotNumber
);
320 DPRINT(" Offset 0x%lx\n", Offset
);
321 DPRINT(" Length 0x%lx\n", Length
);
329 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
330 while ((Len
> 0) && (Address
< 0x100))
332 HalpSetCMOS((UCHAR
)Address
, *Ptr
);
337 KeReleaseSpinLock(&CmosLock
, oldIrql
);
339 else if (BusNumber
== 1)
342 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
343 while ((Len
> 0) && (Address
< 0x1000))
345 HalpSetECMOS((USHORT
)Address
, *Ptr
);
350 KeReleaseSpinLock(&CmosLock
, oldIrql
);
353 return(Length
- Len
);