1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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 = scr->pci;
if(!p) return;
scr->mmio = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
if(!scr->mmio) return;
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,
};
|