diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2008-12-13 10:45:50 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2008-12-13 10:45:50 -0500 |
commit | 4e6c9706240a33e13de3da98815d8f4d281a9e9a (patch) | |
tree | 045ebf1724d9bb9b37f3d8f4d3dd247d6f769b1c /src/clock.c | |
parent | 4bbd3b3599714089a8e2c451ae62cc056760c746 (diff) | |
download | seabios-hppa-4e6c9706240a33e13de3da98815d8f4d281a9e9a.zip seabios-hppa-4e6c9706240a33e13de3da98815d8f4d281a9e9a.tar.gz seabios-hppa-4e6c9706240a33e13de3da98815d8f4d281a9e9a.tar.bz2 |
Implement time based checks even when looping on an ioport.
Implement real timeout code in ATA.
Implement real timeout code for RTC updating check.
Diffstat (limited to 'src/clock.c')
-rw-r--r-- | src/clock.c | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/src/clock.c b/src/clock.c index 7261f2d..5933ad3 100644 --- a/src/clock.c +++ b/src/clock.c @@ -114,11 +114,42 @@ mdelay(u32 count) tscsleep(count * khz); } +// Return the TSC value that is 'msecs' time in the future. +u64 +calc_future_tsc(u32 msecs) +{ + u32 khz = GET_VAR(CS, cpu_khz); + return rdtscll() + ((u64)khz * msecs); +} + /**************************************************************** * Init ****************************************************************/ +static int +rtc_updating() +{ + // This function checks to see if the update-in-progress bit + // is set in CMOS Status Register A. If not, it returns 0. + // 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. + + if ((inb_cmos(CMOS_STATUS_A) & 0x80) == 0) + return 0; + u64 end = calc_future_tsc(1); + do { + if ((inb_cmos(CMOS_STATUS_A) & 0x80) == 0) + return 0; + } while (rdtscll() <= end); + + // update-in-progress never transitioned to 0 + return -1; +} + static void pit_setup() { @@ -142,6 +173,7 @@ timer_setup() calibrate_tsc(); pit_setup(); + rtc_updating(); u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS)); u32 ticks = (seconds * 18206507) / 1000000; u32 minutes = bcd2bin(inb_cmos(CMOS_RTC_MINUTES)); @@ -169,26 +201,6 @@ init_rtc() * Standard clock functions ****************************************************************/ -static u8 -rtc_updating() -{ - // This function checks to see if the update-in-progress bit - // is set in CMOS Status Register A. If not, it returns 0. - // 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. - // The count I use below guarantees coverage or more than - // this time, with any reasonable IPS setting. - - u16 count = 25000; - while (--count != 0) { - if ( (inb_cmos(CMOS_STATUS_A) & 0x80) == 0 ) - return 0; - } - return 1; // update-in-progress never transitioned to 0 -} - // get current clock count static void handle_1a00(struct bregs *regs) |