Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/devrtc.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/devrtc.c 1991/0911
## diff -e /dev/null /n/bootesdump/1991/0911/sys/src/9/safari/devrtc.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"
#include	"devtab.h"

enum {
	Paddr=		0x70,	/* address port */
	Pdata=		0x71,	/* data port */

	Seconds=	0x00,
	Minutes=	0x02,
	Hours=		0x04, 
	Mday=		0x07,
	Month=		0x08,
	Year=		0x09,
	Status=		0x0A,

	Nbcd=		6,
};

typedef struct Rtc	Rtc;
struct Rtc
{
	int	sec;
	int	min;
	int	hour;
	int	mday;
	int	mon;
	int	year;
};

QLock rtclock;	/* mutex on clock operations */

#define	NRTC	1
Dirtab rtcdir[]={
	"rtc",		{1, 0},	0,	0600,
};

ulong rtc2sec(Rtc*);
void sec2rtc(ulong, Rtc*);
int *yrsize(int);

void
rtcreset(void)
{
}

void
rtcinit(void)
{
}

Chan*
rtcattach(char *spec)
{
	return devattach('r', spec);
}

Chan*
rtcclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int	 
rtcwalk(Chan *c, char *name)
{
	return devwalk(c, name, rtcdir, NRTC, devgen);
}

void	 
rtcstat(Chan *c, char *dp)
{
	devstat(c, dp, rtcdir, NRTC, devgen);
}

Chan*
rtcopen(Chan *c, int omode)
{
	return devopen(c, omode, rtcdir, NRTC, devgen);
}

void	 
rtccreate(Chan *c, char *name, int omode, ulong perm)
{
	error(Eperm);
}

void	 
rtcclose(Chan *c)
{
}

#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))

long	 
rtctime(void)
{
	int i,j;
	uchar ch;
	uchar bcdclock[Nbcd];
	char atime[64];
	Rtc rtc;

	outb(Paddr, Status);
	while(inb(Pdata) & 1)
		;
	outb(Paddr, Seconds);	bcdclock[0] = inb(Pdata);
	outb(Paddr, Minutes);	bcdclock[1] = inb(Pdata);
	outb(Paddr, Hours);	bcdclock[2] = inb(Pdata);
	outb(Paddr, Mday);	bcdclock[3] = inb(Pdata);
	outb(Paddr, Month);	bcdclock[4] = inb(Pdata);
	outb(Paddr, Year);	bcdclock[5] = inb(Pdata);

	/*
	 *  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
	 */
	if(rtc.year < 70)
		rtc.year += 2000;
	else
		rtc.year += 1900;
	return rtc2sec(&rtc);
}

long	 
rtcread(Chan *c, void *buf, long n, ulong offset)
{
	ulong t, ot;

	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, rtcdir, NRTC, devgen);

	qlock(&rtclock);
	t = rtctime();
	do{
		ot = t;
		t = rtctime();	/* make sure there's no skew */
	}while(t != ot);
	qunlock(&rtclock);
	n = readnum(offset, buf, n, t, 12);
	return n;

}

#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)

long	 
rtcwrite(Chan *c, void *buf, long n, ulong offset)
{
	Rtc rtc;
	ulong secs;
	int i,j;
	uchar ch;
	uchar bcdclock[Nbcd];
	uchar *nv;
	char *cp, *ep;

	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);

	/*
	 *  convert to bcd
	 */
	sec2rtc(secs, &rtc);
	PUTBCD(rtc.sec, 0);
	PUTBCD(rtc.min, 1);
	PUTBCD(rtc.hour, 2);
	PUTBCD(rtc.mday, 3);
	PUTBCD(rtc.mon, 4);
	PUTBCD(rtc.year, 5);

	/*
	 *  write the clock
	 */
	qlock(&rtclock);
	outb(Paddr, Seconds);	outb(Pdata, bcdclock[0]);
	outb(Paddr, Minutes);	outb(Pdata, bcdclock[1]);
	outb(Paddr, Hours);	outb(Pdata, bcdclock[2]);
	outb(Paddr, Mday);	outb(Pdata, bcdclock[3]);
	outb(Paddr, Month);	outb(Pdata, bcdclock[4]);
	outb(Paddr, Year);	outb(Pdata, bcdclock[5]);
	qunlock(&rtclock);

	return n;
}

