summaryrefslogtreecommitdiff
path: root/sys/src/9
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2011-04-15 20:29:46 +0200
committeraiju <devnull@localhost>2011-04-15 20:29:46 +0200
commit68d6b0808bbd57a91abf2a5ac4571e4372a8d3fc (patch)
tree4b0b6214de9c0e70fc26d09264c41557f1f23510 /sys/src/9
parenta95f7282410ebfa4e2a4ff816e8486e7e0f8284a (diff)
added geode driver
Diffstat (limited to 'sys/src/9')
-rw-r--r--sys/src/9/pc/devarch.c20
-rw-r--r--sys/src/9/pc/pc1
-rw-r--r--sys/src/9/pc/vgageode.c126
3 files changed, 147 insertions, 0 deletions
diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c
index bd216c2ad..3228736ee 100644
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -33,6 +33,7 @@ enum {
Qiob,
Qiow,
Qiol,
+ Qmsr,
Qbase,
Qmax = 16,
@@ -55,6 +56,7 @@ static Dirtab archdir[Qmax] = {
"iob", { Qiob, 0 }, 0, 0660,
"iow", { Qiow, 0 }, 0, 0660,
"iol", { Qiol, 0 }, 0, 0660,
+ "msr", { Qmsr, 0}, 0, 0660,
};
Lock archwlock; /* the lock is only for changing archdir */
int narchdir = Qbase;
@@ -356,6 +358,7 @@ archread(Chan *c, void *a, long n, vlong offset)
int port;
ushort *sp;
ulong *lp;
+ vlong *vp;
IOMap *m;
Rdwrfn *fn;
@@ -389,6 +392,14 @@ archread(Chan *c, void *a, long n, vlong offset)
*lp++ = inl(port);
return n;
+ case Qmsr:
+ if(n & 7)
+ error(Ebadarg);
+ vp = a;
+ for(port = offset; port < offset+n; port += 8)
+ rdmsr(port, vp++);
+ return n;
+
case Qioalloc:
break;
@@ -429,6 +440,7 @@ archwrite(Chan *c, void *a, long n, vlong offset)
int port;
ushort *sp;
ulong *lp;
+ vlong *vp;
Rdwrfn *fn;
switch((ulong)c->qid.path){
@@ -458,6 +470,14 @@ archwrite(Chan *c, void *a, long n, vlong offset)
outl(port, *lp++);
return n;
+ case Qmsr:
+ if(n & 7)
+ error(Ebadarg);
+ vp = a;
+ for(port = offset; port < offset+n; port += 8)
+ wrmsr(port, *vp++);
+ return n;
+
default:
if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
return fn(c, a, n, offset);
diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc
index d05e60baa..ba897e94a 100644
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -108,6 +108,7 @@ misc
vgatvp3026 =cur
vgavesa
vgavmware +cur
+ vgageode +cur
ip
tcp
diff --git a/sys/src/9/pc/vgageode.c b/sys/src/9/pc/vgageode.c
new file mode 100644
index 000000000..513f942ec
--- /dev/null
+++ b/sys/src/9/pc/vgageode.c
@@ -0,0 +1,126 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ DC_UNLOCK = 0,
+ DC_UNLOCKVALUE = 0x4758,
+ DC_GENERAL_CFG = 1,
+ CURE = 2,
+ DC_CURS_ST_OFFSET = 6,
+ DC_CURSOR_X = 24,
+ DC_CURSOR_Y = 25,
+ DC_PAL_ADDRESS = 28,
+ DC_PAL_DATA
+};
+
+static void
+geodeenable(VGAscr* scr)
+{
+ Pcidev *p;
+
+ if(scr->mmio) return;
+ p = pcimatch(0, 0x1022, 0x2081);
+ if(!p) return;
+ scr->mmio = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
+ if(!scr->mmio) return;
+ scr->pci = p;
+ addvgaseg("geodegp", p->mem[1].bar&~0x0F, p->mem[1].size);
+ addvgaseg("geodemmio", p->mem[2].bar&~0x0F, p->mem[2].size);
+ addvgaseg("geodevid", p->mem[3].bar&~0x0F, p->mem[3].size);
+ vgalinearpci(scr);
+ if(scr->apsize)
+ addvgaseg("geodescreen", scr->paddr, scr->apsize);
+ scr->storage = 0x800000;
+}
+
+static void
+geodelinear(VGAscr*, int, int)
+{
+}
+
+static void
+geodecurload(VGAscr* scr, Cursor* curs)
+{
+ uvlong *p, and1, xor1, and2, xor2;
+ int i;
+ uchar *c, *s;
+
+ if(!scr->mmio) return;
+ p = (uvlong*)((uchar*)scr->vaddr + scr->storage);
+ c = curs->clr;
+ s = curs->set;
+ for(i=0;i<16;i++) {
+ and1 = 0xFF ^ (*s ^ *c++);
+ xor1 = *s++;
+ and1 &= ~xor1;
+ and2 = 0xFF ^ (*s ^ *c++);
+ xor2 = *s++;
+ and2 &= ~xor2;
+ *p++ = (and1 << 56) | (and2 << 48) | 0xFFFFFFFFFFFFLL;
+ *p++ = (xor1 << 56) | (xor2 << 48);
+ }
+ for(;i<128;i++) {
+ *p++ = -1;
+ *p++ = 0;
+ }
+ scr->offset = curs->offset;
+}
+
+static int
+geodecurmove(VGAscr* scr, Point p) {
+ if(!scr->mmio) return 1;
+ ((ulong*)scr->mmio)[DC_UNLOCK] = DC_UNLOCKVALUE;
+ ((ulong*)scr->mmio)[DC_CURSOR_X] = p.x + scr->offset.x;
+ ((ulong*)scr->mmio)[DC_CURSOR_Y] = p.y + scr->offset.y;
+ return 0;
+}
+
+static void
+geodecurenable(VGAscr* scr)
+{
+ geodeenable(scr);
+ if(!scr->mmio) return;
+ geodecurload(scr, &arrow);
+ geodecurmove(scr, ZP);
+ ((ulong*)scr->mmio)[DC_UNLOCK] = DC_UNLOCKVALUE;
+ ((ulong*)scr->mmio)[DC_CURS_ST_OFFSET] = scr->storage;
+ ((ulong*)scr->mmio)[DC_GENERAL_CFG] |= CURE;
+ /* set cursor colours */
+ ((ulong*)scr->mmio)[DC_PAL_ADDRESS] = 0x100;
+ ((ulong*)scr->mmio)[DC_PAL_DATA] = -1;
+ ((ulong*)scr->mmio)[DC_PAL_DATA] = 0;
+}
+
+static void
+geodecurdisable(VGAscr* scr)
+{
+ if(!scr->mmio) return;
+ ((ulong*)scr->mmio)[DC_UNLOCK] = DC_UNLOCKVALUE;
+ ((ulong*)scr->mmio)[DC_GENERAL_CFG] &= ~CURE;
+}
+
+VGAdev vgageodedev = {
+ "geode",
+ geodeenable,
+ .linear = geodelinear,
+};
+
+
+VGAcur vgageodecur = {
+ "geodehwgc",
+ geodecurenable,
+ geodecurdisable,
+ geodecurload,
+ geodecurmove,
+};