ref: 022856f94e7a0298660139e294752d5d2646e604
parent: d9af840ca248f27e6b9d2a135e537c41b3578d52
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Apr 2 14:35:43 EDT 2015
sgi: keyboard, mouse and cursor for indy
--- a/sys/src/9/sgi/dat.h
+++ b/sys/src/9/sgi/dat.h
@@ -67,6 +67,7 @@
ulong pipeqsize; /* size in bytes of pipe queues */
int nuart; /* number of uart devices */
int monitor;
+ int keyboard;
};
/*
--- /dev/null
+++ b/sys/src/9/sgi/devkbd.c
@@ -1,0 +1,339 @@
+/*
+ * keyboard input
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Data= 0x40+3, /* data port */
+ Cmd= 0x44+3, /* command port (write) */
+ Status= 0x44+3, /* status port (read) */
+ Inready= 0x01, /* input character ready */
+ Outbusy= 0x02, /* output busy */
+ Sysflag= 0x04, /* system flag */
+ Cmddata= 0x08, /* cmd==0, data==1 */
+ Inhibit= 0x10, /* keyboard/mouse inhibited */
+ Minready= 0x20, /* mouse character ready */
+ Rtimeout= 0x40, /* general timeout */
+ Parity= 0x80,
+};
+
+enum
+{
+ /* controller command byte */
+ Cscs1= (1<<6), /* scan code set 1 */
+ Cauxdis= (1<<5), /* mouse disable */
+ Ckbddis= (1<<4), /* kbd disable */
+ Csf= (1<<2), /* system flag */
+ Cauxint= (1<<1), /* mouse interrupt enable */
+ Ckbdint= (1<<0), /* kbd interrupt enable */
+};
+
+enum {
+ Qdir,
+ Qscancode,
+ Qleds,
+};
+
+static Dirtab kbdtab[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "scancode", {Qscancode, 0}, 0, 0440,
+ "leds", {Qleds, 0}, 0, 0220,
+};
+
+static Lock i8042lock;
+static uchar ccc, dummy;
+
+static struct {
+ Ref ref;
+ Queue *q;
+ uchar *io;
+} kbd;
+
+
+#define inb(r) (dummy=kbd.io[r])
+#define outb(r,b) (kbd.io[r]=b)
+
+/*
+ * wait for output no longer busy
+ */
+static int
+outready(void)
+{
+ int tries;
+
+ for(tries = 0; (inb(Status) & Outbusy); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * wait for input
+ */
+static int
+inready(void)
+{
+ int tries;
+
+ for(tries = 0; !(inb(Status) & Inready); tries++){
+ if(tries > 500)
+ return -1;
+ delay(2);
+ }
+ return 0;
+}
+
+/*
+ * set keyboard's leds for lock states (scroll, numeric, caps).
+ *
+ * at least one keyboard (from Qtronics) also sets its numeric-lock
+ * behaviour to match the led state, though it has no numeric keypad,
+ * and some BIOSes bring the system up with numeric-lock set and no
+ * setting to change that. this combination steals the keys for these
+ * characters and makes it impossible to generate them: uiolkjm&*().
+ * thus we'd like to be able to force the numeric-lock led (and behaviour) off.
+ */
+static void
+setleds(int leds)
+{
+ static int old = -1;
+
+ if(!conf.keyboard || leds == old)
+ return;
+ leds &= 7;
+ ilock(&i8042lock);
+ for(;;){
+ if(outready() < 0)
+ break;
+ outb(Data, 0xed); /* `reset keyboard lock states' */
+ if(outready() < 0)
+ break;
+ outb(Data, leds);
+ if(outready() < 0)
+ break;
+ old = leds;
+ break;
+ }
+ iunlock(&i8042lock);
+}
+
+/*
+ * keyboard interrupt
+ */
+static void
+i8042intr(Ureg*, void*)
+{
+ extern void sgimouseputc(int);
+
+ int s, c;
+ uchar b;
+
+ /*
+ * get status
+ */
+ ilock(&i8042lock);
+ s = inb(Status);
+ if(!(s&Inready)){
+ iunlock(&i8042lock);
+ return;
+ }
+
+ /*
+ * get the character
+ */
+ c = inb(Data);
+ iunlock(&i8042lock);
+
+ b = c & 0xff;
+
+ /*
+ * if it's the aux port...
+ */
+ if(s & Minready){
+ sgimouseputc(b);
+ return;
+ }
+
+ qproduce(kbd.q, &b, 1);
+}
+
+static void
+pollintr(void)
+{
+ i8042intr(nil, nil);
+}
+
+static Chan *
+kbdattach(char *spec)
+{
+ return devattach(L'b', spec);
+}
+
+static Walkqid*
+kbdwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, kbdtab, nelem(kbdtab), devgen);
+}
+
+static int
+kbdstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, kbdtab, nelem(kbdtab), devgen);
+}
+
+static Chan*
+kbdopen(Chan *c, int omode)
+{
+ if(!iseve())
+ error(Eperm);
+ if(c->qid.path == Qscancode){
+ if(waserror()){
+ decref(&kbd.ref);
+ nexterror();
+ }
+ if(incref(&kbd.ref) != 1)
+ error(Einuse);
+ c = devopen(c, omode, kbdtab, nelem(kbdtab), devgen);
+ poperror();
+ return c;
+ }
+ return devopen(c, omode, kbdtab, nelem(kbdtab), devgen);
+}
+
+static void
+kbdclose(Chan *c)
+{
+ if((c->flag & COPEN) && c->qid.path == Qscancode)
+ decref(&kbd.ref);
+}
+
+static Block*
+kbdbread(Chan *c, long n, ulong off)
+{
+ if(c->qid.path == Qscancode)
+ return qbread(kbd.q, n);
+ else
+ return devbread(c, n, off);
+}
+
+static long
+kbdread(Chan *c, void *a, long n, vlong)
+{
+ if(c->qid.path == Qscancode)
+ return qread(kbd.q, a, n);
+ if(c->qid.path == Qdir)
+ return devdirread(c, a, n, kbdtab, nelem(kbdtab), devgen);
+
+ error(Egreg);
+ return 0;
+}
+
+static long
+kbdwrite(Chan *c, void *a, long n, vlong)
+{
+ char tmp[8+1], *p;
+
+ if(c->qid.path != Qleds)
+ error(Egreg);
+
+ p = tmp + n;
+ if(n >= sizeof(tmp))
+ p = tmp + sizeof(tmp)-1;
+ memmove(tmp, a, p - tmp);
+ *p = 0;
+
+ setleds(atoi(tmp));
+
+ return n;
+}
+
+
+static char *initfailed = "i8042: kbdinit failed\n";
+
+static int
+outbyte(int port, int c)
+{
+ outb(port, c);
+ if(outready() < 0) {
+ print(initfailed);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+kbdinit(void)
+{
+ int c, try;
+
+ kbd.io = IO(uchar, HPC3_KBDMS);
+ kbd.q = qopen(1024, Qcoalesce, 0, 0);
+ if(kbd.q == nil)
+ panic("kbdinit: qopen");
+ qnoblock(kbd.q, 1);
+
+ /* wait for a quiescent controller */
+ try = 1000;
+ while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
+ if(c & Inready)
+ inb(Data);
+ delay(1);
+ }
+ if (try <= 0) {
+ print(initfailed);
+ return;
+ }
+
+ /* get current controller command byte */
+ outb(Cmd, 0x20);
+ if(inready() < 0){
+ print("i8042: kbdinit can't read ccc\n");
+ ccc = 0;
+ } else
+ ccc = inb(Data);
+
+ /* enable kbd xfers and interrupts */
+ ccc &= ~Ckbddis;
+ ccc |= Csf | Ckbdint | Cscs1;
+ if(outready() < 0) {
+ print(initfailed);
+ return;
+ }
+ /* disable mouse */
+ if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0){
+ print("i8042: kbdinit mouse disable failed\n");
+ return;
+ }
+
+ conf.keyboard = 1;
+ addclock0link(pollintr, 5);
+}
+
+Dev kbddevtab = {
+ L'b',
+ "kbd",
+
+ devreset,
+ kbdinit,
+ devshutdown,
+ kbdattach,
+ kbdwalk,
+ kbdstat,
+ kbdopen,
+ devcreate,
+ kbdclose,
+ kbdread,
+ kbdbread,
+ kbdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
--- a/sys/src/9/sgi/indy
+++ b/sys/src/9/sgi/indy
@@ -18,6 +18,7 @@
# sd
draw screen
mouse
+ kbd
link
etherseeq
--- a/sys/src/9/sgi/io.h
+++ b/sys/src/9/sgi/io.h
@@ -40,10 +40,15 @@
#define LIO_0_ISR (INT2_BASE+0x3)
#define LIO_0_MASK (INT2_BASE+0x7)
+#define LIO_1_ISR (INT2_BASE+0xb)
+#define LIO_1_MASK (INT2_BASE+0xf)
+#define LIO_2_ISR (INT2_BASE+0x13)
+#define LIO_2_MASK (INT2_BASE+0x17)
-#define HPC3_ETHER 0x1fb80000
+#define HPC3_ETHER 0x1fb80000
+#define HPC3_KBDMS 0x1fbd9800
+#define GIO_NEWPORT 0x1f0f0000 /* indy */
#define MEMCFG0 0x1fa000c4 /* mem. size config. reg. 0 (w, rw) */
#define MEMCFG1 0x1fa000cc /* mem. size config. reg. 1 (w, rw) */
-#define GIO_NEWPORT 0x1f0f0000 /* indy */
--- a/sys/src/9/sgi/main.c
+++ b/sys/src/9/sgi/main.c
@@ -154,6 +154,13 @@
}
}
+static int
+havegfx(void)
+{
+ char *s = getconf("ConsoleOut");
+ return s != nil && strstr(s, "video()") != nil;
+}
+
void
main(void)
{
@@ -173,7 +180,10 @@
timersinit();
fmtinit();
- screeninit();
+ if(havegfx()){
+ conf.monitor = 1;
+ screeninit();
+ }
ckpagemask(PGSZ, BY2PG);
tlbinit();
@@ -252,8 +262,6 @@
ksetenv("service", "terminal", 0);
ksetenv("bootargs", "tcp", 0);
-
- /* make kbdfs attach to /dev/eia0 arcs console */
ksetenv("console", "0", 0);
/* no usb */
@@ -264,7 +272,8 @@
}
/* process input for arcs console */
- kproc("arcs", arcsproc, 0);
+ if(!conf.keyboard)
+ kproc("arcs", arcsproc, 0);
kproc("alarm", alarmkproc, 0);
touser(sp);
--- a/sys/src/9/sgi/screen.c
+++ b/sys/src/9/sgi/screen.c
@@ -446,21 +446,91 @@
Memimage *gscreen;
+static void
+vc2set(uchar r, ushort val)
+{
+ regs->dcbmode = NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX |
+ NPORT_DMODE_W3 | NPORT_DMODE_ECINC | VC2_PROTOCOL;
+ regs->dcbdata0 = r << 24 | val << 8;
+}
+
+static ushort
+vc2get(uchar r)
+{
+ regs->dcbmode = NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX |
+ NPORT_DMODE_W1 | NPORT_DMODE_ECINC | VC2_PROTOCOL;
+ regs->dcbdata0 = r << 24;
+ regs->dcbmode = NPORT_DMODE_AVC2 | VC2_REGADDR_IREG |
+ NPORT_DMODE_W2 | NPORT_DMODE_ECINC | VC2_PROTOCOL;
+ return regs->dcbdata0 >> 16;
+}
+
+static Point curoff;
+
void
cursoron(void)
{
+ Point xy;
+ int s;
+
+ xy = addpt(mousexy(), curoff);
+
+ s = splhi();
+ vc2set(VC2_IREG_CURSX, xy.x);
+ vc2set(VC2_IREG_CURSY, xy.y);
+ vc2set(VC2_IREG_CONTROL, vc2get(VC2_IREG_CONTROL) | VC2_CTRL_ECDISP);
+ splx(s);
}
void
cursoroff(void)
{
+ int s;
+
+ s = splhi();
+ vc2set(VC2_IREG_CONTROL, vc2get(VC2_IREG_CONTROL) & ~VC2_CTRL_ECDISP);
+ splx(s);
}
void
-setcursor(Cursor*)
+setcursor(Cursor *curs)
{
-}
+ static uchar mem[(2*32*32)/8];
+ uchar *set, *clr;
+ int i, s;
+ memset(mem, 0, sizeof(mem));
+
+ /*
+ * convert to two 32x32 bitmaps
+ */
+ set = mem;
+ clr = mem + (32*32)/8;
+ for(i=0;i<32;i++) {
+ *set++ = curs->set[i];
+ *clr++ = curs->clr[i];
+ if(i & 1){
+ set += 2;
+ clr += 2;
+ }
+ }
+ curoff = addpt(Pt(30,30), curs->offset);
+
+ /*
+ * upload two bytes at a time
+ */
+ s = splhi();
+ vc2set(VC2_IREG_RADDR, vc2get(VC2_IREG_CENTRY));
+ regs->dcbmode = NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+ NPORT_DMODE_W2 | VC2_PROTOCOL;
+ for(i = 0; i < sizeof(mem); i += 2){
+ while(regs->stat & NPORT_STAT_BBUSY)
+ ;
+ regs->dcbdata0 = *(ushort*)(&mem[i]) << 16;
+ }
+ splx(s);
+}
+
static void
setmode(void)
{
@@ -486,6 +556,8 @@
regs->drawmode1 = DM1_RGBPLANES |
NPORT_DMODE1_CCLT | NPORT_DMODE1_CCEQ | NPORT_DMODE1_CCGT | NPORT_DMODE1_LOSRC |
NPORT_DMODE1_DD24 | NPORT_DMODE1_RGBMD | NPORT_DMODE1_HD32 | NPORT_DMODE1_RWPCKD;
+
+ setcursor(&arrow);
}
void
@@ -526,13 +598,12 @@
enum {
RGBX32 = CHAN4(CRed, 8, CGreen, 8, CBlue, 8, CIgnore, 8),
};
-
- conf.monitor = 1;
memimageinit();
gscreen = allocmemimage(Rect(0,0,1280,1024), RGBX32);
if(gscreen == nil)
panic("screeninit: gscreen == nil");
memfillcolor(gscreen, 0xFFFFFFFF);
+ mouseaccelerate(3);
}
uchar*
@@ -565,4 +636,36 @@
void
mousectl(Cmdbuf *)
{
+}
+
+/*
+ * sgi mouse protocol
+ * byte 0 - Y0 X0 Y7 X7 F M R L
+ * byte 1 - X7 X6 X5 X4 X3 X2 X1 X0
+ * byte 2 - Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ */
+void
+sgimouseputc(int c)
+{
+ static uchar msg[3];
+ static int nb;
+ int dx, dy, newbuttons;
+ static uchar b[] = { 0, 1, 4, 5, 2, 3, 6, 7 };
+ static ulong lasttick;
+ ulong m;
+
+ /* Resynchronize in stream with timing. */
+ m = MACHP(0)->ticks;
+ if(TK2SEC(m - lasttick) > 2)
+ nb = 0;
+ lasttick = m;
+
+ msg[nb] = c;
+ if(++nb == 3){
+ nb = 0;
+ newbuttons = b[msg[0]&7];
+ dx = (char)msg[1];
+ dy = -(char)msg[2];
+ mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
+ }
}
--- a/sys/src/9/sgi/uartarcs.c
+++ b/sys/src/9/sgi/uartarcs.c
@@ -56,7 +56,6 @@
while(waserror())
;
for(;;){
- //sched();
tsleep(&up->sleep, return0, nil, 50);
c = arcsgetc();
if(c < 0)