Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!ames!ptsfa!ihnp4!cuae2!ltuxa!we53!sw013b!dj3b1!killer!tsp From: tsp@killer.UUCP Newsgroups: comp.os.minix Subject: Clock setting program for AST Six Pack Message-ID: <771@killer.UUCP> Date: Mon, 13-Apr-87 15:34:56 EST Article-I.D.: killer.771 Posted: Mon Apr 13 15:34:56 1987 Date-Received: Sun, 19-Apr-87 03:16:02 EST Organization: The Unix(tm) Connection, Dallas, Texas Lines: 272 Keywords: /etc/rc, clock, AST Attached is a clock setting program for an AST Six Pack card. I use this in /etc/rc as: /etc/astclock /usr/bin/echo -n "Current time is: " /usr/bin/date No makefile is included, just: cc -o astclock astclock.c port_io.s Known bugs: I couldn't seem to get the ten-year count from the AST clock chip. Instead, I just add a constant DECADE to the years value. If anyone knows how to read the ten-year count, please make the changes and post the diffs. Tom Poindexter April 13, 1987 ---------cut here--------------------------------------------------------- echo x - astclock.c gres '^X' '' > astclock.c << '/' X/* astclock.c - set MINIX's system clock from an AST Six Pack board */ X/* should be run in /etc/rc as /etc/astclock */ X/* date values to seconds calculation borrowed from date.c */ X/* port_in() & port_out() in port_io.s were grafted from klib88.s */ X/* author: Tom Poindexter, April 9, 1987 */ X/* I hereby place this software in the public domain */ X X#include "stdio.h" X Xint days_per_month[] = X { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; X Xstruct tm { X int year, month, day, hour, min, sec; X}; X X/* define the current decade */ X#define DECADE 80 X X/* ports for the ast clock; first is the index, next is the data */ X X#define AST_IDX_REG 0x02c0 X#define AST_VAL_REG 0x02c1 X X/* registers on the ast clock; data returned in lowest 4 bits */ X X#define SEC_1s 0 X#define SEC_10s 1 X#define MIN_1s 2 X#define MIN_10s 3 X#define HR_1s 4 X#define HR_10s 5 X#define DAY_1s 7 X#define DAY_10s 8 X#define MON_1s 9 X#define MON_10s 10 X#define YR_1s 11 X#define YR_10s 12 X#define CLK_MODE 13 X#define CLK_ENABLE 0x0c X X#define LOW_4 0x000f X X#define TRIES 10 X X X X/******************************************************************/ X Xmain() X{ X struct tm tm1; X struct tm tm2; X int i; X long t; X long calc_sec(); X int stime(); /* stime() sets the date in minix */ X X /* try several times to read the clock */ X X for (i = 0; i < TRIES; i++) { X X read_clk(&tm1); /* read the clock twice */ X read_clk(&tm2); X X if (tm1.year == tm2.year && /* and compare the results */ X tm1.month == tm2.month && X tm1.day == tm2.day && X tm1.hour == tm2.hour && X tm1.min == tm2.min && X tm1.sec == tm2.sec) { X X t = calc_sec(&tm1); /* calculate the seconds */ X X if (stime(&t) == -1) { /* and set the time */ X die("astclock: can't set stime(), are you super user?\n"); X } X X exit(0); /* normal termination */ X X } X X } X X /* too many errors in reading the ast clock chip, give up */ X X die("astclock: can't get a consistent time from the ast clock"); X X} X/* end of main */ X X X/* calculate seconds since epoch; this code borrowed from `date.c' */ X Xlong calc_sec(tp) Xstruct tm *tp; X{ X int i = 0; X long ct; X long s_p_min; X long s_p_hour; X long s_p_day; X long s_p_year; X X /* first, calculate seconds per known intervals */ X s_p_min = 60; X s_p_hour = 60 * s_p_min; X s_p_day = 24 * s_p_hour; X s_p_year = 365 * s_p_day; X X /* calculate seconds from epoch until the start of this year */ X tp->year -= 70; /* deal with years since 1970 */ X ct = tp->year * s_p_year; /* seconds per year since epoch */ X ct += ((tp->year + 1) / 4) * s_p_day; /* add in the leap years and */ X if (((tp->year + 2) % 4) == 0) { /* check if this year is a leap */ X days_per_month[1]++; /* and make feb one more day */ X } X X /* calculate seconds from january until the start of this month */ X tp->month--; X while (i < tp->month) { X ct += days_per_month[i++] * s_p_day; X } X X /* calculate seconds of the days this month */ X ct += --tp->day * s_p_day; X X /* calculate seconds of the hour this day */ X ct += tp->hour * s_p_hour; X X /* calculate seconds of the minutes this hour */ X ct += tp->min * s_p_min; X X /* and finally add in the seconds so far this minute */ X ct += tp->sec; X X return (ct); X } X X X/* read the ast clock and fill values into a tm structure */ X Xread_clk(tp) Xstruct tm *tp; X{ X X/* can't seem to get the 10 year count from the clock chip - the X following should work, but YR_10s always returns 0 X tp->year = (rd_ast_clk(YR_10s) * 10) + rd_ast_clk(YR_1s); X*/ X X tp->year = DECADE + rd_ast_clk(YR_1s); X tp->month = (rd_ast_clk(MON_10s) * 10) + rd_ast_clk(MON_1s); X tp->day = (rd_ast_clk(DAY_10s) * 10) + rd_ast_clk(DAY_1s); X tp->hour = (rd_ast_clk(HR_10s) * 10) + rd_ast_clk(HR_1s); X tp->min = (rd_ast_clk(MIN_10s) * 10) + rd_ast_clk(MIN_1s); X tp->sec = (rd_ast_clk(SEC_10s) * 10) + rd_ast_clk(SEC_1s); X X} X/* end of read_clk */ X X X/* rd_ast_clk() - read a register from the ricoh rp5c15 clock chip */ X Xint rd_ast_clk(reg) Xint reg; X{ X int val; X X port_out(AST_IDX_REG, CLK_MODE); /* index on the clock mode reg */ X port_out(AST_VAL_REG, CLK_ENABLE); /* make sure timers are enabled */ X port_out(AST_IDX_REG, reg); /* index on the register desired */ X port_in (AST_VAL_REG, &val); /* and get the value of the reg */ X X return (val & LOW_4); /* make sure lower 4 bits only */ X X} X/* end of rd_ast_clk */ X X X/* die() - print a message on stderr and exit with false code */ X Xdie(msg) Xchar *msg; X{ X fprintf(stderr,msg); X fflush(stderr); X _cleanup(); X exit(1); X X} X/* end of die */ X X X/* end of astclock.c */ / echo x - port_io.s gres '^X' '' > port_io.s << '/' X| this file was grafted from klib88.s X X.globl _port_out, _port_in X X X X|*===========================================================================* X|* port_out * X|*===========================================================================* X| port_out(port, value) writes 'value' on the I/O port 'port'. X X_port_out: X push bx | save bx X mov bx,sp | index off bx X push ax | save ax X push dx | save dx X mov dx,4(bx) | dx = port X mov ax,6(bx) | ax = value X out | output 1 byte X pop dx | restore dx X pop ax | restore ax X pop bx | restore bx X ret | return to caller X X X|*===========================================================================* X|* port_in * X|*===========================================================================* X| port_in(port, &value) reads from port 'port' and puts the result in 'value'. X_port_in: X push bx | save bx X mov bx,sp | index off bx X push ax | save ax X push dx | save dx X mov dx,4(bx) | dx = port X in | input 1 byte X xorb ah,ah | clear ah X mov bx,6(bx) | fetch address where byte is to go X mov (bx),ax | return byte to caller in param X pop dx | restore dx X pop ax | restore ax X pop bx | restore bx X ret | return to caller X X / Tom Poindexter ..!ihnp4!killer!tsp