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