|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 8267 (0x204b)
Types: TextFile
Notes: UNIX file
Names: »date.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »frankh/src/oki/date.c«
/*
* Print and set the date.
* modifications for OKI chip support - 07/31/85 fah
*/
#include <stdio.h>
#include <ctype.h>
#include <types.h>
#include <time.h>
#include <timeb.h>
#include <utmp.h>
#include <stat.h>
#define TFCFLAG 0 /* Truly French GMT is UTC */
#define PBDDR 0x57
#define PCDD 0x0D
#define PCDATA 0x1F
#define PBDATA 0x1D
#define MCCR 0x03
#define MICR 0x01
#define PBCSR 0x13
#define SIOCRC 0x0F
int gmtflag; /* Do things in Greenwich Mean Time */
int okiflag;
struct tm *gtime();
struct timeb tb;
struct utmp utmps[2];
char utmpf[] = "/usr/adm/wtmp";
struct stat sbuf;
time_t timep[2];
char btimf[] = "/etc/boottime";
#define MIN (60L)
#define HOUR (60L*60L)
#define DAY (60L*60L*24L)
#define APR 3
#define OCT 9
/*
* Table of days per month.
* This will be adjusted for leap years.
*/
char dpm[] = {
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
main(argc, argv)
char *argv[];
{
register char *s;
register struct tm *tmp;
long ltime;
char *tzone;
okiflag = 0;
if (argc>1 && *argv[1]=='-') {
if (argv[1][2] != '\0')
usage();
if (argv[1][1] == 'u')
gmtflag = 1;
else
if (argv[1][1] == 'c') {
okiflag = 1;
okiset(); /* set coherent time to oki time */
}
else
usage();
argc--;
argv++;
}
if (argc > 2)
usage();
if (argc > 1)
sdate(argv[1]);
ftime(&tb);
ltime = tb.time;
s = asctime(tmp = gtime(<ime));
s[24] = '\0';
if (!gmtflag)
tzone = tzname[tmp->tm_isdst];
else
tzone = TFCFLAG ? "UTC" : "GMT";
printf("%s %s\n", s, tzone);
}
/*
* Set the date/time based on
* string `s'.
*/
sdate(s)
char *s;
{
register char *sp;
int status;
int ufd;
long ltime;
struct tm *tmp;
ftime(&tb);
ltime = tb.time;
utmps[0].ut_time = ltime;
tmp = gtime(<ime);
for (sp = s; *sp != '\0'; sp++)
;
if ((sp -= 2) < s)
usage();
if (sp>s && sp[-1]=='.') {
tmp->tm_sec = convert(sp, 60, s);
sp--;
} else {
sp += 2;
tmp->tm_sec = 0;
}
tmp->tm_min = convert(sp-=2, 60, s);
tmp->tm_hour = convert(sp-=2, 24, s);
if ((sp-=2) >= s) {
tmp->tm_mday = convert(sp, 31+1, s);
if ((sp-=2) >= s) {
tmp->tm_mon = convert(sp, 12+1, s) - 1;
if ((sp-=2) >= s)
tmp->tm_year = convert(sp, 100, s);
}
}
if (tmp->tm_mday > dpm[tmp->tm_mon])
usage();
ctset(tmp); /* convert to ltime & set coherent time */
}
ctset(tmp)
struct tm *tmp;
{
register int year;
register int month;
int status;
int ufd;
long ltime;
/*
* Convert using the year, month, day, hour, minute,
* and second values in the `tm' structure.
* When all is completed, take care of timezone.
*/
ltime = tmp->tm_sec + MIN*tmp->tm_min + HOUR*tmp->tm_hour;
ltime += (tmp->tm_mday-1) * DAY;
year = 1900 + tmp->tm_year;
/*
* Adjust length of February in leap years.
*/
if (!isleap(year))
dpm[1] = 28;
month = tmp->tm_mon;
while (--month >= 0)
ltime += dpm[month] * DAY;
while (--year >= 1970)
ltime += (long)DAY * (isleap(year) ? 366 : 365);
if (!gmtflag) {
ltime += timezone;
tmp = localtime(<ime);
if (tmp->tm_isdst)
ltime -= HOUR;
}
status = stime(<ime);
if (status < 0) {
error("No permission\n");
return;
}
if (gmtflag == 1 & okiflag == 0)
okit(ltime); /* if setting GMT time, set oki time */
/* Correct the modtime of /etc/boottime */
stat(btimf, &sbuf);
timep[0] = ltime - utmps[0].ut_time + sbuf.st_mtime;
timep[1] = timep[0];
utime(btimf, timep);
/* Note the change of time in /usr/adm/wtmp */
utmps[1].ut_time = ltime;
utmps[0].ut_line[0] = '|';
utmps[1].ut_line[0] = '}';
if ((ufd = open(utmpf, 1)) >= 0) {
lseek(ufd, 0L, 2);
write(ufd, utmps, sizeof (utmps));
close(ufd);
}
}
/*
* Return 1 on leap years.
*/
isleap(yr)
register yr;
{
if (yr%4000 == 0)
return (0);
if (yr%400==0 || (yr%100!=0 && yr%4==0))
return (1);
return (0);
}
/*
* Convert a piece of the time.
* The pointer cp should never fall before
* beg and the two digits parsed should be
* less than max.
*/
convert(cp, max, beg)
register char *cp;
char *beg;
{
register val;
if (cp<beg || !isdigit(cp[0]) || !isdigit(cp[1]))
usage();
val = (cp[0]-'0')*10 + cp[1]-'0';
if (val >= max)
usage();
return (val);
}
/*
* Return either local time or Greenwich
* Mean `tm' in a `tm' structure.
*/
struct tm *
gtime(tp)
register time_t *tp;
{
return (gmtflag ? gmtime(tp) : localtime(tp));
}
usage()
{
error("Usage: date [-uc] [yymmddhhmm[.ss]]\n");
}
error(x)
{
printf("%r", &x);
exit(1);
}
/*
* set time in OKI chip
*/
okit(ltime)
long ltime;
{
struct tm *tmm;
register int fd, i;
int j, status;
int stm[15];
tmm = gtime(<ime); /* this sets proper day of the week in */
/* the tmm structure. */
initio(); /* load driver for I/O */
fd = open("/dev/port", 2);
setup(fd); /* setup 8036 for oki chip. */
stm[1] = tmm->tm_sec / 10;
stm[0] = tmm->tm_sec - 10 * stm[1];
stm[3] = tmm->tm_min / 10;
stm[2] = tmm->tm_min - 10 * stm[3];
stm[5] = tmm->tm_hour / 10;
stm[4] = tmm->tm_hour - 10 * stm[5];
stm[6] = tmm->tm_wday;
stm[8] = tmm->tm_mday / 10;
stm[7] = tmm->tm_mday - 10 * stm[8];
stm[10] = (tmm->tm_mon + 1) / 10;
stm[9] = (tmm->tm_mon + 1) - 10 * stm[10];
stm[12] = tmm->tm_year / 10;
stm[11] = tmm->tm_year - 10 * stm[12];
stm[5] = stm[5] | 0x8; /* set to 24 hr mode */
seloki(fd); /* select OKI chip */
for( i = 0; i < 13; ++i) /* do writes to clock chip */
okiw( i, stm[i], fd);
okiw( 0x0D, 0, fd); /* clear post-stage counters */
desoki(fd);
cloio(); /* unload I/O driver */
printf("Backup clock set. ");
}
/*
* set Coherent time from OKI clock chip.
*/
okiset()
{
struct tm *tmp;
register int fd;
int ufd, j, status;
int stm[15];
long ltime;
gmtflag = 1; /* time in OKI part is GMT! always! */
ftime(&tb);
ltime = tb.time;
utmps[0].ut_time = ltime;
tmp = gtime(<ime);
initio(); /* load driver for I/O */
fd = open("/dev/port", 2);
setup(fd); /* set up 8036 */
seloki(fd); /* select oki chip */
tmp->tm_sec = okir(0, fd) + okir(1, fd) * 10;
tmp->tm_min = okir(2, fd) + okir(3, fd) * 10;
tmp->tm_hour = okir(4, fd) + (okir(5, fd) & 0x3) * 10;
tmp->tm_mday = okir(7, fd) + (okir(8, fd) & 0x3) * 10;
tmp->tm_mon = (okir(9, fd) + okir(0xA, fd) * 10) - 1;
tmp->tm_year = okir(0xB, fd) + okir(0xC, fd) * 10;
tmp->tm_wday = okir(6, fd);
okiw( 0x0D, 0, fd); /* clear post-stage counters */
desoki(fd); /* deselect oki chip */
cloio(); /* unload I/O driver */
ctset(tmp); /* set coherent time from tmp structure */
printf("Internal Coherent clock set.\n");
exit(0);
}
okir(reg, fd)
int fd;
unsigned int reg;
{
unsigned int tmp;
setreg(reg, fd); /* set register address */
/*
* make PB0-3 input lines
*/
outb(fd, PBDDR, (inb(fd, PBDDR) | 0x0F));
outb(fd, PBDATA, (inb(fd, PBDATA) | 0x10)); /* set READ high */
tmp = inb(fd, PBDATA) & 0x0F; /* read D0-D3 */
outb(fd, PBDATA, (inb(fd, PBDATA) & ~0x10)); /* set READ low */
/*
* make PB0-3 output lines
*/
outb(fd, PBDDR, (inb(fd, PBDDR) & 0xF0));
return(tmp);
}
okiw(reg, data, fd)
int fd;
unsigned int reg;
unsigned int data;
{
setreg(reg, fd); /* set register address in OKI chip */
outb(fd, PBDATA, ((inb(fd, PBDATA) & 0xF0) | data)); /* set D0-D3 */
outb(fd, PBDATA, (inb(fd, PBDATA) | 0x20)); /* toggle WRITE */
outb(fd, PBDATA, (inb(fd, PBDATA) & ~0x20));
}
/*
* set a register address in OKI chip
*/
setreg(reg, fd)
int fd, reg;
{
outb(fd, PBDATA, (inb(fd, PBDATA) & 0xF0) | reg); /* write reg addr. */
outb(fd, PBDATA, (inb(fd, PBDATA) | 0x40)); /* toggle ADWRITE */
outb(fd, PBDATA, (inb(fd, PBDATA) & ~0x40));
}
setup(fd)
int fd;
{
/*
* do some setup of 8036 for oki chip.
*/
outb( fd, PCDATA, inb(fd, PCDATA) & 0x0F); /* enable 0-3 write */
outb( fd, PCDD, 0x05); /* set up CS line */
outb( fd, PCDATA, (inb(fd, PCDATA) & 0x0F) | 0x02); /* set select = 1 */
outb( fd, PBDATA, 0);
}
/*
* select & stop counting in oki chip.
*/
seloki(fd)
int fd;
{
outb( fd, PCDATA, inb(fd, PCDATA) & 0x0D); /* set select = 0 */
outb( fd, PBDATA, inb(fd, PBDATA) | 0x80); /* set stop = 1 */
}
/*
* de-select & start count in oki chip.
*/
desoki(fd)
int fd;
{
outb( fd, PBDATA, inb(fd, PBDATA) & ~0x80); /* set stop = 0 */
outb( fd, PCDATA, (inb(fd, PCDATA) & 0x0f) | 0x02); /* sel = 1 */
}