[comp.os.minix] Real time clock

sch@oce.UUCP (06/16/87)

A few days ago, Ed Subelman posted a program to read the date and time from
a 'Multi I/O card'. In my XT clone I have such a card, but the program didn't
seem to work properly.
Under MS-DOS I use the program timer.com (version 1.3) to read and set my 
real-time clock. I also have a small program, sysclk.com, that does just the
thing I want, it reads the real-time clock and sets the system clock. After 
disassembling this program, I found that my real time clock uses address
0x0340 (address 0x0240 is also supported). This file contains a program that
works on my 'made in the orient Multi I/O card', it's a quick and dirty
interpretation of the disassembled code of the file sysclk.com.
The port I/O routines are the same as in the posting of Ed Subelman, they are
from the file klib88.s.

---------- begin of sysclk.c -------------------------------------------------
/* sysclk.c - get date and time from real time clock on address 0x0240 or 
 * address 0x0340 and print it on standard out as MMDDYYhhmmss.
 * 
 * Should be run in /etc/rc as:   date `sysclk`
 *
 * Compile as:   cc -o sysclk sysclk.c port_io.s
 *
 * Author: Rob Prikanowski 
 *         06-jun-87
 */

int	tim_addr,bad_clk;
char	comm[] = { 7, 6, 9, 4, 3, 2, 1, 5 };
char	data_in[] = { 0, 0, 0, 0, 0, 0, 0, 7 };

main()
{
    get_addr();
    if (bad_clk)
    {
        prints("Clock not found!\n");
        exit(-1);
    }
    get_time();
    exit(0);
} /* end of function: main */

get_time()
{
    short	num;
    int		i,inp_val,offset;
    char	*out_p,*in_p;

    num = 6;
    out_p = comm;
    in_p = data_in;
    do {
        offset = (int) *out_p++;
        port_in(offset + tim_addr,&inp_val);
        *in_p++ = (char) adjust(inp_val);
        num--;
    } while (num);
    in_p = data_in;
    for (i=0; i!=6; i++) num2((int) *in_p++);
    prints("\n");
} /* end of function: get_time */

get_addr()
{
    short	inp_val;

    tim_addr = 0x0240;
    port_in(tim_addr + 1,&inp_val);
    if (inp_val > 0x99)
    {
        tim_addr = 0x0340;
        port_in(tim_addr + 1,&inp_val);
        if (inp_val > 0x99)
        {
            bad_clk = 1;
        }
        else init_clk();
    }
    else init_clk();
} /* end of function: get_addr */

init_clk()
{
    short	temp;
    int		inp_val;

    port_in(tim_addr + 8,&inp_val);
    if (inp_val != 0)
    {
        temp = inp_val & 7;
        port_in(tim_addr + 7,&inp_val);
        inp_val = adjust(inp_val);
        inp_val = inp_val >= 7 ? 112 : inp_val << 4;
        if (inp_val < temp)
        {
            inp_val |= 0x80;
            port_out(tim_addr + 8,inp_val);
            port_in(tim_addr + 9,&inp_val);
            inp_val++;
            port_out(tim_addr + 9,inp_val);
        }
    }
    bad_clk = 0;
} /* end of function: init_clk */

adjust(val)
short	val;
{
    int	temp;

    val &= 0x00FF;
    val <<= 4;
    temp = (val & 0x00FF) >> 4;
    val &= 0xFF00;
    val |= temp;
    temp = (val >> 8) * 10;
    val &= 0x00FF;
    val += temp;
    val &= 0x00FF;
    return(val);
} /* end of function: adjust */

num2(n)
int	n;
{
    if (n < 10) prints("0%s",itoa(n));
    else prints("%s",itoa(n));
} /* end of function: num2 */
---------- begin of port_io.s ------------------------------------------------
| this file was grafted from klib88.s

.globl _port_out, _port_in

|*===========================================================================*
|*				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
---------- end of port_io.s --------------------------------------------------



					Rob Prikanowski
					Oce Nederland B.V.
					Venlo
					The Netherlands

=======================================================
 This note does not necessarily represent the position
 of Oce-Nederland B.V. Therefore no liability or
 responsibility for whatever will be accepted.
=======================================================