plan 9 kernel history: overview | file list | diff list

1999/0122/mpc/devrtc.c (diff list | history)

1999/0121/sys/src/9/mpc/devrtc.c:97,1031999/0122/sys/src/9/mpc/devrtc.c:97,103 (short | long)
1999/0121    
rtcread(Chan *c, void *buf, long n, vlong offset) 
{ 
	ulong t; 
	char *b; 
1999/0122    
//	char *b; 
1999/0121    
 
	if(c->qid.path & CHDIR) 
		return devdirread(c, buf, n, rtcdir, NRTC, devgen); 
1999/0121/sys/src/9/mpc/devrtc.c:108,1141999/0122/sys/src/9/mpc/devrtc.c:108,114
1999/0121    
		n = readnum(offset, buf, n, t, 12); 
		return n; 
	case Qswitch: 
		return readnum(offset, buf, n, (m->bcsr[2]>>19)&0xF, 12); 
1999/0122    
		return readnum(offset, buf, n, 0xf/*(m->bcsr[2]>>19)&0xF*/, 12); 
1999/0121    
	} 
	error(Egreg); 
	return 0;		/* not reached */ 
1999/0122/sys/src/9/mpc/devrtc.c:7,221999/0608/sys/src/9/mpc/devrtc.c:7,15 (short | long)
1999/0121    
 
#include	"io.h" 
 
/* 
 * MPC8xx real time clock 
 * FADS board option switch 
 * interrupt statistics 
 */ 
                 
enum{ 
	Qrtc = 1, 
	Qswitch, 
	Qintstat, 
1999/0608    
	Qnvram, 
1999/0121    
 
	/* sccr */ 
	RTDIV=	1<<24, 
1999/0122/sys/src/9/mpc/devrtc.c:25,381999/0608/sys/src/9/mpc/devrtc.c:18,35
1999/0121    
	/* rtcsc */ 
	RTE=	1<<0, 
	R38K=	1<<4, 
1999/0608    
 
	Nvoff=		4*1024,	/* where usable nvram lives */ 
	Nvsize=		4*1024, 
1999/0121    
}; 
 
static	QLock	rtclock;		/* mutex on clock operations */ 
1999/0608    
static Lock nvrtlock; 
1999/0121    
 
1999/0608    
 
1999/0121    
static Dirtab rtcdir[]={ 
	"rtc",		{Qrtc, 0},	12,	0666, 
	"switch",	{Qswitch, 0}, 0, 0444, 
	"intstat",	{Qintstat, 0}, 0, 0444, 
1999/0608    
	"nvram",	{Qnvram, 0},	Nvsize,	0664, 
1999/0121    
}; 
#define	NRTC	(sizeof(rtcdir)/sizeof(rtcdir[0])) 
 
1999/0122/sys/src/9/mpc/devrtc.c:79,871999/0608/sys/src/9/mpc/devrtc.c:76,83
1999/0121    
		if(strcmp(up->user, eve)!=0 && omode!=OREAD) 
			error(Eperm); 
		break; 
	case Qswitch: 
	case Qintstat: 
		if(omode!=OREAD) 
1999/0608    
	case Qnvram: 
		if(strcmp(up->user, eve)!=0) 
1999/0121    
			error(Eperm); 
		break; 
	} 
1999/0122/sys/src/9/mpc/devrtc.c:97,1031999/0608/sys/src/9/mpc/devrtc.c:93,98
1999/0121    
rtcread(Chan *c, void *buf, long n, vlong offset) 
{ 
	ulong t; 
1999/0122    
//	char *b; 
1999/0121    
 
	if(c->qid.path & CHDIR) 
		return devdirread(c, buf, n, rtcdir, NRTC, devgen); 
1999/0122/sys/src/9/mpc/devrtc.c:107,1141999/0608/sys/src/9/mpc/devrtc.c:102,117
1999/0121    
		t = m->iomem->rtc; 
		n = readnum(offset, buf, n, t, 12); 
		return n; 
	case Qswitch: 
1999/0122    
		return readnum(offset, buf, n, 0xf/*(m->bcsr[2]>>19)&0xF*/, 12); 
1999/0608    
	case Qnvram: 
		if(offset >= Nvsize) 
			return 0; 
		t = offset; 
		if(t + n > Nvsize) 
			n = Nvsize - t; 
		ilock(&nvrtlock); 
		memmove(buf, (uchar*)(NVRAMMEM + Nvoff + t), n); 
		iunlock(&nvrtlock); 
		return n; 
1999/0121    
	} 
	error(Egreg); 
	return 0;		/* not reached */ 
