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

1999/0228/carrera/devrtc.c (diff list | history)

1993/0916/sys/src/9/carrera/devrtc.c:116,1281994/0225/sys/src/9/carrera/devrtc.c:116,126 (short | long)
1993/0916    
bcd2binary(int reg) 
{ 
	uchar x; 
/* 
1994/0225    
 
1993/0916    
	x = (*(uchar*)Rtcindex)&~0x7f; 
	*(uchar*)Rtcindex = x|reg; 
	x = *(uchar*)Rtcdata; 
	return (x&0xf) + 10*(x>>4); 
/**/ 
	return 0; 
} 
 
long	  
1993/0916/sys/src/9/carrera/devrtc.c:191,2011994/0225/sys/src/9/carrera/devrtc.c:189,197
1993/0916    
binary2bcd(int reg, uchar val) 
{ 
	uchar x; 
/* 
	x = (*(uchar*)Rtcindex)&~0x7f; 
	*(uchar*)Rtcindex = x|reg; 
	*(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4); 
/**/ 
} 
 
 
1994/0225/sys/src/9/carrera/devrtc.c:24,301995/0108/sys/src/9/carrera/devrtc.c:24,31 (short | long)
1993/0916    
QLock rtclock;	/* mutex on clock operations */ 
 
 
enum{ 
1995/0108    
enum 
{ 
1993/0916    
	Qrtc = 1, 
	Qnvram, 
 
1994/0225/sys/src/9/carrera/devrtc.c:185,1901995/0108/sys/src/9/carrera/devrtc.c:186,197
1993/0916    
	return 0; 
} 
 
1995/0108    
Block* 
rtcbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
1993/0916    
static void 
binary2bcd(int reg, uchar val) 
{ 
1994/0225/sys/src/9/carrera/devrtc.c:247,2521995/0108/sys/src/9/carrera/devrtc.c:254,265
1993/0916    
	} 
	error(Ebadarg); 
	return 0; 
1995/0108    
} 
 
long 
rtcbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1993/0916    
} 
 
void	  
1995/0108/sys/src/9/carrera/devrtc.c:4,101996/0223/sys/src/9/carrera/devrtc.c:4,9 (short | long)
1993/0916    
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
#include	"devtab.h" 
#include	"io.h" 
 
/* 
1996/0223/sys/src/9/carrera/devrtc.c:20,261997/0327/sys/src/9/carrera/devrtc.c:20,26 (short | long)
1993/0916    
	int	mon; 
	int	year; 
}; 
QLock rtclock;	/* mutex on clock operations */ 
1997/0327    
static QLock rtclock;	/* mutex on clock operations */ 
1993/0916    
 
 
1995/0108    
enum 
1996/0223/sys/src/9/carrera/devrtc.c:39,891997/0327/sys/src/9/carrera/devrtc.c:39,71
1993/0916    
	Nvsize = 4096, 
}; 
 
#define	NRTC	2 
Dirtab rtcdir[]={ 
	"nvram",	{Qnvram, 0},	Nvsize,	0664, 
	"rtc",		{Qrtc, 0},	0,	0664, 
}; 
 
ulong rtc2sec(Rtc*); 
void sec2rtc(ulong, Rtc*); 
int *yrsize(int); 
1997/0327    
static ulong rtc2sec(Rtc*); 
static void sec2rtc(ulong, Rtc*); 
1993/0916    
 
void 
rtcreset(void) 
{ 
} 
                 
void 
rtcinit(void) 
{ 
} 
                 
Chan* 
1997/0327    
static Chan* 
1993/0916    
rtcattach(char *spec) 
{ 
	return devattach('r', spec); 
} 
 
Chan* 
rtcclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
                 
int	  
1997/0327    
static int	  
1993/0916    
rtcwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, rtcdir, NRTC, devgen); 
1997/0327    
	return devwalk(c, name, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
} 
 
void	  
1997/0327    
static void	  
1993/0916    
rtcstat(Chan *c, char *dp) 
{ 
	devstat(c, dp, rtcdir, NRTC, devgen); 
1997/0327    
	devstat(c, dp, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
} 
 
Chan* 
1997/0327    
static Chan* 
1993/0916    
rtcopen(Chan *c, int omode) 
{ 
	omode = openmode(omode); 
1996/0223/sys/src/9/carrera/devrtc.c:96,1121997/0327/sys/src/9/carrera/devrtc.c:78,87
1993/0916    
		if(strcmp(up->user, eve)!=0) 
			error(Eperm); 
	} 
	return devopen(c, omode, rtcdir, NRTC, devgen); 
1997/0327    
	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
} 
 
void	  
rtccreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	USED(c, name, omode, perm); 
	error(Eperm); 
} 
                 
void	  
1997/0327    
static void	  
1993/0916    
rtcclose(Chan *c) 
{ 
	USED(c); 
1996/0223/sys/src/9/carrera/devrtc.c:151,1571997/0327/sys/src/9/carrera/devrtc.c:126,132
1993/0916    
	return rtc2sec(&rtc); 
} 
 
long	  
1997/0327    
static long	  
1993/0916    
rtcread(Chan *c, void *buf, long n, ulong offset) 
{ 
	ulong t, ot; 
1996/0223/sys/src/9/carrera/devrtc.c:158,1641997/0327/sys/src/9/carrera/devrtc.c:133,139
1993/0916    
	uchar *f, *to, *e; 
 
	if(c->qid.path & CHDIR) 
		return devdirread(c, buf, n, rtcdir, NRTC, devgen); 
1997/0327    
		return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
 
	switch(c->qid.path){ 
	case Qrtc: 
1996/0223/sys/src/9/carrera/devrtc.c:185,1961997/0327/sys/src/9/carrera/devrtc.c:160,165
1993/0916    
	return 0; 
} 
 
1995/0108    
Block* 
rtcbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
                 
1993/0916    
static void 
binary2bcd(int reg, uchar val) 
{ 
1996/0223/sys/src/9/carrera/devrtc.c:201,2071997/0327/sys/src/9/carrera/devrtc.c:170,176
1993/0916    
} 
 
 
long	  
1997/0327    
static long	  
1993/0916    
rtcwrite(Chan *c, void *buf, long n, ulong offset) 
{ 
	Rtc rtc; 
1996/0223/sys/src/9/carrera/devrtc.c:255,2801997/0327/sys/src/9/carrera/devrtc.c:224,247
1993/0916    
	return 0; 
1995/0108    
} 
 
long 
rtcbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1993/0916    
} 
1997/0327    
Dev rtcdevtab = { 
	devreset, 
	devinit, 
	rtcattach, 
	devclone, 
	rtcwalk, 
	rtcstat, 
	rtcopen, 
	devcreate, 
	rtcclose, 
	rtcread, 
	devbread, 
	rtcwrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 
1993/0916    
 
void	  
rtcremove(Chan *c) 
{ 
	USED(c); 
	error(Eperm); 
} 
                 
void	  
rtcwstat(Chan *c, char *dp) 
{ 
	USED(c, dp); 
	error(Eperm); 
} 
                 
#define SEC2MIN 60L 
#define SEC2HOUR (60L*SEC2MIN) 
#define SEC2DAY (24L*SEC2HOUR) 
1996/0223/sys/src/9/carrera/devrtc.c:294,3001997/0327/sys/src/9/carrera/devrtc.c:261,267
1993/0916    
/* 
 *  return the days/month for the given year 
 */ 
int * 
1997/0327    
static int* 
1993/0916    
yrsize(int yr) 
{ 
	if((yr % 4) == 0) 
1996/0223/sys/src/9/carrera/devrtc.c:306,3121997/0327/sys/src/9/carrera/devrtc.c:273,279
1993/0916    
/* 
 *  compute seconds since Jan 1 1970 
 */ 
ulong 
1997/0327    
static ulong 
1993/0916    
rtc2sec(Rtc *rtc) 
{ 
	ulong secs; 
1996/0223/sys/src/9/carrera/devrtc.c:341,3471997/0327/sys/src/9/carrera/devrtc.c:308,314
1993/0916    
/* 
 *  compute rtc from seconds since Jan 1 1970 
 */ 
void 
1997/0327    
static void 
1993/0916    
sec2rtc(ulong secs, Rtc *rtc) 
{ 
	int d; 
1997/0327/sys/src/9/carrera/devrtc.c:98,1351997/0401/sys/src/9/carrera/devrtc.c:98,165 (short | long)
1993/0916    
	return (x&0xf) + 10*(x>>4); 
} 
 
long	  
rtctime(void) 
1997/0401    
static long	  
_rtctime(void) 
1993/0916    
{ 
	Rtc rtc; 
	int x; 
1997/0401    
	int i, x; 
1993/0916    
 
	/* 
	 *  read and convert from bcd 
	 */ 
	x = splhi(); 
	rtc.sec = bcd2binary(Seconds); 
	rtc.min = bcd2binary(Minutes); 
	rtc.hour = bcd2binary(Hours); 
	rtc.mday = bcd2binary(Mday); 
	rtc.mon = bcd2binary(Month); 
	rtc.year = bcd2binary(Year); 
	splx(x); 
1997/0401    
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		x = *(uchar*)Rtcdata; 
		if(x & 0x80) 
			continue; 
1993/0916    
 
	/* 
	 *  the world starts jan 1 1970 
	 */ 
	if(rtc.year < 70) 
		rtc.year += 2000; 
	else 
		rtc.year += 1900; 
1997/0401    
		/* 
		 *  read and convert from bcd 
		 */ 
		rtc.sec = bcd2binary(Seconds); 
		rtc.min = bcd2binary(Minutes); 
		rtc.hour = bcd2binary(Hours); 
		rtc.mday = bcd2binary(Mday); 
		rtc.mon = bcd2binary(Month); 
		rtc.year = bcd2binary(Year)+1970; 
 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		x = *(uchar*)Rtcdata; 
		if((x & 0x80) == 0) 
			break; 
	} 
 
1993/0916    
	return rtc2sec(&rtc); 
} 
 
1997/0401    
static Lock rtlock; 
 
long 
rtctime(void) 
{ 
	int i; 
	long t, ot; 
 
	ilock(&rtlock); 
 
	/* loop till we get two reads in a row the same */ 
	t = _rtctime(); 
	for(i = 0; i < 100; i++){ 
		ot = t; 
		t = _rtctime(); 
		if(ot == t) 
			break; 
	} 
	if(i == 100) print("we are boofheads\n"); 
 
	iunlock(&rtlock); 
 
	return t; 
} 
 
1997/0327    
static long	  
1993/0916    
rtcread(Chan *c, void *buf, long n, ulong offset) 
{ 
	ulong t, ot; 
1997/0401    
	ulong t; 
1993/0916    
	uchar *f, *to, *e; 
 
	if(c->qid.path & CHDIR) 
1997/0327/sys/src/9/carrera/devrtc.c:137,1471997/0401/sys/src/9/carrera/devrtc.c:167,175
1993/0916    
 
	switch(c->qid.path){ 
	case Qrtc: 
1997/0401    
		qlock(&rtclock); 
1993/0916    
		t = rtctime(); 
		do{ 
			ot = t; 
			t = rtctime();	/* make sure there's no skew */ 
		}while(t != ot); 
1997/0401    
		qunlock(&rtclock); 
1993/0916    
		n = readnum(offset, buf, n, t, 12); 
		return n; 
	case Qnvram: 
1997/0327/sys/src/9/carrera/devrtc.c:204,2101997/0401/sys/src/9/carrera/devrtc.c:232,238
1993/0916    
		binary2bcd(Hours, rtc.hour); 
		binary2bcd(Mday, rtc.mday); 
		binary2bcd(Month, rtc.mon); 
		binary2bcd(Year, rtc.year); 
1997/0401    
		binary2bcd(Year, rtc.year-1970); 
1993/0916    
		splx(s); 
 
		return n; 
1997/0401/sys/src/9/carrera/devrtc.c:35,421997/0403/sys/src/9/carrera/devrtc.c:35,47 (short | long)
1993/0916    
	Month=		0x08, 
	Year=		0x09, 
	Status=		0x0A, 
1997/0403    
	StatusB=	0x0B, 
	StatusC=	0x0C, 
	StatusD=	0x0D, 
1993/0916    
 
	Nvsize = 4096, 
1997/0403    
 
	Nclock=		6, 
1993/0916    
}; 
 
Dirtab rtcdir[]={ 
1997/0401/sys/src/9/carrera/devrtc.c:47,551997/0403/sys/src/9/carrera/devrtc.c:52,82
1997/0327    
static ulong rtc2sec(Rtc*); 
static void sec2rtc(ulong, Rtc*); 
1993/0916    
 
1997/0403    
static uchar statusB; 
 
static void 
getstatusB(void) 
{ 
	int i, x; 
	uchar r; 
 
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		r = *(uchar*)Rtcdata; 
		if(r & 0x80) 
			continue; 
 
		*(uchar*)Rtcindex = x|StatusB; 
		statusB = *(uchar*)Rtcdata; 
		break; 
	} 
} 
 
1997/0327    
static Chan* 
1993/0916    
rtcattach(char *spec) 
{ 
1997/0403    
	getstatusB(); 
1993/0916    
	return devattach('r', spec); 
} 
 
1997/0401/sys/src/9/carrera/devrtc.c:98,1331997/0403/sys/src/9/carrera/devrtc.c:125,226
1993/0916    
	return (x&0xf) + 10*(x>>4); 
} 
 
1997/0403    
#define GETBCD(o) ((clock[o]&0xf) + 10*(clock[o]>>4)) 
 
static void 
dumprtcstatus(void) 
{ 
	int i, x; 
	uchar status[4], r; 
 
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		r = *(uchar*)Rtcdata; 
		if(r & 0x80) 
			continue; 
 
		status[0] = r; 
		*(uchar*)Rtcindex = x|StatusB; 
		status[1] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|StatusC; 
		status[2] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|StatusD; 
		status[3] = *(uchar*)Rtcdata; 
 
		*(uchar*)Rtcindex = x|Status; 
		r = *(uchar*)Rtcdata; 
		if((r & 0x80) == 0) 
			break; 
	} 
 
	print("RTC: %uX %uX %uX %uX\n", status[0], status[1], status[2], status[3]); 
} 
 
1997/0401    
static long	  
_rtctime(void) 
1993/0916    
{ 
	Rtc rtc; 
1997/0401    
	int i, x; 
1997/0403    
	uchar clock[Nclock], r; 
	int busy; 
1993/0916    
 
1997/0403    
	/* don't do the read until the clock is no longer busy */ 
	busy = 0; 
1997/0401    
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		x = *(uchar*)Rtcdata; 
		if(x & 0x80) 
1997/0403    
		r = *(uchar*)Rtcdata; 
		if(r & 0x80){ 
			busy++; 
1997/0401    
			continue; 
1997/0403    
		} 
1993/0916    
 
1997/0401    
		/* 
		 *  read and convert from bcd 
		 */ 
		rtc.sec = bcd2binary(Seconds); 
		rtc.min = bcd2binary(Minutes); 
		rtc.hour = bcd2binary(Hours); 
		rtc.mday = bcd2binary(Mday); 
		rtc.mon = bcd2binary(Month); 
		rtc.year = bcd2binary(Year)+1970; 
1997/0403    
		/* read clock values */ 
		*(uchar*)Rtcindex = x|Seconds; 
		clock[0] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|Minutes; 
		clock[1] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|Hours; 
		clock[2] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|Mday; 
		clock[3] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|Month; 
		clock[4] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|Year; 
		clock[5] = *(uchar*)Rtcdata; 
1997/0401    
 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		x = *(uchar*)Rtcdata; 
		if((x & 0x80) == 0) 
1997/0403    
		r = *(uchar*)Rtcdata; 
		if((r & 0x80) == 0) 
1997/0401    
			break; 
	} 
 
1997/0403    
	if(statusB & 0x04){ 
		rtc.sec = clock[0]; 
		rtc.min = clock[1]; 
		rtc.hour = clock[2]; 
		rtc.mday = clock[3]; 
		rtc.mon = clock[4]; 
		rtc.year = clock[5]; 
	} 
	else{ 
		/* 
		 *  convert from BCD 
		 */ 
		rtc.sec = GETBCD(0); 
		rtc.min = GETBCD(1); 
		rtc.hour = GETBCD(2); 
		rtc.mday = GETBCD(3); 
		rtc.mon = GETBCD(4); 
		rtc.year = GETBCD(5); 
	} 
 
	/* 
	 *  the world starts jan 1 1970 
	 */ 
	rtc.year += 1970; 
 
1993/0916    
	return rtc2sec(&rtc); 
} 
 
1997/0401/sys/src/9/carrera/devrtc.c:136,1411997/0403/sys/src/9/carrera/devrtc.c:229,236
1997/0401    
long 
rtctime(void) 
{ 
1997/0403    
#define notdef 
#ifdef notdef 
1997/0401    
	int i; 
	long t, ot; 
 
1997/0401/sys/src/9/carrera/devrtc.c:149,1591997/0403/sys/src/9/carrera/devrtc.c:244,259
1997/0401    
		if(ot == t) 
			break; 
	} 
	if(i == 100) print("we are boofheads\n"); 
                 
	iunlock(&rtlock); 
 
1997/0403    
	if(i == 100) print("we are boofheads\n"); 
 
1997/0401    
	return t; 
1997/0403    
#else 
	extern ulong boottime; 
 
	return boottime+TK2SEC(MACHP(0)->ticks); 
#endif /* notdef */ 
1997/0401    
} 
 
1997/0327    
static long	  
1997/0401/sys/src/9/carrera/devrtc.c:169,1741997/0403/sys/src/9/carrera/devrtc.c:269,275
1993/0916    
	case Qrtc: 
1997/0401    
		qlock(&rtclock); 
1993/0916    
		t = rtctime(); 
1997/0403    
dumprtcstatus(); 
1997/0401    
		qunlock(&rtclock); 
1993/0916    
		n = readnum(offset, buf, n, t, 12); 
		return n; 
1997/0401/sys/src/9/carrera/devrtc.c:192,2001997/0403/sys/src/9/carrera/devrtc.c:293,305
1993/0916    
binary2bcd(int reg, uchar val) 
{ 
	uchar x; 
1997/0403    
 
1993/0916    
	x = (*(uchar*)Rtcindex)&~0x7f; 
	*(uchar*)Rtcindex = x|reg; 
	*(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4); 
1997/0403    
	if(statusB & 0x04) 
		*(uchar*)Rtcdata = val; 
	else 
		*(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4); 
1993/0916    
} 
 
 
1997/0403/sys/src/9/carrera/devrtc.c:20,281997/0404/sys/src/9/carrera/devrtc.c:20,26 (short | long)
1993/0916    
	int	mon; 
	int	year; 
}; 
1997/0327    
static QLock rtclock;	/* mutex on clock operations */ 
1993/0916    
 
                 
1995/0108    
enum 
{ 
1993/0916    
	Qrtc = 1, 
1997/0403/sys/src/9/carrera/devrtc.c:39,491997/0404/sys/src/9/carrera/devrtc.c:37,52
1997/0403    
	StatusC=	0x0C, 
	StatusD=	0x0D, 
1993/0916    
 
1997/0404    
	Update=		0x80, 
 
1993/0916    
	Nvsize = 4096, 
1997/0403    
 
