1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "../port/lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "../port/error.h"
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth #include "io.h"
9*74a4d8c2SCharles.Forsyth
10*74a4d8c2SCharles.Forsyth /*
11*74a4d8c2SCharles.Forsyth * Mostek MK48T12-15 Zeropower/Timekeeper
12*74a4d8c2SCharles.Forsyth * This driver is actually portable.
13*74a4d8c2SCharles.Forsyth */
14*74a4d8c2SCharles.Forsyth typedef struct Rtc Rtc;
15*74a4d8c2SCharles.Forsyth struct Rtc
16*74a4d8c2SCharles.Forsyth {
17*74a4d8c2SCharles.Forsyth int sec;
18*74a4d8c2SCharles.Forsyth int min;
19*74a4d8c2SCharles.Forsyth int hour;
20*74a4d8c2SCharles.Forsyth int wday;
21*74a4d8c2SCharles.Forsyth int mday;
22*74a4d8c2SCharles.Forsyth int mon;
23*74a4d8c2SCharles.Forsyth int year;
24*74a4d8c2SCharles.Forsyth };
25*74a4d8c2SCharles.Forsyth
26*74a4d8c2SCharles.Forsyth static uchar rtcgencksum(void);
27*74a4d8c2SCharles.Forsyth static void setrtc(Rtc *rtc);
28*74a4d8c2SCharles.Forsyth static long rtctime(void);
29*74a4d8c2SCharles.Forsyth static int *yrsize(int yr);
30*74a4d8c2SCharles.Forsyth static int *yrsize(int yr);
31*74a4d8c2SCharles.Forsyth static ulong rtc2sec(Rtc *rtc);
32*74a4d8c2SCharles.Forsyth static void sec2rtc(ulong secs, Rtc *rtc);
33*74a4d8c2SCharles.Forsyth
34*74a4d8c2SCharles.Forsyth static struct
35*74a4d8c2SCharles.Forsyth {
36*74a4d8c2SCharles.Forsyth uchar *cksum;
37*74a4d8c2SCharles.Forsyth uchar *ram;
38*74a4d8c2SCharles.Forsyth RTCdev *rtc;
39*74a4d8c2SCharles.Forsyth }nvr;
40*74a4d8c2SCharles.Forsyth
41*74a4d8c2SCharles.Forsyth enum{
42*74a4d8c2SCharles.Forsyth Qdir,
43*74a4d8c2SCharles.Forsyth Qrtc,
44*74a4d8c2SCharles.Forsyth Qnvram,
45*74a4d8c2SCharles.Forsyth };
46*74a4d8c2SCharles.Forsyth
47*74a4d8c2SCharles.Forsyth QLock rtclock; /* mutex on clock operations */
48*74a4d8c2SCharles.Forsyth
49*74a4d8c2SCharles.Forsyth static Dirtab rtcdir[]={
50*74a4d8c2SCharles.Forsyth ".", {Qdir, 0, QTDIR}, 0, 0555,
51*74a4d8c2SCharles.Forsyth "rtc", {Qrtc, 0}, 0, 0666,
52*74a4d8c2SCharles.Forsyth "nvram", {Qnvram, 0}, NVWRITE, 0666,
53*74a4d8c2SCharles.Forsyth };
54*74a4d8c2SCharles.Forsyth #define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0]))
55*74a4d8c2SCharles.Forsyth
56*74a4d8c2SCharles.Forsyth static void
rtcinit(void)57*74a4d8c2SCharles.Forsyth rtcinit(void)
58*74a4d8c2SCharles.Forsyth {
59*74a4d8c2SCharles.Forsyth KMap *k;
60*74a4d8c2SCharles.Forsyth
61*74a4d8c2SCharles.Forsyth k = kmappa(NVR_CKSUM_PHYS, PTENOCACHE|PTEIO);
62*74a4d8c2SCharles.Forsyth nvr.cksum = (uchar*)VA(k);
63*74a4d8c2SCharles.Forsyth
64*74a4d8c2SCharles.Forsyth k = kmappa(NVR_PHYS, PTENOCACHE|PTEIO);
65*74a4d8c2SCharles.Forsyth nvr.ram = (uchar*)VA(k);
66*74a4d8c2SCharles.Forsyth nvr.rtc = (RTCdev*)(VA(k)+RTCOFF);
67*74a4d8c2SCharles.Forsyth
68*74a4d8c2SCharles.Forsyth rtcgencksum();
69*74a4d8c2SCharles.Forsyth }
70*74a4d8c2SCharles.Forsyth
71*74a4d8c2SCharles.Forsyth static Chan*
rtcattach(char * spec)72*74a4d8c2SCharles.Forsyth rtcattach(char *spec)
73*74a4d8c2SCharles.Forsyth {
74*74a4d8c2SCharles.Forsyth return devattach('r',spec);
75*74a4d8c2SCharles.Forsyth }
76*74a4d8c2SCharles.Forsyth
77*74a4d8c2SCharles.Forsyth static Walkqid*
rtcwalk(Chan * c,Chan * nc,char ** name,int nname)78*74a4d8c2SCharles.Forsyth rtcwalk(Chan *c, Chan *nc, char **name, int nname)
79*74a4d8c2SCharles.Forsyth {
80*74a4d8c2SCharles.Forsyth return devwalk(c, nc, name, nname, rtcdir, NRTC, devgen);
81*74a4d8c2SCharles.Forsyth }
82*74a4d8c2SCharles.Forsyth
83*74a4d8c2SCharles.Forsyth static int
rtcstat(Chan * c,uchar * dp,int n)84*74a4d8c2SCharles.Forsyth rtcstat(Chan *c, uchar *dp, int n)
85*74a4d8c2SCharles.Forsyth {
86*74a4d8c2SCharles.Forsyth return devstat(c, dp, n, rtcdir, NRTC, devgen);
87*74a4d8c2SCharles.Forsyth }
88*74a4d8c2SCharles.Forsyth
89*74a4d8c2SCharles.Forsyth static Chan*
rtcopen(Chan * c,int omode)90*74a4d8c2SCharles.Forsyth rtcopen(Chan *c, int omode)
91*74a4d8c2SCharles.Forsyth {
92*74a4d8c2SCharles.Forsyth omode = openmode(omode);
93*74a4d8c2SCharles.Forsyth switch((ulong)c->qid.path){
94*74a4d8c2SCharles.Forsyth case Qrtc:
95*74a4d8c2SCharles.Forsyth if(strcmp(up->env->user, eve)!=0 && omode!=OREAD)
96*74a4d8c2SCharles.Forsyth error(Eperm);
97*74a4d8c2SCharles.Forsyth break;
98*74a4d8c2SCharles.Forsyth case Qnvram:
99*74a4d8c2SCharles.Forsyth if(strcmp(up->env->user, eve)!=0)
100*74a4d8c2SCharles.Forsyth error(Eperm);
101*74a4d8c2SCharles.Forsyth }
102*74a4d8c2SCharles.Forsyth return devopen(c, omode, rtcdir, NRTC, devgen);
103*74a4d8c2SCharles.Forsyth }
104*74a4d8c2SCharles.Forsyth
105*74a4d8c2SCharles.Forsyth static void
rtccreate(Chan * c,char * name,int omode,ulong perm)106*74a4d8c2SCharles.Forsyth rtccreate(Chan *c, char *name, int omode, ulong perm)
107*74a4d8c2SCharles.Forsyth {
108*74a4d8c2SCharles.Forsyth USED(c, name, omode, perm);
109*74a4d8c2SCharles.Forsyth error(Eperm);
110*74a4d8c2SCharles.Forsyth }
111*74a4d8c2SCharles.Forsyth
112*74a4d8c2SCharles.Forsyth static void
rtcclose(Chan * c)113*74a4d8c2SCharles.Forsyth rtcclose(Chan *c)
114*74a4d8c2SCharles.Forsyth {
115*74a4d8c2SCharles.Forsyth USED(c);
116*74a4d8c2SCharles.Forsyth }
117*74a4d8c2SCharles.Forsyth
118*74a4d8c2SCharles.Forsyth static long
rtcread(Chan * c,void * buf,long n,vlong offset)119*74a4d8c2SCharles.Forsyth rtcread(Chan *c, void *buf, long n, vlong offset)
120*74a4d8c2SCharles.Forsyth {
121*74a4d8c2SCharles.Forsyth ulong t, ot;
122*74a4d8c2SCharles.Forsyth
123*74a4d8c2SCharles.Forsyth if(c->qid.type & QTDIR)
124*74a4d8c2SCharles.Forsyth return devdirread(c, buf, n, rtcdir, NRTC, devgen);
125*74a4d8c2SCharles.Forsyth
126*74a4d8c2SCharles.Forsyth switch((ulong)c->qid.path){
127*74a4d8c2SCharles.Forsyth case Qrtc:
128*74a4d8c2SCharles.Forsyth qlock(&rtclock);
129*74a4d8c2SCharles.Forsyth t = rtctime();
130*74a4d8c2SCharles.Forsyth do{
131*74a4d8c2SCharles.Forsyth ot = t;
132*74a4d8c2SCharles.Forsyth t = rtctime(); /* make sure there's no skew */
133*74a4d8c2SCharles.Forsyth }while(t != ot);
134*74a4d8c2SCharles.Forsyth qunlock(&rtclock);
135*74a4d8c2SCharles.Forsyth n = readnum(offset, buf, n, t, 12);
136*74a4d8c2SCharles.Forsyth return n;
137*74a4d8c2SCharles.Forsyth case Qnvram:
138*74a4d8c2SCharles.Forsyth if(offset > NVREAD)
139*74a4d8c2SCharles.Forsyth return 0;
140*74a4d8c2SCharles.Forsyth if(n > NVREAD - offset)
141*74a4d8c2SCharles.Forsyth n = NVREAD - offset;
142*74a4d8c2SCharles.Forsyth qlock(&rtclock);
143*74a4d8c2SCharles.Forsyth memmove(buf, nvr.ram+offset, n);
144*74a4d8c2SCharles.Forsyth qunlock(&rtclock);
145*74a4d8c2SCharles.Forsyth return n;
146*74a4d8c2SCharles.Forsyth }
147*74a4d8c2SCharles.Forsyth error(Egreg);
148*74a4d8c2SCharles.Forsyth return 0; /* not reached */
149*74a4d8c2SCharles.Forsyth }
150*74a4d8c2SCharles.Forsyth
151*74a4d8c2SCharles.Forsyth /*
152*74a4d8c2SCharles.Forsyth * XXX - Tad: fixme to generate the correct checksum
153*74a4d8c2SCharles.Forsyth */
154*74a4d8c2SCharles.Forsyth static uchar
rtcgencksum(void)155*74a4d8c2SCharles.Forsyth rtcgencksum(void)
156*74a4d8c2SCharles.Forsyth {
157*74a4d8c2SCharles.Forsyth uchar cksum;
158*74a4d8c2SCharles.Forsyth int i;
159*74a4d8c2SCharles.Forsyth static uchar p1cksum = 0;
160*74a4d8c2SCharles.Forsyth static uchar p1cksumvalid=0;
161*74a4d8c2SCharles.Forsyth
162*74a4d8c2SCharles.Forsyth if(!p1cksumvalid) {
163*74a4d8c2SCharles.Forsyth for(i=1; i < 0x1000 ; i++)
164*74a4d8c2SCharles.Forsyth p1cksum ^= nvr.cksum[i];
165*74a4d8c2SCharles.Forsyth p1cksumvalid = 1;
166*74a4d8c2SCharles.Forsyth }
167*74a4d8c2SCharles.Forsyth
168*74a4d8c2SCharles.Forsyth cksum = p1cksum;
169*74a4d8c2SCharles.Forsyth
170*74a4d8c2SCharles.Forsyth for(i=0; i < 0xfdf ; i++) {
171*74a4d8c2SCharles.Forsyth cksum ^= nvr.ram[i];
172*74a4d8c2SCharles.Forsyth }
173*74a4d8c2SCharles.Forsyth
174*74a4d8c2SCharles.Forsyth return cksum;
175*74a4d8c2SCharles.Forsyth }
176*74a4d8c2SCharles.Forsyth
177*74a4d8c2SCharles.Forsyth static long
rtcwrite(Chan * c,void * buf,long n,vlong offset)178*74a4d8c2SCharles.Forsyth rtcwrite(Chan *c, void *buf, long n, vlong offset)
179*74a4d8c2SCharles.Forsyth {
180*74a4d8c2SCharles.Forsyth Rtc rtc;
181*74a4d8c2SCharles.Forsyth ulong secs;
182*74a4d8c2SCharles.Forsyth char *cp, sbuf[32];
183*74a4d8c2SCharles.Forsyth
184*74a4d8c2SCharles.Forsyth switch((ulong)c->qid.path){
185*74a4d8c2SCharles.Forsyth case Qrtc:
186*74a4d8c2SCharles.Forsyth /*
187*74a4d8c2SCharles.Forsyth * read the time
188*74a4d8c2SCharles.Forsyth */
189*74a4d8c2SCharles.Forsyth if(offset != 0 || n >= sizeof(sbuf)-1)
190*74a4d8c2SCharles.Forsyth error(Ebadarg);
191*74a4d8c2SCharles.Forsyth memmove(sbuf, buf, n);
192*74a4d8c2SCharles.Forsyth sbuf[n] = '\0';
193*74a4d8c2SCharles.Forsyth cp = sbuf;
194*74a4d8c2SCharles.Forsyth while(*cp){
195*74a4d8c2SCharles.Forsyth if(*cp>='0' && *cp<='9')
196*74a4d8c2SCharles.Forsyth break;
197*74a4d8c2SCharles.Forsyth cp++;
198*74a4d8c2SCharles.Forsyth }
199*74a4d8c2SCharles.Forsyth secs = strtoul(cp, 0, 0);
200*74a4d8c2SCharles.Forsyth /*
201*74a4d8c2SCharles.Forsyth * convert to bcd
202*74a4d8c2SCharles.Forsyth */
203*74a4d8c2SCharles.Forsyth sec2rtc(secs, &rtc);
204*74a4d8c2SCharles.Forsyth /*
205*74a4d8c2SCharles.Forsyth * write it
206*74a4d8c2SCharles.Forsyth */
207*74a4d8c2SCharles.Forsyth qlock(&rtclock);
208*74a4d8c2SCharles.Forsyth setrtc(&rtc);
209*74a4d8c2SCharles.Forsyth qunlock(&rtclock);
210*74a4d8c2SCharles.Forsyth return n;
211*74a4d8c2SCharles.Forsyth case Qnvram:
212*74a4d8c2SCharles.Forsyth if(offset > NVWRITE)
213*74a4d8c2SCharles.Forsyth return 0;
214*74a4d8c2SCharles.Forsyth if(n > NVWRITE - offset)
215*74a4d8c2SCharles.Forsyth n = NVWRITE - offset;
216*74a4d8c2SCharles.Forsyth qlock(&rtclock);
217*74a4d8c2SCharles.Forsyth memmove(nvr.ram+offset, buf, n);
218*74a4d8c2SCharles.Forsyth *nvr.cksum = rtcgencksum();
219*74a4d8c2SCharles.Forsyth qunlock(&rtclock);
220*74a4d8c2SCharles.Forsyth return n;
221*74a4d8c2SCharles.Forsyth }
222*74a4d8c2SCharles.Forsyth error(Egreg);
223*74a4d8c2SCharles.Forsyth return 0; /* not reached */
224*74a4d8c2SCharles.Forsyth }
225*74a4d8c2SCharles.Forsyth
226*74a4d8c2SCharles.Forsyth #define bcd2dec(bcd) (((((bcd)>>4) & 0x0F) * 10) + ((bcd) & 0x0F))
227*74a4d8c2SCharles.Forsyth #define dec2bcd(dec) ((((dec)/10)<<4)|((dec)%10))
228*74a4d8c2SCharles.Forsyth
229*74a4d8c2SCharles.Forsyth static void
setrtc(Rtc * rtc)230*74a4d8c2SCharles.Forsyth setrtc(Rtc *rtc)
231*74a4d8c2SCharles.Forsyth {
232*74a4d8c2SCharles.Forsyth struct RTCdev *dev;
233*74a4d8c2SCharles.Forsyth
234*74a4d8c2SCharles.Forsyth dev = nvr.rtc;
235*74a4d8c2SCharles.Forsyth dev->control |= RTCWRITE;
236*74a4d8c2SCharles.Forsyth wbflush();
237*74a4d8c2SCharles.Forsyth dev->year = dec2bcd(rtc->year % 100);
238*74a4d8c2SCharles.Forsyth dev->mon = dec2bcd(rtc->mon);
239*74a4d8c2SCharles.Forsyth dev->mday = dec2bcd(rtc->mday);
240*74a4d8c2SCharles.Forsyth dev->hour = dec2bcd(rtc->hour);
241*74a4d8c2SCharles.Forsyth dev->min = dec2bcd(rtc->min);
242*74a4d8c2SCharles.Forsyth dev->sec = dec2bcd(rtc->sec);
243*74a4d8c2SCharles.Forsyth wbflush();
244*74a4d8c2SCharles.Forsyth dev->control &= ~RTCWRITE;
245*74a4d8c2SCharles.Forsyth wbflush();
246*74a4d8c2SCharles.Forsyth }
247*74a4d8c2SCharles.Forsyth
248*74a4d8c2SCharles.Forsyth static long
rtctime(void)249*74a4d8c2SCharles.Forsyth rtctime(void)
250*74a4d8c2SCharles.Forsyth {
251*74a4d8c2SCharles.Forsyth struct RTCdev *dev;
252*74a4d8c2SCharles.Forsyth Rtc rtc;
253*74a4d8c2SCharles.Forsyth
254*74a4d8c2SCharles.Forsyth dev = nvr.rtc;
255*74a4d8c2SCharles.Forsyth dev->control |= RTCREAD;
256*74a4d8c2SCharles.Forsyth wbflush();
257*74a4d8c2SCharles.Forsyth rtc.sec = bcd2dec(dev->sec) & 0x7F;
258*74a4d8c2SCharles.Forsyth rtc.min = bcd2dec(dev->min & 0x7F);
259*74a4d8c2SCharles.Forsyth rtc.hour = bcd2dec(dev->hour & 0x3F);
260*74a4d8c2SCharles.Forsyth rtc.mday = bcd2dec(dev->mday & 0x3F);
261*74a4d8c2SCharles.Forsyth rtc.mon = bcd2dec(dev->mon & 0x3F);
262*74a4d8c2SCharles.Forsyth rtc.year = bcd2dec(dev->year);
263*74a4d8c2SCharles.Forsyth dev->control &= ~RTCREAD;
264*74a4d8c2SCharles.Forsyth wbflush();
265*74a4d8c2SCharles.Forsyth
266*74a4d8c2SCharles.Forsyth if (rtc.mon < 1 || rtc.mon > 12)
267*74a4d8c2SCharles.Forsyth return 0;
268*74a4d8c2SCharles.Forsyth /*
269*74a4d8c2SCharles.Forsyth * the world starts Jan 1 1970
270*74a4d8c2SCharles.Forsyth */
271*74a4d8c2SCharles.Forsyth if(rtc.year < 70)
272*74a4d8c2SCharles.Forsyth rtc.year += 2000;
273*74a4d8c2SCharles.Forsyth else
274*74a4d8c2SCharles.Forsyth rtc.year += 1900;
275*74a4d8c2SCharles.Forsyth
276*74a4d8c2SCharles.Forsyth return rtc2sec(&rtc);
277*74a4d8c2SCharles.Forsyth }
278*74a4d8c2SCharles.Forsyth
279*74a4d8c2SCharles.Forsyth #define SEC2MIN 60L
280*74a4d8c2SCharles.Forsyth #define SEC2HOUR (60L*SEC2MIN)
281*74a4d8c2SCharles.Forsyth #define SEC2DAY (24L*SEC2HOUR)
282*74a4d8c2SCharles.Forsyth
283*74a4d8c2SCharles.Forsyth /*
284*74a4d8c2SCharles.Forsyth * days per month plus days/year
285*74a4d8c2SCharles.Forsyth */
286*74a4d8c2SCharles.Forsyth static int dmsize[] =
287*74a4d8c2SCharles.Forsyth {
288*74a4d8c2SCharles.Forsyth 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
289*74a4d8c2SCharles.Forsyth };
290*74a4d8c2SCharles.Forsyth static int ldmsize[] =
291*74a4d8c2SCharles.Forsyth {
292*74a4d8c2SCharles.Forsyth 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
293*74a4d8c2SCharles.Forsyth };
294*74a4d8c2SCharles.Forsyth
295*74a4d8c2SCharles.Forsyth /*
296*74a4d8c2SCharles.Forsyth * return the days/month for the given year
297*74a4d8c2SCharles.Forsyth */
298*74a4d8c2SCharles.Forsyth static int *
yrsize(int yr)299*74a4d8c2SCharles.Forsyth yrsize(int yr)
300*74a4d8c2SCharles.Forsyth {
301*74a4d8c2SCharles.Forsyth if((yr % 4) == 0)
302*74a4d8c2SCharles.Forsyth return ldmsize;
303*74a4d8c2SCharles.Forsyth else
304*74a4d8c2SCharles.Forsyth return dmsize;
305*74a4d8c2SCharles.Forsyth }
306*74a4d8c2SCharles.Forsyth
307*74a4d8c2SCharles.Forsyth /*
308*74a4d8c2SCharles.Forsyth * compute seconds since Jan 1 1970
309*74a4d8c2SCharles.Forsyth */
310*74a4d8c2SCharles.Forsyth static ulong
rtc2sec(Rtc * rtc)311*74a4d8c2SCharles.Forsyth rtc2sec(Rtc *rtc)
312*74a4d8c2SCharles.Forsyth {
313*74a4d8c2SCharles.Forsyth ulong secs;
314*74a4d8c2SCharles.Forsyth int i;
315*74a4d8c2SCharles.Forsyth int *d2m;
316*74a4d8c2SCharles.Forsyth
317*74a4d8c2SCharles.Forsyth secs = 0;
318*74a4d8c2SCharles.Forsyth
319*74a4d8c2SCharles.Forsyth /*
320*74a4d8c2SCharles.Forsyth * seconds per year
321*74a4d8c2SCharles.Forsyth */
322*74a4d8c2SCharles.Forsyth for(i = 1970; i < rtc->year; i++){
323*74a4d8c2SCharles.Forsyth d2m = yrsize(i);
324*74a4d8c2SCharles.Forsyth secs += d2m[0] * SEC2DAY;
325*74a4d8c2SCharles.Forsyth }
326*74a4d8c2SCharles.Forsyth
327*74a4d8c2SCharles.Forsyth /*
328*74a4d8c2SCharles.Forsyth * seconds per month
329*74a4d8c2SCharles.Forsyth */
330*74a4d8c2SCharles.Forsyth d2m = yrsize(rtc->year);
331*74a4d8c2SCharles.Forsyth for(i = 1; i < rtc->mon; i++)
332*74a4d8c2SCharles.Forsyth secs += d2m[i] * SEC2DAY;
333*74a4d8c2SCharles.Forsyth
334*74a4d8c2SCharles.Forsyth secs += (rtc->mday-1) * SEC2DAY;
335*74a4d8c2SCharles.Forsyth secs += rtc->hour * SEC2HOUR;
336*74a4d8c2SCharles.Forsyth secs += rtc->min * SEC2MIN;
337*74a4d8c2SCharles.Forsyth secs += rtc->sec;
338*74a4d8c2SCharles.Forsyth
339*74a4d8c2SCharles.Forsyth return secs;
340*74a4d8c2SCharles.Forsyth }
341*74a4d8c2SCharles.Forsyth
342*74a4d8c2SCharles.Forsyth /*
343*74a4d8c2SCharles.Forsyth * compute rtc from seconds since Jan 1 1970
344*74a4d8c2SCharles.Forsyth */
345*74a4d8c2SCharles.Forsyth static void
sec2rtc(ulong secs,Rtc * rtc)346*74a4d8c2SCharles.Forsyth sec2rtc(ulong secs, Rtc *rtc)
347*74a4d8c2SCharles.Forsyth {
348*74a4d8c2SCharles.Forsyth int d;
349*74a4d8c2SCharles.Forsyth long hms, day;
350*74a4d8c2SCharles.Forsyth int *d2m;
351*74a4d8c2SCharles.Forsyth
352*74a4d8c2SCharles.Forsyth /*
353*74a4d8c2SCharles.Forsyth * break initial number into days
354*74a4d8c2SCharles.Forsyth */
355*74a4d8c2SCharles.Forsyth hms = secs % SEC2DAY;
356*74a4d8c2SCharles.Forsyth day = secs / SEC2DAY;
357*74a4d8c2SCharles.Forsyth if(hms < 0) {
358*74a4d8c2SCharles.Forsyth hms += SEC2DAY;
359*74a4d8c2SCharles.Forsyth day -= 1;
360*74a4d8c2SCharles.Forsyth }
361*74a4d8c2SCharles.Forsyth
362*74a4d8c2SCharles.Forsyth /*
363*74a4d8c2SCharles.Forsyth * generate hours:minutes:seconds
364*74a4d8c2SCharles.Forsyth */
365*74a4d8c2SCharles.Forsyth rtc->sec = hms % 60;
366*74a4d8c2SCharles.Forsyth d = hms / 60;
367*74a4d8c2SCharles.Forsyth rtc->min = d % 60;
368*74a4d8c2SCharles.Forsyth d /= 60;
369*74a4d8c2SCharles.Forsyth rtc->hour = d;
370*74a4d8c2SCharles.Forsyth
371*74a4d8c2SCharles.Forsyth /*
372*74a4d8c2SCharles.Forsyth * year number
373*74a4d8c2SCharles.Forsyth */
374*74a4d8c2SCharles.Forsyth if(day >= 0)
375*74a4d8c2SCharles.Forsyth for(d = 1970; day >= *yrsize(d); d++)
376*74a4d8c2SCharles.Forsyth day -= *yrsize(d);
377*74a4d8c2SCharles.Forsyth else
378*74a4d8c2SCharles.Forsyth for (d = 1970; day < 0; d--)
379*74a4d8c2SCharles.Forsyth day += *yrsize(d-1);
380*74a4d8c2SCharles.Forsyth rtc->year = d;
381*74a4d8c2SCharles.Forsyth
382*74a4d8c2SCharles.Forsyth /*
383*74a4d8c2SCharles.Forsyth * generate month
384*74a4d8c2SCharles.Forsyth */
385*74a4d8c2SCharles.Forsyth d2m = yrsize(rtc->year);
386*74a4d8c2SCharles.Forsyth for(d = 1; day >= d2m[d]; d++)
387*74a4d8c2SCharles.Forsyth day -= d2m[d];
388*74a4d8c2SCharles.Forsyth rtc->mday = day + 1;
389*74a4d8c2SCharles.Forsyth rtc->mon = d;
390*74a4d8c2SCharles.Forsyth
391*74a4d8c2SCharles.Forsyth return;
392*74a4d8c2SCharles.Forsyth }
393*74a4d8c2SCharles.Forsyth
394*74a4d8c2SCharles.Forsyth Dev rtcdevtab = {
395*74a4d8c2SCharles.Forsyth 'r',
396*74a4d8c2SCharles.Forsyth "rtc",
397*74a4d8c2SCharles.Forsyth
398*74a4d8c2SCharles.Forsyth devreset,
399*74a4d8c2SCharles.Forsyth rtcinit,
400*74a4d8c2SCharles.Forsyth devshutdown,
401*74a4d8c2SCharles.Forsyth rtcattach,
402*74a4d8c2SCharles.Forsyth rtcwalk,
403*74a4d8c2SCharles.Forsyth rtcstat,
404*74a4d8c2SCharles.Forsyth rtcopen,
405*74a4d8c2SCharles.Forsyth rtccreate,
406*74a4d8c2SCharles.Forsyth rtcclose,
407*74a4d8c2SCharles.Forsyth rtcread,
408*74a4d8c2SCharles.Forsyth devbread,
409*74a4d8c2SCharles.Forsyth rtcwrite,
410*74a4d8c2SCharles.Forsyth devbwrite,
411*74a4d8c2SCharles.Forsyth devremove,
412*74a4d8c2SCharles.Forsyth devwstat,
413*74a4d8c2SCharles.Forsyth };
414