Plan 9 from Bell Labs’s /usr/web/sources/patch/applied/kw-clock/clock.c.backup

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


/*
 * kirkwood clock
 */
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"

#include "ureg.h"

#define TIMERREG	((TimerReg*)AddrTimer)

enum {
	Tcycles = CLOCKFREQ / HZ,		/* cycles per clock tick */

	/* timer ctl bits */
	Tmr0enable	= 1<<0,
	Tmr0periodic	= 1<<1,
	Tmr1enable	= 1<<2,
	Tmr1periodic	= 1<<3,
	TmrWDenable	= 1<<4,
	TmrWDperiodic	= 1<<5,
};

typedef struct TimerReg TimerReg;
struct TimerReg
{
	ulong	ctl;
	ulong	pad[3];
	ulong	reload0;
	ulong	timer0;
	ulong	reload1;
	ulong	timer1;
	ulong	reloadwd;
	ulong	timerwd;
};

static void
clockintr(Ureg *ureg, void*)
{
	TIMERREG->timerwd = CLOCKFREQ;		/* reassure the watchdog */
	m->fastclock++;
	coherence();
	timerintr(ureg, 0);
	intrclear(Irqbridge, IRQcputimer0);
}

/* stop clock interrupts and disable the watchdog timer */
void
clockshutdown(void)
{
	TIMERREG->ctl = 0;
	coherence();
}

void
clockinit(void)
{
	int s;
	long cyc;
	TimerReg *tmr = TIMERREG;

	clockshutdown();
	intrenable(Irqbridge, IRQcputimer0, clockintr, nil, "clock");

	s = spllo();			/* risky */
	/* take any deferred clock (& other) interrupts here */
	splx(s);

	/* adjust m->bootdelay, used by delay()? */
	m->ticks = 0;
	m->fastclock = 0;

	tmr->timer0 = Tcycles;
	tmr->ctl = Tmr0enable;		/* just once */
	coherence();

	s = spllo();			/* risky */
	/* one iteration seems to take about 40 ns. */
	for (cyc = Tcycles; cyc > 0 && m->fastclock == 0; cyc--)
		;
	splx(s);

	if (m->fastclock == 0) {
		serialputc('?');
		if (tmr->timer0 == 0)
			panic("clock not interrupting");
		else if (tmr->timer0 == tmr->reload0)
			panic("clock not ticking");
		else
			panic("clock running very slowly");
	}

	clockshutdown();
	tmr->timer0  = Tcycles;
	tmr->reload0 = Tcycles;
	tmr->timerwd = CLOCKFREQ;
	coherence();
	tmr->ctl = Tmr0enable | Tmr0periodic | TmrWDenable;
	CPUCSREG->rstout |= RstoutWatchdog;
	coherence();
}

void
timerset(uvlong next)
{
#ifdef FANCYTIMERS
	Tn *tn;
	Tval offset;

	ilock(&timers.tn1lock);
	tn = (Tn*)Tn1;
	tn->cr = Tm;

	offset = next + tn->cv;
	if(offset < timers.tn1minperiod)
		offset = timers.tn1minperiod;
	else if(offset > timers.tn1maxperiod)
		offset = timers.tn1maxperiod;

	tn->lc = offset;
	tn->cr = Tm|Te;
	iunlock(&timers.tn1lock);
#else
	USED(next);
#endif
}

/*
 * shift by 8 to provide enough resolution that dropping the tick rate
 * won't mess up TOD calculation and cause infrequent clock interrupts.
 */
uvlong
fastticks(uvlong *hz)
{
	if(hz)
		*hz = HZ << 8;
	return m->fastclock << 8;
}

ulong
µs(void)
{
	return fastticks2us(fastticks(nil));
}

void
microdelay(int l)
{
	int i;

	l *= m->delayloop;
	l /= 1000;
	if(l <= 0)
		l = 1;
	for(i = 0; i < l; i++)
		;
}

void
delay(int l)
{
	ulong i, j;

	j = m->delayloop;
	while(l-- > 0)
		for(i=0; i < j; i++)
			;
}

ulong
perfticks(void)
{
//	return ((Tn*)Tn0)->cv;		// TODO: FANCYTIMERS
	return (ulong)fastticks(nil);
}

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.