static char rcsid[] = "$Header: kgclock.c,v 820.1 86/12/04 19:55:55 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

#include "kg.h"
#if NKG > 0
/*
 * Intel 8253 interval timer as statistics clock
 *
 * Idea and name borrowed from the Vax kgclock.c.
 */
#include "../machine/pte.h"
#include "../machine/psl.h"

#include "../h/param.h"
#include "../h/map.h"
#include "../h/buf.h"
#include "../h/time.h"
#include "../h/kernel.h"

#include "../s32dev/mbvar.h"
#include "../s32/clock.h"
#include "../s32/cpu.h"

int	kgprobe(), kgattach();
struct	mb_device *kginfo[1];
u_short	kgstd[] = { 0xff, 0 };			/* token */
struct	mb_driver kgdriver = { 0, kgprobe, 0, kgattach, kgstd, "kg", kginfo };

#define PHZ 100

/*ARGSUSED*/
kgprobe(reg, intr, unit)
	caddr_t reg;
	int (*intr)();
{
	int kgclock();

	if (intr != kgclock || unit != 0)
		return 0;
	/* give the system clock a maximum count, and us a minimum count */
	CLKADDR->c_mode = C_MODE0 | C_SEL1 | C_WORD;
	CLKADDR->c_c1 = 1;
	CLKADDR->c_c1 = 0;
	CLKADDR->c_mode = C_MODE0 | C_SEL0 | C_WORD;
	CLKADDR->c_c1 = 0;
	CLKADDR->c_c1 = 0;
	V_STATUS |= V_ENINT;		/* no need for delay */
	V_STATUS &= ~V_ENINT;
	return sizeof (struct clock);
}

/*ARGSUSED*/
kgattach(md)
	struct mb_device *md;
{
}

/*
 * start the sampling clock
 */
startkgclock()
{

	if (*kginfo && (*kginfo)->md_alive) {
		CLKADDR->c_mode = C_MODE0 | C_SEL1 | C_WORD;
		CLKADDR->c_c1 = C_RATE / PHZ;
		CLKADDR->c_c1 = C_RATE / PHZ >> NBBY;
	}
	V_STATUS |= V_ENINT;
}

kgclock(unit)
{
	register struct stack {		/* stack of our caller */
		int reg[4];
		u_short ps;
		caddr_t pc;
	} *p;
	static long otime;
	static long calibrate;

	CLKADDR->c_mode = C_MODE0 | C_SEL1 | C_WORD;
	CLKADDR->c_c1 = C_RATE / PHZ;
	CLKADDR->c_c1 = C_RATE / PHZ >> NBBY;
	if (phz == 0) {
		if (otime == 0) {
			otime = time.tv_sec + 1;
			calibrate = 0;
		}
		if (time.tv_sec >= otime)
			calibrate++;
		if (time.tv_sec >= otime + 4) {
			phz = calibrate / 4;
			otime = 0;
		}
		return;
	}
	p = (struct stack *)&((int **)&unit)[-2][2];	/* KLUDGE */
	gatherstats(p->pc, p->ps);
}
#endif