void	 
rtcremove(Chan *c)
{
	error(Eperm);
}

void	 
rtcwstat(Chan *c, char *dp)
{
	error(Eperm);
}

#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
 */
int *
yrsize(int yr)
{
	if((yr % 4) == 0)
		return ldmsize;
	else
		return dmsize;
}

/*
 *  compute seconds since Jan 1 1970
 */
ulong
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
 */
void
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;
}
.
## diffname pc/devrtc.c 1991/1112
## diff -e /n/bootesdump/1991/0911/sys/src/9/safari/devrtc.c /n/bootesdump/1991/1112/sys/src/9/safari/devrtc.c
39c
	"rtc",		{1, 0},	0,	0666,
.
## diffname pc/devrtc.c 1991/1211
## diff -e /n/bootesdump/1991/1112/sys/src/9/safari/devrtc.c /n/bootesdump/1991/1211/sys/src/9/safari/devrtc.c
8a
/*
 *  real time clock and non-volatile ram
 */

.
## diffname pc/devrtc.c 1992/0111
## diff -e /n/bootesdump/1991/1211/sys/src/9/safari/devrtc.c /n/bootesdump/1992/0111/sys/src/9/safari/devrtc.c
6c
#include	"../port/error.h"
.
## diffname pc/devrtc.c 1992/0321
## diff -e /n/bootesdump/1992/0111/sys/src/9/safari/devrtc.c /n/bootesdump/1992/0321/sys/src/9/safari/devrtc.c
2c
#include	"../port/lib.h"
.
## diffname pc/devrtc.c 1992/0711
## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devrtc.c /n/bootesdump/1992/0711/sys/src/9/safari/devrtc.c
224a
	USED(c, dp);
.
218a
	USED(c);
.
174a
	USED(c);
.
172d
169,170d
109d
106,107d
98a
	USED(c);
.
92a
	USED(c, name, omode, perm);
.
## diffname pc/devrtc.c 1992/0819
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devrtc.c /n/bootesdump/1992/0819/sys/src/9/pc/devrtc.c
86a
	omode = openmode(omode);
	switch(c->qid.path){
	case Qrtc:
		if(omode == OREAD)
			break;
		/* fall through */
	case Qnvram:
		if(strcmp(u->p->user, eve)!=0 || !cpuserver)
			error(Eperm);
	}
.
## diffname pc/devrtc.c 1992/0820
## diff -e /n/bootesdump/1992/0819/sys/src/9/pc/devrtc.c /n/bootesdump/1992/0820/sys/src/9/pc/devrtc.c
43c
	"rtc",		{Qrtc, 0},	0,	0666,
.
40a
enum{
	Qrtc = 1,
	Qnvram,
};

.
## diffname pc/devrtc.c 1992/0826
## diff -e /n/bootesdump/1992/0820/sys/src/9/pc/devrtc.c /n/bootesdump/1992/0826/sys/src/9/pc/devrtc.c
95,97c
		if(omode != OREAD && strcmp(u->p->user, eve)!=0)
			error(Eperm);
		break;
.
## diffname pc/devrtc.c 1992/0902
## diff -e /n/bootesdump/1992/0826/sys/src/9/pc/devrtc.c /n/bootesdump/1992/0902/sys/src/9/pc/devrtc.c
95c
		if(strcmp(u->p->user, eve)!=0 && omode!=OREAD)
.
## diffname pc/devrtc.c 1992/1006
## diff -e /n/bootesdump/1992/0902/sys/src/9/pc/devrtc.c /n/bootesdump/1992/1006/sys/src/9/pc/devrtc.c
355a

