Annotation of lucent/sys/src/9/pc/devrtc.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.