Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/bitsy/clock.c

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


## diffname bitsy/clock.c 2000/0902
## diff -e /dev/null /n/emeliedump/2000/0902/sys/src/9/bitsy/clock.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"
#include	"../port/error.h"

typedef struct Clock0link Clock0link;
typedef struct Clock0link {
	void		(*clock)(void);
	Clock0link*	link;
} Clock0link;

static Clock0link *clock0link;
static Lock clock0lock;

void
addclock0link(void (*clock)(void))
{
	Clock0link *lp;

	if((lp = malloc(sizeof(Clock0link))) == 0){
		print("addclock0link: too many links\n");
		return;
	}
	ilock(&clock0lock);
	lp->clock = clock;
	lp->link = clock0link;
	clock0link = lp;
	iunlock(&clock0lock);
}


vlong
fastticks(uvlong *hz)
{
	USED(hz);

	return m->ticks;
}

void
clockintr(Ureg*, void*)
{
}

void
delay(int ms)
{
	USED(ms);
}
.
## diffname bitsy/clock.c 2000/0905
## diff -e /n/emeliedump/2000/0902/sys/src/9/bitsy/clock.c /n/emeliedump/2000/0905/sys/src/9/bitsy/clock.c
52c
	ms *= 1000;
	while(ms-->0)
		;
.
## diffname bitsy/clock.c 2000/1006
## diff -e /n/emeliedump/2000/0905/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1006/sys/src/9/bitsy/clock.c
52,54c
	ulong cnt, old;

	while(ms-- > 0){
		cnt = ClockFreq/1000;
		while(cnt-- > 0){
			old = timerregs->oscr;
			while(old == timerregs->oscr)
				;
		}
	}
		
.
46a
	/* reset previous interrupt */
	timerregs->ossr |= 1<<0;

	/* post interrupt 1/HZ secs from now */
	timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
	iprint("timer interrupt\n");

	m->ticks++;
	if(m->ticks >= 100)
		exit(0);
.
44c
static void
.
39,41c
	if(hz != nil)
		*hz = ClockFreq;
	return timerregs->oscr;
.
35a
	/* enable interrupts on match register 0, turn off all others */
	timerregs->oier = 1<<0;
	intrenable(IRQtimer0, clockintr, nil, "clock");

	/* post interrupt 1/HZ secs from now */
	timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
}

