[comp.os.minix] Read the battery-backed-up clock on the PC/AT

martin@minster.UUCP (03/10/87)

Thanks to everyone who sent me information about the clock on the IBM PC/AT,
I guess I'll probably be receiving mail for ever more, but never mind, it's
nice that people bother to help....
It turns out I had guessed right, but the behavior was slightly different
from what I expected, so I hadn't realised I'd got it right!!

Anyway here is the program I hacked up in the last hour (therefore not much
testing has been done :-)). It works on my system, my /etc/rc now says:

	/usr/bin/date `/usr/bin/rddate`

and I don't have to worry about the time any more (phew!).

Exercises for the reader:
1	Make a time.h header, and a bbupclock.h header, removing the
	horrible constants.
2	Allow the clock to be set.
3	At the moment the clock is in 24 hour, BCD mode. rddate should
	(possibly) understand the other formats, just in case.
4	This could be incorporated into date, at the expense of portability.
5	Add a /dev/time special device, so that this can also be done
	nicely on systems with memory management.
6	And probably lots more.

Lets hope this starts the ball rolling, and we begin to get some sources
posted here.

	Martin

usenet: mcvax!ukc!minster!martin
surface:
	Martin C. Atkins
	Department of Computer Science
	University of York
	Heslington
	York Y01 5DD
	ENGLAND

--

: sh this file
echo x - rddate.c
gres '^X' '' > rddate.c << '/'
X/*
X *	Program to read the date/time from the PC/AT's battery-backed-up
X *	clock, suitable for use with date.
X *	Martin C. Atkins, 10/3/87
X *
X *	Copy this freely, but Keep this comment!!
X */
X#include <stdio.h>
X
Xstruct tm {
X	int day;
X	int month;
X	int year;
X	int hour;
X	int minute;
X	int second;
X} tm;
X
X
Xmain()
X{
X	int attempt = 10;
X	struct tm now, then;
X
X	do {
X		readtime(&then);
X		readtime(&now);
X	} while (--attempt > 0 && differ(&now, &then));
X
X	if(attempt <= 0) {
X		fprintf(stderr, "Can't get a consistant time\n");
X		exit(1);
X	}
X	putnum(now.month);
X	putnum(now.day);
X	putnum(now.year);
X	putnum(now.hour);
X	putnum(now.minute);
X	putnum(now.second);
X	putchar('\n');
X	fflush(stdout);
X	exit(0);
X}
X
Xreadtime(tb)
Xstruct tm *tb;
X{
X	tb->second = rdclock(0);
X	tb->minute = rdclock(2);
X	tb->hour = rdclock(4);
X	tb->day = rdclock(7);
X	tb->month = rdclock(8);
X	tb->year = rdclock(9);
X}
X
Xrdclock(port)
Xint port;
X{
X	int v;
X	port_out(0x70, port);
X	v = port_in(0x71);
X	return (v&0x0f) + (v>>4)*10;
X}
X
Xdiffer(a, b)
Xstruct tm *a, *b;
X{
X	if(a->second != b->second || a->minute != b->minute)
X		return 1;
X	if(a->hour != b->hour || a->day != b->day)
X		return 1;
X	if(a->month != b->month || a->year != b->year)
X		return 1;
X	return 0;
X}
X
Xputnum(v)
Xint v;
X{
X	putchar('0' + v/10);
X	putchar('0' + v%10);
X}
/
echo x - ports.s
gres '^X' '' > ports.s << '/'
X|
X|	routines to read/write i/o ports
X|	Similar to those in klib88.s
X|
X
X	.globl	_port_in, _port_out
X
X|
X|	i = port_in(port)
X|
X_port_in:
X	push	bx
X	mov	bx,sp
X	push	dx
X	mov	dx,4(bx)
X	in
X	xorb	ah,ah
X	pop	dx
X	pop	bx
X	ret
X
X|
X|	port_out(port, data)
X|
X_port_out:
X	push	bx
X	mov	bx,sp
X	push	ax
X	push	dx
X	mov	dx,4(bx)
X	mov	ax,6(bx)
X	out
X	pop	dx
X	pop	ax
X	pop	bx
X	ret
/

n0ano@wldrdg.UUCP (03/19/87)

In order to utilize the battery back-up clock on the PC/AT,
..!minster!martin (martin @ Department of Computer Science,
University of York, England suggests adding the following to the
/etc/rc file:

> 
> 	/usr/bin/date `/usr/bin/rddate`
> 

The concern I have with this is that the back-graves (``) are
implemented in the shell with a pipe and a pipe allocates a
new i-node.  If this command were executed before the current
file system had been checked problems could result.  Allocating
a new i-node in a corrupted file system is a bad thing to do.

Admittedly this problem is probably unlikely to occur under MINIX
since the root file system, the file system this command is most
likely to be running under, is in RAM and is by definition
uncorrupted.  Still, I think it would be better to have "rddate"
just do an "stime" system call and set the date directly.

Note that this discussion applies to UNIX System V.  I have not
been able to verify this under MINIX since Prentice-Hall has not
seen fit to release my copy of MINIX yet.  We will of course ignore
the fact that I paid them for MINIX two months ago.

Donald Dugger
Wildridge Consulting
..!nbires!onecom!wldrdg!n0ano