aboutsummaryrefslogtreecommitdiff
path: root/src/clock.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2008-12-13 10:45:50 -0500
committerKevin O'Connor <kevin@koconnor.net>2008-12-13 10:45:50 -0500
commit4e6c9706240a33e13de3da98815d8f4d281a9e9a (patch)
tree045ebf1724d9bb9b37f3d8f4d3dd247d6f769b1c /src/clock.c
parent4bbd3b3599714089a8e2c451ae62cc056760c746 (diff)
downloadseabios-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.c52
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)