.
34a
void
clockinit(void)
{
	/* map the clock registers */
	timerregs = mapspecial(OSTIMERREGS, 32);
.
9a
typedef struct OSTimer
{
	ulong	osmr[4];	/* match registers */
	ulong	oscr;		/* counter register */
	ulong	ossr;		/* status register */
	ulong	ower;		/* watchdog enable register */
	ulong	oier;		/* timer interrupt enable register */
} OSTimer;

static OSTimer *timerregs = (OSTimer*)OSTIMERREGS;

enum
{
	/* hardware counter frequency */
	ClockFreq=	3686400,
};

static void	clockintr(Ureg*, void*);

.
## diffname bitsy/clock.c 2000/1007
## diff -e /n/emeliedump/2000/1006/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1007/sys/src/9/bitsy/clock.c
104d
97,102c
		start = timerregs->oscr;
		while(timerregs->oscr-start < ClockFreq/1000);
.
94c
	ulong start;
.
62a
	timerregs->oier = 1<<0;
.
61c
	timerregs->ossr |= 1<<0;
.
21,26d
## diffname bitsy/clock.c 2000/1008
## diff -e /n/emeliedump/2000/1007/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1008/sys/src/9/bitsy/clock.c
82,83d
79d
## diffname bitsy/clock.c 2000/1015
## diff -e /n/emeliedump/2000/1008/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1015/sys/src/9/bitsy/clock.c
80a

	if(m->proc)
		m->proc->pc = ureg->pc;

	accounttime();
	if(kproftimer != nil)
		kproftimer(ureg->pc);

	checkalarms();
	ilock(&clock0lock);
	for(lp = clock0link; lp; lp = lp->link)
		lp->clock();
	iunlock(&clock0lock);

	if(up == 0 || up->state != Running)
		return;

	if(anyready())
		sched();
	
	if((ureg->psr & PsrMask) == PsrMusr) {
		(*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
		segclock(ureg->pc);
	}
.
73a
	Clock0link *lp;

.
72c
clockintr(Ureg *ureg, void*)
.
## diffname bitsy/clock.c 2000/1019
## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1019/sys/src/9/bitsy/clock.c
114,116c
	if(clockinited){
		while(ms-- > 0){
			start = timerregs->oscr;
			while(timerregs->oscr-start < ClockFreq/1000);
		}
	} else {
		while(ms-- > 0){
			for(i = 0; i < 1000; i++)
				;
		}
.
112a
	int i;
.
60a

	clockinited = 1;
.
19a
static int clockinited;
.
## diffname bitsy/clock.c 2000/1020
## diff -e /n/emeliedump/2000/1019/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1020/sys/src/9/bitsy/clock.c
98a

	if(active.exiting && (active.machs & (1<<m->machno)))
		exit(0);
	inclockintr = 0;
.
89a
	if(inclockintr)
		return;		/* interrupted ourself */

	inclockintr = 1;

.
77a
	static int inclockintr;
.
## diffname bitsy/clock.c 2000/1101
## diff -e /n/emeliedump/2000/1020/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1101/sys/src/9/bitsy/clock.c
98c
		(*kproftimer)(ureg->pc);
.
## diffname bitsy/clock.c 2000/1107
## diff -e /n/emeliedump/2000/1101/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1107/sys/src/9/bitsy/clock.c
86,119c
	portclock();
.
34,49d
19,32d
10,17d
## diffname bitsy/clock.c 2000/1110
## diff -e /n/emeliedump/2000/1107/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1110/sys/src/9/bitsy/clock.c
68a

void
µdelay(int µs)
{
	ulong start;
	int i;

	if(clockinited){
		start = timerregs->oscr;
		while(timerregs->oscr - start < µs∗ClockFreq/1000000);
	} else {
		while(µs-- > 0){
			for(i = 0; i < 10; i++)
				;
		}
	}
}
.
## diffname bitsy/clock.c 2000/1111
## diff -e /n/emeliedump/2000/1110/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1111/sys/src/9/bitsy/clock.c
78c
		while(timerregs->oscr - start < (µs*ClockFreq)/1000000)
			;
.
60c
			while(timerregs->oscr-start < ClockFreq/1000)
				;
.
48c
	portclock(ureg);
.
39,41d
10a
static OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
static int clockinited;

static void	clockintr(Ureg*, void*);

.
9a
typedef struct OSTimer
{
	ulong	osmr[4];	/* match registers */
	ulong	oscr;		/* counter register */
	ulong	ossr;		/* status register */
	ulong	ower;		/* watchdog enable register */
	ulong	oier;		/* timer interrupt enable register */
} OSTimer;
.
## diffname bitsy/clock.c 2000/1121
## diff -e /n/emeliedump/2000/1111/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1121/sys/src/9/bitsy/clock.c
33a

	/* figure out processor frequency */
	x = powerregs->ppcr & 0x1f;
	conf.hz = ClockFreq*(x*4+16);
	conf.mhz = (conf.hz+499999)/1000000;

	print("%lud MHZ WeakARM\n", conf.mhz);
.
26a
	ulong x;

.
## diffname bitsy/clock.c 2000/1130
## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1130/sys/src/9/bitsy/clock.c
66a
	drawactive(0);	/* screen saver */
.
## diffname bitsy/clock.c 2000/1205
## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1205/sys/src/9/bitsy/clock.c
34c
	intrenable(IRQ, IRQtimer0, clockintr, nil, "clock");
.
## diffname bitsy/clock.c 2000/1215
## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/clock.c /n/emeliedump/2000/1215/sys/src/9/bitsy/clock.c
55c
	x = timerregs->oscr;
	if(x < last)
		high += 1LL<<32;
	last = x;
	return high+x;
.
52a
	static vlong high;
	static ulong last;
	ulong x;

.
49a
/*  turn 32 bit counter into a 64 bit one.  since todfix calls
 *  us at least once a second and we overflow once every 1165
 *  seconds, we won't miss an overflow.
 */
.
## diffname bitsy/clock.c 2001/0324
## diff -e /n/emeliedump/2000/1215/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0324/sys/src/9/bitsy/clock.c
42c
	/* get processor type */
	id = getcpuid();

	print("%lud MHZ ARM, version %ux part %ux stepping %uxd\n", conf.mhz,
		(id>>16)&0xff, (id>>4)&0xfff, id&0xf);
.
27a
	ulong id;
.
## diffname bitsy/clock.c 2001/0327
## diff -e /n/emeliedump/2001/0324/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0327/sys/src/9/bitsy/clock.c
46c
	print("%lud MHZ ARM, ver %lux/part %lux/step %lud\n", conf.mhz,
.
## diffname bitsy/clock.c 2001/0421
## diff -e /n/emeliedump/2001/0327/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0421/sys/src/9/bitsy/clock.c
116c
		while(timerregs->oscr - start < 1UL+(µs*ClockFreq)/1000000UL)
.
113a
	µs++;
.
109c
µdelay(ulong µs)
.
## diffname bitsy/clock.c 2001/0618
## diff -e /n/emeliedump/2001/0421/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0618/sys/src/9/bitsy/clock.c
22a

void
clockpower(int on)
{

	if (on){
		timerregs->ossr |= 1<<0;
		timerregs->oier = 1<<0;
		timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
	}
}
.
19c
OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
.
## diffname bitsy/clock.c 2001/0622
## diff -e /n/emeliedump/2001/0618/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0622/sys/src/9/bitsy/clock.c
32a
	clockinited = on;
.
## diffname bitsy/clock.c 2001/0813
## diff -e /n/emeliedump/2001/0622/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0813/sys/src/9/bitsy/clock.c
15c
	ulong	ower;	/* watchdog enable register */
.
## diffname bitsy/clock.c 2001/0905
## diff -e /n/emeliedump/2001/0813/sys/src/9/bitsy/clock.c /n/emeliedump/2001/0905/sys/src/9/bitsy/clock.c
137a

ulong
TK2MS(ulong ticks)
{
	uvlong t, hz;

	t = ticks;
	hz = HZ;
	t *= 1000L;
	t = t/hz;
	ticks = t;
	return ticks;
}
.
## diffname bitsy/clock.c 2002/0405
## diff -e /n/emeliedump/2001/0905/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0405/sys/src/9/bitsy/clock.c
93,97c
	timerset(timerintr(ureg, nil));
.
89a

.
86a
void
timerset(vlong v)
{
	ulong when;	/* Must be unsigned! */

	if (v == 0LL)
		when = timerregs->oscr + Minfreq;
	else {
		when = v;

		/* post next interrupt: calculate # of tics from now */
		when = when - timerregs->oscr - Maxfreq;
		if (when - timerregs->oscr > Minfreq)
			when = timerregs->oscr + Maxfreq;
	}
	timerregs->osmr[0] = when;
}

.
63a
	timersinit();

.
23a
enum
{
	Minfreq = ClockFreq/HZ,		/* At least one interrupt per HZ (10 ms) */
	Maxfreq = ClockFreq/10000,	/* At most one interrupt every 100 µs */
};

.
## diffname bitsy/clock.c 2002/0406
## diff -e /n/emeliedump/2002/0405/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0406/sys/src/9/bitsy/clock.c
120a
	if ((count++ % 100) == 0)
		iprint("%lud ", timerregs->osmr[0] - timerregs->oscr);
.
115a
	static ulong count;
.
108a
		}
.
106,107c
		tics = when - timerregs->oscr - Maxfreq;
		if (tics > Minfreq){
			iprint("%lud %lud %lud %d\n", when, tics, timerregs->oscr, Minfreq);
.
98c
	ulong when, tics;	/* Must be unsigned! */
	static int count;
.
96c
timerset(uvlong v)
.
82c
	static uvlong high;
.
26c
	Minfreq = ClockFreq/HZ,		/* At least one interrupt per HZ (50 ms) */
.
12,16c
	ulong		osmr[4];	/* match registers */
	volatile ulong	oscr;		/* counter register */
	ulong		ossr;		/* status register */
	ulong		ower;	/* watchdog enable register */
	ulong		oier;		/* timer interrupt enable register */
.
## diffname bitsy/clock.c 2002/0408
## diff -e /n/emeliedump/2002/0406/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0408/sys/src/9/bitsy/clock.c
124,126c
	timerintr(ureg, when);
.
122a
	when += Minfreq;
	timerregs->osmr[0] = when;	/* insurance */
.
119,120d
113c
	timerregs->osmr[0] = next;
.
106,111c
	/* post next interrupt: calculate # of tics from now */
	tics = next - timerregs->oscr - Maxfreq;
	if (tics > Minfreq){
		iprint("%lud %lud %lud %d\n", next, tics, timerregs->oscr, Minfreq);
		next = timerregs->oscr + Maxfreq;
.
101,104c
	next = v;
.
98c
	ulong next, tics;	/* Must be unsigned! */
.
68c
	when = timerregs->oscr + Minfreq;
	timerregs->osmr[0] = when;
.
37c
		timerregs->osmr[0] = timerregs->oscr + Minfreq;
.
22a
static uvlong when;	/* scheduled time of next interrupt */
.
## diffname bitsy/clock.c 2002/0410
## diff -e /n/emeliedump/2002/0408/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0410/sys/src/9/bitsy/clock.c
81c
uvlong
.
## diffname bitsy/clock.c 2002/0411
## diff -e /n/emeliedump/2002/0410/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0411/sys/src/9/bitsy/clock.c
108c
		timeradjust++;
.
24a
long	timeradjust;

.
22,23c
static void		clockintr(Ureg*, void*);
static uvlong	when;	/* scheduled time of next interrupt */
.
## diffname bitsy/clock.c 2002/0606
## diff -e /n/emeliedump/2002/0411/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0606/sys/src/9/bitsy/clock.c
148c
microdelay(int µs)
.
## diffname bitsy/clock.c 2002/0710
## diff -e /n/emeliedump/2002/0606/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0710/sys/src/9/bitsy/clock.c
165,177d
## diffname bitsy/clock.c 2002/0822
## diff -e /n/emeliedump/2002/0710/sys/src/9/bitsy/clock.c /n/emeliedump/2002/0822/sys/src/9/bitsy/clock.c
164a

/*  
 *  performance measurement ticks.  must be low overhead.
 *  doesn't have to count over a second.
 */
ulong
perfticks(void)
{
	return timerregs->oscr;
}
.
## diffname bitsy/clock.c 2002/1112
## diff -e /n/emeliedump/2002/0822/sys/src/9/bitsy/clock.c /n/emeliedump/2002/1112/sys/src/9/bitsy/clock.c
124a
}

void
rtcalarm(ulong secs)
{
	vlong t;

	if (t == 0){
		iprint("RTC alarm cancelled\n");
		rtcregs->rtsr &= ~RTSR_ale;
		rtcregs->rtar = 0xffffffff;
	} else {
		t = todget(nil);
		t = t / 1000000000ULL; // nsec to secs
		if (secs < t)
			return;
		secs -= t;
		iprint("RTC alarm set to %uld seconds from now\n", secs);
		rtcregs->rtar = rtcregs->rcnr + secs;
		rtcregs->rtsr|= RTSR_ale;
	}
}

static void
rtcintr(Ureg*, void*)
{
	/* reset interrupt */
	rtcregs->rtsr&= ~RTSR_ale;
	rtcregs->rtsr&= ~RTSR_al;

	rtcregs->rtar = 0;
	iprint("RTC alarm: %lud\n", rtcregs->rcnr);
.
73a
	/* enable RTC interrupts and alarms */
	intrenable(IRQ, IRQrtc, rtcintr, nil, "rtc");
	rtcregs->rttr = 0x8000; 	// make rcnr   1Hz
	rtcregs->rcnr = 0;		// reset counter
	rtcregs->rtsr |= RTSR_al;
	rtcregs->rtsr |= RTSR_ale;

.
52c
	timerregs = mapspecial(OSTIMERREGS, sizeof(OSTimer));
	rtcregs   = mapspecial(RTCREGS, sizeof(RTCregs));
.
42a
	return 0L;
.
41c
		if (rtcregs->rttr == 0){
			rtcregs->rttr = 0x8000; // nominal frequency.
			rtcregs->rcnr = 0;
			rtcregs->rtar = 0xffffffff;
			rtcregs->rtsr |= RTSR_ale;
			rtcregs->rtsr |= RTSR_hze;
		}
		if (rtcregs->rcnr > savedtime)
			return rtcregs->rcnr - savedtime;
	} else
		savedtime = rtcregs->rcnr;
.
35a
	static ulong savedtime;
.
33c
ulong
.
22c
static void	clockintr(Ureg*, void*);
static void	rtcintr(Ureg*, void*);
.
19a
RTCregs *rtcregs = (RTCregs*)RTCREGS;
.
18a
typedef struct RTCregs 
{
	ulong	rtar;	/* alarm */
	ulong	rcnr;	/* count */
	ulong	rttr;	/* trim */
	ulong	dummy;	/* hole */
	ulong	rtsr;	/* status */
} RTCregs;

.
9a

enum {
	RTCREGS	=	0x90010000,	/* real time clock registers */
	RTSR_al	=	0x01,		/* alarm detected */
	RTSR_hz	=	0x02,		/* 1Hz tick */
	RTSR_ale=	0x04,		/* alarm interrupt enable */
	RTSR_hze=	0x08,		/* 1Hz tick enable */

	Never	=	0xffffffff,
};

.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].