	Nclock=		6, 
1993/0916    
}; 
 
1997/0404    
#define GETBCD(v)	(((v) & 0x0F) + 10*((v)>>4)) 
#define PUTBCD(v)	((v) % 10)|((((v)/10) % 10)<<4) 
 
1993/0916    
Dirtab rtcdir[]={ 
	"nvram",	{Qnvram, 0},	Nvsize,	0664, 
	"rtc",		{Qrtc, 0},	0,	0664, 
1997/0403/sys/src/9/carrera/devrtc.c:52,611997/0404/sys/src/9/carrera/devrtc.c:55,65
1997/0327    
static ulong rtc2sec(Rtc*); 
static void sec2rtc(ulong, Rtc*); 
1993/0916    
 
1997/0403    
static uchar statusB; 
1997/0404    
static int isbinary; 
static Lock rtclock; 
1997/0403    
 
static void 
getstatusB(void) 
1997/0404    
rtcreset(void) 
1997/0403    
{ 
	int i, x; 
	uchar r; 
1997/0403/sys/src/9/carrera/devrtc.c:68,741997/0404/sys/src/9/carrera/devrtc.c:72,78
1997/0403    
			continue; 
 
		*(uchar*)Rtcindex = x|StatusB; 
		statusB = *(uchar*)Rtcdata; 
1997/0404    
		isbinary = *(uchar*)Rtcdata & 0x04; 
1997/0403    
		break; 
	} 
} 
1997/0403/sys/src/9/carrera/devrtc.c:76,821997/0404/sys/src/9/carrera/devrtc.c:80,85
1997/0327    
static Chan* 
1993/0916    
rtcattach(char *spec) 
{ 
1997/0403    
	getstatusB(); 
1993/0916    
	return devattach('r', spec); 
} 
 
1997/0403/sys/src/9/carrera/devrtc.c:114,2191997/0404/sys/src/9/carrera/devrtc.c:117,167
1993/0916    
	USED(c); 
} 
 
static uchar 
bcd2binary(int reg) 
{ 
	uchar x; 
1994/0225    
                 
1993/0916    
	x = (*(uchar*)Rtcindex)&~0x7f; 
	*(uchar*)Rtcindex = x|reg; 
	x = *(uchar*)Rtcdata; 
	return (x&0xf) + 10*(x>>4); 
} 
                 
1997/0403    
#define GETBCD(o) ((clock[o]&0xf) + 10*(clock[o]>>4)) 
                 
static void 
dumprtcstatus(void) 
{ 
	int i, x; 
	uchar status[4], r; 
                 
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		r = *(uchar*)Rtcdata; 
		if(r & 0x80) 
			continue; 
                 
		status[0] = r; 
		*(uchar*)Rtcindex = x|StatusB; 
		status[1] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|StatusC; 
		status[2] = *(uchar*)Rtcdata; 
		*(uchar*)Rtcindex = x|StatusD; 
		status[3] = *(uchar*)Rtcdata; 
                 
		*(uchar*)Rtcindex = x|Status; 
		r = *(uchar*)Rtcdata; 
		if((r & 0x80) == 0) 
			break; 
	} 
                 
	print("RTC: %uX %uX %uX %uX\n", status[0], status[1], status[2], status[3]); 
} 
                 
1997/0401    
static long	  
_rtctime(void) 
1993/0916    
{ 
	Rtc rtc; 
1997/0401    
	int i, x; 
1997/0403    
	uchar clock[Nclock], r; 
	int busy; 
1997/0404    
	uchar r; 
1993/0916    
 
1997/0403    
	/* don't do the read until the clock is no longer busy */ 
	busy = 0; 
1997/0401    
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
1997/0403    
		r = *(uchar*)Rtcdata; 
		if(r & 0x80){ 
			busy++; 
1997/0404    
		if(r & Update) 
1997/0401    
			continue; 
1997/0403    
		} 
1993/0916    
 
1997/0403    
		/* read clock values */ 
		*(uchar*)Rtcindex = x|Seconds; 
		clock[0] = *(uchar*)Rtcdata; 
1997/0404    
		rtc.sec = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Minutes; 
		clock[1] = *(uchar*)Rtcdata; 
1997/0404    
		rtc.min = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Hours; 
		clock[2] = *(uchar*)Rtcdata; 
1997/0404    
		rtc.hour = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Mday; 
		clock[3] = *(uchar*)Rtcdata; 
1997/0404    
		rtc.mday = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Month; 
		clock[4] = *(uchar*)Rtcdata; 
1997/0404    
		rtc.mon = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Year; 
		clock[5] = *(uchar*)Rtcdata; 
1997/0404    
		rtc.year = *(uchar*)Rtcdata; 
1997/0401    
 
		*(uchar*)Rtcindex = x|Status; 
1997/0403    
		r = *(uchar*)Rtcdata; 
		if((r & 0x80) == 0) 
1997/0404    
		if((r & Update) == 0) 
1997/0401    
			break; 
	} 
 