1999/0122/sys/src/9/mpc/devrtc.c:120,1251999/0608/sys/src/9/mpc/devrtc.c:123,129
1999/0121    
	ulong secs; 
	char *cp, *ep; 
	IMM *io; 
1999/0608    
	ulong t; 
1999/0121    
 
	switch(c->qid.path){ 
	case Qrtc: 
1999/0122/sys/src/9/mpc/devrtc.c:145,1521999/0608/sys/src/9/mpc/devrtc.c:149,164
1999/0121    
		io->rtck = ~KEEP_ALIVE_KEY; 
		iopunlock(); 
		return n; 
	case Qswitch: 
		return 0; 
1999/0608    
	case Qnvram: 
		if(offset >= Nvsize) 
			return 0; 
		t = offset; 
		if(t + n > Nvsize) 
			n = Nvsize - t; 
		ilock(&nvrtlock); 
		memmove((uchar*)(NVRAMMEM + Nvoff + offset), buf, n); 
		iunlock(&nvrtlock); 
		return n; 
1999/0121    
	} 
	error(Egreg); 
	return 0;		/* not reached */ 
1999/0608/sys/src/9/mpc/devrtc.c:10,151999/0612/sys/src/9/mpc/devrtc.c:10,16 (short | long)
1999/0121    
enum{ 
	Qrtc = 1, 
1999/0608    
	Qnvram, 
1999/0612    
	Qnvram2, 
1999/0121    
 
	/* sccr */ 
	RTDIV=	1<<24, 
1999/0608/sys/src/9/mpc/devrtc.c:21,261999/0612/sys/src/9/mpc/devrtc.c:22,29
1999/0608    
 
	Nvoff=		4*1024,	/* where usable nvram lives */ 
	Nvsize=		4*1024, 
1999/0612    
	Nvoff2=		8*1024,	/* where usable nvram lives */ 
	Nvsize2=	4*1024, 
1999/0121    
}; 
 
static	QLock	rtclock;		/* mutex on clock operations */ 
1999/0608/sys/src/9/mpc/devrtc.c:30,351999/0612/sys/src/9/mpc/devrtc.c:33,39
1999/0121    
static Dirtab rtcdir[]={ 
	"rtc",		{Qrtc, 0},	12,	0666, 
1999/0608    
	"nvram",	{Qnvram, 0},	Nvsize,	0664, 
1999/0612    
	"nvram2",	{Qnvram2, 0},	Nvsize,	0664, 
1999/0121    
}; 
#define	NRTC	(sizeof(rtcdir)/sizeof(rtcdir[0])) 
 
1999/0608/sys/src/9/mpc/devrtc.c:77,821999/0612/sys/src/9/mpc/devrtc.c:81,87
1999/0121    
			error(Eperm); 
		break; 
1999/0608    
	case Qnvram: 
1999/0612    
	case Qnvram2: 
1999/0608    
		if(strcmp(up->user, eve)!=0) 
1999/0121    
			error(Eperm); 
		break; 
1999/0608/sys/src/9/mpc/devrtc.c:112,1171999/0612/sys/src/9/mpc/devrtc.c:117,132
1999/0608    
		memmove(buf, (uchar*)(NVRAMMEM + Nvoff + t), n); 
		iunlock(&nvrtlock); 
		return n; 
1999/0612    
	case Qnvram2: 
		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; 
1999/0121    
	} 
	error(Egreg); 
	return 0;		/* not reached */ 
1999/0608/sys/src/9/mpc/devrtc.c:157,1621999/0612/sys/src/9/mpc/devrtc.c:172,187
1999/0608    
			n = Nvsize - t; 
		ilock(&nvrtlock); 
		memmove((uchar*)(NVRAMMEM + Nvoff + offset), buf, n); 
