From 6a589dc19f0180af472dd57211833cd0381a15d0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 25 Feb 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-02-25 --- pc/mouse.c | 123 +++++++++++++++++++++++++++++++++++------------- pc/screen.h | 2 +- port/devmouse.c | 6 +-- port/tod.c | 117 ++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 199 insertions(+), 49 deletions(-) diff --git a/pc/mouse.c b/pc/mouse.c index b94a48b1c03d7c17c41390cf156f0a20764cb2a3..a5aec038466ef7b9b860529a3e96c6488e79778a 100644 --- a/pc/mouse.c +++ b/pc/mouse.c @@ -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); diff --git a/pc/screen.h b/pc/screen.h index 4252b2b8266b34d40b906b648ce58a6f104c9de6..38bc3db89f5276251d5973fad363604f716766ba 100644 --- a/pc/screen.h +++ b/pc/screen.h @@ -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); diff --git a/port/devmouse.c b/port/devmouse.c index 0ad6fa164cc3ba578b04a25574bd6b39116789f3..743245458e1b171ed2ba996615d92a897c6da0a2 100644 --- a/port/devmouse.c +++ b/port/devmouse.c @@ -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 diff --git a/port/tod.c b/port/tod.c index 4d321b3bf3bf273954ccb0e9579c7b70d2aaad9b..665f646a798622b88636512f2510f8bc62d36e61 100644 --- a/port/tod.c +++ b/port/tod.c @@ -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<>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<>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< 33) + tod.s1 = 33; + tod.multiplier = (TODFREQ<>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