diff options
author | aiju <devnull@localhost> | 2011-04-15 20:29:46 +0200 |
---|---|---|
committer | aiju <devnull@localhost> | 2011-04-15 20:29:46 +0200 |
commit | 68d6b0808bbd57a91abf2a5ac4571e4372a8d3fc (patch) | |
tree | 4b0b6214de9c0e70fc26d09264c41557f1f23510 /sys/src/9 | |
parent | a95f7282410ebfa4e2a4ff816e8486e7e0f8284a (diff) |
added geode driver
Diffstat (limited to 'sys/src/9')
-rw-r--r-- | sys/src/9/pc/devarch.c | 20 | ||||
-rw-r--r-- | sys/src/9/pc/pc | 1 | ||||
-rw-r--r-- | sys/src/9/pc/vgageode.c | 126 |
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, +}; |