uchar
nvramread(int offset)
{
	outb(Paddr, offset);
	return inb(Pdata);
}
.
## diffname pc/devrtc.c 1992/1014
## diff -e /n/bootesdump/1992/1006/sys/src/9/pc/devrtc.c /n/bootesdump/1992/1014/sys/src/9/pc/devrtc.c
62a
	print("nvrm(0x2b) == 0x%lux\n", nvramread(0x2b));
.
## diffname pc/devrtc.c 1992/1015
## diff -e /n/bootesdump/1992/1014/sys/src/9/pc/devrtc.c /n/bootesdump/1992/1015/sys/src/9/pc/devrtc.c
63d
## diffname pc/devrtc.c 1992/1208
## diff -e /n/bootesdump/1992/1015/sys/src/9/pc/devrtc.c /n/bootesdump/1992/1208/sys/src/9/pc/devrtc.c
126,128c
	for(i = 0; i < 10000; i++){
		outb(Paddr, Status);
		if((inb(Pdata) & 1) == 0)
			break;
	}
.
124a
	int i;
.
## diffname pc/devrtc.c 1993/0319
## diff -e /n/bootesdump/1992/1208/sys/src/9/pc/devrtc.c /n/bootesdump/1993/0319/sys/src/9/pc/devrtc.c
216,228c
		/*
		 *  write the clock
		 */
		qlock(&rtclock);
		outb(Paddr, Seconds);	outb(Pdata, bcdclock[0]);
		outb(Paddr, Minutes);	outb(Pdata, bcdclock[1]);
		outb(Paddr, Hours);	outb(Pdata, bcdclock[2]);
		outb(Paddr, Mday);	outb(Pdata, bcdclock[3]);
		outb(Paddr, Month);	outb(Pdata, bcdclock[4]);
		outb(Paddr, Year);	outb(Pdata, bcdclock[5]);
		qunlock(&rtclock);
		return n;
	case Qnvram:
		a = buf;
		if(waserror()){
			qunlock(&rtclock);
			nexterror();
		}
		qlock(&rtclock);
		for(t = offset; t < offset + n; t++){
			if(t >= Nvsize)
				break;
			outb(Paddr, Nvoff+t);
			outb(Pdata, *a++);
		}
		qunlock(&rtclock);
		poperror();
		return t - offset;
	}
	error(Ebadarg);
	return 0;
.
205,214c
	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);
	
		/*
		 *  convert to bcd
		 */
		sec2rtc(secs, &rtc);
		PUTBCD(rtc.sec, 0);
		PUTBCD(rtc.min, 1);
		PUTBCD(rtc.hour, 2);
		PUTBCD(rtc.mday, 3);
		PUTBCD(rtc.mon, 4);
		PUTBCD(rtc.year, 5);
.
193,203d
183a
	int t;
	char *a;
.
167,176c
	switch(c->qid.path){
	case Qrtc:
		qlock(&rtclock);
		t = rtctime();
		do{
			ot = t;
			t = rtctime();	/* make sure there's no skew */
		}while(t != ot);
		qunlock(&rtclock);
		n = readnum(offset, buf, n, t, 12);
		return n;
	case Qnvram:
		a = buf;
		if(waserror()){
			qunlock(&rtclock);
			nexterror();
		}
		qlock(&rtclock);
		for(t = offset; t < offset + n; t++){
			if(t >= Nvsize)
				break;
			outb(Paddr, Nvoff+t);
			*a++ = inb(Pdata);
		}
		qunlock(&rtclock);
		poperror();
		return t - offset;
	}
	error(Ebadarg);
	return 0;
.
162a
	char *a;
.
99c
		if(strcmp(u->p->user, eve)!=0)
.
47a
	"nvram",	{Qnvram, 0},	Nvsize,	0666,
.
46c
#define	NRTC	2
.
24a
	Nvoff=		128,	/* where usable nvram lives */
	Nvsize=		128,

