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.
=======================================================