[comp.os.minix] readclock.c for PS2/30

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 );
}