3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/cmos.c
5 * PURPOSE: CMOS Access Routines (Real Time Clock and LastKnownGood)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Timo Kreuzer (timo.kreuzer@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 UCHAR HalpCmosCenturyOffset
;
21 /* PRIVATE FUNCTIONS *********************************************************/
25 HalpReadCmos(IN UCHAR Reg
)
27 /* Select the register */
28 WRITE_PORT_UCHAR(CMOS_CONTROL_PORT
, Reg
);
31 return READ_PORT_UCHAR(CMOS_DATA_PORT
);
36 HalpWriteCmos(IN UCHAR Reg
,
39 /* Select the register */
40 WRITE_PORT_UCHAR(CMOS_CONTROL_PORT
, Reg
);
43 WRITE_PORT_UCHAR(CMOS_DATA_PORT
, Value
);
48 HalpGetCmosData(IN ULONG BusNumber
,
53 PUCHAR Ptr
= (PUCHAR
)Buffer
;
54 ULONG Address
= SlotNumber
;
57 /* Do nothing if we don't have a length */
58 if (!Length
) return 0;
60 /* Acquire CMOS Lock */
61 HalpAcquireSystemHardwareSpinLock();
63 /* Check if this is simple CMOS */
66 /* Loop the buffer up to 0xFF */
67 while ((Len
> 0) && (Address
< 0x100))
70 *Ptr
= HalpReadCmos((UCHAR
)Address
);
72 /* Update position and length */
78 else if (BusNumber
== 1)
80 /* Loop the buffer up to 0xFFFF */
81 while ((Len
> 0) && (Address
< 0x10000))
84 *Ptr
= HalpReadCmos((UCHAR
)Address
);
86 /* Update position and length */
93 /* Release CMOS Lock */
94 HalpReleaseCmosSpinLock();
96 /* Return length read */
102 HalpSetCmosData(IN ULONG BusNumber
,
107 PUCHAR Ptr
= (PUCHAR
)Buffer
;
108 ULONG Address
= SlotNumber
;
111 /* Do nothing if we don't have a length */
112 if (!Length
) return 0;
114 /* Acquire CMOS Lock */
115 HalpAcquireSystemHardwareSpinLock();
117 /* Check if this is simple CMOS */
120 /* Loop the buffer up to 0xFF */
121 while ((Len
> 0) && (Address
< 0x100))
124 HalpWriteCmos((UCHAR
)Address
, *Ptr
);
126 /* Update position and length */
132 else if (BusNumber
== 1)
134 /* Loop the buffer up to 0xFFFF */
135 while ((Len
> 0) && (Address
< 0x10000))
138 HalpWriteCmos((UCHAR
)Address
, *Ptr
);
140 /* Update position and length */
147 /* Release CMOS Lock */
148 HalpReleaseCmosSpinLock();
150 /* Return length read */
156 HalpInitializeCmos(VOID
)
158 /* Set default century offset byte */
159 HalpCmosCenturyOffset
= 50;
161 /* No support for EISA or MCA */
162 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
165 /* PUBLIC FUNCTIONS **********************************************************/
172 HalGetEnvironmentVariable(IN PCH Name
,
173 IN USHORT ValueLength
,
178 /* Only variable supported on x86 */
179 if (_stricmp(Name
, "LastKnownGood")) return ENOENT
;
181 /* Acquire CMOS Lock */
182 HalpAcquireSystemHardwareSpinLock();
184 /* Query the current value */
185 Val
= HalpReadCmos(RTC_REGISTER_B
) & 0x01;
187 /* Release CMOS lock */
188 HalpReleaseCmosSpinLock();
194 strncpy(Value
, "FALSE", ValueLength
);
199 strncpy(Value
, "TRUE", ValueLength
);
211 HalSetEnvironmentVariable(IN PCH Name
,
216 /* Only variable supported on x86 */
217 if (_stricmp(Name
, "LastKnownGood")) return ENOMEM
;
219 /* Check if this is true or false */
220 if (!_stricmp(Value
, "TRUE"))
222 /* It's true, acquire CMOS lock */
223 HalpAcquireSystemHardwareSpinLock();
225 /* Read the current value and add the flag */
226 Val
= HalpReadCmos(RTC_REGISTER_B
) | 1;
228 else if (!_stricmp(Value
, "FALSE"))
230 /* It's false, acquire CMOS lock */
231 HalpAcquireSystemHardwareSpinLock();
233 /* Read the current value and mask out the flag */
234 Val
= HalpReadCmos(RTC_REGISTER_B
) & ~1;
242 /* Write new value */
243 HalpWriteCmos(RTC_REGISTER_B
, Val
);
245 /* Release the lock and return success */
246 HalpReleaseCmosSpinLock();
255 HalQueryRealTimeClock(OUT PTIME_FIELDS Time
)
257 /* Acquire CMOS Lock */
258 HalpAcquireSystemHardwareSpinLock();
260 /* Loop while update is in progress */
261 while ((HalpReadCmos(RTC_REGISTER_A
)) & RTC_REG_A_UIP
);
263 /* Set the time data */
264 Time
->Second
= BCD_INT(HalpReadCmos(0));
265 Time
->Minute
= BCD_INT(HalpReadCmos(2));
266 Time
->Hour
= BCD_INT(HalpReadCmos(4));
267 Time
->Weekday
= BCD_INT(HalpReadCmos(6));
268 Time
->Day
= BCD_INT(HalpReadCmos(7));
269 Time
->Month
= BCD_INT(HalpReadCmos(8));
270 Time
->Year
= BCD_INT(HalpReadCmos(9));
271 Time
->Milliseconds
= 0;
273 /* FIXME: Check century byte */
275 /* Compensate for the century field */
276 Time
->Year
+= (Time
->Year
> 80) ? 1900: 2000;
278 /* Release CMOS lock */
279 HalpReleaseCmosSpinLock();
281 /* Always return TRUE */
290 HalSetRealTimeClock(IN PTIME_FIELDS Time
)
292 /* Acquire CMOS Lock */
293 HalpAcquireSystemHardwareSpinLock();
295 /* Loop while update is in progress */
296 while ((HalpReadCmos(RTC_REGISTER_A
)) & RTC_REG_A_UIP
);
298 /* Write time fields to CMOS RTC */
299 HalpWriteCmos(0, INT_BCD(Time
->Second
));
300 HalpWriteCmos(2, INT_BCD(Time
->Minute
));
301 HalpWriteCmos(4, INT_BCD(Time
->Hour
));
302 HalpWriteCmos(6, INT_BCD(Time
->Weekday
));
303 HalpWriteCmos(7, INT_BCD(Time
->Day
));
304 HalpWriteCmos(8, INT_BCD(Time
->Month
));
305 HalpWriteCmos(9, INT_BCD(Time
->Year
% 100));
307 /* FIXME: Set the century byte */
309 /* Release CMOS lock */
310 HalpReleaseCmosSpinLock();
312 /* Always return TRUE */