[comp.os.minix] set date/time from quadram clock

bunda@cs.utexas.edu (John Bunda) (07/13/88)

Since I couldn't find one in the archives, here is code
to set minix date and time from the clock-calendar on a
Quadram Quadboard.  It is a rather transparent conversion
of a wretched basic program, but it works...

The port_io.s file is lifted from klib88.s.  No makefile is
included, just compile with:  
    cc -o qclk qclk.c port_io.s
and chmem to 2k or so.
then change the date line in /etc/rc to:
qclk | date -q >/dev/null
to set the date and time when you boot.  This is a minix shell
archive.  
----------------cut here------------------------
echo x - qclk.c
gres '^X' '' > qclk.c << '/'
X/*   qclk.c
X
X     Read current time and date from battery clock
X     on Quadram or compatable clock, and place on
X     standard output as MMDDYYhhmmss.
X
X     the clock chip is the OKI MSM5832, interfaced through
X     an Intel 8255 or similar.  This was adapted from a BASIC
X     program provided with the Quadboard.
X
X     this is how the clock vector maps to time/date:
X
X     index  10 9 | 8  7 | 12  11 | 5  4 | 3  2 | 1  0
X     digit    MM  |  DD  |   YY   |  HH  |  MM |  SS
X
X   (c) 1988 John Bunda, Austin, TX.  Permission granted 
X   to copy and distribute non-commercially.  User assumes 
X   all risks in the use of this software; no warranty.
X                                                   */
X/* possible values to be output to ctl_port */
X
X#define HOLD           0x90  /* stop clock (to read) */
X#define READ           0xb0  /* set data bus to output */
X#define WRITE          0xd0  /* set data bus to input */
X
X/* direction of 8255 A port (sent to dir_port) */
X
X#define DATA_IN      0x90
X#define DATA_OUT     0x80
X
Xint data_port,select_port,ctl_port,dir_port;
Xstatic char q[14];
Xstatic int ord[13] = {10, 9, 8, 7, 12, 11, 5, 4, 3, 2, 1, 0};
X
X
Xmain()
X{
X   int i,t;
X   char d;
X   set_ports();        /* enable and set access ports */
X   adjust_clock();     /* do correction adjustments */
X
X   /* read current time and date from clock */
X
X   port_out (dir_port, DATA_IN);
X   port_out (ctl_port, READ);
X   for ( i = 0 ; i < 12; i++)
X     {
X       port_out (select_port , ord[i]);
X       port_in (data_port, &t);
X       d = 48 + (t & (ord[i]==5 || ord[i]==8 ? 3 : 15)); 
X       printf("%c",d);
X     }
X   printf("\n");
X}
X
Xset_ports()
X{
X   int t;
X   port_out(0x313,0x90);
X   port_out(0x311,97);
X   port_in (0x311, &t);
X   data_port = (t == 97 ? 0x310 : 0x210);
X   select_port = data_port + 1;
X   ctl_port = data_port + 2;
X   dir_port = data_port + 3;
X}
X
X
X
Xadjust_clock()
X   /* various necessary adjustments for leap year, etc. */
X{
X  int t,x,i,th,leap;
X  port_out (dir_port, DATA_IN);
X  port_out (select_port, 5);
X  port_out (ctl_port, READ);
X  port_in (data_port, &th);
X  port_out (dir_port, DATA_OUT);
X  port_out (select_port, 5);
X  port_out (ctl_port, HOLD);
X  port_out (data_port, th & 3 | 8);
X  port_out (ctl_port, WRITE);
X
X  /* adjust for leap year */
X
X  port_out (dir_port, DATA_IN);
X  port_out (ctl_port, READ);
X
X   for (i = 9; i <= 12 ; i++)
X     {
X       port_out (select_port, i);
X       port_in (data_port, &t);
X       q[i] = t;
X     }
X   leap = 10 * q[10] + q[9] > 2 & 1;
X   leap = 4 & (leap + 10 * q[12] + q[11] & 3) == 0;
X   port_out (dir_port, DATA_IN);
X   port_out (select_port, 8);
X   port_out (ctl_port, READ);
X   port_in (data_port, &x);
X   port_out (dir_port, DATA_OUT);
X   port_out (select_port, 8);
X   port_out (ctl_port, HOLD);
X   port_out (data_port, x & 3 | leap);
X   port_out (ctl_port, WRITE);
X}
/
echo x - port_io.s
gres '^X' '' > port_io.s << '/'
X| this file was grafted from klib88.s
X
X.globl _port_out, _port_in
X
X
X
X|*===========================================================================*
X|*                              port_out   *
X|*===========================================================================*
X| port_out(port, value) writes 'value' on the I/O port 'port'.
X
X_port_out:
X        push bx                 | save bx
X        mov bx,sp               | index off bx
X        push ax                 | save ax
X        push dx                 | save dx
X        mov dx,4(bx)            | dx = port
X        mov ax,6(bx)            | ax = value
X        out                     | output 1 byte
X        pop dx                  | restore dx
X        pop ax                  | restore ax
X        pop bx                  | restore bx
X        ret                     | return to caller
X
X
X|*===========================================================================*
X|*                              port_in   *
X|*===========================================================================*
X| port_in(port, &value) reads from port 'port' and puts the result in 'value'.
X_port_in:
X        push bx                 | save bx
X        mov bx,sp               | index off bx
X        push ax                 | save ax
X        push dx                 | save dx
X        mov dx,4(bx)            | dx = port
X        in                      | input 1 byte
X        xorb ah,ah              | clear ah
X        mov bx,6(bx)            | fetch address where byte is to go
X        mov (bx),ax             | return byte to caller in param
X        pop dx                  | restore dx
X        pop ax                  | restore ax
X        pop bx                  | restore bx
X        ret                     | return to caller
/


-- 
................................................................
John Bunda            UT CS Dept.      The proof is trivial, and
bunda@cs.utexas.edu   Austin, Texas    left as an exercise.