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)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 UCHAR HalpCmosCenturyOffset
;
20 /* PRIVATE FUNCTIONS *********************************************************/
24 HalpReadCmos(IN UCHAR Reg
)
26 /* Select the register */
27 WRITE_PORT_UCHAR(CMOS_CONTROL_PORT
, Reg
);
30 return READ_PORT_UCHAR(CMOS_DATA_PORT
);
35 HalpWriteCmos(IN UCHAR Reg
,
38 /* Select the register */
39 WRITE_PORT_UCHAR(CMOS_CONTROL_PORT
, Reg
);
42 WRITE_PORT_UCHAR(CMOS_DATA_PORT
, Value
);
47 HalpGetCmosData(IN ULONG BusNumber
,
52 PUCHAR Ptr
= (PUCHAR
)Buffer
;
53 ULONG Address
= SlotNumber
;
56 /* Do nothing if we don't have a length */
57 if (!Length
) return 0;
59 /* Acquire CMOS Lock */
60 HalpAcquireSystemHardwareSpinLock();
62 /* Check if this is simple CMOS */
65 /* Loop the buffer up to 0xFF */
66 while ((Len
> 0) && (Address
< 0x100))
69 *Ptr
= HalpReadCmos((UCHAR
)Address
);
71 /* Update position and length */
77 else if (BusNumber
== 1)
79 /* Loop the buffer up to 0xFFFF */
80 while ((Len
> 0) && (Address
< 0x10000))
83 *Ptr
= HalpReadCmos((UCHAR
)Address
);
85 /* Update position and length */
92 /* Release CMOS Lock */
93 HalpReleaseCmosSpinLock();
95 /* Return length read */
101 HalpSetCmosData(IN ULONG BusNumber
,
106 PUCHAR Ptr
= (PUCHAR
)Buffer
;
107 ULONG Address
= SlotNumber
;
110 /* Do nothing if we don't have a length */
111 if (!Length
) return 0;
113 /* Acquire CMOS Lock */
114 HalpAcquireSystemHardwareSpinLock();
116 /* Check if this is simple CMOS */
119 /* Loop the buffer up to 0xFF */
120 while ((Len
> 0) && (Address
< 0x100))
123 HalpWriteCmos((UCHAR
)Address
, *Ptr
);
125 /* Update position and length */
131 else if (BusNumber
== 1)
133 /* Loop the buffer up to 0xFFFF */
134 while ((Len
> 0) && (Address
< 0x10000))
137 HalpWriteCmos((UCHAR
)Address
, *Ptr
);
139 /* Update position and length */
146 /* Release CMOS Lock */
147 HalpReleaseCmosSpinLock();
149 /* Return length read */
155 HalpInitializeCmos(VOID
)
157 /* Set default century offset byte */
158 HalpCmosCenturyOffset
= 50;
160 /* No support for EISA or MCA */
161 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
164 /* PUBLIC FUNCTIONS **********************************************************/
171 HalGetEnvironmentVariable(IN PCH Name
,
172 IN USHORT ValueLength
,
177 /* Only variable supported on x86 */
178 if (_stricmp(Name
, "LastKnownGood")) return ENOENT
;
180 /* Acquire CMOS Lock */
181 HalpAcquireSystemHardwareSpinLock();
183 /* Query the current value */
184 Val
= HalpReadCmos(RTC_REGISTER_B
) & 0x01;
186 /* Release CMOS lock */
187 HalpReleaseCmosSpinLock();
193 strncpy(Value
, "FALSE", ValueLength
);
198 strncpy(Value
, "TRUE", ValueLength
);
210 HalSetEnvironmentVariable(IN PCH Name
,
215 /* Only variable supported on x86 */
216 if (_stricmp(Name
, "LastKnownGood")) return ENOMEM
;
218 /* Check if this is true or false */
219 if (!_stricmp(Value
, "TRUE"))
221 /* It's true, acquire CMOS lock */
222 HalpAcquireSystemHardwareSpinLock();
224 /* Read the current value and add the flag */
225 Val
= HalpReadCmos(RTC_REGISTER_B
) | 1;
227 else if (!_stricmp(Value
, "FALSE"))
229 /* It's false, acquire CMOS lock */
230 HalpAcquireSystemHardwareSpinLock();
232 /* Read the current value and mask out the flag */
233 Val
= HalpReadCmos(RTC_REGISTER_B
) & ~1;
241 /* Write new value */
242 HalpWriteCmos(RTC_REGISTER_B
, Val
);
244 /* Release the lock and return success */
245 HalpReleaseCmosSpinLock();
254 HalQueryRealTimeClock(OUT PTIME_FIELDS Time
)
256 /* Acquire CMOS Lock */
257 HalpAcquireSystemHardwareSpinLock();
259 /* Loop while update is in progress */
260 while ((HalpReadCmos(RTC_REGISTER_A
)) & RTC_REG_A_UIP
);
262 /* Set the time data */
263 Time
->Second
= BCD_INT(HalpReadCmos(0));
264 Time
->Minute
= BCD_INT(HalpReadCmos(2));
265 Time
->Hour
= BCD_INT(HalpReadCmos(4));
266 Time
->Weekday
= BCD_INT(HalpReadCmos(6));
267 Time
->Day
= BCD_INT(HalpReadCmos(7));
268 Time
->Month
= BCD_INT(HalpReadCmos(8));
269 Time
->Year
= BCD_INT(HalpReadCmos(9));
270 Time
->Milliseconds
= 0;
272 /* FIXME: Check century byte */
274 /* Compensate for the century field */
275 Time
->Year
+= (Time
->Year
> 80) ? 1900: 2000;
277 /* Release CMOS lock */
278 HalpReleaseCmosSpinLock();
280 /* Always return TRUE */
289 HalSetRealTimeClock(IN PTIME_FIELDS Time
)
291 /* Acquire CMOS Lock */
292 HalpAcquireSystemHardwareSpinLock();
294 /* Loop while update is in progress */
295 while ((HalpReadCmos(RTC_REGISTER_A
)) & RTC_REG_A_UIP
);
297 /* Write time fields to CMOS RTC */
298 HalpWriteCmos(0, INT_BCD(Time
->Second
));
299 HalpWriteCmos(2, INT_BCD(Time
->Minute
));
300 HalpWriteCmos(4, INT_BCD(Time
->Hour
));
301 HalpWriteCmos(6, INT_BCD(Time
->Weekday
));
302 HalpWriteCmos(7, INT_BCD(Time
->Day
));
303 HalpWriteCmos(8, INT_BCD(Time
->Month
));
304 HalpWriteCmos(9, INT_BCD(Time
->Year
% 100));
306 /* FIXME: Set the century byte */
308 /* Release CMOS lock */
309 HalpReleaseCmosSpinLock();
311 /* Always return TRUE */