.
## diffname pc/devrtc.c 1993/0915
## diff -e /n/bootesdump/1993/0319/sys/src/9/pc/devrtc.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devrtc.c
103c
		if(strcmp(up->user, eve)!=0)
.
99c
		if(strcmp(up->user, eve)!=0 && omode!=OREAD)
.
51,52c
	"nvram",	{Qnvram, 0},	Nvsize,	0664,
	"rtc",		{Qrtc, 0},	0,	0664,
.
26c
	Nvsize=		256,
.
## diffname pc/devrtc.c 1995/0108
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devrtc.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devrtc.c
276a
}

long
rtcbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
203a
Block*
rtcbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname pc/devrtc.c 1995/0726
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devrtc.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devrtc.c
112d
110c
rtccreate(Chan*, char*, int, ulong)
.
## diffname pc/devrtc.c 1995/0822
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devrtc.c /n/fornaxdump/1995/0822/sys/src/brazil/pc/devrtc.c
300d
298c
rtcwstat(Chan*, char*)
.
293d
291c
rtcremove(Chan*)
.
221d
118d
116c
rtcclose(Chan*)
.
## diffname pc/devrtc.c 1996/0223
## diff -e /n/fornaxdump/1995/0822/sys/src/brazil/pc/devrtc.c /n/fornaxdump/1996/0223/sys/src/brazil/pc/devrtc.c
7d
## diffname pc/devrtc.c 1997/0208
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/pc/devrtc.c /n/emeliedump/1997/0208/sys/src/brazil/pc/devrtc.c
173,176d
163c
	ulong t;
.
159a
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;
}

.
133,138d
130c
		if(inb(Pdata) & 0x80)
			continue;

		/* read clock values */
		outb(Paddr, Seconds);	bcdclock[0] = inb(Pdata);
		outb(Paddr, Minutes);	bcdclock[1] = inb(Pdata);
		outb(Paddr, Hours);	bcdclock[2] = inb(Pdata);
		outb(Paddr, Mday);	bcdclock[3] = inb(Pdata);
		outb(Paddr, Month);	bcdclock[4] = inb(Pdata);
		outb(Paddr, Year);	bcdclock[5] = inb(Pdata);

		outb(Paddr, Status);
		if((inb(Pdata) & 0x80) == 0)
.
127a
	/* don't do the read until the clock is no longer busy */
.
121,122c
static long	 
_rtctime(void)
.
## diffname pc/devrtc.c 1997/0327
## diff -e /n/emeliedump/1997/0208/sys/src/brazil/pc/devrtc.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devrtc.c
445,446c
	uchar data;

	lock(&nvramlock);
	outb(Paddr, addr);
	data = inb(Pdata);
	unlock(&nvramlock);

	return data;
}

