| plan 9 kernel history: overview | file list | diff list |
2000/0817/mpc/devrtc.c (diff list | history)
| mpc/devrtc.c on 1999/0121 | ||
| 1999/0121 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "io.h" enum{ Qrtc = 1, | |
| 1999/0608 | Qnvram, | |
| 2000/0817 | Qeeprom, | |
| 1999/0612 | Qnvram2, | |
| 2000/0516 | Qled, | |
| 1999/0121 | /* sccr */ RTDIV= 1<<24, RTSEL= 1<<23, /* rtcsc */ RTE= 1<<0, R38K= 1<<4, | |
| 1999/0608 | ||
| 2000/0817 | Nvoff= 0, /* where usable EEPROM lives */ Nvsize= 256,/*128x16=256x8*/ | |
| 1999/0618 | Nvoff2= 8*1024, /* where second usable nvram lives */ | |
| 1999/0612 | Nvsize2= 4*1024, | |
| 1999/0121 | }; static QLock rtclock; /* mutex on clock operations */ | |
| 1999/0608 | static Lock nvrtlock; | |
| 2000/0817 | static Lock eepromlock; | |
| 1999/0121 | static Dirtab rtcdir[]={ "rtc", {Qrtc, 0}, 12, 0666, | |
| 2000/0817 | "eeprom", {Qeeprom, 0}, Nvsize, 0664, | |
| 1999/0612 | "nvram2", {Qnvram2, 0}, Nvsize, 0664, | |
| 2000/0516 | "led", {Qled, 0}, 0, 0664, | |
| 1999/0121 | }; #define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0])) | |
| 2000/0817 | extern void spiread(ulong addr, uchar *buf); extern void spiwrite(ulong addr, uchar *buf); extern void spiresult(void); extern void spienwrite(void); extern void spidiswrite(void); extern void spiwriteall(uchar *buf); | |
| 1999/0121 | static void rtcreset(void) { IMM *io; int n; io = m->iomem; io->rtcsck = KEEP_ALIVE_KEY; n = (RTClevel<<8)|RTE; if(m->oscclk == 5) n |= R38K; io->rtcsc = n; io->rtcsck = ~KEEP_ALIVE_KEY; print("sccr=#%8.8lux plprcr=#%8.8lux\n", io->sccr, io->plprcr); } static Chan* rtcattach(char *spec) { return devattach('r', spec); } static int rtcwalk(Chan *c, char *name) { return devwalk(c, name, rtcdir, NRTC, devgen); } static void rtcstat(Chan *c, char *dp) { devstat(c, dp, rtcdir, NRTC, devgen); } static Chan* rtcopen(Chan *c, int omode) { omode = openmode(omode); switch(c->qid.path){ case Qrtc: | |
| 2000/0516 | case Qled: | |
| 1999/0121 | if(strcmp(up->user, eve)!=0 && omode!=OREAD) error(Eperm); break; | |
| 2000/0817 | case Qeeprom: //case Qnvram: | |
| 1999/0612 | case Qnvram2: | |
| 1999/0608 | if(strcmp(up->user, eve)!=0) | |
| 1999/0121 | error(Eperm); break; } return devopen(c, omode, rtcdir, NRTC, devgen); } static void rtcclose(Chan*) { } static long rtcread(Chan *c, void *buf, long n, vlong offset) { | |
| 2000/0817 | ulong t,readaddr; uchar spibuf[2]; int index; | |
| 1999/0121 | if(c->qid.path & CHDIR) return devdirread(c, buf, n, rtcdir, NRTC, devgen); switch(c->qid.path){ case Qrtc: t = m->iomem->rtc; n = readnum(offset, buf, n, t, 12); return n; | |
| 2000/0817 | case Qeeprom: //case Qnvram: | |
| 1999/0608 | if(offset >= Nvsize) return 0; t = offset; if(t + n > Nvsize) n = Nvsize - t; | |
| 2000/0817 | ilock(&eepromlock); /* read from eeprom through spi, two bytes a time*/ index=0; if(t%2!=0){ print("not starting from an even address\n"); readaddr=(t-1)/2; spiread(readaddr,spibuf); memmove((uchar*)buf+index,(uchar *)spibuf+1,1); index++; readaddr++; } else readaddr=t/2; while(index<n){ spiread(readaddr,spibuf); memmove((uchar*)buf+index,spibuf,1); if(index+1<n) memmove((uchar*)buf+index+1,(uchar*)spibuf+1,1); readaddr++; index+=2; } /* print("result of reading is \n"); for(index=0;index<n;index++) print(" %ux ",((uchar*)buf)[index]); print("\n"); */ iunlock(&eepromlock); | |
| 1999/0608 | return n; | |
| 1999/0612 | case Qnvram2: | |
| 2000/0817 | print("ram 2\n"); | |
| 2000/0516 | return 0; | |
| 1999/0612 | if(offset >= Nvsize2) return 0; t = offset; if(t + n > Nvsize2) n = Nvsize2 - t; ilock(&nvrtlock); memmove(buf, (uchar*)(NVRAMMEM + Nvoff2 + t), n); iunlock(&nvrtlock); return n; | |
| 2000/0516 | case Qled: | |
| 2000/0817 | if(offset >= 5) return 0; t = offset; if(t + n > 5) n = 5 - t; memmove(buf, "kitty" + t, n); return n; | |
| 1999/0121 | } error(Egreg); return 0; /* not reached */ } static long rtcwrite(Chan *c, void *buf, long n, vlong offset) { ulong secs; char *cp, *ep; IMM *io; | |
| 2000/0817 | ulong t,readaddr,writeaddr; int index; uchar spibuf[2]; | |
| 1999/0121 | switch(c->qid.path){ case Qrtc: if(offset!=0) error(Ebadarg); /* * read the time */ cp = ep = buf; ep += n; while(cp < ep){ if(*cp>='0' && *cp<='9') break; cp++; } secs = strtoul(cp, 0, 0); /* * set it */ io = ioplock(); io->rtck = KEEP_ALIVE_KEY; io->rtc = secs; io->rtck = ~KEEP_ALIVE_KEY; iopunlock(); return n; | |
| 2000/0817 | case Qeeprom: //case Qnvram: print("write %d to eeprom\n",n); | |
| 1999/0608 | if(offset >= Nvsize) return 0; t = offset; if(t + n > Nvsize) n = Nvsize - t; | |
| 2000/0817 | ilock(&eepromlock); index=0; spienwrite(); /*if the writing addr starts at an odd address, we need to read in the higher byte first, combined it with the lower byte, and then write them out */ if(t%2!=0){ print("not starting from an even address\n"); readaddr=(t-1)/2; spiread(readaddr,spibuf); memmove((uchar*)spibuf+1,(uchar*)buf+index,1); //spienwrite(); spiwrite(readaddr,spibuf); //spidiswrite(); index++; writeaddr=readaddr+1; } else writeaddr=t/2; while(index<n){ if(index+1==n){ //spienwrite(); spiread(writeaddr,spibuf); //spidiswrite(); } else memmove((uchar*)spibuf+1,(uchar*)buf+index+1,1); memmove((uchar*)spibuf,(uchar*)buf+index,1); // spienwrite(); spiwrite(writeaddr,spibuf); // spidiswrite(); writeaddr++; index+=2; } spidiswrite(); //memmove((uchar*)(NVRAMMEM + Nvoff + offset), buf, n); iunlock(&eepromlock); | |
| 1999/0612 | return n; | |
| 2000/0817 | ||
| 1999/0612 | case Qnvram2: | |
| 2000/0817 | memmove((uchar*)spibuf,(uchar*)buf,2); spiwriteall(spibuf); | |
| 2000/0516 | return 0; | |
| 1999/0612 | if(offset >= Nvsize2) return 0; t = offset; if(t + n > Nvsize2) n = Nvsize2 - t; ilock(&nvrtlock); memmove((uchar*)(NVRAMMEM + Nvoff2 + offset), buf, n); | |
| 1999/0608 | iunlock(&nvrtlock); | |
| 2000/0516 | return n; case Qled: if(strncmp(buf, "on", 2) == 0) powerupled(); else if(strncmp(buf, "off", 3) == 0) powerdownled(); else error("unknown command"); | |
| 1999/0608 | return n; | |
| 1999/0121 | } error(Egreg); return 0; /* not reached */ } long rtctime(void) { return m->iomem->rtc; } Dev rtcdevtab = { 'r', "rtc", rtcreset, devinit, rtcattach, devclone, rtcwalk, rtcstat, rtcopen, devcreate, rtcclose, rtcread, devbread, rtcwrite, devbwrite, devremove, devwstat, }; | |