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

1990/12041/power/devrtc.c (diff list | history)

1990/1204/sys/src/9/power/devrtc.c:8,171990/12041/sys/src/9/power/devrtc.c:8,21 (short | long | prev | next)
1990/1204    
 
#include	"io.h" 
 
typedef struct Rtc Rtc; 
1990/12041    
typedef struct Rtc	Rtc; 
 
enum { 
	Nbcd = 8	/* number of bcd bytes in the clock */ 
}; 
 
1990/1204    
struct Rtc 
{ 
	QLock; 
	int	sec; 
	int	min; 
	int	hour; 
1990/1204/sys/src/9/power/devrtc.c:19,271990/12041/sys/src/9/power/devrtc.c:23,32
1990/1204    
	int	mon; 
	int	year; 
}; 
Rtc rtc; 
 
Dirtab rtcdir[]={ 
1990/12041    
QLock rtclock;	/* mutex on clock operations */ 
 
static Dirtab rtcdir[]={ 
1990/1204    
	"rtc",		{1},	0,	0600, 
}; 
 
1990/1204/sys/src/9/power/devrtc.c:30,351990/12041/sys/src/9/power/devrtc.c:35,44
1990/1204    
	0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c 
}; 
 
1990/12041    
ulong rtc2sec(Rtc*); 
void sec2rtc(ulong, Rtc*); 
int *yrsize(int); 
 
