Subject: GT307 clock program (#424)
Index:	sbin/gt307/gt307.c 2.11BSD

Description:
	This is a contributed program to read the Computer Products
	GT307 Clock Calendar board.  

Repeat-By:
	N/A
Fix:
	Thanks to Robin Birch (robin@falstaf.demon.co.uk) for contributing
	this to 2.11BSD! 

	I only created the Makefile and manpage so errors in those should
	be directed to me or the newsgroup.  Questions or problems with
	the program should be directed to Robin since he has one of the
	boards.

	To install this program cut where indicated and save to a file 
	(/tmp/424).  Then:

		cd /tmp
		sh 424
		patch -p0 < 424.patch
		sh 424.shar
		cd /usr/src/sbin/gt307
		make
		make install
		make clean

	That's all there is to it.  Thanks again Robin.

	As always this and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.

-----------------------------cut here--------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	424.patch
#	424.shar
# This archive created: Tue Aug 10 19:57:24 1999
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f '424.patch'
then
	echo shar: "will not over-write existing file '424.patch'"
else
sed 's/^X//' << \SHAR_EOF > '424.patch'
X*** /usr/src/sbin/Makefile.old	Fri Jan 10 19:56:49 1997
X--- /usr/src/sbin/Makefile	Wed Jul 21 19:35:35 1999
X***************
X*** 1,13 ****
X  #
X  # Public domain - 1996/10/26 - sms
X  #
X! #	@(#)Makefile	1.2 (2.11BSD) 1997/1/10
X  #
X  DESTDIR=
X  CFLAGS=	-O
X  SEPFLAG= -i
X  
X! SUBDIR= XNSrouted badsect clri dcheck dmesg dump dumpfs fsck icheck \
X  	ifconfig init mkfs mknod mkpasswd mount ncheck newfs \
X  	quotacheck reboot restor route routed savecore \
X  	shutdown slattach swapon testnet tunefs umount
X--- 1,13 ----
X  #
X  # Public domain - 1996/10/26 - sms
X  #
X! #	@(#)Makefile	1.3 (2.11BSD) 1999/7/21
X  #
X  DESTDIR=
X  CFLAGS=	-O
X  SEPFLAG= -i
X  
X! SUBDIR= XNSrouted badsect clri dcheck dmesg dump dumpfs fsck gt307 icheck \
X  	ifconfig init mkfs mknod mkpasswd mount ncheck newfs \
X  	quotacheck reboot restor route routed savecore \
X  	shutdown slattach swapon testnet tunefs umount
X*** /VERSION.old	Thu Aug  5 20:59:43 1999
X--- /VERSION	Tue Aug 10 19:56:45 1999
X***************
X*** 1,5 ****
X! Current Patch Level: 423
X! Date: August 5, 1999
X  
X  2.11 BSD
X  ============
X--- 1,5 ----
X! Current Patch Level: 424
X! Date: August 10, 1999
X  
X  2.11 BSD
X  ============
SHAR_EOF
fi
if test -f '424.shar'
then
	echo shar: "will not over-write existing file '424.shar'"
else
sed 's/^X//' << \SHAR_EOF > '424.shar'
X#! /bin/sh
X# This is a shell archive, meaning:
X# 1. Remove everything above the #! /bin/sh line.
X# 2. Save the resulting text in a file.
X# 3. Execute the file with /bin/sh (not csh) to create:
X#	/usr/src/sbin/gt307
X# This archive created: Tue Aug 10 19:55:25 1999
Xexport PATH; PATH=/bin:/usr/bin:$PATH
Xif test ! -d '/usr/src/sbin/gt307'
Xthen
X	mkdir '/usr/src/sbin/gt307'
Xfi
Xcd '/usr/src/sbin/gt307'
Xif test -f 'gt307.c'
Xthen
X	echo shar: "will not over-write existing file 'gt307.c'"
Xelse
Xsed 's/^Z//' << \SHAR_EOF > 'gt307.c'
XZ/*
XZ *  GT307
XZ *
XZ * Read and set a Computer Products inc GT307 clock calendar card
XZ *
XZ * Author  R Birch
XZ * Date    July 1999
XZ *
XZ * You can use this in two ways.  If you use Daylight Savings Time when
XZ * the card is intialised then it can be used to maintain local time.
XZ * If DST is not used then this is probably best used to maintain the card
XZ * on UTC.
XZ *
XZ * Usage:
XZ *
XZ *    gt307 [-d n][-l] [yymmddhhmm.ss]
XZ *
XZ *    -d sets DST on or off n = 1 (on) n = 0 (off)
XZ *    -l switches output between long or short.  Short is suitable
XZ *      as an input into date(8)
XZ *    The time string is the same as date(8) for input.
XZ*/
XZ
XZ#if !defined(lint) && defined(DOSCCS)
XZstatic char sccsid[] = "@(#)GT307.c 1.00 (2.11BSD) 99/7/4";
XZ#endif
XZ
XZ#include <stdlib.h>
XZ#include <unistd.h>
XZ#include <stdio.h>
XZ#include <assert.h>
XZ#include <sys/errno.h>
XZ#include <sys/types.h>
XZ
XZ#define BASE_ADDR 0177704
XZ#define IO_VEC 0450
XZ#define SEG_REG 6
XZ#define IO_SIZE 1
XZ
XZ#define REG_A   012
XZ#define REG_B   013
XZ#define REG_C   014
XZ#define REG_D   015
XZ
XZ#define UIP    0200
XZ#define DV2    0100
XZ#define DV1     040
XZ#define DV0     020
XZ#define RS3     010
XZ#define RS2      04
XZ#define RS1      02
XZ#define RS0      01
XZ
XZ#define SET    0200
XZ#define PIE    0100
XZ#define AIE     040
XZ#define UIE     020
XZ#define SQWE    010
XZ#define DM       04
XZ#define D24      02
XZ#define DSE      01
XZ
XZ#define IRQF    0200
XZ#define PF      0100
XZ#define AF       040
XZ#define UF       020
XZ
XZ#define VRT     0200
XZ
XZ#define CONST   1
XZ
XZchar *days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
XZchar *months[] = {"Jan","Feb","Mar","Apr","May","Jun",
XZ		  "Jul","Aug","Sep","Oct","Nov","Dec"};
XZ
XZmain(argc, argv)
XZint argc;
XZchar *argv[];
XZ{
XZ
XZ        register unsigned char   *io_ptr;
XZ        char    time_str[80];
XZ        unsigned int    seg_reg = SEG_REG;
XZ        unsigned int    io_size = IO_SIZE;
XZ        unsigned int    physaddr = BASE_ADDR;
XZ        unsigned char   memval;
XZ        int     ch;
XZ        int     lflag;
XZ        int     dst_flag;
XZ        int     year;
XZ        int     bigyear;
XZ        int     month;
XZ        int     date;
XZ        int     day;
XZ        int     hours;
XZ        int     minutes;
XZ        int     seconds;
XZ
XZ/*
XZ * Set up the page address pointer.  This is written to allow simple
XZ * changing of the #defines at the start of the program to ripple through
XZ * to the rest of the code.  Do not allow 0 because that would collide
XZ * with the first 8kb of code or data.  Do not allow 7 because that would
XZ * collide with our stack.
XZ*/
XZ	assert(seg_reg > 0 && seg_reg < 7);
XZ	io_ptr = (unsigned char *)((u_int)020000 * seg_reg);
XZ/*
XZ * Map the new page to the physical address of the card.
XZ*/
XZ        if	(phys(seg_reg, io_size, physaddr) == -1)
XZ		err(1, "phys(%d, %d, 0%o)", seg_reg, io_size, physaddr);
XZ/*
XZ * process command line
XZ*/
XZ        dst_flag = 0;           /* Set defaults */
XZ        lflag = 0;
XZ
XZ        while	((ch = getopt(argc, argv,"d:l")) != EOF)
XZ                switch((char)ch){
XZ                        case 'd':
XZ                                dst_flag = atoi(optarg) ? 1 : 0;
XZ                                break;
XZ                        case 'l':
XZ                                lflag = 1;
XZ                                break;
XZ                        default:
XZ                                errx(1,"invalid parameters.\n");
XZ                        }
XZ        argc -= optind;
XZ        argv += optind;
XZ
XZ        if	(argc > 1)
XZ                errx(1,"invalid parameters.");
XZ
XZ/*
XZ * If we still have an argument left then we are setting the clock,
XZ * otherwise we are displaying what is in the card.
XZ*/
XZ        if	(!argc)
XZ                goto display;
XZ        goto setup;
XZ
XZdisplay:
XZ/*
XZ * Look at the card to check whether the time on the card is
XZ * valid or not.
XZ*/
XZ        memval = (unsigned char)*(io_ptr + REG_D);
XZ        if	((memval & VRT) == 0)
XZ                errx(1," board clock invalid, reinitialise.");
XZ/*
XZ        Get the time from the card
XZ*/
XZ        memval = (unsigned char)*(io_ptr + REG_A);
XZ        while((memval & UIP) == 1)
XZ                memval = (unsigned char)*(io_ptr + REG_A);
XZ
XZ        seconds = (int)*(io_ptr);
XZ        minutes = (int)*(io_ptr + 2);
XZ        hours = (int)*(io_ptr + 4);
XZ        day = (int)*(io_ptr + 6);
XZ        date = (int)*(io_ptr + 7);
XZ        month = (int)*(io_ptr + 8);
XZ        year = (int)*(io_ptr + 9);
XZ
XZ        if(year <= 70)
XZ                bigyear = year + 2000;
XZ        else
XZ                bigyear = year + 1900;
XZ
XZ        if	(lflag == 0)
XZ                printf("%02d%02d%02d%02d%02d.%02d\n",year,month,date,
XZ                        hours,minutes,seconds);
XZ        else
XZ                printf("%s %s %d %02d:%02d:%02d %04d\n",
XZ                        days[weekday(date,month, bigyear)],months[month - 1],
XZ                        date,hours,minutes,seconds,bigyear);
XZ        exit(0);
XZ
XZ/*
XZ * set the card up given the input time contained in command line.
XZ*/
XZsetup:
XZ
XZ/*
XZ *      Reset card for interrupts
XZ*/
XZ        memval = (unsigned char)(SET | D24 | DM);
XZ        if	(dst_flag == 1)
XZ                memval = memval | DSE;
XZ        *(io_ptr + REG_B) = (unsigned char)memval;
XZ
XZ        memval = (unsigned char)DV1;
XZ        *(io_ptr + REG_A) = (unsigned char)memval;
XZ
XZ        strcpy(time_str,*argv);
XZ
XZ        seconds = 0;
XZ        minutes = 0;
XZ        hours = 0;
XZ        day = 0;
XZ        date = 0;
XZ        month = 0;
XZ        year = 0;
XZ
XZ        (void)sscanf(time_str,"%2d%2d%2d%2d%2d.%2d",&year,&month,&date,&hours,
XZ                &minutes,&seconds);
XZ
XZ        if	(year <= 70)
XZ                bigyear = year + 2000;
XZ        else
XZ                bigyear = year + 1900;
XZ
XZ        day = weekday(date,month,bigyear) + 1;
XZ
XZ        *(io_ptr) = (unsigned char)seconds;
XZ        *(io_ptr + 2) = (unsigned char)minutes;
XZ        *(io_ptr + 4) = (unsigned char)hours;
XZ        *(io_ptr + 6) = (unsigned char)day;
XZ        *(io_ptr + 7) = (unsigned char)date;
XZ        *(io_ptr + 8) = (unsigned char)month;
XZ        *(io_ptr + 9) = (unsigned char)year;
XZ
XZ/*
XZ *      Start the card
XZ*/
XZ        memval = (unsigned char)*(io_ptr + 013);
XZ        memval = memval & 0177;
XZ        *(io_ptr + 013) = (unsigned char)memval;
XZ
XZ        exit(0);
XZ	}
XZ
XZint weekday(day, month, year)
XZint day, month, year;
XZ{
XZ        int index, yrndx, mondx;
XZ        
XZ        if(month <= 2)
XZ        {
XZ                month += 12;
XZ                year--;
XZ        }
XZ
XZ        yrndx = year + (year/4) - (year/100) + (year/400);
XZ        mondx = (2 * month) + (3 * (month + 1)) / 5;
XZ        index = day + mondx + yrndx + CONST;
XZ
XZ        return(index % 7);
XZ}       
XSHAR_EOF
Xchmod 644 'gt307.c'
Xfi
Xif test -f 'Makefile'
Xthen
X	echo shar: "will not over-write existing file 'Makefile'"
Xelse
Xsed 's/^Z//' << \SHAR_EOF > 'Makefile'
XZ#
XZ# Public Domain.  1999/7/21 - Steven Schultz
XZ#
XZ#	@(#)Makefile	1.0 (2.11BSD) 1999/7/21
XZ#
XZCFLAGS=	 -O
XZSEPFLAG= -i
XZSRCS=	gt307.c
XZOBJS=	gt307.o
XZMAN=	gt307.0
XZMANSRC=	gt307.8
XZ
XZall: gt307 gt307.0
XZ
XZgt307: ${OBJS}
XZ	${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS}
XZ
XZgt307.0: ${MANSRC}
XZ	/usr/man/manroff ${MANSRC} > ${MAN}
XZ
XZclean:
XZ	rm -f ${OBJS} ${MAN} gt307 tags 
XZ
XZdepend: ${SRCS}
XZ	mkdep ${CFLAGS} ${SRCS}
XZ
XZinstall: gt307
XZ	install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8
XZ	install -s -o root -g bin -m 755 gt307 ${DESTDIR}/sbin/gt307
XZ
XZlint: ${SRCS}
XZ	lint -hax ${SRCS}
XZ
XZtags: ${SRCS}
XZ	ctags ${SRCS}
XZ# DO NOT DELETE THIS LINE -- mkdep uses it.
XZ# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
XSHAR_EOF
Xchmod 644 'Makefile'
Xfi
Xif test -f 'gt307.8'
Xthen
X	echo shar: "will not over-write existing file 'gt307.8'"
Xelse
Xsed 's/^Z//' << \SHAR_EOF > 'gt307.8'
XZ.\" Public domain - 1999/7/21 - Steven Schultz
XZ.\"	@(#)gt307.8	1.0 (2.11BSD) 1999/7/21
XZ.\"
XZ.TH GT307 8 "July 21, 1999"
XZ.UC 4
XZ.SH NAME
XZgt307 \- read and set GT307 clock board
XZ.SH SYNOPSIS
XZ.B gt307
XZ[
XZ\fB\-d\fP n
XZ]
XZ[
XZ\fB\-l\fP
XZ]
XZ[
XZ\fByymmddhhmm.ss\fP
XZ]
XZ.SH DESCRIPTION
XZThe
XZ.B gt307
XZis used to read and/or set a Computer Products Inc GT307
XZclock calendar board.  If the date argument is not given
XZthe board is read but not written.
XZ.PP
XZThe options are:
XZ.TP 20
XZ\fB\-d\fP n
XZsets Daylight Savings Time (DST) on if \fBn\fP is 1, off if \fBn\fP if 0.
XZ.TP 20
XZ\fB\-l\fP
XZswitches output between long and short formats.  The short format is
XZsuitable for input to the 
XZ.IR date (8) 
XZcommand.
XZ.PP
XZ.B gt307
XZis a user mode program only (not a standalone/bootable program like
XZ.B toyset
XZ).  The kernel does not know how to read a GT307 clock.  Thus the
XZrecommended use of
XZ.B gt307
XZis to set the system time from within the
XZ.IR rc (8)
XZfile:
XZ.sp
XZ.in +1.0i
XZdate `/sbin/gt307 -l`
XZ.br
XZ.in -1.0i
XZ.SH FILES
XZNone.
XZ.SH SEE ALSO
XZdate(8),
XZphys(2),
XZrc(8)
XZ.SH BUGS
XZ.B gt307
XZuses the 
XZ.BR phys (2)
XZsyscall to access the I/O page and thus can only be run by the superuser.  
XZMaking
XZthis program
XZsetuid (so that users can read the GT307 board) could be a large threat
XZto system integrity in the event of bugs in the program.  It is \fBNOT\fP
XZrecommended that 
XZ.B gt307
XZbe made setuid.
XZ.SH HISTORY
XZThe
XZ.B gt307
XZcommand first appeared in 2.11BSD.   It was contributed by Robin
XZBirch 
XZ.br
XZ(robin@falstaf.demon.co.uk).
XZ.PP
XZThe Makefile, manpage and integration into
XZ2.11BSD were done by Steven Schultz (sms@moe.2bsd.com).
XSHAR_EOF
Xchmod 644 'gt307.8'
Xfi
Xchmod 755 .
Xcd ..
Xexit 0
X#	End of shell archive
SHAR_EOF
fi
exit 0
#	End of shell archive