1997/0403    
	if(statusB & 0x04){ 
		rtc.sec = clock[0]; 
		rtc.min = clock[1]; 
		rtc.hour = clock[2]; 
		rtc.mday = clock[3]; 
		rtc.mon = clock[4]; 
		rtc.year = clock[5]; 
	} 
	else{ 
1997/0404    
	if(!isbinary){ 
1997/0403    
		/* 
		 *  convert from BCD 
		 */ 
		rtc.sec = GETBCD(0); 
		rtc.min = GETBCD(1); 
		rtc.hour = GETBCD(2); 
		rtc.mday = GETBCD(3); 
		rtc.mon = GETBCD(4); 
		rtc.year = GETBCD(5); 
1997/0404    
		rtc.sec = GETBCD(rtc.sec); 
		rtc.min = GETBCD(rtc.min); 
		rtc.hour = GETBCD(rtc.hour); 
		rtc.mday = GETBCD(rtc.mday); 
		rtc.mon = GETBCD(rtc.mon); 
		rtc.year = GETBCD(rtc.year); 
1997/0403    
	} 
 
	/* 
1997/0403/sys/src/9/carrera/devrtc.c:224,2401997/0404/sys/src/9/carrera/devrtc.c:172,184
1993/0916    
	return rtc2sec(&rtc); 
} 
 
1997/0401    
static Lock rtlock; 
                 
long 
rtctime(void) 
{ 
1997/0403    
#define notdef 
#ifdef notdef 
1997/0401    
	int i; 
	long t, ot; 
 
	ilock(&rtlock); 
1997/0404    
	ilock(&rtclock); 
1997/0401    
 
	/* loop till we get two reads in a row the same */ 
	t = _rtctime(); 
1997/0403/sys/src/9/carrera/devrtc.c:244,2651997/0404/sys/src/9/carrera/devrtc.c:188,201
1997/0401    
		if(ot == t) 
			break; 
	} 
	iunlock(&rtlock); 
1997/0404    
	iunlock(&rtclock); 
1997/0401    
 
1997/0403    
	if(i == 100) print("we are boofheads\n"); 
                 
1997/0401    
	return t; 
1997/0403    
#else 
	extern ulong boottime; 
                 
	return boottime+TK2SEC(MACHP(0)->ticks); 
#endif /* notdef */ 
1997/0401    
} 
 
1997/0327    
static long	  
1993/0916    
rtcread(Chan *c, void *buf, long n, ulong offset) 
{ 
1997/0401    
	ulong t; 
1993/0916    
	uchar *f, *to, *e; 
 
	if(c->qid.path & CHDIR) 
1997/0403/sys/src/9/carrera/devrtc.c:267,2781997/0404/sys/src/9/carrera/devrtc.c:203,209
1993/0916    
 
	switch(c->qid.path){ 
	case Qrtc: 
1997/0401    
		qlock(&rtclock); 
1993/0916    
		t = rtctime(); 
1997/0403    
dumprtcstatus(); 
1997/0401    
		qunlock(&rtclock); 
1993/0916    
		n = readnum(offset, buf, n, t, 12); 
		return n; 
1997/0404    
		return readnum(offset, buf, n, rtctime(), 12); 
1993/0916    
	case Qnvram: 
		if(offset > Nvsize) 
			return -1; 
1997/0403/sys/src/9/carrera/devrtc.c:289,3081997/0404/sys/src/9/carrera/devrtc.c:220,225
1993/0916    
	return 0; 
} 
 
static void 
binary2bcd(int reg, uchar val) 
{ 
	uchar x; 
1997/0403    
                 
1993/0916    
	x = (*(uchar*)Rtcindex)&~0x7f; 
	*(uchar*)Rtcindex = x|reg; 
1997/0403    
	if(statusB & 0x04) 
		*(uchar*)Rtcdata = val; 
	else 
		*(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4); 
1993/0916    
} 
                 
                 
1997/0327    
static long	  
1993/0916    
rtcwrite(Chan *c, void *buf, long n, ulong offset) 
{ 
1997/0403/sys/src/9/carrera/devrtc.c:310,3161997/0404/sys/src/9/carrera/devrtc.c:227,233
1993/0916    
	ulong secs; 
	char *cp, *ep; 
	uchar *f, *t, *e; 
	int s; 
1997/0404    
	uchar x; 
1993/0916    
 
	USED(c); 
	switch(c->qid.path){ 
1997/0403/sys/src/9/carrera/devrtc.c:327,3451997/0404/sys/src/9/carrera/devrtc.c:244,280
1993/0916    
		} 
		secs = strtoul(cp, 0, 0); 
		sec2rtc(secs, &rtc); 
	                 
		/* 
		 *  convert to bcd 
		 */ 
		s = splhi(); 
		binary2bcd(Seconds, rtc.sec); 
		binary2bcd(Minutes, rtc.min); 
		binary2bcd(Hours, rtc.hour); 
		binary2bcd(Mday, rtc.mday); 
		binary2bcd(Month, rtc.mon); 
1997/0401    
		binary2bcd(Year, rtc.year-1970); 
1993/0916    
		splx(s); 
1997/0404    
		rtc.year -= 1970; 
1993/0916    
 
1997/0404    
		if(!isbinary){	 
			/* 
			 *  convert to bcd 
			 */ 
			rtc.sec = PUTBCD(rtc.sec); 
			rtc.min = PUTBCD(rtc.min); 
			rtc.hour = PUTBCD(rtc.hour); 
			rtc.mday = PUTBCD(rtc.mday); 
			rtc.mon = PUTBCD(rtc.mon); 
			rtc.year = PUTBCD(rtc.year); 
		} 
 
		ilock(&rtclock); 
		/* set clock values */ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Seconds; 
		*(uchar*)Rtcdata = rtc.sec; 
		*(uchar*)Rtcindex = x|Minutes; 
		*(uchar*)Rtcdata = rtc.min; 
		*(uchar*)Rtcindex = x|Hours; 
		*(uchar*)Rtcdata = rtc.hour; 
		*(uchar*)Rtcindex = x|Mday; 
		*(uchar*)Rtcdata = rtc.mday; 
		*(uchar*)Rtcindex = x|Month; 
		*(uchar*)Rtcdata = rtc.mon; 
		*(uchar*)Rtcindex = x|Year; 
		*(uchar*)Rtcdata = rtc.year; 
		iunlock(&rtclock); 
 
1993/0916    
		return n; 
	case Qnvram: 
		if(offset > Nvsize) 
1997/0403/sys/src/9/carrera/devrtc.c:358,3641997/0404/sys/src/9/carrera/devrtc.c:293,299
1995/0108    
} 
 
1997/0327    
Dev rtcdevtab = { 
	devreset, 
1997/0404    
	rtcreset, 
1997/0327    
	devinit, 
	rtcattach, 
	devclone, 
1997/0404/sys/src/9/carrera/devrtc.c:293,2981997/0408/sys/src/9/carrera/devrtc.c:293,301 (short | long)
1995/0108    
} 
 
1997/0327    
Dev rtcdevtab = { 
1997/0408    
	'r', 
	"rtc", 
 
1997/0404    
	rtcreset, 
1997/0327    
	devinit, 
	rtcattach, 
1997/0408/sys/src/9/carrera/devrtc.c:175,1801997/0411/sys/src/9/carrera/devrtc.c:175,181 (short | long)
1997/0401    
long 
rtctime(void) 
{ 
1997/0411    
#ifdef notdef 
1997/0401    
	int i; 
	long t, ot; 
 
1997/0408/sys/src/9/carrera/devrtc.c:191,1961997/0411/sys/src/9/carrera/devrtc.c:192,202
1997/0404    
	iunlock(&rtclock); 
1997/0401    
 
	return t; 
1997/0411    
#else 
	extern ulong boottime; 
 
	return boottime+TK2SEC(MACHP(0)->ticks); 
#endif /* notdef */ 
1997/0401    
} 
 
1997/0327    
static long	  
1997/0411/sys/src/9/carrera/devrtc.c:112,1201998/0319/sys/src/9/carrera/devrtc.c:112,119 (short | long)
Change dev read and write to use vlong offset. Formatting edits.
rsc Fri Mar 4 12:44:25 2005
1993/0916    
} 
 
1997/0327    
static void	  
1993/0916    
rtcclose(Chan *c) 
1998/0319    
rtcclose(Chan*) 
1993/0916    
{ 
	USED(c); 
} 
 
1997/0401    
static long	  
1997/0411/sys/src/9/carrera/devrtc.c:200,2081998/0319/sys/src/9/carrera/devrtc.c:199,208
1997/0401    
} 
 
