2 * devrtc - real-time clock, for kirkwood
5 #include "../port/lib.h"
9 #include "../port/error.h"
12 typedef struct RtcReg RtcReg;
13 typedef struct Rtc Rtc;
41 static Dirtab rtcdir[] = {
42 ".", {Qdir, 0, QTDIR}, 0, 0555,
43 "rtc", {Qrtc}, NUMSIZE, 0664,
45 static RtcReg *rtcreg; /* filled in by attach */
49 #define SEC2HOUR (60*SEC2MIN)
50 #define SEC2DAY (24L*SEC2HOUR)
53 * days per month plus days/year
57 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
59 static int ldmsize[] =
61 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
65 * return the days/month for the given year
77 * compute seconds since Jan 1 1970
90 for(i = 1970; i < rtc->year; i++){
92 secs += d2m[0] * SEC2DAY;
98 d2m = yrsize(rtc->year);
99 for(i = 1; i < rtc->mon; i++)
100 secs += d2m[i] * SEC2DAY;
102 secs += (rtc->mday-1) * SEC2DAY;
103 secs += rtc->hour * SEC2HOUR;
104 secs += rtc->min * SEC2MIN;
111 * compute rtc from seconds since Jan 1 1970
114 sec2rtc(ulong secs, Rtc *rtc)
121 * break initial number into days
123 hms = secs % SEC2DAY;
124 day = secs / SEC2DAY;
131 * 19700101 was thursday
133 rtc->wday = (day + 7340036L) % 7;
136 * generate hours:minutes:seconds
148 for(d = 1970; day >= *yrsize(d); d++)
151 for (d = 1970; day < 0; d--)
158 d2m = yrsize(rtc->year);
159 for(d = 1; day >= d2m[d]; d++)
179 Rtcpm = 1<<21, /* pm bit */
180 Rtc12 = 1<<22, /* 12 hr clock */
190 for(i = 0; i < 2 * sizeof d; i++){
191 d += ((bcd >> (4*i)) & 0xf) * m;
203 for(i = 0; d != 0; i++){
204 bcd |= (d%10) << (4*i);
219 rtc.sec = bcd2dec(t & Rtcsec);
220 rtc.min = bcd2dec((t & Rtcmin) >> Rtcms);
223 rtc.hour = bcd2dec((t & Rtchr12) >> Rtchrs) - 1; /* 1—12 */
227 rtc.hour = bcd2dec((t & Rtchr24) >> Rtchrs); /* 0—23 */
229 rtc.mday = bcd2dec(d & Rdmday); /* 1—31 */
230 rtc.mon = bcd2dec((d & Rdmon) >> Rdms); /* 1—12 */
231 rtc.year = bcd2dec((d & Rdyear) >> Rdys) + 2000; /* year%100 */
233 // print("%0.2d:%0.2d:%.02d %0.2d/%0.2d/%0.2d\n", /* HH:MM:SS YY/MM/DD */
234 // rtc.hour, rtc.min, rtc.sec, rtc.year, rtc.mon, rtc.mday);
235 return rtc2sec(&rtc);
246 /* loop until we get two reads in a row the same */
249 for(i = 0; i < 100 && ot != t; i++){
254 print("rtctime: we are boofheads\n");
264 rtcreg->time = dec2bcd(rtc->wday) << 24 | dec2bcd(rtc->hour) << 16 |
265 dec2bcd(rtc->min) << 8 | dec2bcd(rtc->sec);
266 rtcreg->date = dec2bcd(rtc->year - 2000) << 16 |
267 dec2bcd(rtc->mon) << 8 | dec2bcd(rtc->mday);
272 rtcattach(char *spec)
274 rtcreg = (RtcReg*)soc.rtc;
275 return devattach(L'r', spec);
279 rtcwalk(Chan *c, Chan *nc, char **name, int nname)
281 return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
285 rtcstat(Chan *c, uchar *dp, int n)
287 return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
291 rtcopen(Chan *c, int omode)
293 return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
302 rtcread(Chan *c, void *buf, long n, vlong off)
304 if(c->qid.type & QTDIR)
305 return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
307 switch((ulong)c->qid.path){
311 return readnum(off, buf, n, rtctime(), NUMSIZE);
316 rtcwrite(Chan *c, void *buf, long n, vlong off)
322 switch((ulong)c->qid.path){
326 if(offset != 0 || n >= sizeof(sbuf)-1)
328 memmove(sbuf, buf, n);
330 for(cp = sbuf; *cp != '\0'; cp++)
331 if(*cp >= '0' && *cp <= '9')
333 sec2rtc(strtoul(cp, 0, 0), &rtc);