|
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 - 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 */ }