1990/1204    
/* 
 *  issue pattern recognition bits to nv ram to address the 
 *  real time clock 
1990/1204/sys/src/9/power/devrtc.c:51,571990/12041/sys/src/9/power/devrtc.c:60,66
1990/1204    
	 *  stuff the pattern recognition codes one bit at 
	 *  a time into *nv. 
	 */ 
	for(i = 0; i < sizeof(pattern); i++){ 
1990/12041    
	for(i = 0; i < Nbcd; i++){ 
1990/1204    
		ch = pattern[i]; 
		for (j = 0; j < 8; j++){ 
			*nv = ch & 0x1; 
1990/1204/sys/src/9/power/devrtc.c:103,1081990/12041/sys/src/9/power/devrtc.c:112,121
1990/1204    
Chan* 
rtcopen(Chan *c, int omode) 
{ 
1990/12041    
	if(c->qid.path==1 && (omode&(OWRITE|OTRUNC))){ 
		if(strcmp(u->p->pgrp->user, "bootes"))	/* BUG */ 
			error(Eperm); 
	} 
1990/1204    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
1990/1204/sys/src/9/power/devrtc.c:120,1261990/12041/sys/src/9/power/devrtc.c:133,139
1990/1204    
{ 
} 
 
#define GETBCD(o) ((clock[o]&0xf) + 10*(clock[o]>>4)) 
1990/12041    
#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4)) 
1990/1204    
 
long	  
rtcread(Chan *c, void *buf, long n) 
1990/1204/sys/src/9/power/devrtc.c:128,1561990/12041/sys/src/9/power/devrtc.c:141,178
1990/1204    
	int i,j; 
	uchar ch; 
	uchar *nv; 
	uchar clock[8]; 
1990/12041    
	uchar bcdclock[Nbcd]; 
1990/1204    
	char atime[64]; 
1990/12041    
	Rtc rtc; 
1990/1204    
 
	if(c->offset!=0) 
		error(Ebadarg);  
	nv = RTC; 
 
	/* 
	 *  set up the pattern for the clock 
	 */ 
	qlock(&rtc); 
1990/12041    
	qlock(&rtclock); 
1990/1204    
	rtcpattern(); 
 
	/* 
	 *  read out the clock one bit at a time 
	 */ 
	for (i = 0; i < 8; i++){ 
1990/12041    
	for (i = 0; i < Nbcd; i++){ 
1990/1204    
		ch = 0; 
		for (j = 0; j < 8; j++) 
			ch |= ((*nv & 0x1) << j); 
		clock[i] = ch; 
1990/12041    
		bcdclock[i] = ch; 
1990/1204    
	} 
	qunlock(&rtc); 
1990/12041    
	qunlock(&rtclock); 
 
	/* 
	 *  see if the clock oscillator is on 
	 */ 
	if(bcdclock[4] & 0x20) 
		return 0;		/* nope, time is bogus */ 
 
	/* 
	 *  convert from BCD 
	 */ 
1990/1204    
	rtc.sec = GETBCD(1); 
	rtc.min = GETBCD(2); 
	rtc.hour = GETBCD(3); 
1990/1204/sys/src/9/power/devrtc.c:166,2311990/12041/sys/src/9/power/devrtc.c:188,240
1990/1204    
	else 
		rtc.year += 1900; 
 
	sprint(atime, "%.2d:%.2d:%.2d %d/%d/%d", rtc.hour, rtc.min, rtc.sec, 
		rtc.mon, rtc.mday, rtc.year); 
	i = strlen(atime); 
                 
	if(c->offset >= i) 
		return 0; 
	if(c->offset + n > i) 
		n = i - c->offset; 
	strncpy(buf, &atime[c->offset], n); 
                 
	return n; 
1990/12041    
	return readnum(c->offset, buf, n, rtc2sec(&rtc), 12); 
1990/1204    
} 
 
static int perm[] = 
{ 
	3, 2, 1, 6, 5, 7 
}; 
1990/12041    
#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4) 
1990/1204    
 
long	  
rtcwrite(Chan *c, void *buf, long n) 
{ 
1990/12041    
	Rtc rtc; 
	ulong secs; 
1990/1204    
	int i,j; 
	uchar ch; 
	uchar clock[8]; 
1990/12041    
	uchar bcdclock[Nbcd]; 
1990/1204    
	uchar *nv; 
	char *cp; 
1990/12041    
	char *cp, *ep; 
1990/1204    
 
	if(c->offset!=0) 
		error(Ebadarg); 
 
	/* 
	 *  parse (most any separator will do) 
1990/12041    
	 *  read the time 
1990/1204    
	 */ 
	ch = 0; 
	j = 0; 
	clock[0] = clock[4] = 0; 
	cp = buf; 
	for(i = 0; i < n; i++){ 
		switch(*cp){ 
		case ':': case ' ': case '\t': case '/': case '-': 
			clock[perm[j++]] = ch; 
			ch = 0; 
1990/12041    
	cp = ep = buf; 
	ep += n; 
	while(cp < ep){ 
		if(*cp>='0' && *cp<='9') 
1990/1204    
			break; 
		case '0': case '1': case '2': case '3': case '4': 
		case '5': case '6': case '7': case '8': case '9': 
			ch = (ch<<4) | (*cp - '0'); 
			break; 
		default: 
			error(Ebadarg); 
		} 
		cp++; 
	} 
	clock[perm[j++]] = ch; 
	if(j != 6) 
		error(Ebadarg); 
1990/12041    
	secs = strtoul(cp, 0, 0); 
1990/1204    
 
	/* 
1990/12041    
	 *  convert to bcd 
	 */ 
	sec2rtc(secs, &rtc); 
	bcdclock[0] = bcdclock[4] = 0; 
	PUTBCD(rtc.sec, 1); 
	PUTBCD(rtc.min, 2); 
	PUTBCD(rtc.hour, 3); 
	PUTBCD(rtc.mday, 5); 
	PUTBCD(rtc.mon, 6); 
	PUTBCD(rtc.year, 7); 
 
	/* 
1990/1204    
	 *  set up the pattern for the clock 
	 */ 
	qlock(&rtc); 
1990/12041    
	qlock(&rtclock); 
1990/1204    
	rtcpattern(); 
 
	/* 
1990/1204/sys/src/9/power/devrtc.c:232,2451990/12041/sys/src/9/power/devrtc.c:241,255
1990/1204    
	 *  write the clock one bit at a time 
	 */ 
	nv = RTC; 
	for (i = 0; i < 8; i++){ 
		ch = clock[i]; 
1990/12041    
	for (i = 0; i < Nbcd; i++){ 
		ch = bcdclock[i]; 
1990/1204    
		for (j = 0; j < 8; j++){ 
			*nv = ch & 1; 
			ch >>= 1; 
		} 
	} 
	qunlock(&rtc); 
1990/12041    
	qunlock(&rtclock); 
 
1990/1204    
	return n; 
} 
 
1990/1204/sys/src/9/power/devrtc.c:255,2891990/12041/sys/src/9/power/devrtc.c:265,330
1990/1204    
	error(Eperm); 
} 
 
#define SEC2MIN 60 
#define SEC2HOUR (60*SEC2MIN) 
#define SEC2DAY (24*SEC2HOUR) 
#define SEC2YR (365*SEC2DAY) 
1990/12041    
#define SEC2MIN 60L 
#define SEC2HOUR (60L*SEC2MIN) 
#define SEC2DAY (24L*SEC2HOUR) 
1990/1204    
 
static	char	dmsize[12] = 
1990/12041    
/* 
 *  days per month plus days/year 
 */ 
static	int	dmsize[] = 
1990/1204    
{ 
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
1990/12041    
	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
1990/1204    
}; 
1990/12041    
static	int	ldmsize[] = 
{ 
	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 
}; 
1990/1204    
 
/* 
1990/12041    
 *  return the days/month for the given year 
 */ 
int * 
yrsize(int yr) 
{ 
	if((yr % 4) == 0) 
		return ldmsize; 
	else 
		return dmsize; 
} 
 
/* 
1990/1204    
 *  compute seconds since Jan 1 1970 
 */ 
ulong 
rtc2sec(void) 
1990/12041    
rtc2sec(Rtc *rtc) 
1990/1204    
{ 
	ulong secs; 
	int i; 
1990/12041    
	int *d2m; 
1990/1204    
 
	for(i = 1970; i < rtc.year; i++) 
		secs += dysize(i); 
	for(i = 0; i < rtc.mon-1; i++) 
		secs += dmsize[i] * SEC2DAY; 
	if(dysize(rtc.year)==366 && rtc.mon>2) 
		secs += SEC2DAY; 
	secs += (rtc.mday-1) * SEC2DAY; 
	secs += rtc.hour * SEC2HOUR; 
	secs += rtc.min * SEC2MIN; 
	secs += rtc.sec; 
1990/12041    
	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; 
 
1990/1204    
	return secs; 
} 
 
1990/1204/sys/src/9/power/devrtc.c:290,2991990/12041/sys/src/9/power/devrtc.c:331,342
1990/1204    
/* 
 *  compute rtc from seconds since Jan 1 1970 
 */ 
sec2rtc(ulong secs) 
1990/12041    
void 
sec2rtc(ulong secs, Rtc *rtc) 
1990/1204    
{ 
	int d0, d1; 
1990/12041    
	int d; 
1990/1204    
	long hms, day; 
1990/12041    
	int *d2m; 
1990/1204    
 
	/* 
	 * break initial number into days 
1990/1204/sys/src/9/power/devrtc.c:308,3521990/12041/sys/src/9/power/devrtc.c:351,381
1990/1204    
	/* 
	 * generate hours:minutes:seconds 
	 */ 
	rtc.sec = hms % SEC2MIN; 
	d1 = hms / SEC2MIN; 
	rtc.min = d1 % SEC2MIN; 
	d1 /= SEC2MIN; 
	rtc.hour = d1; 
1990/12041    
	rtc->sec = hms % 60; 
	d = hms / 60; 
	rtc->min = d % 60; 
	d /= 60; 
	rtc->hour = d; 
1990/1204    
 
	/* 
	 * year number 
	 */ 
	if(day >= 0) 
		for(d1 = 70; day >= dysize(d1); d1++) 
			day -= dysize(d1); 
1990/12041    
		for(d = 1970; day >= *yrsize(d); d++) 
			day -= *yrsize(d); 
1990/1204    
	else 
		for (d1 = 70; day < 0; d1--) 
			day += dysize(d1-1); 
	rtc.year = d1; 
1990/12041    
		for (d = 1970; day < 0; d--) 
			day += *yrsize(d-1); 
	rtc->year = d; 
1990/1204    
 
	/* 
	 * generate month 
	 */ 
	if(dysize(d1) == 366) 
		dmsize[1] = 29; 
	for(d1 = 0; d0 >= dmsize[d1]; d1++) 
		d0 -= dmsize[d1]; 
	dmsize[1] = 28; 
	rtc.mday = d0 + 1; 
	rtc.mon = d1; 
1990/12041    
	d2m = yrsize(rtc->year); 
	for(d = 1; day >= d2m[d]; d++) 
		day -= d2m[d]; 
	rtc->mday = day + 1; 
	rtc->mon = d; 
 
1990/1204    
	return; 
} 
                 
/* 
 *  days to year 
 */ 
static 
dysize(int y) 
{ 
                 
	if((y%4) == 0) 
		return 366; 
	return 365; 
} 
                 


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