blob: 1d268f048282a5f482a37ab150fdb1ba09ba3ba3 [file] [log] [blame]
Eric Biederman05f26fc2003-06-11 21:55:00 +00001#include <pc80/mc146818rtc.h>
2#include <part/fallback_boot.h>
3
4static unsigned char cmos_read(unsigned char addr)
5{
6 outb(addr, RTC_BASE_PORT + 0);
7 return inb(RTC_BASE_PORT + 1);
8}
9
10static void cmos_write(unsigned char val, unsigned char addr)
11{
12 outb(addr, RTC_BASE_PORT + 0);
13 outb(val, RTC_BASE_PORT + 1);
14}
15
16static int cmos_error(void)
17{
18 unsigned char reg_d;
19 /* See if the cmos error condition has been flagged */
20 reg_d = cmos_read(RTC_REG_D);
21 return (reg_d & RTC_VRT) == 0;
22}
23
24static int cmos_chksum_valid(void)
25{
26 unsigned char addr;
27 unsigned long sum, old_sum;
28 sum = 0;
29 /* Comput the cmos checksum */
30 for(addr = LB_CKS_RANGE_START; addr <= LB_CKS_RANGE_END; addr++) {
31 sum += cmos_read(addr);
32 }
33 sum = (sum & 0xffff) ^ 0xffff;
34
35 /* Read the stored checksum */
36 old_sum = cmos_read(LB_CKS_LOC) << 8;
37 old_sum |= cmos_read(LB_CKS_LOC+1);
38
39 return sum == old_sum;
40}
41
42
43static int do_normal_boot(void)
44{
45 unsigned char byte;
46
47 if (cmos_error() || !cmos_chksum_valid()) {
48 unsigned char byte;
49 /* There are no impossible values, no cheksums so just
50 * trust whatever value we have in the the cmos,
51 * but clear the fallback bit.
52 */
53 byte = cmos_read(RTC_BOOT_BYTE);
54 byte &= 0x0c;
55 byte |= MAX_REBOOT_CNT << 4;
56 cmos_write(byte, RTC_BOOT_BYTE);
57 }
58
59 /* The RTC_BOOT_BYTE is now o.k. see where to go. */
60 byte = cmos_read(RTC_BOOT_BYTE);
61
62 /* Are we in normal mode? */
63 if (byte & 1) {
64 byte &= 0x0f; /* yes, clear the boot count */
65 }
66
67 /* Are we already at the max count? */
68 if ((byte >> 4) < MAX_REBOOT_CNT) {
69 byte += 1 << 4; /* No, add 1 to the count */
70 }
71 else {
72 byte &= 0xfc; /* Yes, put in fallback mode */
73 }
74
75 /* Is this the first boot? */
76 if ((byte >> 4) <= 1) {
77 byte = (byte & 0xfc) | ((byte & 1) << 1); /* yes, shift the boot bits */
78 }
79
80 /* Save the boot byte */
81 cmos_write(byte, RTC_BOOT_BYTE);
82
83 return ((byte >> 4) < MAX_REBOOT_CNT);
84}