1999/0612    
		iunlock(&nvrtlock); 
		return n; 
	case Qnvram2: 
		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); 
		return n; 
1999/0121    
	} 
1999/0612/sys/src/9/mpc/devrtc.c:22,281999/0618/sys/src/9/mpc/devrtc.c:22,28 (short | long)
1999/0608    
 
	Nvoff=		4*1024,	/* where usable nvram lives */ 
	Nvsize=		4*1024, 
1999/0612    
	Nvoff2=		8*1024,	/* where usable nvram lives */ 
1999/0618    
	Nvoff2=		8*1024,	/* where second usable nvram lives */ 
1999/0612    
	Nvsize2=	4*1024, 
1999/0121    
}; 
 
1999/0618/sys/src/9/mpc/devrtc.c:11,162000/0516/sys/src/9/mpc/devrtc.c:11,17 (short | long)
1999/0121    
	Qrtc = 1, 
1999/0608    
	Qnvram, 
1999/0612    
	Qnvram2, 
2000/0516    
	Qled, 
1999/0121    
 
	/* sccr */ 
	RTDIV=	1<<24, 
1999/0618/sys/src/9/mpc/devrtc.c:29,392000/0516/sys/src/9/mpc/devrtc.c:30,40
1999/0121    
static	QLock	rtclock;		/* mutex on clock operations */ 
1999/0608    
static Lock nvrtlock; 
1999/0121    
 
1999/0608    
                 
1999/0121    
static Dirtab rtcdir[]={ 
	"rtc",		{Qrtc, 0},	12,	0666, 
1999/0608    
	"nvram",	{Qnvram, 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])) 
 
1999/0618/sys/src/9/mpc/devrtc.c:77,822000/0516/sys/src/9/mpc/devrtc.c:78,84
1999/0121    
	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; 
1999/0618/sys/src/9/mpc/devrtc.c:108,1132000/0516/sys/src/9/mpc/devrtc.c:110,116
1999/0121    
		n = readnum(offset, buf, n, t, 12); 
		return n; 
1999/0608    
	case Qnvram: 
2000/0516    
		return 0; 
1999/0608    
		if(offset >= Nvsize) 
			return 0; 
		t = offset; 
1999/0618/sys/src/9/mpc/devrtc.c:118,1232000/0516/sys/src/9/mpc/devrtc.c:121,127
1999/0608    
		iunlock(&nvrtlock); 
		return n; 
1999/0612    
	case Qnvram2: 
2000/0516    
		return 0; 
1999/0612    
		if(offset >= Nvsize2) 
			return 0; 
		t = offset; 
1999/0618/sys/src/9/mpc/devrtc.c:127,1322000/0516/sys/src/9/mpc/devrtc.c:131,138
1999/0612    
		memmove(buf, (uchar*)(NVRAMMEM + Nvoff2 + t), n); 
		iunlock(&nvrtlock); 
		return n; 
2000/0516    
	case Qled: 
		return 0; 
1999/0121    
	} 
	error(Egreg); 
	return 0;		/* not reached */ 
1999/0618/sys/src/9/mpc/devrtc.c:165,1702000/0516/sys/src/9/mpc/devrtc.c:171,177
1999/0121    
		iopunlock(); 
		return n; 
1999/0608    
	case Qnvram: 
2000/0516    
		return 0; 
1999/0608    
		if(offset >= Nvsize) 
			return 0; 
		t = offset; 
1999/0618/sys/src/9/mpc/devrtc.c:175,1802000/0516/sys/src/9/mpc/devrtc.c:182,188
1999/0612    
		iunlock(&nvrtlock); 
		return n; 
	case Qnvram2: 
2000/0516    
		return 0; 
1999/0612    
		if(offset >= Nvsize2) 
			return 0; 
		t = offset; 
1999/0618/sys/src/9/mpc/devrtc.c:183,1882000/0516/sys/src/9/mpc/devrtc.c:191,204
1999/0612    
		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); 
