1 // Support for MC146818 Real Time Clock chip.
3 // Copyright (C) 2008-2013 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002 MandrakeSoft S.A.
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
8 #include "biosvar.h" // GET_LOW
9 #include "rtc.h" // rtc_read
10 #include "stacks.h" // yield
11 #include "util.h" // timer_calc
12 #include "x86.h" // inb
17 index |= NMI_DISABLE_BIT;
18 outb(index, PORT_CMOS_INDEX);
19 return inb(PORT_CMOS_DATA);
23 rtc_write(u8 index, u8 val)
25 index |= NMI_DISABLE_BIT;
26 outb(index, PORT_CMOS_INDEX);
27 outb(val, PORT_CMOS_DATA);
31 rtc_mask(u8 index, u8 off, u8 on)
33 outb(index, PORT_CMOS_INDEX);
34 u8 val = inb(PORT_CMOS_DATA);
35 outb((val & ~off) | on, PORT_CMOS_DATA);
41 // This function checks to see if the update-in-progress bit
42 // is set in CMOS Status Register A. If not, it returns 0.
43 // If it is set, it tries to wait until there is a transition
44 // to 0, and will return 0 if such a transition occurs. A -1
45 // is returned only after timing out. The maximum period
46 // that this bit should be set is constrained to (1984+244)
47 // useconds, but we wait for longer just to be sure.
49 if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0)
51 u32 end = timer_calc(15);
53 if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0)
56 // update-in-progress never transitioned to 0
65 rtc_write(CMOS_STATUS_A, 0x26); // 32,768Khz src, 976.5625us updates
66 rtc_mask(CMOS_STATUS_B, ~RTC_B_DSE, RTC_B_24HR);
67 rtc_read(CMOS_STATUS_C);
68 rtc_read(CMOS_STATUS_D);
76 int count = GET_LOW(RTCusers);
77 SET_LOW(RTCusers, count+1);
80 // Turn on the Periodic Interrupt timer
81 rtc_mask(CMOS_STATUS_B, 0, RTC_B_PIE);
87 int count = GET_LOW(RTCusers);
88 SET_LOW(RTCusers, count-1);
91 // Clear the Periodic Interrupt.
92 rtc_mask(CMOS_STATUS_B, RTC_B_PIE, 0);