[comp.os.minix] Clock Diffs for Real Time Clock

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