~kris/9p

9hist

6a589dc19f0180af472dd57211833cd0381a15d0 — David du Colombier 27 years ago f6f547e
Plan 9 from Bell Labs 1999-02-25
4 files changed, 199 insertions(+), 49 deletions(-)

M pc/mouse.c
M pc/screen.h
M port/devmouse.c
M port/tod.c
M pc/mouse.c => pc/mouse.c +90 -33
@@ 101,6 101,80 @@ ps2mouse(void)
	mousetype = MousePS2;
}

static int intellimouse;
static int resolution;
static int accelerated;

static void
setaccelerated(int x)
{
	accelerated = x;
	switch(mousetype){
	case MousePS2:
		i8042auxcmd(0xE7);
		break;
	default:
		mouseaccelerate(x);
		break;
	}
}

static void
setlinear(void)
{
	accelerated = 0;
	switch(mousetype){
	case MousePS2:
		i8042auxcmd(0xE6);
		break;
	default:
		mouseaccelerate(0);
		break;
	}
}

static void
setres(int n)
{
	resolution = n;
	switch(mousetype){
	case MousePS2:
		i8042auxcmd(0xE8);
		i8042auxcmd(n);
		break;
	}
}

static void
setintellimouse(void)
{
	intellimouse = 1;
	switch(mousetype){
	case MousePS2:
		i8042auxcmd(0xF3);	/* set sample */
		i8042auxcmd(0xC8);
		i8042auxcmd(0xF3);	/* set sample */
		i8042auxcmd(0x64);
		i8042auxcmd(0xF3);	/* set sample */
		i8042auxcmd(0x50);
		break;
	}
}

static void
resetmouse(void)
{
	switch(mousetype){
	case MousePS2:
		i8042auxcmd(0xF6);
		i8042auxcmd(0xEA);	/* streaming */
		i8042auxcmd(0xE8);	/* set resolution */
		i8042auxcmd(3);
		i8042auxcmd(0xF4);	/* enabled */
		break;
	}
}

void
mousectl(char* field[], int n)
{


@@ 119,44 193,27 @@ mousectl(char* field[], int n)
		}
	} else if(strcmp(field[0], "ps2") == 0){
		ps2mouse();
	} else if(strcmp(field[0], "ps2intellimouse") == 0){
		ps2mouse();
		setintellimouse();
	} else if(strcmp(field[0], "accelerated") == 0){
		switch(mousetype){
		case MousePS2:
			i8042auxcmd(0xE7);
			break;
		default:
			if(n == 1)
				mouseaccelerate("1");
			else
				mouseaccelerate(field[1]);
			break;
		}
		setaccelerated(n == 1 ? 1 : atoi(field[1]));
	} else if(strcmp(field[0], "linear") == 0){
		switch(mousetype){
		case MousePS2:
			i8042auxcmd(0xE6);
			break;
		default:
			mouseaccelerate("0");
			break;
		}
		setlinear();
	} else if(strcmp(field[0], "res") == 0){
		if(n < 2)
			n = 1;
		else
		if(n >= 2)
			n = atoi(field[1]);
		switch(mousetype){
		case MousePS2:
			i8042auxcmd(0xE8);
			i8042auxcmd(n);
			break;
		}
		setres(n);
	} else if(strcmp(field[0], "reset") == 0){
		i8042auxcmd(0xF6);
		i8042auxcmd(0xEA);	/* streaming */
		i8042auxcmd(0xE8);	/* set resolution */
		i8042auxcmd(3);
		i8042auxcmd(0xF4);	/* enabled */
		resetmouse();
		if(accelerated)
			setaccelerated(accelerated);
		if(resolution)
			setres(resolution);
		if(intellimouse)
			setintellimouse();
	} else if(strcmp(field[0], "intellimouse") == 0){
		setintellimouse();
	}
	else
		error(Ebadctl);

M pc/screen.h => pc/screen.h +1 -1
@@ 9,7 9,7 @@ struct Cursorinfo {
extern void mousetrack(int, int, int);
extern Point mousexy(void);

extern void mouseaccelerate(char*);
extern void mouseaccelerate(int);
extern int m3mouseputc(void*, int);
extern int mouseputc(void*, int);


M port/devmouse.c => port/devmouse.c +2 -4
@@ 535,11 535,9 @@ mousexy(void)
}

