[comp.os.minix] Loader for MINIX clock from AT CMOS RAM

ESC1332%ESOC.BITNET@wiscvm.wisc.edu (K.Keyte) (08/27/87)

The following contains two files:

           ldclock.c         For loading the clock
           ports.s           For port I/O

Compile ldclock.c and load it with ports.s (under MINIX this is done
with 'cc -o ldclock ldclock.c ports.s')

Split the two programs at the cuts.

Please send me any comments!

   Karl (ESC1332@ESOC.BITNET)

**------------------------ CUT HERE ----------------------**

/**************************************************************************
 *                                                                        *
 *  A procedure to load the MINIX software clock from the battery backed  *
 *  real-time clock of the PC-AT computer. The data is taken from some of *
 *  the 64 bytes of CMOS RAM and addressed using:                         *
 *                                                                        *
 *      Port   0x70 : CMOS RAM index port - Write Only                    *
 *             0x71 : CMOS RAM data port - Read/Write                     *
 *                                                                        *
 *  Written by Karl Keyte (ESC1332@ESOC.BITNET)                           *
 *  Date : 20th July 1987                                                 *
 *                                                                        *
 **************************************************************************/

#define cmos_index 0x70
#define cmos_data 0x71
#define SECONDS 0x00
#define MINUTES 0x02
#define HOURS 0x04
#define DATE 0x07
#define MONTH 0x08
#define YEAR 0x09

int days[] = {0,31,59,90,120,151,181,212,243,273,304,334,
              0,31,60,91,121,152,182,213,244,274,305,335};

main()
{
   unsigned long ct;
   int dt, hrs, mins, mnth, secs, year;
   short extra, leap;

   get_value(&secs, SECONDS);
   get_value(&mins, MINUTES);
   get_value(&hrs, HOURS);
   get_value(&dt, DATE);
   get_value(&mnth, MONTH);
   get_value(&year, YEAR);

   if (year<80) year += 100;

   leap = (mnth>2 && year%4 == 0) ? 1 : 0;
   extra = leap + (year-69)/4;

   ct = secs;
   ct += mins*60;
   ct += (long) hrs*3600;
   ct += (long) (days[leap*12+mnth-1]+dt-1+extra)*86400;
   ct += (long) (year-70)*365*86400;

   if (stime(&ct))
      printf("Permission denied\n");
}

/*------------------------------------------------------------------------*/

get_value(storage, port_offset)
unsigned int      *storage,
                  port_offset;
{
   int   temp = 0;

   *storage = 0xff;
   while (*storage == 0xff || *storage != temp) {
      port_out(cmos_index,port_offset);
      port_in(cmos_data,storage);
      port_out(cmos_index,port_offset);
      port_in(cmos_data,&temp);
   }
   *storage = 10*(*storage>>4)+(*storage & 0x0f);
}


**------------------------- CUT HERE ---------------------**

|*===========================================================================*
|*                              port_out                                     *
|*===========================================================================*
| port_out(port, value) writes 'value' on the I/O port 'port'.

_port_out:
        push bx                 | save bx
        mov bx,sp               | index off bx
        push ax                 | save ax
        push dx                 | save dx
        mov dx,4(bx)            | dx = port
        mov ax,6(bx)            | ax = value
        out                     | output 1 byte
        pop dx                  | restore dx
        pop ax                  | restore ax
        pop bx                  | restore bx
        ret                     | return to caller


|*===========================================================================*
|*                              port_in                                      *
|*===========================================================================*
| port_in(port, &value) reads from port 'port' and puts the result in 'value'.
_port_in:
        push bx                 | save bx
        mov bx,sp               | index off bx
        push ax                 | save ax
        push dx                 | save dx
        mov dx,4(bx)            | dx = port
        in                      | input 1 byte
        xorb ah,ah              | clear ah
        mov bx,6(bx)            | fetch address where byte is to go
        mov (bx),ax             | return byte to caller in param
        pop dx                  | restore dx
        pop ax                  | restore ax
        pop bx                  | restore bx
        ret                     | return to caller