]> git.lizzy.rs Git - plan9front.git/commitdiff
sgi: keyboard, mouse and cursor for indy
authorcinap_lenrek <cinap_lenrek@felloff.net>
Thu, 2 Apr 2015 16:35:43 +0000 (18:35 +0200)
committercinap_lenrek <cinap_lenrek@felloff.net>
Thu, 2 Apr 2015 16:35:43 +0000 (18:35 +0200)
sys/src/9/sgi/dat.h
sys/src/9/sgi/devkbd.c [new file with mode: 0644]
sys/src/9/sgi/indy
sys/src/9/sgi/io.h
sys/src/9/sgi/main.c
sys/src/9/sgi/screen.c
sys/src/9/sgi/uartarcs.c

index 49cb2f8d95ca2567e64cbddec0b56ee84fb01145..b0e47a6cb7d9f4d168ad8a277cd57acb08fc183f 100644 (file)
@@ -67,6 +67,7 @@ struct Conf
        ulong   pipeqsize;      /* size in bytes of pipe queues */
        int     nuart;          /* number of uart devices */
        int     monitor;
+       int     keyboard;
 };
 
 /*
diff --git a/sys/src/9/sgi/devkbd.c b/sys/src/9/sgi/devkbd.c
new file mode 100644 (file)
index 0000000..01e52d3
--- /dev/null
@@ -0,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,
+};
index 817133b626c6aed9f0955df1d44648584362a809..e361622536f67952bece3e56c2291f6774987224 100644 (file)
@@ -18,6 +18,7 @@ dev
 #      sd
        draw screen
        mouse
+       kbd
        
 link
        etherseeq
index 54331e3c7de2e6daf053b7b896ae2ed39fa4203d..4a86c42771e883bbbc056e06f2c546446b2e6fe2 100644 (file)
@@ -40,10 +40,15 @@ enum {
 
 #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 */
index d58763a2bebea258a45a98f79ab0d9b1997ea43f..086ab4fb24024d844e562b86827f4df44010e43e 100644 (file)
@@ -154,6 +154,13 @@ meminit(void)
        }
 }
 
+static int
+havegfx(void)
+{
+       char *s = getconf("ConsoleOut");
+       return s != nil && strstr(s, "video()") != nil;
+}
+
 void
 main(void)
 {
@@ -173,7 +180,10 @@ main(void)
        timersinit();
        fmtinit();
 
-       screeninit();
+       if(havegfx()){
+               conf.monitor = 1;
+               screeninit();
+       }
 
        ckpagemask(PGSZ, BY2PG);
        tlbinit();
@@ -252,8 +262,6 @@ init0(void)
                        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 @@ init0(void)
        }
 
        /* process input for arcs console */
-       kproc("arcs", arcsproc, 0);
+       if(!conf.keyboard)
+               kproc("arcs", arcsproc, 0);
 
        kproc("alarm", alarmkproc, 0);
        touser(sp);
index f8567869e81ddfdca9fd2ecb5444e7a3371df675..1c059a0f5f5b5f774684ab9f7cb8d931267f6f93 100644 (file)
@@ -446,20 +446,90 @@ Cursor    arrow = {
 
 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 @@ setmode(void)
        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 @@ screeninit(void)
        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*
@@ -566,3 +637,35 @@ 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));
+       }
+}
index 128aa6a32285827fd02c10c26b32534e33cb47fc..461b5e5e7915ef9290c1922950a2253a51af20ac 100644 (file)
@@ -56,7 +56,6 @@ arcsproc(void*)
        while(waserror())
                ;
        for(;;){
-               //sched();
                tsleep(&up->sleep, return0, nil, 50);
                c = arcsgetc();
                if(c < 0)