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