1997/0327    
static long	  
1993/0916    
rtcread(Chan *c, void *buf, long n, ulong offset) 
1998/0319    
rtcread(Chan *c, void *buf, long n, vlong off) 
1993/0916    
{ 
	uchar *f, *to, *e; 
1998/0319    
	ulong offset = off; 
1993/0916    
 
	if(c->qid.path & CHDIR) 
1997/0327    
		return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen); 
1997/0411/sys/src/9/carrera/devrtc.c:227,2331998/0319/sys/src/9/carrera/devrtc.c:227,233
1993/0916    
} 
 
1997/0327    
static long	  
1993/0916    
rtcwrite(Chan *c, void *buf, long n, ulong offset) 
1998/0319    
rtcwrite(Chan *c, void *buf, long n, vlong off) 
1993/0916    
{ 
	Rtc rtc; 
	ulong secs; 
1997/0411/sys/src/9/carrera/devrtc.c:234,2411998/0319/sys/src/9/carrera/devrtc.c:234,241
1993/0916    
	char *cp, *ep; 
	uchar *f, *t, *e; 
1997/0404    
	uchar x; 
1998/0319    
	ulong offset = off; 
1993/0916    
 
	USED(c); 
	switch(c->qid.path){ 
	case Qrtc: 
		/* 
1998/0319/sys/src/9/carrera/devrtc.c:10,151999/0128/sys/src/9/carrera/devrtc.c:10,17 (short | long)
1993/0916    
 *  real time clock and non-volatile ram 
 */ 
 
1999/0128    
extern ulong boottime; 
 
1993/0916    
typedef struct Rtc	Rtc; 
struct Rtc 
{ 
1998/0319/sys/src/9/carrera/devrtc.c:192,1991999/0128/sys/src/9/carrera/devrtc.c:194,199
1997/0401    
 
	return t; 
1997/0411    
#else 
	extern ulong boottime; 
                 
	return boottime+TK2SEC(MACHP(0)->ticks); 
#endif /* notdef */ 
1997/0401    
} 
1998/0319/sys/src/9/carrera/devrtc.c:264,2691999/0128/sys/src/9/carrera/devrtc.c:264,271
1997/0404    
			rtc.year = PUTBCD(rtc.year); 
		} 
 
1999/0128    
/* disgusting hack because RTC doesn't work and m->ticks drifts */ 
if(boottime == 0){ 
1997/0404    
		ilock(&rtclock); 
		/* set clock values */ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
1998/0319/sys/src/9/carrera/devrtc.c:280,2851999/0128/sys/src/9/carrera/devrtc.c:282,292
1997/0404    
		*(uchar*)Rtcindex = x|Year; 
		*(uchar*)Rtcdata = rtc.year; 
		iunlock(&rtclock); 
1999/0128    
}else{ 
		splhi(); 
		MACHP(0)->ticks = HZ*(secs - boottime);	/* inverse of SEC2TK() */ 
		spllo(); 
} 
1997/0404    
 
1993/0916    
		return n; 
	case Qnvram: 
1999/0128/sys/src/9/carrera/devrtc.c:176,1821999/0228/sys/src/9/carrera/devrtc.c:176,181 (short | long)
1997/0401    
long 
rtctime(void) 
{ 
1997/0411    
#ifdef notdef 
1997/0401    
	int i; 
	long t, ot; 
 
1999/0128/sys/src/9/carrera/devrtc.c:193,2011999/0228/sys/src/9/carrera/devrtc.c:192,197
1997/0404    
	iunlock(&rtclock); 
1997/0401    
 
	return t; 
1997/0411    
#else 
	return boottime+TK2SEC(MACHP(0)->ticks); 
#endif /* notdef */ 
1997/0401    
} 
 
1997/0327    
static long	  
1999/0128/sys/src/9/carrera/devrtc.c:264,2711999/0228/sys/src/9/carrera/devrtc.c:260,265
1997/0404    
			rtc.year = PUTBCD(rtc.year); 
		} 
 
1999/0128    
/* disgusting hack because RTC doesn't work and m->ticks drifts */ 
if(boottime == 0){ 
1997/0404    
		ilock(&rtclock); 
		/* set clock values */ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
1999/0128/sys/src/9/carrera/devrtc.c:282,2921999/0228/sys/src/9/carrera/devrtc.c:276,281
1997/0404    
		*(uchar*)Rtcindex = x|Year; 
		*(uchar*)Rtcdata = rtc.year; 
		iunlock(&rtclock); 
1999/0128    
}else{ 
		splhi(); 
		MACHP(0)->ticks = HZ*(secs - boottime);	/* inverse of SEC2TK() */ 
		spllo(); 
} 
1997/0404    
 
1993/0916    
		return n; 
	case Qnvram: 