void
nvramwrite(int addr, uchar data)
{
	lock(&nvramlock);
	outb(Paddr, addr);
	outb(Pdata, data);
	unlock(&nvramlock);
.
443c
nvramread(int addr)
.
441a
static Lock nvramlock;

.
393c
static void
.
358c
static ulong
.
346c
static int*
.
315,326d
309,313c
Dev rtcdevtab = {
	devreset,
	devinit,
	rtcattach,
	devclone,
	rtcwalk,
	rtcstat,
	rtcopen,
	devcreate,
	rtcclose,
	rtcread,
	devbread,
	rtcwrite,
	devbwrite,
	devremove,
	devwstat,
};
.
237,238c
static long	 
rtcwrite(Chan* c, void* buf, long n, ulong offset)
.
229,234d
199c
		return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
.
192,193c
static long	 
rtcread(Chan* c, void* buf, long n, ulong offset)
.
167c
static Lock rtlock;
.
108,114c
static void	 
.
105c
	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
.
89,94d
86,87c
static Chan*
rtcopen(Chan* c, int omode)
.
83c
	devstat(c, dp, rtcdir, nelem(rtcdir), devgen);
.
80,81c
static void	 
rtcstat(Chan* c, char* dp)
.
77c
	return devwalk(c, name, rtcdir, nelem(rtcdir), devgen);
.
74,75c
static int	 
rtcwalk(Chan* c, char* name)
.
61,70d
58,59c
static Chan*
rtcattach(char* spec)
.
54,56c
static ulong rtc2sec(Rtc*);
static void sec2rtc(ulong, Rtc*);
.
48d
## diffname pc/devrtc.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devrtc.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devrtc.c
279a
	'r',
	"rtc",

.
## diffname pc/devrtc.c 1998/0319
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devrtc.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devrtc.c
215a
	ulong offset = off;
.
208c
rtcwrite(Chan* c, void* buf, long n, vlong off)
.
172a
	ulong offset = off;
.
169c
rtcread(Chan* c, void* buf, long n, vlong off)
.
## diffname pc/devrtc.c 1999/0113
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devrtc.c /n/emeliedump/1999/0113/sys/src/brazil/pc/devrtc.c
324c
	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
.
322c
yrsize(int y)
.
## diffname pc/devrtc.c 1999/0129
## diff -e /n/emeliedump/1999/0113/sys/src/brazil/pc/devrtc.c /n/emeliedump/1999/0129/sys/src/brazil/pc/devrtc.c
438c
	iunlock(&nvrtlock);
.
435c
	ilock(&nvrtlock);
.
427c
	iunlock(&nvrtlock);
.
424c
	ilock(&nvrtlock);
.
417,418d
273,274c
		iunlock(&nvrtlock);

		free(start);
.
266c
		memmove(a, buf, n);
		poperror();

		ilock(&nvrtlock);
.
263c
			free(start);
.
261c
		if(n == 0)
			return 0;
		if(n > Nvsize)
			n = Nvsize;
	
		start = a = smalloc(n);
.
258c
		iunlock(&nvrtlock);
.
251c
		ilock(&nvrtlock);
.
212c
	char *a, *start;
.
199a

		free(start);
.
198c
		iunlock(&nvrtlock);

		if(waserror()){
			free(start);
			nexterror();
		}
		memmove(buf, start, t - offset);
.
186,191c
		if(n == 0)
			return 0;
		if(n > Nvsize)
			n = Nvsize;
		a = start = smalloc(n);

		ilock(&nvrtlock);
.
182d
180d
172c
	char *a, *start;
.
163c
	iunlock(&nvrtlock);
.
151c
	ilock(&nvrtlock);
.
143c
static Lock nvrtlock;
.
41d
## diffname pc/devrtc.c 1999/0714
## diff -e /n/emeliedump/1999/0129/sys/src/brazil/pc/devrtc.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devrtc.c
301c
	rtcinit,
.
54a
void
rtcinit(void)
{
	if(ioalloc(Paddr, 2, 0, "rtc/nvr") < 0)
		panic("rtcinit: ioalloc failed");
}

.
## diffname pc/devrtc.c 2001/0527
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devrtc.c /n/emeliedump/2001/0527/sys/src/9/pc/devrtc.c
310d
236c
	switch((ulong)c->qid.path){
.
184c
	switch((ulong)c->qid.path){
.
181c
	if(c->qid.type & QTDIR)
.
84c
	switch((ulong)c->qid.path){
.
77c
	return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
.
74,75c
static int	 
rtcstat(Chan* c, uchar* dp, int n)
.
71c
	return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
.
68,69c
static Walkqid*	 
rtcwalk(Chan* c, Chan *nc, char** name, int nname)
.
47a
	".",	{Qdir, 0, QTDIR},	0,	0555,
.
43c
	Qdir = 0,
	Qrtc,
.
## diffname pc/devrtc.c 2002/0109
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devrtc.c /n/emeliedump/2002/0109/sys/src/9/pc/devrtc.c
310a
	devshutdown,
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.