⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devrtc.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"/* *  real time clock and non-volatile ram */enum {	Paddr=		0x70,	/* address port */	Pdata=		0x71,	/* data port */	Seconds=	0x00,	Minutes=	0x02,	Hours=		0x04, 	Mday=		0x07,	Month=		0x08,	Year=		0x09,	Status=		0x0A,	Nvoff=		128,	/* where usable nvram lives */	Nvsize=		256,	Nbcd=		6,};typedef struct Rtc	Rtc;struct Rtc{	int	sec;	int	min;	int	hour;	int	mday;	int	mon;	int	year;};enum{	Qrtc = 1,	Qnvram,};Dirtab rtcdir[]={	"nvram",	{Qnvram, 0},	Nvsize,	0664,	"rtc",		{Qrtc, 0},	0,	0664,};static ulong rtc2sec(Rtc*);static void sec2rtc(ulong, Rtc*);voidrtcinit(void){	if(ioalloc(Paddr, 2, 0, "rtc/nvr") < 0)		panic("rtcinit: ioalloc failed");}static Chan*rtcattach(char* spec){	return devattach('r', spec);}static int	 rtcwalk(Chan* c, char* name){	return devwalk(c, name, rtcdir, nelem(rtcdir), devgen);}static void	 rtcstat(Chan* c, char* dp){	devstat(c, dp, rtcdir, nelem(rtcdir), devgen);}static Chan*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);	}	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);}static void	 rtcclose(Chan*){}#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))static long	 _rtctime(void){	uchar bcdclock[Nbcd];	Rtc rtc;	int i;	/* don't do the read until the clock is no longer busy */	for(i = 0; i < 10000; i++){		outb(Paddr, Status);		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)			break;	}	/*	 *  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);}static Lock nvrtlock;longrtctime(void){	int i;	long t, ot;	ilock(&nvrtlock);	/* 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(&nvrtlock);	return t;}static long	 rtcread(Chan* c, void* buf, long n, vlong off){	ulong t;	char *a, *start;	ulong offset = off;	if(c->qid.path & CHDIR)		return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);	switch(c->qid.path){	case Qrtc:		t = rtctime();		n = readnum(offset, buf, n, t, 12);		return n;	case Qnvram:		if(n == 0)			return 0;		if(n > Nvsize)			n = Nvsize;		a = start = smalloc(n);		ilock(&nvrtlock);		for(t = offset; t < offset + n; t++){			if(t >= Nvsize)				break;			outb(Paddr, Nvoff+t);			*a++ = inb(Pdata);		}		iunlock(&nvrtlock);		if(waserror()){			free(start);			nexterror();		}		memmove(buf, start, t - offset);		poperror();		free(start);		return t - offset;	}	error(Ebadarg);	return 0;}#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)static long	 rtcwrite(Chan* c, void* buf, long n, vlong off){	int t;	char *a, *start;	Rtc rtc;	ulong secs;	uchar bcdclock[Nbcd];	char *cp, *ep;	ulong offset = off;	if(offset!=0)		error(Ebadarg);	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);		/*		 *  write the clock		 */		ilock(&nvrtlock);		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]);		iunlock(&nvrtlock);		return n;	case Qnvram:		if(n == 0)			return 0;		if(n > Nvsize)			n = Nvsize;			start = a = smalloc(n);		if(waserror()){			free(start);			nexterror();		}		memmove(a, buf, n);		poperror();		ilock(&nvrtlock);		for(t = offset; t < offset + n; t++){			if(t >= Nvsize)				break;			outb(Paddr, Nvoff+t);			outb(Pdata, *a++);		}		iunlock(&nvrtlock);		free(start);		return t - offset;	}	error(Ebadarg);	return 0;}Dev rtcdevtab = {	'r',	"rtc",	devreset,	rtcinit,	rtcattach,	devclone,	rtcwalk,	rtcstat,	rtcopen,	devcreate,	rtcclose,	rtcread,	devbread,	rtcwrite,	devbwrite,	devremove,	devwstat,};#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 */static int*yrsize(int y){	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))		return ldmsize;	else		return dmsize;}/* *  compute seconds since Jan 1 1970 */static ulongrtc2sec(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 */static voidsec2rtc(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;}ucharnvramread(int addr){	uchar data;	ilock(&nvrtlock);	outb(Paddr, addr);	data = inb(Pdata);	iunlock(&nvrtlock);	return data;}voidnvramwrite(int addr, uchar data){	ilock(&nvrtlock);	outb(Paddr, addr);	outb(Pdata, data);	iunlock(&nvrtlock);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -