gis@datlog.co.uk ( Ian Stewartson ) (06/02/88)
The clock diffs as promised in my earlier article. I misunderstood something about inews and have been out of the office - thus the delay. Just a note about the date diffs. When I was testing this code, I came across the problem corrected by the diffs whereby Febuary had 30 days. **** DIFFS for kernel/clock.c **** sed -e 's/^X//' > clock.c.diff << '/' X41a42,51 X> #define MINUTE 60L /* Seconds in a minute */ X> #define HOUR (60L * MINUTE) /* Seconds in an hour */ X> #define DAY (24L * HOUR) /* Seconds in a day */ X> #define YEAR (365L * DAY) /* Seconds in a year */ X> #define LYEAR (366L * DAY) /* Seconds in a leap year */ X> #define TO_BCD(x) x = ((x / 10) << 4) | (x % 10) X> #define FROM_BCD(x) x = ((x >> 4) * 10) + (x & 0x0f) X> #define REDUCE(x,y) while (stime >= y) {stime -= y; x++;} X> #define CMOS_CLOCK 0x70 /* CMOS Clock port */ X> #define CMOS_CLOCK1 0x71 /* CMOS Clock port */ X121a132,173 X> PRIVATE struct { X> int tm_sec; /* Number of seconds in BCD */ X> int tm_min; /* Number of minutes in BCD */ X> int tm_hour; /* Number of hours in BCD */ X> int tm_mday; /* Month day in BCD */ X> int tm_mon; /* Month in BCD */ X> int tm_year; /* Year in BCD */ X> int tm_century; /* Century in BCD */ X> } RC_time; X> X> PRIVATE int days_per_month[] = X> { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; X> X> /* X> * Wait for Real Time Clock to go ready X> */ X> X> PRIVATE rt_clock_wait() X> { X> int i; X> unsigned int j; X> X> for (i = 0; i < 600; i++) X> { X> port_out (CMOS_CLOCK, 0x0a); X> port_in (CMOS_CLOCK1, &j); X> X> if (!(j & 0x80)) X> return; X> } X> X> /* If waited to go ready - re-initialise it */ X> X> port_out (CMOS_CLOCK, 0x0a); X> port_out (CMOS_CLOCK1, 0x26); X> port_out (CMOS_CLOCK, 0x0b); X> port_out (CMOS_CLOCK1, 0x82); X> port_out (CMOS_CLOCK, 0x0c); X> port_in (CMOS_CLOCK1, &j); X> port_out (CMOS_CLOCK, 0x0d); X> port_in (CMOS_CLOCK1, &j); X> } X126,131c178,242 X< PRIVATE do_get_time() X< { X< /* Get and return the current clock time in ticks. */ X< X< mc.m_type = REAL_TIME; /* set message type for reply */ X< mc.NEW_TIME = boot_time + realtime/HZ; /* current real time */ X--- X> PRIVATE do_get_time() { X> /* Get and return the current clock time in ticks. */ X> X> long stime = 0L; X> int i, j; X> X> mc.m_type = REAL_TIME; /* set message type for reply */ X> X> /* If this is not an AT, no real time clock */ X> X> if (!pc_at) X> { X> mc.NEW_TIME = boot_time + realtime/HZ; /* current real time */ X> return; X> } X> X> /* Process the real time clock */ X> X> rt_clock_wait(); X> lock(); X> port_out (CMOS_CLOCK, 0); X> port_in (CMOS_CLOCK1, &RC_time.tm_sec); X> port_out (CMOS_CLOCK, 2); X> port_in (CMOS_CLOCK1, &RC_time.tm_min); X> port_out (CMOS_CLOCK, 4); X> port_in (CMOS_CLOCK1, &RC_time.tm_hour); X> port_out (CMOS_CLOCK, 7); X> port_in (CMOS_CLOCK1, &RC_time.tm_mday); X> port_out (CMOS_CLOCK, 8); X> port_in (CMOS_CLOCK1, &RC_time.tm_mon); X> port_out (CMOS_CLOCK, 9); X> port_in (CMOS_CLOCK1, &RC_time.tm_year); X> port_out (CMOS_CLOCK, 0x32); X> port_in (CMOS_CLOCK1, &RC_time.tm_century); X> unlock(); X> X> /* Convert from BCD */ X> X> FROM_BCD(RC_time.tm_sec); X> FROM_BCD(RC_time.tm_min); X> FROM_BCD(RC_time.tm_hour); X> FROM_BCD(RC_time.tm_mday); X> FROM_BCD(RC_time.tm_mon); X> FROM_BCD(RC_time.tm_year); X> FROM_BCD(RC_time.tm_century); X> X> RC_time.tm_year += (RC_time.tm_century * 100); X> j = RC_time.tm_year - 1970; X> RC_time.tm_mon--; X> days_per_month[1] = ((j + 2) % 4 == 0) ? 29 : 28; X> X> for (i = 0; i < RC_time.tm_mon; i++) X> stime += (long)days_per_month[i]; X> X> stime += (long)j * 365L; X> stime += (long)((j + 1) / 4); X> stime += (long)(RC_time.tm_mday - 1); X> stime *= DAY; X> stime += (long)RC_time.tm_hour * HOUR; X> stime += (long)RC_time.tm_min * MINUTE; X> stime += RC_time.tm_sec; X> X> mc.NEW_TIME = stime; X> boot_time = stime - realtime/HZ; X> return; X143c254,330 X< boot_time = m_ptr->NEW_TIME - realtime/HZ; X--- X> real_time length; X> real_time stime = m_ptr->NEW_TIME; X> int temp; X> X> /* If this is not an AT, there is no real time clock */ X> X> boot_time = stime - realtime/HZ; X> X> if (!pc_at) X> return; X> X> /* Otherwise, use the real time clock and get the year number */ X> X> RC_time.tm_year = 1970; X> X> while (stime > 0L) X> { X> length = (RC_time.tm_year % 4 == 0) ? LYEAR : YEAR; X> X> if (stime < length) X> break; X> X> stime -= length; X> RC_time.tm_year++; X> } X> X> /* Get the year day number, hours, minutes and seconds */ X> X> days_per_month[1] = (RC_time.tm_year % 4 == 0) ? 29 : 28; X> X> RC_time.tm_mon = 0; X> while (stime >= (days_per_month[RC_time.tm_mon] * DAY)) X> stime -= days_per_month[RC_time.tm_mon++] * DAY; X> X> RC_time.tm_mon++; X> X> RC_time.tm_mday = 1; X> REDUCE(RC_time.tm_mday, DAY); X> X> X> RC_time.tm_hour = 0; X> REDUCE(RC_time.tm_hour, HOUR); X> X> RC_time.tm_min = 0; X> REDUCE(RC_time.tm_min, MINUTE); X> X> RC_time.tm_sec = (int)stime; X> X> /* Convert to BCD */ X> X> RC_time.tm_century = RC_time.tm_year / 100; X> RC_time.tm_year %= 100; X> TO_BCD(RC_time.tm_sec); X> TO_BCD(RC_time.tm_min); X> TO_BCD(RC_time.tm_hour); X> TO_BCD(RC_time.tm_mday); X> TO_BCD(RC_time.tm_mon); X> TO_BCD(RC_time.tm_year); X> TO_BCD(RC_time.tm_century); X> X> rt_clock_wait(); X> lock(); X> port_out (CMOS_CLOCK, 0); X> port_out (CMOS_CLOCK1, RC_time.tm_sec); X> port_out (CMOS_CLOCK, 2); X> port_out (CMOS_CLOCK1, RC_time.tm_min); X> port_out (CMOS_CLOCK, 4); X> port_out (CMOS_CLOCK1, RC_time.tm_hour); X> port_out (CMOS_CLOCK, 7); X> port_out (CMOS_CLOCK1, RC_time.tm_mday); X> port_out (CMOS_CLOCK, 8); X> port_out (CMOS_CLOCK1, RC_time.tm_mon); X> port_out (CMOS_CLOCK, 9); X> port_out (CMOS_CLOCK1, RC_time.tm_year); X> port_out (CMOS_CLOCK, 0x32); X> port_out (CMOS_CLOCK1, RC_time.tm_century); X> unlock(); / **** END OF DIFFS for kernel/clock.c **** Ian Stewartson Data Logic Ltd, Queens House, Greenhill Way, Harrow, Middlesex, HA1 1YR, UK. (Phone) +44 1 863 0383 (Telex) 888103 (Fax) +44 1 861 2010 (Network) gis@datlog.co.uk or ukc!datlog!gis