2000/0516/sys/src/9/mpc/devrtc.c:10,152000/0817/sys/src/9/mpc/devrtc.c:10,16 (short | long)
1999/0121    
enum{ 
	Qrtc = 1, 
1999/0608    
	Qnvram, 
2000/0817    
    Qeeprom, 
1999/0612    
	Qnvram2, 
2000/0516    
	Qled, 
1999/0121    
 
2000/0516/sys/src/9/mpc/devrtc.c:21,282000/0817/sys/src/9/mpc/devrtc.c:22,29
1999/0121    
	RTE=	1<<0, 
	R38K=	1<<4, 
1999/0608    
 
	Nvoff=		4*1024,	/* where usable nvram lives */ 
	Nvsize=		4*1024, 
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    
}; 
2000/0516/sys/src/9/mpc/devrtc.c:29,432000/0817/sys/src/9/mpc/devrtc.c:30,52
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, 
1999/0608    
	"nvram",	{Qnvram, 0},	Nvsize,	0664, 
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) 
{ 
2000/0516/sys/src/9/mpc/devrtc.c:82,882000/0817/sys/src/9/mpc/devrtc.c:91,98
1999/0121    
		if(strcmp(up->user, eve)!=0 && omode!=OREAD) 
			error(Eperm); 
		break; 
1999/0608    
	case Qnvram: 
2000/0817    
	case Qeeprom: 
    //case Qnvram: 
1999/0612    
	case Qnvram2: 
1999/0608    
		if(strcmp(up->user, eve)!=0) 
1999/0121    
			error(Eperm); 
2000/0516/sys/src/9/mpc/devrtc.c:99,1062000/0817/sys/src/9/mpc/devrtc.c:109,118
1999/0121    
static long	  
rtcread(Chan *c, void *buf, long n, vlong offset) 
{ 
	ulong t; 
                 
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); 
 
2000/0516/sys/src/9/mpc/devrtc.c:109,1262000/0817/sys/src/9/mpc/devrtc.c:121,167
1999/0121    
		t = m->iomem->rtc; 
		n = readnum(offset, buf, n, t, 12); 
		return n; 
1999/0608    
	case Qnvram: 
2000/0516    
		return 0; 
2000/0817    
	case Qeeprom: 
    //case Qnvram: 
1999/0608    
		if(offset >= Nvsize) 
			return 0; 
		t = offset; 
		if(t + n > Nvsize) 
			n = Nvsize - t; 
		ilock(&nvrtlock); 
		memmove(buf, (uchar*)(NVRAMMEM + Nvoff + t), n); 
		iunlock(&nvrtlock); 
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; 
2000/0516/sys/src/9/mpc/devrtc.c:132,1382000/0817/sys/src/9/mpc/devrtc.c:173,185
1999/0612    
		iunlock(&nvrtlock); 
		return n; 
2000/0516    
	case Qled: 
		return 0; 
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 */ 
2000/0516/sys/src/9/mpc/devrtc.c:144,1502000/0817/sys/src/9/mpc/devrtc.c:191,199
1999/0121    
	ulong secs; 
	char *cp, *ep; 
	IMM *io; 
1999/0608    
	ulong t; 
2000/0817    
	ulong t,readaddr,writeaddr; 
    int index; 
    uchar spibuf[2]; 
1999/0121    
 
	switch(c->qid.path){ 
	case Qrtc: 
2000/0516/sys/src/9/mpc/devrtc.c:170,1872000/0817/sys/src/9/mpc/devrtc.c:219,279
1999/0121    
		io->rtck = ~KEEP_ALIVE_KEY; 
		iopunlock(); 
		return n; 
1999/0608    
	case Qnvram: 
2000/0516    
		return 0; 
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; 
		ilock(&nvrtlock); 
		memmove((uchar*)(NVRAMMEM + Nvoff + offset), buf, n); 
1999/0612    
		iunlock(&nvrtlock); 
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; 
2000/0817/sys/src/9/mpc/devrtc.c:1,3252001/0527/sys/src/9/mpc/devrtc.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:28:39 2005
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, 
}; 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)