- Remove svn:needs-lock, svn:eol-type, and svn:eol-tyle properties.
[reactos.git] / reactos / hal / halx86 / generic / cmos.c
1 /*
2 * PROJECT: ReactOS HAL
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)
7 * Eric Kohl (ekohl@abo.rhein-zeitung.de)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <hal.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18 KSPIN_LOCK HalpSystemHardwareLock;
19
20 /* PRIVATE FUNCTIONS *********************************************************/
21
22 FORCEINLINE
23 UCHAR
24 HalpReadCmos(IN UCHAR Reg)
25 {
26 /* Select the register */
27 WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, Reg);
28
29 /* Query the value */
30 return READ_PORT_UCHAR(CMOS_DATA_PORT);
31 }
32
33 FORCEINLINE
34 VOID
35 HalpWriteCmos(IN UCHAR Reg,
36 IN UCHAR Value)
37 {
38 /* Select the register */
39 WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, Reg);
40
41 /* Write the value */
42 WRITE_PORT_UCHAR(CMOS_DATA_PORT, Value);
43 }
44
45 ULONG
46 NTAPI
47 HalpGetCmosData(IN ULONG BusNumber,
48 IN ULONG SlotNumber,
49 IN PVOID Buffer,
50 IN ULONG Length)
51 {
52 PUCHAR Ptr = (PUCHAR)Buffer;
53 ULONG Address = SlotNumber;
54 ULONG Len = Length;
55
56 /* FIXME: Acquire CMOS Lock */
57
58 /* Do nothing if we don't have a length */
59 if (!Length) return 0;
60
61 /* Check if this is simple CMOS */
62 if (!BusNumber)
63 {
64 /* Loop the buffer up to 0xFF */
65 while ((Len > 0) && (Address < 0x100))
66 {
67 /* Read the data */
68 *Ptr = HalpReadCmos((UCHAR)Address);
69
70 /* Update position and length */
71 Ptr++;
72 Address++;
73 Len--;
74 }
75 }
76 else if (BusNumber == 1)
77 {
78 /* Loop the buffer up to 0xFFFF */
79 while ((Len > 0) && (Address < 0x10000))
80 {
81 /* Write the data */
82 *Ptr = HalpReadCmos((UCHAR)Address);
83
84 /* Update position and length */
85 Ptr++;
86 Address++;
87 Len--;
88 }
89 }
90
91 /* FIXME: Release the CMOS Lock */
92
93 /* Return length read */
94 return Length - Len;
95 }
96
97 ULONG
98 NTAPI
99 HalpSetCmosData(IN ULONG BusNumber,
100 IN ULONG SlotNumber,
101 IN PVOID Buffer,
102 IN ULONG Length)
103 {
104 PUCHAR Ptr = (PUCHAR)Buffer;
105 ULONG Address = SlotNumber;
106 ULONG Len = Length;
107
108 /* FIXME: Acquire CMOS Lock */
109
110 /* Do nothing if we don't have a length */
111 if (!Length) return 0;
112
113 /* Check if this is simple CMOS */
114 if (!BusNumber)
115 {
116 /* Loop the buffer up to 0xFF */
117 while ((Len > 0) && (Address < 0x100))
118 {
119 /* Write the data */
120 HalpWriteCmos((UCHAR)Address, *Ptr);
121
122 /* Update position and length */
123 Ptr++;
124 Address++;
125 Len--;
126 }
127 }
128 else if (BusNumber == 1)
129 {
130 /* Loop the buffer up to 0xFFFF */
131 while ((Len > 0) && (Address < 0x10000))
132 {
133 /* Write the data */
134 HalpWriteCmos((UCHAR)Address, *Ptr);
135
136 /* Update position and length */
137 Ptr++;
138 Address++;
139 Len--;
140 }
141 }
142
143 /* FIXME: Release the CMOS Lock */
144
145 /* Return length read */
146 return Length - Len;
147 }
148
149 /* PUBLIC FUNCTIONS **********************************************************/
150
151 /*
152 * @implemented
153 */
154 ARC_STATUS
155 NTAPI
156 HalGetEnvironmentVariable(IN PCH Name,
157 IN USHORT ValueLength,
158 IN PCH Value)
159 {
160 UCHAR Val;
161
162 /* Only variable supported on x86 */
163 if (_stricmp(Name, "LastKnownGood")) return ENOENT;
164
165 /* FIXME: Acquire CMOS Lock */
166
167 /* Query the current value */
168 Val = HalpReadCmos(RTC_REGISTER_B) & 0x01;
169
170 /* FIXME: Release CMOS lock */
171
172 /* Check the flag */
173 if (Val)
174 {
175 /* Return false */
176 strncpy(Value, "FALSE", ValueLength);
177 }
178 else
179 {
180 /* Return true */
181 strncpy(Value, "TRUE", ValueLength);
182 }
183
184 /* Return success */
185 return ESUCCESS;
186 }
187
188 /*
189 * @implemented
190 */
191 ARC_STATUS
192 NTAPI
193 HalSetEnvironmentVariable(IN PCH Name,
194 IN PCH Value)
195 {
196 UCHAR Val;
197
198 /* Only variable supported on x86 */
199 if (_stricmp(Name, "LastKnownGood")) return ENOMEM;
200
201 /* Check if this is true or false */
202 if (!_stricmp(Value, "TRUE"))
203 {
204 /* It's true, acquire CMOS lock (FIXME) */
205
206 /* Read the current value and add the flag */
207 Val = HalpReadCmos(RTC_REGISTER_B) | 1;
208 }
209 else if (!_stricmp(Value, "FALSE"))
210 {
211 /* It's false, acquire CMOS lock (FIXME) */
212
213 /* Read the current value and mask out the flag */
214 Val = HalpReadCmos(RTC_REGISTER_B) & ~1;
215 }
216 else
217 {
218 /* Fail */
219 return ENOMEM;
220 }
221
222 /* Write new value */
223 HalpWriteCmos(RTC_REGISTER_B, Val);
224
225 /* Release the lock and return success */
226 return ESUCCESS;
227 }
228
229 /*
230 * @implemented
231 */
232 BOOLEAN
233 NTAPI
234 HalQueryRealTimeClock(OUT PTIME_FIELDS Time)
235 {
236 /* FIXME: Acquire CMOS Lock */
237
238 /* Loop while update is in progress */
239 while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);
240
241 /* Set the time data */
242 Time->Second = BCD_INT(HalpReadCmos(0));
243 Time->Minute = BCD_INT(HalpReadCmos(2));
244 Time->Hour = BCD_INT(HalpReadCmos(4));
245 Time->Weekday = BCD_INT(HalpReadCmos(6));
246 Time->Day = BCD_INT(HalpReadCmos(7));
247 Time->Month = BCD_INT(HalpReadCmos(8));
248 Time->Year = BCD_INT(HalpReadCmos(9));
249 Time->Milliseconds = 0;
250
251 /* FIXME: Check century byte */
252
253 /* Compensate for the century field */
254 Time->Year += (Time->Year > 80) ? 1900: 2000;
255
256 /* FIXME: Release CMOS Lock */
257
258 /* Always return TRUE */
259 return TRUE;
260 }
261
262 /*
263 * @implemented
264 */
265 BOOLEAN
266 NTAPI
267 HalSetRealTimeClock(IN PTIME_FIELDS Time)
268 {
269 /* FIXME: Acquire CMOS Lock */
270
271 /* Loop while update is in progress */
272 while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);
273
274 /* Write time fields to CMOS RTC */
275 HalpWriteCmos(0, INT_BCD(Time->Second));
276 HalpWriteCmos(2, INT_BCD(Time->Minute));
277 HalpWriteCmos(4, INT_BCD(Time->Hour));
278 HalpWriteCmos(6, INT_BCD(Time->Weekday));
279 HalpWriteCmos(7, INT_BCD(Time->Day));
280 HalpWriteCmos(8, INT_BCD(Time->Month));
281 HalpWriteCmos(9, INT_BCD(Time->Year % 100));
282
283 /* FIXME: Set the century byte */
284
285 /* FIXME: Release the CMOS Lock */
286
287 /* Always return TRUE */
288 return TRUE;
289 }
290
291 /* EOF */