]> git.proxmox.com Git - mirror_edk2.git/blame - PcAtChipsetPkg/PcRtc/RealTimeClock.c
Reviewed the code comments in the Include/Protocol directory for typos, grammar issue...
[mirror_edk2.git] / PcAtChipsetPkg / PcRtc / RealTimeClock.c
CommitLineData
c69dd9df 1/*++\r
2\r
3Copyright (c) 2005 - 2007, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 PcRtc.c\r
14\r
15Abstract:\r
16\r
17 RTC Architectural Protocol GUID as defined in EFI 2.0\r
18\r
19--*/\r
20\r
21#include "RealTimeClock.h"\r
22\r
23BOOLEAN\r
24DayValid (\r
25 IN EFI_TIME *Time\r
26 );\r
27\r
28BOOLEAN\r
29IsLeapYear (\r
30 IN EFI_TIME *Time\r
31 );\r
32\r
33BOOLEAN \r
34IsWithinOneDay (\r
35 IN EFI_TIME *From,\r
36 IN EFI_TIME *To\r
37 );\r
38\r
39INTN\r
40CompareHMS (\r
41 IN EFI_TIME *From,\r
42 IN EFI_TIME *To\r
43 );\r
269c0ba2 44\r
45INTN mDayOfMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};\r
c69dd9df 46 \r
47UINT8\r
48RtcRead (\r
49 IN UINT8 Address\r
50 )\r
51/*++\r
52\r
53Routine Description:\r
54\r
55 TODO: Add function description\r
56\r
57Arguments:\r
58\r
59 Address - TODO: add argument description\r
60\r
61Returns:\r
62\r
63 TODO: add return values\r
64\r
65--*/\r
66{\r
67 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
68 return IoRead8 (PCAT_RTC_DATA_REGISTER);\r
69}\r
70\r
71INTN\r
72CompareHMS (\r
73 IN EFI_TIME *From,\r
74 IN EFI_TIME *To\r
75 )\r
76/*++\r
77\r
78Routine Description: \r
79\r
80 Compare the Hour, Minute and Second of the 'From' time and the 'To' time.\r
81 Only compare H/M/S in EFI_TIME and ignore other fields here. \r
82\r
83Arguments:\r
84\r
85 From - the first time\r
86 To - the second time \r
87\r
88Returns:\r
89\r
90 >0 : The H/M/S of the 'From' time is later than those of 'To' time\r
91 ==0 : The H/M/S of the 'From' time is same as those of 'To' time\r
92 <0 : The H/M/S of the 'From' time is earlier than those of 'To' time\r
93\r
94--*/\r
95\r
96{\r
97 if ((From->Hour > To->Hour) ||\r
98 ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||\r
99 ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second))) {\r
100 return 1; \r
101 } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {\r
102 return 0;\r
103 } else {\r
104 return -1;\r
105 }\r
106}\r
107\r
108VOID\r
109RtcWrite (\r
110 IN UINT8 Address,\r
111 IN UINT8 Data\r
112 )\r
113/*++\r
114\r
115Routine Description:\r
116\r
117 TODO: Add function description\r
118\r
119Arguments:\r
120\r
121 Address - TODO: add argument description\r
122 Data - TODO: add argument description\r
123\r
124Returns:\r
125\r
126 TODO: add return values\r
127\r
128--*/\r
129{\r
130 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
131 IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);\r
132}\r
133\r
134EFI_STATUS\r
135PcRtcInit (\r
136 IN PC_RTC_MODULE_GLOBALS *Global\r
137 )\r
138/*++\r
139\r
140Routine Description:\r
141\r
142 TODO: Add function description\r
143\r
144Arguments:\r
145\r
146 Global - TODO: add argument description\r
147\r
148Returns:\r
149\r
150 EFI_DEVICE_ERROR - TODO: Add description for return value\r
151 EFI_SUCCESS - TODO: Add description for return value\r
152\r
153--*/\r
154{\r
155 EFI_STATUS Status;\r
156 RTC_REGISTER_A RegisterA;\r
157 RTC_REGISTER_B RegisterB;\r
e188a609 158 //RTC_REGISTER_C RegisterC;\r
c69dd9df 159 RTC_REGISTER_D RegisterD;\r
160 UINT8 Century;\r
161 EFI_TIME Time;\r
162\r
163 //\r
164 // Acquire RTC Lock to make access to RTC atomic\r
165 //\r
166 EfiAcquireLock (&Global->RtcLock);\r
167\r
168 //\r
169 // Initialize RTC Register\r
170 //\r
171 // Make sure Division Chain is properly configured,\r
172 // or RTC clock won't "tick" -- time won't increment\r
173 //\r
174 RegisterA.Data = RTC_INIT_REGISTER_A;\r
175 RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);\r
176\r
177 //\r
178 // Read Register B\r
179 //\r
180 RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
181\r
182 //\r
183 // Clear RTC flag register\r
184 //\r
e188a609 185 //RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);\r
c69dd9df 186\r
187 //\r
188 // Clear RTC register D\r
189 //\r
190 RegisterD.Data = RTC_INIT_REGISTER_D;\r
191 RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);\r
192\r
193 //\r
194 // Wait for up to 0.1 seconds for the RTC to be updated\r
195 //\r
e25803f0 196 // KEN: BUGBUG following wait action will cause failure under vmware environment.\r
197 //\r
198 //Status = RtcWaitToUpdate (100000);\r
199 //if (EFI_ERROR (Status)) {\r
200 // EfiReleaseLock (&Global->RtcLock);\r
201 // return EFI_DEVICE_ERROR;\r
202 //}\r
c69dd9df 203 //\r
204 // Get the Time/Date/Daylight Savings values.\r
205 //\r
206 Time.Second = RtcRead (RTC_ADDRESS_SECONDS);\r
207 Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
208 Time.Hour = RtcRead (RTC_ADDRESS_HOURS);\r
209 Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
210 Time.Month = RtcRead (RTC_ADDRESS_MONTH);\r
211 Time.Year = RtcRead (RTC_ADDRESS_YEAR);\r
212\r
213 ConvertRtcTimeToEfiTime (&Time, RegisterB);\r
214\r
215 if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
216 Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
217 } else {\r
218 Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));\r
219 }\r
220\r
221 Time.Year = (UINT16) (Century * 100 + Time.Year);\r
222\r
223 //\r
224 // Set RTC configuration after get original time\r
225 //\r
226 RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B);\r
227\r
228 //\r
229 // Release RTC Lock.\r
230 //\r
231 EfiReleaseLock (&Global->RtcLock);\r
232\r
233 //\r
234 // Validate time fields\r
235 //\r
236 Status = RtcTimeFieldsValid (&Time);\r
237 if (EFI_ERROR (Status)) {\r
238 Time.Second = RTC_INIT_SECOND;\r
239 Time.Minute = RTC_INIT_MINUTE;\r
240 Time.Hour = RTC_INIT_HOUR;\r
241 Time.Day = RTC_INIT_DAY;\r
242 Time.Month = RTC_INIT_MONTH;\r
243 Time.Year = RTC_INIT_YEAR;\r
244 }\r
245 //\r
246 // Reset time value according to new RTC configuration\r
247 //\r
248 PcRtcSetTime (&Time, Global);\r
249\r
250 return EFI_SUCCESS;\r
251}\r
252\r
253EFI_STATUS\r
254PcRtcGetTime (\r
255 OUT EFI_TIME *Time,\r
256 IN EFI_TIME_CAPABILITIES *Capabilities,\r
257 IN PC_RTC_MODULE_GLOBALS *Global\r
258 )\r
259/*++\r
260\r
261Routine Description:\r
262\r
263 Arguments:\r
264\r
265 Returns: \r
266--*/\r
267// TODO: Time - add argument and description to function comment\r
268// TODO: Capabilities - add argument and description to function comment\r
269// TODO: Global - add argument and description to function comment\r
270// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
271// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
272// TODO: EFI_SUCCESS - add return value to function comment\r
273{\r
274 EFI_STATUS Status;\r
275 RTC_REGISTER_B RegisterB;\r
276 UINT8 Century;\r
e188a609 277 //UINTN BufferSize;\r
c69dd9df 278\r
279 //\r
280 // Check parameters for null pointer\r
281 //\r
282 if (Time == NULL) {\r
283 return EFI_INVALID_PARAMETER;\r
284\r
285 }\r
286 //\r
287 // Acquire RTC Lock to make access to RTC atomic\r
288 //\r
289 EfiAcquireLock (&Global->RtcLock);\r
290\r
291 //\r
292 // Wait for up to 0.1 seconds for the RTC to be updated\r
293 //\r
294 Status = RtcWaitToUpdate (100000);\r
295 if (EFI_ERROR (Status)) {\r
296 EfiReleaseLock (&Global->RtcLock);\r
297 return Status;\r
298 }\r
299 //\r
300 // Read Register B\r
301 //\r
302 RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
303\r
304 //\r
305 // Get the Time/Date/Daylight Savings values.\r
306 //\r
307 Time->Second = RtcRead (RTC_ADDRESS_SECONDS);\r
308 Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
309 Time->Hour = RtcRead (RTC_ADDRESS_HOURS);\r
310 Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
311 Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
312 Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
313\r
314 ConvertRtcTimeToEfiTime (Time, RegisterB);\r
315\r
316 if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
317 Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
318 } else {\r
319 Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));\r
320 }\r
321\r
322 Time->Year = (UINT16) (Century * 100 + Time->Year);\r
323\r
324 //\r
325 // Release RTC Lock.\r
326 //\r
327 EfiReleaseLock (&Global->RtcLock);\r
328\r
329 //\r
330 // Get the variable that containts the TimeZone and Daylight fields\r
331 //\r
332 Time->TimeZone = Global->SavedTimeZone;\r
333 Time->Daylight = Global->Daylight;\r
334\r
e188a609 335 //BufferSize = sizeof (INT16) + sizeof (UINT8);\r
c69dd9df 336\r
337 //\r
338 // Make sure all field values are in correct range\r
339 //\r
340 Status = RtcTimeFieldsValid (Time);\r
341 if (EFI_ERROR (Status)) {\r
342 return EFI_DEVICE_ERROR;\r
343 }\r
344 //\r
345 // Fill in Capabilities if it was passed in\r
346 //\r
347 if (Capabilities) {\r
348 Capabilities->Resolution = 1;\r
349 //\r
350 // 1 hertz\r
351 //\r
352 Capabilities->Accuracy = 50000000;\r
353 //\r
354 // 50 ppm\r
355 //\r
356 Capabilities->SetsToZero = FALSE;\r
357 }\r
358\r
359 return EFI_SUCCESS;\r
360}\r
361\r
362EFI_STATUS\r
363PcRtcSetTime (\r
364 IN EFI_TIME *Time,\r
365 IN PC_RTC_MODULE_GLOBALS *Global\r
366 )\r
367/*++\r
368\r
369Routine Description:\r
370\r
371 Arguments:\r
372\r
373 Returns: \r
374--*/\r
375// TODO: Time - add argument and description to function comment\r
376// TODO: Global - add argument and description to function comment\r
377// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
378{\r
379 EFI_STATUS Status;\r
380 EFI_TIME RtcTime;\r
381 RTC_REGISTER_B RegisterB;\r
382 UINT8 Century;\r
383\r
384 if (Time == NULL) {\r
385 return EFI_INVALID_PARAMETER;\r
386 }\r
387 //\r
388 // Make sure that the time fields are valid\r
389 //\r
390 Status = RtcTimeFieldsValid (Time);\r
391 if (EFI_ERROR (Status)) {\r
392 return Status;\r
393 }\r
394\r
395 CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
396\r
397 //\r
398 // Acquire RTC Lock to make access to RTC atomic\r
399 //\r
400 EfiAcquireLock (&Global->RtcLock);\r
401\r
402 //\r
403 // Wait for up to 0.1 seconds for the RTC to be updated\r
404 //\r
405 Status = RtcWaitToUpdate (100000);\r
406 if (EFI_ERROR (Status)) {\r
407 EfiReleaseLock (&Global->RtcLock);\r
408 return Status;\r
409 }\r
410 //\r
411 // Read Register B, and inhibit updates of the RTC\r
412 //\r
413 RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
414 RegisterB.Bits.SET = 1;\r
415 RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
416\r
417 ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
418\r
419 RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);\r
420 RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);\r
421 RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);\r
422 RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);\r
423 RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);\r
424 RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);\r
425 if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
426 Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80));\r
427 }\r
428\r
429 RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
430\r
431 //\r
432 // Allow updates of the RTC registers\r
433 //\r
434 RegisterB.Bits.SET = 0;\r
435 RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
436\r
437 //\r
438 // Release RTC Lock.\r
439 //\r
440 EfiReleaseLock (&Global->RtcLock);\r
441\r
442 //\r
443 // Set the variable that containts the TimeZone and Daylight fields\r
444 //\r
445 Global->SavedTimeZone = Time->TimeZone;\r
446 Global->Daylight = Time->Daylight;\r
447 return Status;\r
448}\r
449\r
450EFI_STATUS\r
451EFIAPI\r
452PcRtcGetWakeupTime (\r
453 OUT BOOLEAN *Enabled,\r
454 OUT BOOLEAN *Pending,\r
455 OUT EFI_TIME *Time,\r
456 IN PC_RTC_MODULE_GLOBALS *Global\r
457 )\r
458/*++\r
459\r
460Routine Description:\r
461\r
462 Arguments:\r
463\r
464 \r
465\r
466Returns: \r
467--*/\r
468// TODO: Enabled - add argument and description to function comment\r
469// TODO: Pending - add argument and description to function comment\r
470// TODO: Time - add argument and description to function comment\r
471// TODO: Global - add argument and description to function comment\r
472// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
473// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
474// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
475// TODO: EFI_SUCCESS - add return value to function comment\r
476{\r
477 EFI_STATUS Status;\r
478 RTC_REGISTER_B RegisterB;\r
479 RTC_REGISTER_C RegisterC;\r
480 UINT8 Century;\r
481\r
482 //\r
483 // Check paramters for null pointers\r
484 //\r
485 if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {\r
486 return EFI_INVALID_PARAMETER;\r
487\r
488 }\r
489 //\r
490 // Acquire RTC Lock to make access to RTC atomic\r
491 //\r
492 EfiAcquireLock (&Global->RtcLock);\r
493\r
494 //\r
495 // Wait for up to 0.1 seconds for the RTC to be updated\r
496 //\r
497 Status = RtcWaitToUpdate (100000);\r
498 if (EFI_ERROR (Status)) {\r
499 EfiReleaseLock (&Global->RtcLock);\r
500 return EFI_DEVICE_ERROR;\r
501 }\r
502 //\r
503 // Read Register B and Register C\r
504 //\r
505 RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
506 RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);\r
507\r
508 //\r
509 // Get the Time/Date/Daylight Savings values.\r
510 //\r
511 *Enabled = RegisterB.Bits.AIE;\r
512 if (*Enabled) {\r
513 Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);\r
514 Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);\r
515 Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);\r
516 Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
517 Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
518 Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
519 } else {\r
520 Time->Second = 0;\r
521 Time->Minute = 0;\r
522 Time->Hour = 0;\r
523 Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
524 Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
525 Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
526 }\r
527\r
528 ConvertRtcTimeToEfiTime (Time, RegisterB);\r
529\r
530 if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
531 Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
532 } else {\r
533 Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));\r
534 }\r
535\r
536 Time->Year = (UINT16) (Century * 100 + Time->Year);\r
537\r
538 //\r
539 // Release RTC Lock.\r
540 //\r
541 EfiReleaseLock (&Global->RtcLock);\r
542\r
543 //\r
544 // Make sure all field values are in correct range\r
545 //\r
546 Status = RtcTimeFieldsValid (Time);\r
547 if (EFI_ERROR (Status)) {\r
548 return EFI_DEVICE_ERROR;\r
549 }\r
550\r
551 *Pending = RegisterC.Bits.AF;\r
552\r
553 return EFI_SUCCESS;\r
554}\r
555\r
556EFI_STATUS\r
557EFIAPI\r
558PcRtcSetWakeupTime (\r
559 IN BOOLEAN Enable,\r
560 OUT EFI_TIME *Time,\r
561 IN PC_RTC_MODULE_GLOBALS *Global\r
562 )\r
563/*++\r
564\r
565Routine Description:\r
566\r
567 Arguments:\r
568\r
569 \r
570\r
571Returns: \r
572--*/\r
573// TODO: Enable - add argument and description to function comment\r
574// TODO: Time - add argument and description to function comment\r
575// TODO: Global - add argument and description to function comment\r
576// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
577// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
578// TODO: EFI_UNSUPPORTED - add return value to function comment\r
579// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
580// TODO: EFI_SUCCESS - add return value to function comment\r
581{\r
582 EFI_STATUS Status;\r
583 EFI_TIME RtcTime;\r
584 RTC_REGISTER_B RegisterB;\r
585 UINT8 Century;\r
586 EFI_TIME_CAPABILITIES Capabilities;\r
587\r
588 if (Enable) {\r
589\r
590 if (Time == NULL) {\r
591 return EFI_INVALID_PARAMETER;\r
592 }\r
593 //\r
594 // Make sure that the time fields are valid\r
595 //\r
596 Status = RtcTimeFieldsValid (Time);\r
597 if (EFI_ERROR (Status)) {\r
598 return EFI_INVALID_PARAMETER;\r
599 }\r
600 //\r
601 // Just support set alarm time within 24 hours\r
602 //\r
603 PcRtcGetTime (&RtcTime, &Capabilities, Global);\r
604 if (!IsWithinOneDay (&RtcTime, Time)) {\r
605 return EFI_UNSUPPORTED;\r
606 }\r
607 //\r
608 // Make a local copy of the time and date\r
609 //\r
610 CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
611\r
612 }\r
613 //\r
614 // Acquire RTC Lock to make access to RTC atomic\r
615 //\r
616 EfiAcquireLock (&Global->RtcLock);\r
617\r
618 //\r
619 // Wait for up to 0.1 seconds for the RTC to be updated\r
620 //\r
621 Status = RtcWaitToUpdate (100000);\r
622 if (EFI_ERROR (Status)) {\r
623 EfiReleaseLock (&Global->RtcLock);\r
624 return EFI_DEVICE_ERROR;\r
625 }\r
626 //\r
627 // Read Register B, and inhibit updates of the RTC\r
628 //\r
629 RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
630\r
631 RegisterB.Bits.SET = 1;\r
632 RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
633\r
634 if (Enable) {\r
635 ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
636\r
637 //\r
638 // Set RTC alarm time\r
639 //\r
640 RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);\r
641 RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);\r
642 RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);\r
643\r
644 RegisterB.Bits.AIE = 1;\r
645\r
646 } else {\r
647 RegisterB.Bits.AIE = 0;\r
648 }\r
649 //\r
650 // Allow updates of the RTC registers\r
651 //\r
652 RegisterB.Bits.SET = 0;\r
653 RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
654\r
655 //\r
656 // Release RTC Lock.\r
657 //\r
658 EfiReleaseLock (&Global->RtcLock);\r
659\r
660 return EFI_SUCCESS;\r
661}\r
662\r
663UINT8\r
664BcdToDecimal (\r
665 IN UINT8 BcdValue\r
666 )\r
667/*++\r
668\r
669Routine Description:\r
670\r
671 Arguments:\r
672\r
673 \r
674\r
675Returns: \r
676--*/\r
677// TODO: BcdValue - add argument and description to function comment\r
678{\r
679 UINTN High;\r
680 UINTN Low;\r
681\r
682 High = BcdValue >> 4;\r
683 Low = BcdValue - (High << 4);\r
684\r
685 return (UINT8) (Low + (High * 10));\r
686}\r
687\r
688EFI_STATUS\r
689RtcTestCenturyRegister (\r
690 VOID\r
691 )\r
692/*++\r
693\r
694Routine Description:\r
695\r
696 Arguments:\r
697\r
698 \r
699\r
700Returns: \r
701--*/\r
702// TODO: EFI_SUCCESS - add return value to function comment\r
703// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
704{\r
705 UINT8 Century;\r
706 UINT8 Temp;\r
707\r
708 Century = RtcRead (RTC_ADDRESS_CENTURY);\r
709 //\r
710 // RtcWrite (RTC_ADDRESS_CENTURY, 0x00);\r
711 //\r
712 Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
713 RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
714 if (Temp == 0x19 || Temp == 0x20) {\r
715 return EFI_SUCCESS;\r
716 }\r
717\r
718 return EFI_DEVICE_ERROR;\r
719}\r
720\r
721VOID\r
722ConvertRtcTimeToEfiTime (\r
723 IN EFI_TIME *Time,\r
724 IN RTC_REGISTER_B RegisterB\r
725 )\r
726/*++\r
727\r
728Routine Description:\r
729\r
730 Arguments:\r
731\r
732 \r
733\r
734Returns: \r
735--*/\r
736// TODO: Time - add argument and description to function comment\r
737// TODO: RegisterB - add argument and description to function comment\r
738{\r
739 BOOLEAN PM;\r
740\r
741 if ((Time->Hour) & 0x80) {\r
742 PM = TRUE;\r
743 } else {\r
744 PM = FALSE;\r
745 }\r
746\r
747 Time->Hour = (UINT8) (Time->Hour & 0x7f);\r
748\r
749 if (RegisterB.Bits.DM == 0) {\r
750 Time->Year = BcdToDecimal ((UINT8) Time->Year);\r
751 Time->Month = BcdToDecimal (Time->Month);\r
752 Time->Day = BcdToDecimal (Time->Day);\r
753 Time->Hour = BcdToDecimal (Time->Hour);\r
754 Time->Minute = BcdToDecimal (Time->Minute);\r
755 Time->Second = BcdToDecimal (Time->Second);\r
756 }\r
757 //\r
758 // If time is in 12 hour format, convert it to 24 hour format\r
759 //\r
760 if (RegisterB.Bits.MIL == 0) {\r
761 if (PM && Time->Hour < 12) {\r
762 Time->Hour = (UINT8) (Time->Hour + 12);\r
763 }\r
764\r
765 if (!PM && Time->Hour == 12) {\r
766 Time->Hour = 0;\r
767 }\r
768 }\r
769\r
770 Time->Nanosecond = 0;\r
771 Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
772 Time->Daylight = 0;\r
773}\r
774\r
775EFI_STATUS\r
776RtcWaitToUpdate (\r
777 UINTN Timeout\r
778 )\r
779/*++\r
780\r
781Routine Description:\r
782\r
783 Arguments:\r
784 \r
785\r
786Returns: \r
787--*/\r
788// TODO: Timeout - add argument and description to function comment\r
789// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
790// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
791// TODO: EFI_SUCCESS - add return value to function comment\r
792{\r
793 RTC_REGISTER_A RegisterA;\r
794 RTC_REGISTER_D RegisterD;\r
795\r
796 //\r
797 // See if the RTC is functioning correctly\r
798 //\r
799 RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
800\r
801 if (RegisterD.Bits.VRT == 0) {\r
802 return EFI_DEVICE_ERROR;\r
803 }\r
804 //\r
805 // Wait for up to 0.1 seconds for the RTC to be ready.\r
806 //\r
807 Timeout = (Timeout / 10) + 1;\r
808 RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
809 while (RegisterA.Bits.UIP == 1 && Timeout > 0) {\r
810 MicroSecondDelay (10);\r
811 RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
812 Timeout--;\r
813 }\r
814\r
815 RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
816 if (Timeout == 0 || RegisterD.Bits.VRT == 0) {\r
817 return EFI_DEVICE_ERROR;\r
818 }\r
819\r
820 return EFI_SUCCESS;\r
821}\r
822\r
823EFI_STATUS\r
824RtcTimeFieldsValid (\r
825 IN EFI_TIME *Time\r
826 )\r
827/*++\r
828\r
829Routine Description:\r
830\r
831 Arguments:\r
832 \r
833 Returns: \r
834--*/\r
835// TODO: Time - add argument and description to function comment\r
836// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
837// TODO: EFI_SUCCESS - add return value to function comment\r
838{\r
839 if (Time->Year < 1998 ||\r
840 Time->Year > 2099 ||\r
841 Time->Month < 1 ||\r
842 Time->Month > 12 ||\r
843 (!DayValid (Time)) ||\r
844 Time->Hour > 23 ||\r
845 Time->Minute > 59 ||\r
846 Time->Second > 59 ||\r
847 Time->Nanosecond > 999999999 ||\r
848 (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||\r
849 (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))\r
850 ) {\r
851 return EFI_INVALID_PARAMETER;\r
852 }\r
853\r
854 return EFI_SUCCESS;\r
855}\r
856\r
857BOOLEAN\r
858DayValid (\r
859 IN EFI_TIME *Time\r
860 )\r
861/*++\r
862\r
863Routine Description:\r
864\r
865 TODO: Add function description\r
866\r
867Arguments:\r
868\r
869 Time - TODO: add argument description\r
870\r
871Returns:\r
872\r
873 TODO: add return values\r
874\r
875--*/\r
876{\r
877\r
c69dd9df 878\r
879 if (Time->Day < 1 ||\r
269c0ba2 880 Time->Day > mDayOfMonth[Time->Month - 1] ||\r
c69dd9df 881 (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
882 ) {\r
883 return FALSE;\r
884 }\r
885\r
886 return TRUE;\r
887}\r
888\r
889BOOLEAN\r
890IsLeapYear (\r
891 IN EFI_TIME *Time\r
892 )\r
893/*++\r
894\r
895Routine Description:\r
896\r
897 TODO: Add function description\r
898\r
899Arguments:\r
900\r
901 Time - TODO: add argument description\r
902\r
903Returns:\r
904\r
905 TODO: add return values\r
906\r
907--*/\r
908{\r
909 if (Time->Year % 4 == 0) {\r
910 if (Time->Year % 100 == 0) {\r
911 if (Time->Year % 400 == 0) {\r
912 return TRUE;\r
913 } else {\r
914 return FALSE;\r
915 }\r
916 } else {\r
917 return TRUE;\r
918 }\r
919 } else {\r
920 return FALSE;\r
921 }\r
922}\r
923\r
924VOID\r
925ConvertEfiTimeToRtcTime (\r
926 IN EFI_TIME *Time,\r
927 IN RTC_REGISTER_B RegisterB,\r
928 IN UINT8 *Century\r
929 )\r
930/*++\r
931\r
932Routine Description:\r
933\r
934 Arguments:\r
935\r
936\r
937Returns: \r
938--*/\r
939// TODO: Time - add argument and description to function comment\r
940// TODO: RegisterB - add argument and description to function comment\r
941// TODO: Century - add argument and description to function comment\r
942{\r
943 BOOLEAN PM;\r
944\r
945 PM = TRUE;\r
946 //\r
947 // Adjust hour field if RTC in in 12 hour mode\r
948 //\r
949 if (RegisterB.Bits.MIL == 0) {\r
950 if (Time->Hour < 12) {\r
951 PM = FALSE;\r
952 }\r
953\r
954 if (Time->Hour >= 13) {\r
955 Time->Hour = (UINT8) (Time->Hour - 12);\r
956 } else if (Time->Hour == 0) {\r
957 Time->Hour = 12;\r
958 }\r
959 }\r
960 //\r
961 // Set the Time/Date/Daylight Savings values.\r
962 //\r
963 *Century = DecimaltoBcd ((UINT8) (Time->Year / 100));\r
964\r
965 Time->Year = (UINT16) (Time->Year % 100);\r
966\r
967 if (RegisterB.Bits.DM == 0) {\r
968 Time->Year = DecimaltoBcd ((UINT8) Time->Year);\r
969 Time->Month = DecimaltoBcd (Time->Month);\r
970 Time->Day = DecimaltoBcd (Time->Day);\r
971 Time->Hour = DecimaltoBcd (Time->Hour);\r
972 Time->Minute = DecimaltoBcd (Time->Minute);\r
973 Time->Second = DecimaltoBcd (Time->Second);\r
974 }\r
975 //\r
976 // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.\r
977 //\r
978 if (RegisterB.Bits.MIL == 0 && PM) {\r
979 Time->Hour = (UINT8) (Time->Hour | 0x80);\r
980 }\r
981}\r
982 \r
983BOOLEAN \r
984IsWithinOneDay (\r
985 IN EFI_TIME *From,\r
986 IN EFI_TIME *To\r
987 )\r
988/*++\r
989\r
990Routine Description:\r
991\r
992 Judge whether two days are adjacent.\r
993\r
994Arguments:\r
995\r
996 From - the first day\r
997 To - the second day\r
998\r
999Returns:\r
1000\r
1001 TRUE - The interval of two days are within one day.\r
1002 FALSE - The interval of two days exceed ony day or parameter error.\r
1003\r
1004--*/\r
1005{\r
c69dd9df 1006 BOOLEAN Adjacent = FALSE;\r
1007\r
1008 if (From->Year == To->Year) {\r
1009 if (From->Month == To->Month) {\r
1010 if ((From->Day + 1) == To->Day) {\r
1011 if ((CompareHMS(From, To) >= 0)) {\r
1012 Adjacent = TRUE;\r
1013 }\r
1014 } else if (From->Day == To->Day) {\r
1015 if ((CompareHMS(From, To) <= 0)) {\r
1016 Adjacent = TRUE;\r
1017 }\r
1018 }\r
1019 } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {\r
1020 if ((From->Month == 2) && !IsLeapYear(From)) {\r
1021 if (From->Day == 28) {\r
1022 if ((CompareHMS(From, To) >= 0)) {\r
1023 Adjacent = TRUE;\r
1024 } \r
1025 }\r
269c0ba2 1026 } else if (From->Day == mDayOfMonth[From->Month - 1]) {\r
c69dd9df 1027 if ((CompareHMS(From, To) >= 0)) {\r
1028 Adjacent = TRUE;\r
1029 }\r
1030 }\r
1031 }\r
1032 } else if (((From->Year + 1) == To->Year) &&\r
1033 (From->Month == 12) &&\r
1034 (From->Day == 31) &&\r
1035 (To->Month == 1) &&\r
1036 (To->Day == 1)) {\r
1037 if ((CompareHMS(From, To) >= 0)) {\r
1038 Adjacent = TRUE;\r
1039 }\r
1040 }\r
1041\r
1042 return Adjacent;\r
1043}\r
1044\r
1045UINT8\r
1046DecimaltoBcd (\r
1047 IN UINT8 DecValue\r
1048 )\r
1049/*++\r
1050\r
1051Routine Description:\r
1052\r
1053 Arguments: \r
1054\r
1055Returns: \r
1056\r
1057--*/\r
1058// TODO: DecValue - add argument and description to function comment\r
1059{\r
1060 UINTN High;\r
1061 UINTN Low;\r
1062\r
1063 High = DecValue / 10;\r
1064 Low = DecValue - (High * 10);\r
1065\r
1066 return (UINT8) (Low + (High << 4));\r
1067}\r