1999/0228/sys/src/9/carrera/devrtc.c:1,4312001/0527/sys/src/9/carrera/devrtc.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:21:07 2005
1993/0916    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
#include	"io.h" 
                 
/* 
 *  real time clock and non-volatile ram 
 */ 
                 
1999/0128    
extern ulong boottime; 
                 
1993/0916    
typedef struct Rtc	Rtc; 
struct Rtc 
{ 
	int	sec; 
	int	min; 
	int	hour; 
	int	mday; 
	int	mon; 
	int	year; 
}; 
                 
1995/0108    
enum 
{ 
1993/0916    
	Qrtc = 1, 
	Qnvram, 
                 
	Seconds=	0x00, 
	Minutes=	0x02, 
	Hours=		0x04,  
	Mday=		0x07, 
	Month=		0x08, 
	Year=		0x09, 
	Status=		0x0A, 
1997/0403    
	StatusB=	0x0B, 
	StatusC=	0x0C, 
	StatusD=	0x0D, 
1993/0916    
                 
1997/0404    
	Update=		0x80, 
                 
1993/0916    
	Nvsize = 4096, 
1997/0403    
                 
	Nclock=		6, 
1993/0916    
}; 
                 
1997/0404    
#define GETBCD(v)	(((v) & 0x0F) + 10*((v)>>4)) 
#define PUTBCD(v)	((v) % 10)|((((v)/10) % 10)<<4) 
                 
1993/0916    
Dirtab rtcdir[]={ 
	"nvram",	{Qnvram, 0},	Nvsize,	0664, 
	"rtc",		{Qrtc, 0},	0,	0664, 
}; 
                 
1997/0327    
static ulong rtc2sec(Rtc*); 
static void sec2rtc(ulong, Rtc*); 
1993/0916    
                 
1997/0404    
static int isbinary; 
static Lock rtclock; 
1997/0403    
                 
static void 
1997/0404    
rtcreset(void) 
1997/0403    
{ 
	int i, x; 
	uchar r; 
                 
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
		r = *(uchar*)Rtcdata; 
		if(r & 0x80) 
			continue; 
                 
		*(uchar*)Rtcindex = x|StatusB; 
1997/0404    
		isbinary = *(uchar*)Rtcdata & 0x04; 
1997/0403    
		break; 
	} 
} 
                 
1997/0327    
static Chan* 
1993/0916    
rtcattach(char *spec) 
{ 
	return devattach('r', spec); 
} 
                 
