19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier /*
99ef1f84bSDavid du Colombier * real time clock and non-volatile ram
109ef1f84bSDavid du Colombier */
119ef1f84bSDavid du Colombier
129ef1f84bSDavid du Colombier enum {
139ef1f84bSDavid du Colombier Addr= 0x70, /* address port */
149ef1f84bSDavid du Colombier Data= 0x71, /* data port */
159ef1f84bSDavid du Colombier
169ef1f84bSDavid du Colombier Seconds= 0x00,
179ef1f84bSDavid du Colombier Minutes= 0x02,
189ef1f84bSDavid du Colombier Hours= 0x04,
199ef1f84bSDavid du Colombier Mday= 0x07,
209ef1f84bSDavid du Colombier Month= 0x08,
219ef1f84bSDavid du Colombier Year= 0x09,
229ef1f84bSDavid du Colombier Status= 0x0A,
239ef1f84bSDavid du Colombier
249ef1f84bSDavid du Colombier Nvoff= 128, /* where usable nvram lives */
259ef1f84bSDavid du Colombier Nvsize= 256,
269ef1f84bSDavid du Colombier
279ef1f84bSDavid du Colombier Nbcd= 6,
289ef1f84bSDavid du Colombier };
299ef1f84bSDavid du Colombier
309ef1f84bSDavid du Colombier typedef struct Rtc Rtc;
319ef1f84bSDavid du Colombier struct Rtc
329ef1f84bSDavid du Colombier {
339ef1f84bSDavid du Colombier int sec;
349ef1f84bSDavid du Colombier int min;
359ef1f84bSDavid du Colombier int hour;
369ef1f84bSDavid du Colombier int mday;
379ef1f84bSDavid du Colombier int mon;
389ef1f84bSDavid du Colombier int year;
399ef1f84bSDavid du Colombier };
409ef1f84bSDavid du Colombier
419ef1f84bSDavid du Colombier
429ef1f84bSDavid du Colombier enum{
439ef1f84bSDavid du Colombier Qdir = 0,
449ef1f84bSDavid du Colombier Qrtc,
459ef1f84bSDavid du Colombier Qnvram,
469ef1f84bSDavid du Colombier };
479ef1f84bSDavid du Colombier
489ef1f84bSDavid du Colombier Dirtab rtcdir[]={
499ef1f84bSDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, 0555,
509ef1f84bSDavid du Colombier "nvram", {Qnvram, 0}, Nvsize, 0664,
519ef1f84bSDavid du Colombier "rtc", {Qrtc, 0}, 0, 0664,
529ef1f84bSDavid du Colombier };
539ef1f84bSDavid du Colombier
549ef1f84bSDavid du Colombier static ulong rtc2sec(Rtc*);
559ef1f84bSDavid du Colombier static void sec2rtc(ulong, Rtc*);
569ef1f84bSDavid du Colombier
579ef1f84bSDavid du Colombier void
rtcinit(void)589ef1f84bSDavid du Colombier rtcinit(void)
599ef1f84bSDavid du Colombier {
609ef1f84bSDavid du Colombier if(ioalloc(Addr, 2, 0, "rtc/nvr") < 0)
619ef1f84bSDavid du Colombier panic("rtcinit: ioalloc failed");
629ef1f84bSDavid du Colombier }
639ef1f84bSDavid du Colombier
649ef1f84bSDavid du Colombier static Chan*
rtcattach(char * spec)659ef1f84bSDavid du Colombier rtcattach(char* spec)
669ef1f84bSDavid du Colombier {
679ef1f84bSDavid du Colombier return devattach('r', spec);
689ef1f84bSDavid du Colombier }
699ef1f84bSDavid du Colombier
709ef1f84bSDavid du Colombier static Walkqid*
rtcwalk(Chan * c,Chan * nc,char ** name,int nname)719ef1f84bSDavid du Colombier rtcwalk(Chan* c, Chan *nc, char** name, int nname)
729ef1f84bSDavid du Colombier {
739ef1f84bSDavid du Colombier return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
749ef1f84bSDavid du Colombier }
759ef1f84bSDavid du Colombier
769ef1f84bSDavid du Colombier static long
rtcstat(Chan * c,uchar * dp,long n)779ef1f84bSDavid du Colombier rtcstat(Chan* c, uchar* dp, long n)
789ef1f84bSDavid du Colombier {
799ef1f84bSDavid du Colombier return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
809ef1f84bSDavid du Colombier }
819ef1f84bSDavid du Colombier
829ef1f84bSDavid du Colombier static Chan*
rtcopen(Chan * c,int omode)839ef1f84bSDavid du Colombier rtcopen(Chan* c, int omode)
849ef1f84bSDavid du Colombier {
859ef1f84bSDavid du Colombier omode = openmode(omode);
869ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
879ef1f84bSDavid du Colombier case Qrtc:
889ef1f84bSDavid du Colombier if(strcmp(up->user, eve)!=0 && omode!=OREAD)
899ef1f84bSDavid du Colombier error(Eperm);
909ef1f84bSDavid du Colombier break;
919ef1f84bSDavid du Colombier case Qnvram:
929ef1f84bSDavid du Colombier if(strcmp(up->user, eve)!=0)
939ef1f84bSDavid du Colombier error(Eperm);
949ef1f84bSDavid du Colombier }
959ef1f84bSDavid du Colombier return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
969ef1f84bSDavid du Colombier }
979ef1f84bSDavid du Colombier
989ef1f84bSDavid du Colombier static void
rtcclose(Chan *)999ef1f84bSDavid du Colombier rtcclose(Chan*)
1009ef1f84bSDavid du Colombier {
1019ef1f84bSDavid du Colombier }
1029ef1f84bSDavid du Colombier
1039ef1f84bSDavid du Colombier #define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))
1049ef1f84bSDavid du Colombier
1059ef1f84bSDavid du Colombier static long
rtcextract(void)1069ef1f84bSDavid du Colombier rtcextract(void)
1079ef1f84bSDavid du Colombier {
1089ef1f84bSDavid du Colombier uchar bcdclock[Nbcd];
1099ef1f84bSDavid du Colombier Rtc rtc;
1109ef1f84bSDavid du Colombier int i;
1119ef1f84bSDavid du Colombier
1129ef1f84bSDavid du Colombier /* don't do the read until the clock is no longer busy */
1139ef1f84bSDavid du Colombier for(i = 0; i < 10000; i++){
1149ef1f84bSDavid du Colombier outb(Addr, Status);
1159ef1f84bSDavid du Colombier if(inb(Data) & 0x80)
1169ef1f84bSDavid du Colombier continue;
1179ef1f84bSDavid du Colombier
1189ef1f84bSDavid du Colombier /* read clock values */
1199ef1f84bSDavid du Colombier outb(Addr, Seconds); bcdclock[0] = inb(Data);
1209ef1f84bSDavid du Colombier outb(Addr, Minutes); bcdclock[1] = inb(Data);
1219ef1f84bSDavid du Colombier outb(Addr, Hours); bcdclock[2] = inb(Data);
1229ef1f84bSDavid du Colombier outb(Addr, Mday); bcdclock[3] = inb(Data);
1239ef1f84bSDavid du Colombier outb(Addr, Month); bcdclock[4] = inb(Data);
1249ef1f84bSDavid du Colombier outb(Addr, Year); bcdclock[5] = inb(Data);
1259ef1f84bSDavid du Colombier
1269ef1f84bSDavid du Colombier outb(Addr, Status);
1279ef1f84bSDavid du Colombier if((inb(Data) & 0x80) == 0)
1289ef1f84bSDavid du Colombier break;
1299ef1f84bSDavid du Colombier }
1309ef1f84bSDavid du Colombier
1319ef1f84bSDavid du Colombier /*
1329ef1f84bSDavid du Colombier * convert from BCD
1339ef1f84bSDavid du Colombier */
1349ef1f84bSDavid du Colombier rtc.sec = GETBCD(0);
1359ef1f84bSDavid du Colombier rtc.min = GETBCD(1);
1369ef1f84bSDavid du Colombier rtc.hour = GETBCD(2);
1379ef1f84bSDavid du Colombier rtc.mday = GETBCD(3);
1389ef1f84bSDavid du Colombier rtc.mon = GETBCD(4);
1399ef1f84bSDavid du Colombier rtc.year = GETBCD(5);
1409ef1f84bSDavid du Colombier
1419ef1f84bSDavid du Colombier /*
1429ef1f84bSDavid du Colombier * the world starts jan 1 1970
1439ef1f84bSDavid du Colombier */
1449ef1f84bSDavid du Colombier if(rtc.year < 70)
1459ef1f84bSDavid du Colombier rtc.year += 2000;
1469ef1f84bSDavid du Colombier else
1479ef1f84bSDavid du Colombier rtc.year += 1900;
1489ef1f84bSDavid du Colombier return rtc2sec(&rtc);
1499ef1f84bSDavid du Colombier }
1509ef1f84bSDavid du Colombier
1519ef1f84bSDavid du Colombier static Lock nvrtlock;
1529ef1f84bSDavid du Colombier
1539ef1f84bSDavid du Colombier long
rtctime(void)1549ef1f84bSDavid du Colombier rtctime(void)
1559ef1f84bSDavid du Colombier {
1569ef1f84bSDavid du Colombier int i;
1579ef1f84bSDavid du Colombier long t, ot;
1589ef1f84bSDavid du Colombier
1599ef1f84bSDavid du Colombier ilock(&nvrtlock);
1609ef1f84bSDavid du Colombier
1619ef1f84bSDavid du Colombier /* loop till we get two reads in a row the same */
1629ef1f84bSDavid du Colombier t = rtcextract();
1639ef1f84bSDavid du Colombier for(i = 0; i < 100; i++){
164*b04d1ba2SDavid du Colombier ot = t;
165*b04d1ba2SDavid du Colombier t = rtcextract();
1669ef1f84bSDavid du Colombier if(ot == t)
1679ef1f84bSDavid du Colombier break;
1689ef1f84bSDavid du Colombier }
1699ef1f84bSDavid du Colombier iunlock(&nvrtlock);
1709ef1f84bSDavid du Colombier
1719ef1f84bSDavid du Colombier if(i == 100) print("we are boofheads\n");
1729ef1f84bSDavid du Colombier
1739ef1f84bSDavid du Colombier return t;
1749ef1f84bSDavid du Colombier }
1759ef1f84bSDavid du Colombier
1769ef1f84bSDavid du Colombier static long
rtcread(Chan * c,void * buf,long n,vlong off)1779ef1f84bSDavid du Colombier rtcread(Chan* c, void* buf, long n, vlong off)
1789ef1f84bSDavid du Colombier {
1799ef1f84bSDavid du Colombier ulong t;
1809ef1f84bSDavid du Colombier char *a, *start;
1819ef1f84bSDavid du Colombier ulong offset = off;
1829ef1f84bSDavid du Colombier
1839ef1f84bSDavid du Colombier if(c->qid.type & QTDIR)
1849ef1f84bSDavid du Colombier return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
1859ef1f84bSDavid du Colombier
1869ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
1879ef1f84bSDavid du Colombier case Qrtc:
1889ef1f84bSDavid du Colombier t = rtctime();
1899ef1f84bSDavid du Colombier n = readnum(offset, buf, n, t, 12);
1909ef1f84bSDavid du Colombier return n;
1919ef1f84bSDavid du Colombier case Qnvram:
1929ef1f84bSDavid du Colombier if(n == 0)
1939ef1f84bSDavid du Colombier return 0;
1949ef1f84bSDavid du Colombier if(n > Nvsize)
1959ef1f84bSDavid du Colombier n = Nvsize;
1969ef1f84bSDavid du Colombier a = start = smalloc(n);
1979ef1f84bSDavid du Colombier
1989ef1f84bSDavid du Colombier ilock(&nvrtlock);
1999ef1f84bSDavid du Colombier for(t = offset; t < offset + n; t++){
2009ef1f84bSDavid du Colombier if(t >= Nvsize)
2019ef1f84bSDavid du Colombier break;
2029ef1f84bSDavid du Colombier outb(Addr, Nvoff+t);
2039ef1f84bSDavid du Colombier *a++ = inb(Data);
2049ef1f84bSDavid du Colombier }
2059ef1f84bSDavid du Colombier iunlock(&nvrtlock);
2069ef1f84bSDavid du Colombier
2079ef1f84bSDavid du Colombier if(waserror()){
2089ef1f84bSDavid du Colombier free(start);
2099ef1f84bSDavid du Colombier nexterror();
2109ef1f84bSDavid du Colombier }
2119ef1f84bSDavid du Colombier memmove(buf, start, t - offset);
2129ef1f84bSDavid du Colombier poperror();
2139ef1f84bSDavid du Colombier
2149ef1f84bSDavid du Colombier free(start);
2159ef1f84bSDavid du Colombier return t - offset;
2169ef1f84bSDavid du Colombier }
2179ef1f84bSDavid du Colombier error(Ebadarg);
2189ef1f84bSDavid du Colombier return 0;
2199ef1f84bSDavid du Colombier }
2209ef1f84bSDavid du Colombier
2219ef1f84bSDavid du Colombier #define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)
2229ef1f84bSDavid du Colombier
2239ef1f84bSDavid du Colombier static long
rtcwrite(Chan * c,void * buf,long n,vlong off)2249ef1f84bSDavid du Colombier rtcwrite(Chan* c, void* buf, long n, vlong off)
2259ef1f84bSDavid du Colombier {
2269ef1f84bSDavid du Colombier int t;
2279ef1f84bSDavid du Colombier char *a, *start;
2289ef1f84bSDavid du Colombier Rtc rtc;
2299ef1f84bSDavid du Colombier ulong secs;
2309ef1f84bSDavid du Colombier uchar bcdclock[Nbcd];
2319ef1f84bSDavid du Colombier char *cp, *ep;
2329ef1f84bSDavid du Colombier ulong offset = off;
2339ef1f84bSDavid du Colombier
2349ef1f84bSDavid du Colombier if(offset!=0)
2359ef1f84bSDavid du Colombier error(Ebadarg);
2369ef1f84bSDavid du Colombier
2379ef1f84bSDavid du Colombier
2389ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
2399ef1f84bSDavid du Colombier case Qrtc:
2409ef1f84bSDavid du Colombier /*
2419ef1f84bSDavid du Colombier * read the time
2429ef1f84bSDavid du Colombier */
2439ef1f84bSDavid du Colombier cp = ep = buf;
2449ef1f84bSDavid du Colombier ep += n;
2459ef1f84bSDavid du Colombier while(cp < ep){
2469ef1f84bSDavid du Colombier if(*cp>='0' && *cp<='9')
2479ef1f84bSDavid du Colombier break;
2489ef1f84bSDavid du Colombier cp++;
2499ef1f84bSDavid du Colombier }
2509ef1f84bSDavid du Colombier secs = strtoul(cp, 0, 0);
2519ef1f84bSDavid du Colombier
2529ef1f84bSDavid du Colombier /*
2539ef1f84bSDavid du Colombier * convert to bcd
2549ef1f84bSDavid du Colombier */
2559ef1f84bSDavid du Colombier sec2rtc(secs, &rtc);
2569ef1f84bSDavid du Colombier PUTBCD(rtc.sec, 0);
2579ef1f84bSDavid du Colombier PUTBCD(rtc.min, 1);
2589ef1f84bSDavid du Colombier PUTBCD(rtc.hour, 2);
2599ef1f84bSDavid du Colombier PUTBCD(rtc.mday, 3);
2609ef1f84bSDavid du Colombier PUTBCD(rtc.mon, 4);
2619ef1f84bSDavid du Colombier PUTBCD(rtc.year, 5);
2629ef1f84bSDavid du Colombier
2639ef1f84bSDavid du Colombier /*
2649ef1f84bSDavid du Colombier * write the clock
2659ef1f84bSDavid du Colombier */
2669ef1f84bSDavid du Colombier ilock(&nvrtlock);
2679ef1f84bSDavid du Colombier outb(Addr, Seconds); outb(Data, bcdclock[0]);
2689ef1f84bSDavid du Colombier outb(Addr, Minutes); outb(Data, bcdclock[1]);
2699ef1f84bSDavid du Colombier outb(Addr, Hours); outb(Data, bcdclock[2]);
2709ef1f84bSDavid du Colombier outb(Addr, Mday); outb(Data, bcdclock[3]);
2719ef1f84bSDavid du Colombier outb(Addr, Month); outb(Data, bcdclock[4]);
2729ef1f84bSDavid du Colombier outb(Addr, Year); outb(Data, bcdclock[5]);
2739ef1f84bSDavid du Colombier iunlock(&nvrtlock);
2749ef1f84bSDavid du Colombier return n;
2759ef1f84bSDavid du Colombier case Qnvram:
2769ef1f84bSDavid du Colombier if(n == 0)
2779ef1f84bSDavid du Colombier return 0;
2789ef1f84bSDavid du Colombier if(n > Nvsize)
2799ef1f84bSDavid du Colombier n = Nvsize;
2809ef1f84bSDavid du Colombier
2819ef1f84bSDavid du Colombier start = a = smalloc(n);
2829ef1f84bSDavid du Colombier if(waserror()){
2839ef1f84bSDavid du Colombier free(start);
2849ef1f84bSDavid du Colombier nexterror();
2859ef1f84bSDavid du Colombier }
2869ef1f84bSDavid du Colombier memmove(a, buf, n);
2879ef1f84bSDavid du Colombier poperror();
2889ef1f84bSDavid du Colombier
2899ef1f84bSDavid du Colombier ilock(&nvrtlock);
2909ef1f84bSDavid du Colombier for(t = offset; t < offset + n; t++){
2919ef1f84bSDavid du Colombier if(t >= Nvsize)
2929ef1f84bSDavid du Colombier break;
2939ef1f84bSDavid du Colombier outb(Addr, Nvoff+t);
2949ef1f84bSDavid du Colombier outb(Data, *a++);
2959ef1f84bSDavid du Colombier }
2969ef1f84bSDavid du Colombier iunlock(&nvrtlock);
2979ef1f84bSDavid du Colombier
2989ef1f84bSDavid du Colombier free(start);
2999ef1f84bSDavid du Colombier return t - offset;
3009ef1f84bSDavid du Colombier }
3019ef1f84bSDavid du Colombier error(Ebadarg);
3029ef1f84bSDavid du Colombier return 0;
3039ef1f84bSDavid du Colombier }
3049ef1f84bSDavid du Colombier
3059ef1f84bSDavid du Colombier Dev rtcdevtab = {
3069ef1f84bSDavid du Colombier 'r',
3079ef1f84bSDavid du Colombier "rtc",
3089ef1f84bSDavid du Colombier
3099ef1f84bSDavid du Colombier devreset,
3109ef1f84bSDavid du Colombier rtcinit,
3119ef1f84bSDavid du Colombier devshutdown,
3129ef1f84bSDavid du Colombier rtcattach,
3139ef1f84bSDavid du Colombier rtcwalk,
3149ef1f84bSDavid du Colombier rtcstat,
3159ef1f84bSDavid du Colombier rtcopen,
3169ef1f84bSDavid du Colombier devcreate,
3179ef1f84bSDavid du Colombier rtcclose,
3189ef1f84bSDavid du Colombier rtcread,
3199ef1f84bSDavid du Colombier devbread,
3209ef1f84bSDavid du Colombier rtcwrite,
3219ef1f84bSDavid du Colombier devbwrite,
3229ef1f84bSDavid du Colombier devremove,
3239ef1f84bSDavid du Colombier devwstat,
3249ef1f84bSDavid du Colombier };
3259ef1f84bSDavid du Colombier
3269ef1f84bSDavid du Colombier #define SEC2MIN 60L
3279ef1f84bSDavid du Colombier #define SEC2HOUR (60L*SEC2MIN)
3289ef1f84bSDavid du Colombier #define SEC2DAY (24L*SEC2HOUR)
3299ef1f84bSDavid du Colombier
3309ef1f84bSDavid du Colombier /*
3319ef1f84bSDavid du Colombier * days per month plus days/year
3329ef1f84bSDavid du Colombier */
3339ef1f84bSDavid du Colombier static int dmsize[] =
3349ef1f84bSDavid du Colombier {
3359ef1f84bSDavid du Colombier 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
3369ef1f84bSDavid du Colombier };
3379ef1f84bSDavid du Colombier static int ldmsize[] =
3389ef1f84bSDavid du Colombier {
3399ef1f84bSDavid du Colombier 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
3409ef1f84bSDavid du Colombier };
3419ef1f84bSDavid du Colombier
3429ef1f84bSDavid du Colombier /*
3439ef1f84bSDavid du Colombier * return the days/month for the given year
3449ef1f84bSDavid du Colombier */
3459ef1f84bSDavid du Colombier static int*
yrsize(int y)3469ef1f84bSDavid du Colombier yrsize(int y)
3479ef1f84bSDavid du Colombier {
3489ef1f84bSDavid du Colombier if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
3499ef1f84bSDavid du Colombier return ldmsize;
3509ef1f84bSDavid du Colombier else
3519ef1f84bSDavid du Colombier return dmsize;
3529ef1f84bSDavid du Colombier }
3539ef1f84bSDavid du Colombier
3549ef1f84bSDavid du Colombier /*
3559ef1f84bSDavid du Colombier * compute seconds since Jan 1 1970
3569ef1f84bSDavid du Colombier */
3579ef1f84bSDavid du Colombier static ulong
rtc2sec(Rtc * rtc)3589ef1f84bSDavid du Colombier rtc2sec(Rtc *rtc)
3599ef1f84bSDavid du Colombier {
3609ef1f84bSDavid du Colombier ulong secs;
3619ef1f84bSDavid du Colombier int i;
3629ef1f84bSDavid du Colombier int *d2m;
3639ef1f84bSDavid du Colombier
3649ef1f84bSDavid du Colombier secs = 0;
3659ef1f84bSDavid du Colombier
3669ef1f84bSDavid du Colombier /*
3679ef1f84bSDavid du Colombier * seconds per year
3689ef1f84bSDavid du Colombier */
3699ef1f84bSDavid du Colombier for(i = 1970; i < rtc->year; i++){
3709ef1f84bSDavid du Colombier d2m = yrsize(i);
3719ef1f84bSDavid du Colombier secs += d2m[0] * SEC2DAY;
3729ef1f84bSDavid du Colombier }
3739ef1f84bSDavid du Colombier
3749ef1f84bSDavid du Colombier /*
3759ef1f84bSDavid du Colombier * seconds per month
3769ef1f84bSDavid du Colombier */
3779ef1f84bSDavid du Colombier d2m = yrsize(rtc->year);
3789ef1f84bSDavid du Colombier for(i = 1; i < rtc->mon; i++)
3799ef1f84bSDavid du Colombier secs += d2m[i] * SEC2DAY;
3809ef1f84bSDavid du Colombier
3819ef1f84bSDavid du Colombier secs += (rtc->mday-1) * SEC2DAY;
3829ef1f84bSDavid du Colombier secs += rtc->hour * SEC2HOUR;
3839ef1f84bSDavid du Colombier secs += rtc->min * SEC2MIN;
3849ef1f84bSDavid du Colombier secs += rtc->sec;
3859ef1f84bSDavid du Colombier
3869ef1f84bSDavid du Colombier return secs;
3879ef1f84bSDavid du Colombier }
3889ef1f84bSDavid du Colombier
3899ef1f84bSDavid du Colombier /*
3909ef1f84bSDavid du Colombier * compute rtc from seconds since Jan 1 1970
3919ef1f84bSDavid du Colombier */
3929ef1f84bSDavid du Colombier static void
sec2rtc(ulong secs,Rtc * rtc)3939ef1f84bSDavid du Colombier sec2rtc(ulong secs, Rtc *rtc)
3949ef1f84bSDavid du Colombier {
3959ef1f84bSDavid du Colombier int d;
3969ef1f84bSDavid du Colombier long hms, day;
3979ef1f84bSDavid du Colombier int *d2m;
3989ef1f84bSDavid du Colombier
3999ef1f84bSDavid du Colombier /*
4009ef1f84bSDavid du Colombier * break initial number into days
4019ef1f84bSDavid du Colombier */
4029ef1f84bSDavid du Colombier hms = secs % SEC2DAY;
4039ef1f84bSDavid du Colombier day = secs / SEC2DAY;
4049ef1f84bSDavid du Colombier if(hms < 0) {
4059ef1f84bSDavid du Colombier hms += SEC2DAY;
4069ef1f84bSDavid du Colombier day -= 1;
4079ef1f84bSDavid du Colombier }
4089ef1f84bSDavid du Colombier
4099ef1f84bSDavid du Colombier /*
4109ef1f84bSDavid du Colombier * generate hours:minutes:seconds
4119ef1f84bSDavid du Colombier */
4129ef1f84bSDavid du Colombier rtc->sec = hms % 60;
4139ef1f84bSDavid du Colombier d = hms / 60;
4149ef1f84bSDavid du Colombier rtc->min = d % 60;
4159ef1f84bSDavid du Colombier d /= 60;
4169ef1f84bSDavid du Colombier rtc->hour = d;
4179ef1f84bSDavid du Colombier
4189ef1f84bSDavid du Colombier /*
4199ef1f84bSDavid du Colombier * year number
4209ef1f84bSDavid du Colombier */
4219ef1f84bSDavid du Colombier if(day >= 0)
4229ef1f84bSDavid du Colombier for(d = 1970; day >= *yrsize(d); d++)
4239ef1f84bSDavid du Colombier day -= *yrsize(d);
4249ef1f84bSDavid du Colombier else
4259ef1f84bSDavid du Colombier for (d = 1970; day < 0; d--)
4269ef1f84bSDavid du Colombier day += *yrsize(d-1);
4279ef1f84bSDavid du Colombier rtc->year = d;
4289ef1f84bSDavid du Colombier
4299ef1f84bSDavid du Colombier /*
4309ef1f84bSDavid du Colombier * generate month
4319ef1f84bSDavid du Colombier */
4329ef1f84bSDavid du Colombier d2m = yrsize(rtc->year);
4339ef1f84bSDavid du Colombier for(d = 1; day >= d2m[d]; d++)
4349ef1f84bSDavid du Colombier day -= d2m[d];
4359ef1f84bSDavid du Colombier rtc->mday = day + 1;
4369ef1f84bSDavid du Colombier rtc->mon = d;
4379ef1f84bSDavid du Colombier
4389ef1f84bSDavid du Colombier return;
4399ef1f84bSDavid du Colombier }
4409ef1f84bSDavid du Colombier
4419ef1f84bSDavid du Colombier uchar
nvramread(int addr)4429ef1f84bSDavid du Colombier nvramread(int addr)
4439ef1f84bSDavid du Colombier {
4449ef1f84bSDavid du Colombier uchar data;
4459ef1f84bSDavid du Colombier
4469ef1f84bSDavid du Colombier ilock(&nvrtlock);
4479ef1f84bSDavid du Colombier outb(Addr, addr);
4489ef1f84bSDavid du Colombier data = inb(Data);
4499ef1f84bSDavid du Colombier iunlock(&nvrtlock);
4509ef1f84bSDavid du Colombier
4519ef1f84bSDavid du Colombier return data;
4529ef1f84bSDavid du Colombier }
4539ef1f84bSDavid du Colombier
4549ef1f84bSDavid du Colombier void
nvramwrite(int addr,uchar data)4559ef1f84bSDavid du Colombier nvramwrite(int addr, uchar data)
4569ef1f84bSDavid du Colombier {
4579ef1f84bSDavid du Colombier ilock(&nvrtlock);
4589ef1f84bSDavid du Colombier outb(Addr, addr);
4599ef1f84bSDavid du Colombier outb(Data, data);
4609ef1f84bSDavid du Colombier iunlock(&nvrtlock);
4619ef1f84bSDavid du Colombier }
462