// RTC register flags
#define RTC_A_UIP 0x80
-#define RTC_B_SET 0x80
-#define RTC_B_PIE 0x40
-#define RTC_B_AIE 0x20
-#define RTC_B_UIE 0x10
+
+#define RTC_B_SET 0x80
+#define RTC_B_PIE 0x40
+#define RTC_B_AIE 0x20
+#define RTC_B_UIE 0x10
+#define RTC_B_BIN 0x04
+#define RTC_B_24HR 0x02
+#define RTC_B_DSE 0x01
+
// Bits for PORT_PS2_CTRLB
#define PPCB_T2GATE (1<<0)
#define PIT_TICK_RATE 1193182 // Underlying HZ of PIT
#define CALIBRATE_COUNT 0x800 // Approx 1.7ms
-u32 cpu_khz VAR16_32;
+u32 cpu_khz VAR16VISIBLE;
static void
calibrate_tsc()
{
u64 start = rdtscll();
u64 end = start + diff;
- while (rdtscll() < end)
+ while (rdtscll() <= end)
cpu_relax();
}
// If it is set, it tries to wait until there is a transition
// to 0, and will return 0 if such a transition occurs. A -1
// is returned only after timing out. The maximum period
- // that this bit should be set is constrained to 244useconds, so
- // we wait for 1 msec max.
+ // that this bit should be set is constrained to (1984+244)
+ // useconds, so we wait for 3 msec max.
- if ((inb_cmos(CMOS_STATUS_A) & 0x80) == 0)
+ if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
return 0;
- u64 end = calc_future_tsc(1);
+ u64 end = calc_future_tsc(3);
do {
- if ((inb_cmos(CMOS_STATUS_A) & 0x80) == 0)
+ if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
return 0;
} while (rdtscll() <= end);
outb(0x0, PORT_PIT_COUNTER0);
}
+static void
+init_rtc()
+{
+ outb_cmos(0x26, CMOS_STATUS_A); // 32,768Khz src, 976.5625us updates
+ u8 regB = inb_cmos(CMOS_STATUS_B);
+ outb_cmos((regB & RTC_B_DSE) | RTC_B_24HR, CMOS_STATUS_B);
+ inb_cmos(CMOS_STATUS_C);
+ inb_cmos(CMOS_STATUS_D);
+}
+
static u32
bcd2bin(u8 val)
{
calibrate_tsc();
pit_setup();
+ init_rtc();
rtc_updating();
u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS));
u32 ticks = (seconds * 18206507) / 1000000;
enable_hwirq(8, entry_70);
}
-static void
-init_rtc()
-{
- outb_cmos(0x26, CMOS_STATUS_A);
- outb_cmos(0x02, CMOS_STATUS_B);
- inb_cmos(CMOS_STATUS_C);
- inb_cmos(CMOS_STATUS_D);
-}
-
/****************************************************************
* Standard clock functions
regs->dh = inb_cmos(CMOS_RTC_SECONDS);
regs->cl = inb_cmos(CMOS_RTC_MINUTES);
regs->ch = inb_cmos(CMOS_RTC_HOURS);
- regs->dl = inb_cmos(CMOS_STATUS_B) & 0x01;
+ regs->dl = inb_cmos(CMOS_STATUS_B) & RTC_B_DSE;
regs->ah = 0;
regs->al = regs->ch;
set_success(regs);
outb_cmos(regs->cl, CMOS_RTC_MINUTES);
outb_cmos(regs->ch, CMOS_RTC_HOURS);
// Set Daylight Savings time enabled bit to requested value
- u8 val8 = (inb_cmos(CMOS_STATUS_B) & 0x60) | 0x02 | (regs->dl & 0x01);
+ u8 val8 = ((inb_cmos(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE))
+ | RTC_B_24HR | (regs->dl & RTC_B_DSE));
outb_cmos(val8, CMOS_STATUS_B);
regs->ah = 0;
regs->al = val8; // val last written to Reg B
regs->cl = inb_cmos(CMOS_RTC_YEAR);
regs->dh = inb_cmos(CMOS_RTC_MONTH);
regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH);
- regs->ch = inb_cmos(CMOS_CENTURY);
+ if (CONFIG_COREBOOT) {
+ if (regs->cl > 0x80)
+ regs->ch = 0x19;
+ else
+ regs->ch = 0x20;
+ } else {
+ regs->ch = inb_cmos(CMOS_CENTURY);
+ }
regs->al = regs->ch;
set_success(regs);
}
outb_cmos(regs->cl, CMOS_RTC_YEAR);
outb_cmos(regs->dh, CMOS_RTC_MONTH);
outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH);
- outb_cmos(regs->ch, CMOS_CENTURY);
+ if (!CONFIG_COREBOOT)
+ outb_cmos(regs->ch, CMOS_CENTURY);
// clear halt-clock bit
u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET;
outb_cmos(val8, CMOS_STATUS_B);
// My assumption: RegB = ((RegB & 01111111b) | 00100000b)
u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
regs->ax = 0;
- if (val8 & 0x20) {
+ if (val8 & RTC_B_AIE) {
// Alarm interrupt enabled already
set_fail(regs);
return;
// Interval not already set.
SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING); // Set status byte.
- SET_BDA(ptr_user_wait_complete_flag, (seg << 16) | offset);
+ SET_BDA(user_wait_complete_flag, SEGOFF(seg, offset));
SET_BDA(user_wait_timeout, usecs);
// Turn on the Periodic Interrupt timer
if (!(registerB & (RTC_B_PIE|RTC_B_AIE)))
goto done;
- if (registerC & 0x20) {
+ if (registerC & RTC_B_AIE) {
// Handle Alarm Interrupt.
u32 eax=0, flags;
call16_simpint(0x4a, &eax, &flags);
}
- if (!(registerC & 0x40))
+ if (!(registerC & RTC_B_PIE))
goto done;
// Handle Periodic Interrupt.
u32 time = GET_BDA(user_wait_timeout); // Time left in microseconds.
if (time < 0x3D1) {
// Done waiting - write to specified flag byte.
- u32 segoff = GET_BDA(ptr_user_wait_complete_flag);
- u16 segment = segoff >> 16;
- u16 offset = segoff & 0xffff;
- u8 oldval = GET_FARVAR(segment, *(u8*)(offset+0));
- SET_FARVAR(segment, *(u8*)(offset+0), oldval | 0x80);
+ struct segoff_s segoff = GET_BDA(user_wait_complete_flag);
+ u16 ptr_seg = segoff.seg;
+ u8 *ptr_far = (u8*)(segoff.offset+0);
+ u8 oldval = GET_FARVAR(ptr_seg, *ptr_far);
+ SET_FARVAR(ptr_seg, *ptr_far, oldval | 0x80);
clear_usertimer();
} else {
// Continue waiting.
- time -= 0x3D1;
+ time -= 977;
SET_BDA(user_wait_timeout, time);
}