void
mouseaccelerate(char *x)
mouseaccelerate(int x)
{
	if(x == 0)
		x = "1";
	mouse.acceleration = atoi(x);
	mouse.acceleration = x;
	if(mouse.acceleration < 3)
		mouse.maxacc = 2;
	else

M port/tod.c => port/tod.c +106 -11
@@ 5,22 5,99 @@
#include	"fns.h"
#include	"../port/error.h"

// compute nanosecond epoch time from the fastest ticking clock
// on the system.  converting the time to nanoseconds requires
// the following formula
//
//	t = (((1000000000<<s1)/f)*(ticks>>s2))>>(s1-s2)
//
//  where
//
//	'f'		is the clock frequency
//	'ticks'		are clock ticks
//	's1' and 's2'	are shift ammounts to avoid 64 bit
//			overflows in the calculations
//
//  to avoid too much calculation in gettod(), we calculate
//
//	mult = (1000000000<<s1)/f
//
//  each time f is set.  f is normally set by a user level
//  program writing to /dev/fastclock.
//
//  To calculate s1 and s2, we have to avoid overflowing our
//  signed 64 bit calculations.  Also we wish to accomodate
//  15 minutes of ticks.  This gives us the following
//  constraints:
//
//	1) log2(1000000000<<s1) <= 63
//	   or s1 <= 33
//	2) accomodate 15 minutes of ticks without overflow
//	   or log2(((1000000000<<s1)/f)*((15*60*f)>>s2)) <= 63
//	   or log2(mult) + 12 + log2(f) - s2 <= 63
//	   or log2(mult) + log2(f) - 51 <= s2
//
//  by definition
//
//	3) log2(mult) = log2(1000000000) + s1 - log2(f)
//	   or log2(mult) = 30 + s1 - log2(f)
//
//  To balance the accuracy of the multiplier and the sampled
//  ticks we set
//
//	4) log2(mult) = log2(f>>s2)
//	   or log2(mult) = log2(f) - s2
//
//  Combining 2) and 4) we get
//
//	5) log2(f) - s2 + log2(f) - 51 <= s2
//	   or 2*log2(f) - 51 <= 2*s2
//	   or log2(f) - 25 <= s2
//
//  Combining 3) and 4)
//
//	6) 30 + s1 - log2(f) = log2(f) - s2
//	   or s1 = 2*log2(f) - s2 - 30
//
//  Since shifting ticks left doesn't increase accuracy, and
//  shifting 1000000000 right loses accuracy
//
//	7) s2 >= 0
//	8) s1 >= 0
//
//  As an example, that gives us the following
//
//	for f = 100, log2(f) = 7
//
//		s2 = 0
//		s1 = 0
//
//	for f = 267000000, log2(f) = 28
//
//		s2 = 3
//		s1 = 23
//
//	for f = 2000000000, log2(f) = 31
//
//		s2 = 6
//		s1 = 26
//
//	for f = 8000000000, log2(f) = 33
//
//		s2 = 8
//		s1 = 28

// frequency of the tod clock
#define TODFREQ	1000000000LL

enum
{
	Log2mult=	22,	// multiplier should have 22 bits
	Log2todfreq=	30,	// number of significant bits of TODFREQ
};

static vlong logtab[40];

struct {
	Lock;
	int	shift;		// time = (ticks*multiplier)>>shift
	int	s1;		// time = ((ticks>>s2)*multiplier)>>(s1-s2)
	vlong	multiplier;	// ...
	int	s2;		// ...
	vlong	maxdiff;	// max diff between ticks and last to avoid overflow
	vlong	hz;		// frequency of fast clock
	vlong	last;		// last reading of fast clock
	vlong	off;		// offset from epoch to last


@@ 65,12 142,24 @@ todinit(void)
void
todsetfreq(vlong f)
{
	int lf;

	// this ensures that the multiplier has 22 bits
	ilock(&tod);
	tod.hz = f;
	tod.shift = Log2mult - Log2todfreq + log2(f);
	tod.multiplier = (TODFREQ<<tod.shift)/f;
	lf = log2(f);
	tod.s2 = lf - 25;
	if(tod.s2 < 0)
		tod.s2 = 0;
	tod.s1 = 2*lf - tod.s2 - 30;
	if(tod.s1 < 0)
		tod.s1 = 0;
	if(tod.s1 > 33)
		tod.s1 = 33;
	tod.multiplier = (TODFREQ<<tod.s1)/f;
	tod.maxdiff = 1LL<<(10 + lf);
	iunlock(&tod);
//print("hz %lld mult %lld s1 %d s2 %d maxdiff %lld\n", tod.hz, tod.multiplier, tod.s1, tod.s2, tod.maxdiff);
}

//


@@ 109,11 198,11 @@ todget(void)
	diff = ticks - tod.last;

	// convert to epoch
	x = (diff*tod.multiplier)>>tod.shift;
	x = ((diff>>tod.s2)*tod.multiplier)>>(tod.s1-tod.s2);
	x += tod.off;

	// protect against overflows
	if(diff > (1LL<<(63-Log2mult))){
	if(diff > tod.maxdiff){
		tod.last = ticks;
		tod.off = x;
	}


@@ 135,10 224,16 @@ todfix(void)
{
	if((MACHP(0)->ticks % HZ) != 0)
		return;

	// once a second apply correction
	ilock(&tod);
	if(tod.n > tod.i++)
		tod.off += tod.delta;
	iunlock(&tod);

	// once a minute, make sure we don't overflow
	if((MACHP(0)->ticks % (60*HZ)) == 0)
		todget();
}

long