inf2007@vax.rz.uni-wuerzburg.dbp.de (inf2007) (12/15/89)
We have Minix running on several PS2/30 for teaching. This PC has a non AT-
compatible clock. The new readclock.c can read it.
Robert Regn regn@uniwue.unido.uucp
or ..!uunet!mcvax!unido!uniwue!regn
/* readclock - read the AT real time clock Authors: T. Holm & E. Froese */
/************************************************************************/
/* */
/* readclock.c */
/* */
/* Read the AT real time clock, write the time to */
/* standard output in a form usable by date(1). */
/* If the system is an AT then the time is read */
/* from the built-in clock, and written to standard */
/* output in the form: */
/* */
/* mmddyyhhmmss */
/* */
/* If the system is not an AT then ``-q'' is written */
/* to standard output. This is useful for placement in */
/* the ``/etc/rc'' script: */
/* */
/* /usr/bin/date `/usr/bin/readclock` </dev/tty */
/* */
/************************************************************************/
/* origination 1987-Dec-29 efth */
/************************************************************************/
/* On a IBM PS/2 Model 30 you have to read the components from */
/* different addresses. The clock registers are directly mapped */
/* to IO-addresses. This version can be compiled with "-DPS2". */
/* M. Roetzer and Robert Regn University of Wuerzburg */
/************************************************************************/
/* 1989-Dec-14 */
/************************************************************************/
#ifndef PS2
#define CPU_TYPE_SEGMENT 0xFFFF /* BIOS segment for CPU type */
#define CPU_TYPE_OFFSET 0x000E /* BIOS offset for CPU type */
#define PC_AT 0xFC /* IBM code for PC-AT (0xFFFFE) */
#define CLK_ELE 0x70 /* ptr corresponding to element of time to be */
#define CLK_IO 0x71 /* read or written is written to port clk_ele */
/* the element can then be read or written by */
/* reading or writing port clk_io. */
#define YEAR 9 /* Clock register addresses */
#define MONTH 8
#define DAY 7
#define HOUR 4
#define MINUTE 2
#define SECOND 0
#define STATUS 0x0b
#else
#define YEAR 0xe9
#define MONTH 0xe7
#define DAY 0xe6
#define HOUR 0xe4
#define MINUTE 0xe3
#define SECOND 0xe2
#define STATUS 0xb0
#endif
#define BCD_TO_DEC(x) ( (x>>4) * 10 + (x & 0x0f) )
struct time
{ unsigned year;
unsigned month;
unsigned day;
unsigned hour;
unsigned minute;
unsigned second;
};
main()
{
struct time time1;
struct time time2;
int i;
#ifndef PS2
if ( peek( CPU_TYPE_SEGMENT, CPU_TYPE_OFFSET ) != PC_AT ) {
printf( "-q\n" );
exit( 1 );
}
#endif
for ( i=0; i<10; i++ ) {
get_time( &time1 );
get_time( &time2 );
if ( time1.year == time2.year &&
time1.month == time2.month &&
time1.day == time2.day &&
time1.hour == time2.hour &&
time1.minute == time2.minute &&
time1.second == time2.second )
{
printf( "%02d%02d%02d%02d%02d%02d\n",
time1.month, time1.day, time1.year,
time1.hour, time1.minute, time1.second );
exit( 0 );
}
}
printf( "-q\n" );
exit( 1 );
}
/***********************************************************************/
/* */
/* get_time( time ) */
/* */
/* Update the structure pointed to by time with the current time */
/* as read from the hardware real-time clock of the AT. */
/* If necessary, the time is converted into a binary format before */
/* being stored in the structure. */
/* */
/***********************************************************************/
get_time( t )
struct time *t; {
t->year = read_register( YEAR );
t->month = read_register( MONTH );
t->day = read_register( DAY );
t->hour = read_register( HOUR );
t->minute = read_register( MINUTE );
t->second = read_register( SECOND );
if ( (read_register(STATUS) & 0x04) == 0) {
/* convert BCD to binary if necessary */
t->year = BCD_TO_DEC( t->year );
t->month = BCD_TO_DEC( t->month );
t->day = BCD_TO_DEC( t->day );
t->hour = BCD_TO_DEC( t->hour );
t->minute = BCD_TO_DEC( t->minute );
t->second = BCD_TO_DEC( t->second );
}
}
read_register( reg_addr )
#ifndef PS2
char reg_addr;
#else
int reg_addr;
#endif
{
int val;
#ifndef PS2
port_out( CLK_ELE, reg_addr );
port_in(CLK_IO, &val);
#else
port_in(reg_addr, &val);
#endif
return( val );
}