1997/0327    
static int	  
1993/0916    
rtcwalk(Chan *c, char *name) 
{ 
1997/0327    
	return devwalk(c, name, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
} 
                 
1997/0327    
static void	  
1993/0916    
rtcstat(Chan *c, char *dp) 
{ 
1997/0327    
	devstat(c, dp, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
} 
                 
1997/0327    
static Chan* 
1993/0916    
rtcopen(Chan *c, int omode) 
{ 
	omode = openmode(omode); 
	switch(c->qid.path){ 
	case Qrtc: 
		if(strcmp(up->user, eve)!=0 && omode!=OREAD) 
			error(Eperm); 
		break; 
	case Qnvram: 
		if(strcmp(up->user, eve)!=0) 
			error(Eperm); 
	} 
1997/0327    
	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
} 
                 
1997/0327    
static void	  
1998/0319    
rtcclose(Chan*) 
1993/0916    
{ 
} 
                 
1997/0401    
static long	  
_rtctime(void) 
1993/0916    
{ 
	Rtc rtc; 
1997/0401    
	int i, x; 
1997/0404    
	uchar r; 
1993/0916    
                 
1997/0403    
	/* don't do the read until the clock is no longer busy */ 
1997/0401    
	for(i = 0; i < 10000; i++){ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Status; 
1997/0403    
		r = *(uchar*)Rtcdata; 
1997/0404    
		if(r & Update) 
1997/0401    
			continue; 
1993/0916    
                 
1997/0403    
		/* read clock values */ 
		*(uchar*)Rtcindex = x|Seconds; 
1997/0404    
		rtc.sec = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Minutes; 
1997/0404    
		rtc.min = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Hours; 
1997/0404    
		rtc.hour = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Mday; 
1997/0404    
		rtc.mday = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Month; 
1997/0404    
		rtc.mon = *(uchar*)Rtcdata; 
1997/0403    
		*(uchar*)Rtcindex = x|Year; 
1997/0404    
		rtc.year = *(uchar*)Rtcdata; 
1997/0401    
                 
		*(uchar*)Rtcindex = x|Status; 
1997/0403    
		r = *(uchar*)Rtcdata; 
1997/0404    
		if((r & Update) == 0) 
1997/0401    
			break; 
	} 
                 
1997/0404    
	if(!isbinary){ 
1997/0403    
		/* 
		 *  convert from BCD 
		 */ 
1997/0404    
		rtc.sec = GETBCD(rtc.sec); 
		rtc.min = GETBCD(rtc.min); 
		rtc.hour = GETBCD(rtc.hour); 
		rtc.mday = GETBCD(rtc.mday); 
		rtc.mon = GETBCD(rtc.mon); 
		rtc.year = GETBCD(rtc.year); 
1997/0403    
	} 
                 
	/* 
	 *  the world starts jan 1 1970 
	 */ 
	rtc.year += 1970; 
                 
1993/0916    
	return rtc2sec(&rtc); 
} 
                 
1997/0401    
long 
rtctime(void) 
{ 
	int i; 
	long t, ot; 
                 
1997/0404    
	ilock(&rtclock); 
1997/0401    
                 
	/* loop till we get two reads in a row the same */ 
	t = _rtctime(); 
	for(i = 0; i < 100; i++){ 
		ot = t; 
		t = _rtctime(); 
		if(ot == t) 
			break; 
	} 
1997/0404    
	iunlock(&rtclock); 
1997/0401    
                 
	return t; 
} 
                 
1997/0327    
static long	  
1998/0319    
rtcread(Chan *c, void *buf, long n, vlong off) 
1993/0916    
{ 
	uchar *f, *to, *e; 
1998/0319    
	ulong offset = off; 
1993/0916    
                 
	if(c->qid.path & CHDIR) 
1997/0327    
		return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen); 
1993/0916    
                 
	switch(c->qid.path){ 
	case Qrtc: 
1997/0404    
		return readnum(offset, buf, n, rtctime(), 12); 
1993/0916    
	case Qnvram: 
		if(offset > Nvsize) 
			return -1; 
		if(offset + n > Nvsize) 
			n = Nvsize - offset; 
		f = (uchar*)Nvram+offset; 
		to = buf; 
		e = f + n; 
		while(f < e) 
			*to++ = *f++; 
		return n; 
	} 
	error(Ebadarg); 
	return 0; 
} 
                 
1997/0327    
static long	  
1998/0319    
rtcwrite(Chan *c, void *buf, long n, vlong off) 
1993/0916    
{ 
	Rtc rtc; 
	ulong secs; 
	char *cp, *ep; 
	uchar *f, *t, *e; 
1997/0404    
	uchar x; 
1998/0319    
	ulong offset = off; 
1993/0916    
                 
	switch(c->qid.path){ 
	case Qrtc: 
		/* 
		 *  read the time 
		 */ 
		cp = ep = buf; 
		ep += n; 
		while(cp < ep){ 
			if(*cp>='0' && *cp<='9') 
				break; 
			cp++; 
		} 
		secs = strtoul(cp, 0, 0); 
		sec2rtc(secs, &rtc); 
1997/0404    
		rtc.year -= 1970; 
1993/0916    
                 
1997/0404    
		if(!isbinary){	 
			/* 
			 *  convert to bcd 
			 */ 
			rtc.sec = PUTBCD(rtc.sec); 
			rtc.min = PUTBCD(rtc.min); 
			rtc.hour = PUTBCD(rtc.hour); 
			rtc.mday = PUTBCD(rtc.mday); 
			rtc.mon = PUTBCD(rtc.mon); 
			rtc.year = PUTBCD(rtc.year); 
		} 
                 
		ilock(&rtclock); 
		/* set clock values */ 
		x = (*(uchar*)Rtcindex)&~0x7f; 
		*(uchar*)Rtcindex = x|Seconds; 
		*(uchar*)Rtcdata = rtc.sec; 
		*(uchar*)Rtcindex = x|Minutes; 
		*(uchar*)Rtcdata = rtc.min; 
		*(uchar*)Rtcindex = x|Hours; 
		*(uchar*)Rtcdata = rtc.hour; 
		*(uchar*)Rtcindex = x|Mday; 
		*(uchar*)Rtcdata = rtc.mday; 
		*(uchar*)Rtcindex = x|Month; 
		*(uchar*)Rtcdata = rtc.mon; 
		*(uchar*)Rtcindex = x|Year; 
		*(uchar*)Rtcdata = rtc.year; 
		iunlock(&rtclock); 
                 
1993/0916    
		return n; 
	case Qnvram: 
		if(offset > Nvsize) 
			return -1; 
		if(offset + n > Nvsize) 
			n = Nvsize - offset; 
		t = (uchar*)Nvram+offset; 
		f = buf; 
		e = f + n; 
		while(f < e) 
			*t++ = *f++; 
		return n; 
	} 
	error(Ebadarg); 
	return 0; 
1995/0108    
} 
                 
1997/0327    
Dev rtcdevtab = { 
1997/0408    
	'r', 
	"rtc", 
                 
1997/0404    
	rtcreset, 
1997/0327    
	devinit, 
	rtcattach, 
	devclone, 
	rtcwalk, 
	rtcstat, 
	rtcopen, 
	devcreate, 
	rtcclose, 
	rtcread, 
	devbread, 
	rtcwrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 
1993/0916    
                 
#define SEC2MIN 60L 
#define SEC2HOUR (60L*SEC2MIN) 
#define SEC2DAY (24L*SEC2HOUR) 
                 
/* 
 *  days per month plus days/year 
 */ 
static	int	dmsize[] = 
{ 
	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
}; 
static	int	ldmsize[] = 
{ 
	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
}; 
                 
/* 
 *  return the days/month for the given year 
 */ 
1997/0327    
static int* 
1993/0916    
yrsize(int yr) 
{ 
	if((yr % 4) == 0) 
		return ldmsize; 
	else 
		return dmsize; 
} 
                 
/* 
 *  compute seconds since Jan 1 1970 
 */ 
1997/0327    
static ulong 
1993/0916    
rtc2sec(Rtc *rtc) 
{ 
	ulong secs; 
	int i; 
	int *d2m; 
                 
	secs = 0; 
                 
	/* 
	 *  seconds per year 
	 */ 
	for(i = 1970; i < rtc->year; i++){ 
		d2m = yrsize(i); 
		secs += d2m[0] * SEC2DAY; 
	} 
                 
	/* 
	 *  seconds per month 
	 */ 
	d2m = yrsize(rtc->year); 
	for(i = 1; i < rtc->mon; i++) 
		secs += d2m[i] * SEC2DAY; 
                 
	secs += (rtc->mday-1) * SEC2DAY; 
	secs += rtc->hour * SEC2HOUR; 
	secs += rtc->min * SEC2MIN; 
	secs += rtc->sec; 
                 
	return secs; 
} 
                 
/* 
 *  compute rtc from seconds since Jan 1 1970 
 */ 
1997/0327    
static void 
1993/0916    
sec2rtc(ulong secs, Rtc *rtc) 
{ 
	int d; 
	long hms, day; 
	int *d2m; 
                 
	/* 
	 * break initial number into days 
	 */ 
	hms = secs % SEC2DAY; 
	day = secs / SEC2DAY; 
	if(hms < 0) { 
		hms += SEC2DAY; 
		day -= 1; 
	} 
                 
	/* 
	 * generate hours:minutes:seconds 
	 */ 
	rtc->sec = hms % 60; 
	d = hms / 60; 
	rtc->min = d % 60; 
	d /= 60; 
	rtc->hour = d; 
                 
	/* 
	 * year number 
	 */ 
	if(day >= 0) 
		for(d = 1970; day >= *yrsize(d); d++) 
			day -= *yrsize(d); 
	else 
		for (d = 1970; day < 0; d--) 
			day += *yrsize(d-1); 
	rtc->year = d; 
                 
	/* 
	 * generate month 
	 */ 
	d2m = yrsize(rtc->year); 
	for(d = 1; day >= d2m[d]; d++) 
		day -= d2m[d]; 
	rtc->mday = day + 1; 
	rtc->mon = d; 
                 
	return; 
} 


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