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 /* save flags and disable interrupts */
51 Ki386SaveFlags(Flags
);
52 Ki386DisableInterrupts();
54 WRITE_PORT_UCHAR((PUCHAR
)0x70, Reg
);
55 Val
= READ_PORT_UCHAR((PUCHAR
)0x71);
56 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0);
59 Ki386RestoreFlags(Flags
);
66 HalpSetCMOS(UCHAR Reg
,
73 /* save flags and disable interrupts */
74 Ki386SaveFlags(Flags
);
75 Ki386DisableInterrupts();
77 WRITE_PORT_UCHAR((PUCHAR
)0x70, Reg
);
78 WRITE_PORT_UCHAR((PUCHAR
)0x71, Val
);
79 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0);
82 Ki386RestoreFlags(Flags
);
87 HalpQueryECMOS(USHORT Reg
)
92 /* save flags and disable interrupts */
93 Ki386SaveFlags(Flags
);
94 Ki386DisableInterrupts();
96 WRITE_PORT_UCHAR((PUCHAR
)0x74, (UCHAR
)(Reg
& 0x00FF));
97 WRITE_PORT_UCHAR((PUCHAR
)0x75, (UCHAR
)(Reg
>>8));
98 Val
= READ_PORT_UCHAR((PUCHAR
)0x76);
101 Ki386RestoreFlags(Flags
);
108 HalpSetECMOS(USHORT Reg
,
113 /* save flags and disable interrupts */
114 Ki386SaveFlags(Flags
);
115 Ki386DisableInterrupts();
117 WRITE_PORT_UCHAR((PUCHAR
)0x74, (UCHAR
)(Reg
& 0x00FF));
118 WRITE_PORT_UCHAR((PUCHAR
)0x75, (UCHAR
)(Reg
>>8));
119 WRITE_PORT_UCHAR((PUCHAR
)0x76, Val
);
122 Ki386RestoreFlags(Flags
);
127 HalQueryRealTimeClock(PTIME_FIELDS Time
)
131 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
133 /* check 'Update In Progress' bit */
134 while (HalpQueryCMOS (RTC_REGISTER_A
) & RTC_REG_A_UIP
);
136 Time
->Second
= BCD_INT(HalpQueryCMOS (0));
137 Time
->Minute
= BCD_INT(HalpQueryCMOS (2));
138 Time
->Hour
= BCD_INT(HalpQueryCMOS (4));
139 Time
->Weekday
= BCD_INT(HalpQueryCMOS (6));
140 Time
->Day
= BCD_INT(HalpQueryCMOS (7));
141 Time
->Month
= BCD_INT(HalpQueryCMOS (8));
142 Time
->Year
= BCD_INT(HalpQueryCMOS (9));
151 Time
->Year
+= BCD_INT(HalpQueryCMOS (RTC_REGISTER_CENTURY
)) * 100;
154 KeReleaseSpinLock(&CmosLock
, oldIrql
);
157 DbgPrint ("HalQueryRealTimeClock() %d:%d:%d %d/%d/%d\n",
167 Time
->Milliseconds
= 0;
172 HalSetRealTimeClock(PTIME_FIELDS Time
)
176 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
178 /* check 'Update In Progress' bit */
179 while (HalpQueryCMOS (RTC_REGISTER_A
) & RTC_REG_A_UIP
);
181 HalpSetCMOS (0, (UCHAR
)INT_BCD(Time
->Second
));
182 HalpSetCMOS (2, (UCHAR
)INT_BCD(Time
->Minute
));
183 HalpSetCMOS (4, (UCHAR
)INT_BCD(Time
->Hour
));
184 HalpSetCMOS (6, (UCHAR
)INT_BCD(Time
->Weekday
));
185 HalpSetCMOS (7, (UCHAR
)INT_BCD(Time
->Day
));
186 HalpSetCMOS (8, (UCHAR
)INT_BCD(Time
->Month
));
187 HalpSetCMOS (9, (UCHAR
)INT_BCD(Time
->Year
% 100));
191 HalpSetCMOS (RTC_REGISTER_CENTURY
, INT_BCD(Time
->Year
/ 100));
193 KeReleaseSpinLock(&CmosLock
, oldIrql
);
199 HalGetEnvironmentVariable(PCH Name
,
206 if (_stricmp(Name
, "LastKnownGood") != 0)
211 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
212 if (HalpQueryCMOS(RTC_REGISTER_B
) & 0x01)
214 strncpy(Value
, "FALSE", ValueLength
);
218 strncpy(Value
, "TRUE", ValueLength
);
220 KeReleaseSpinLock(&CmosLock
, oldIrql
);
227 HalSetEnvironmentVariable(PCH Name
,
232 BOOLEAN result
= TRUE
;
234 if (_stricmp(Name
, "LastKnownGood") != 0)
237 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
239 Val
= HalpQueryCMOS(RTC_REGISTER_B
);
241 if (_stricmp(Value
, "TRUE") == 0)
242 HalpSetCMOS(RTC_REGISTER_B
, (UCHAR
)(Val
| 0x01));
243 else if (_stricmp(Value
, "FALSE") == 0)
244 HalpSetCMOS(RTC_REGISTER_B
, (UCHAR
)(Val
& ~0x01));
248 KeReleaseSpinLock(&CmosLock
, oldIrql
);
255 HalpGetCmosData(PBUS_HANDLER BusHandler
,
263 ULONG Address
= SlotNumber
;
267 DPRINT("HalpGetCmosData() called.\n");
268 DPRINT(" BusNumber %lu\n", BusNumber
);
269 DPRINT(" SlotNumber %lu\n", SlotNumber
);
270 DPRINT(" Offset 0x%lx\n", Offset
);
271 DPRINT(" Length 0x%lx\n", Length
);
279 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
280 while ((Len
> 0) && (Address
< 0x100))
282 *Ptr
= HalpQueryCMOS((UCHAR
)Address
);
287 KeReleaseSpinLock(&CmosLock
, oldIrql
);
289 else if (BusNumber
== 1)
292 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
293 while ((Len
> 0) && (Address
< 0x1000))
295 *Ptr
= HalpQueryECMOS((USHORT
)Address
);
300 KeReleaseSpinLock(&CmosLock
, oldIrql
);
303 return(Length
- Len
);
308 HalpSetCmosData(PBUS_HANDLER BusHandler
,
315 PUCHAR Ptr
= (PUCHAR
)Buffer
;
316 ULONG Address
= SlotNumber
;
320 DPRINT("HalpSetCmosData() called.\n");
321 DPRINT(" BusNumber %lu\n", BusNumber
);
322 DPRINT(" SlotNumber %lu\n", SlotNumber
);
323 DPRINT(" Offset 0x%lx\n", Offset
);
324 DPRINT(" Length 0x%lx\n", Length
);
332 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
333 while ((Len
> 0) && (Address
< 0x100))
335 HalpSetCMOS((UCHAR
)Address
, *Ptr
);
340 KeReleaseSpinLock(&CmosLock
, oldIrql
);
342 else if (BusNumber
== 1)
345 KeAcquireSpinLock(&CmosLock
, &oldIrql
);
346 while ((Len
> 0) && (Address
< 0x1000))
348 HalpSetECMOS((USHORT
)Address
, *Ptr
);
353 KeReleaseSpinLock(&CmosLock
, oldIrql
);
356 return(Length
- Len
);