From 4e6c9706240a33e13de3da98815d8f4d281a9e9a Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 13 Dec 2008 10:45:50 -0500 Subject: [PATCH] Implement time based checks even when looping on an ioport. Implement real timeout code in ATA. Implement real timeout code for RTC updating check. --- src/ata.c | 16 ++++------------ src/clock.c | 52 ++++++++++++++++++++++++++++++++-------------------- src/util.h | 1 + 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/ata.c b/src/ata.c index 77f5e34..53f9196 100644 --- a/src/ata.c +++ b/src/ata.c @@ -37,10 +37,9 @@ static int await_ide(u8 when_done, u16 base, u16 timeout) { - u32 time=0, last=0; + u64 end = calc_future_tsc(timeout); for (;;) { u8 status = inb(base+ATA_CB_STAT); - time++; u8 result = 0; if (when_done == BSY) result = status & ATA_CB_STAT_BSY; @@ -55,20 +54,13 @@ await_ide(u8 when_done, u16 base, u16 timeout) if (result) return status; - // mod 2048 each 16 ms - if (time>>16 != last) { - last = time >>16; - dprintf(6, "await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ" - ",!BSY_!DRQ,!BSY_RDY) %d time= %d timeout= %d\n" - , when_done, time>>11, timeout); - } if (status & ATA_CB_STAT_ERR) { dprintf(1, "await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ" - ",!BSY_!DRQ,!BSY_RDY) %d status=%x time= %d timeout= %d\n" - , when_done, status, time>>11, timeout); + ",!BSY_!DRQ,!BSY_RDY) %d status=%x timeout=%d\n" + , when_done, status, timeout); return -1; } - if (timeout == 0 || (time>>11) > timeout) + if (rdtscll() >= end) break; } dprintf(1, "IDE time out\n"); 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) diff --git a/src/util.h b/src/util.h index 5bbe9e8..0966c4c 100644 --- a/src/util.h +++ b/src/util.h @@ -125,6 +125,7 @@ void timer_setup(); void ndelay(u32 count); void udelay(u32 count); void mdelay(u32 count); +u64 calc_future_tsc(u32 msecs); void handle_1583(struct bregs *regs); void handle_1586(struct bregs *regs); -- 2.39.5