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
);