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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#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"
typedef struct Cursor3dfx Cursor3dfx;
struct Cursor3dfx {
int vidProcCfg;
int hwCurPatAddr;
int hwCurLoc;
int hwCurC0;
int hwCurC1;
};
enum {
dramInit0 = 0x18,
dramInit1 = 0x1C,
hwCur = 0x5C,
};
static void
tdfxenable(VGAscr* scr)
{
Pcidev *p;
int i, *mmio;
if(scr->mmio)
return;
p = scr->pci;
if(p == nil || p->vid != 0x121A)
return;
scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
if(scr->mmio == nil)
return;
addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
vgalinearpci(scr);
if(scr->apsize)
addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
/*
* Find a place for the cursor data in display memory.
* If SDRAM then there's 16MB memory else it's SGRAM
* and can count it based on the power-on straps -
* chip size can be 8Mb or 16Mb, and there can be 4 or
* 8 of them.
* Use the last 1KB of the framebuffer.
*/
mmio = (void*)((uchar*)scr->mmio+dramInit0);
if(*(mmio+1) & 0x40000000)
i = 16*1024*1024;
else{
if(*mmio & 0x08000000)
i = 16*1024*1024/8;
else
i = 8*1024*1024/8;
if(*mmio & 0x04000000)
i *= 8;
else
i *= 4;
}
scr->storage = i - 1024;
}
static void
tdfxcurdisable(VGAscr* scr)
{
Cursor3dfx *cursor3dfx;
if(scr->mmio == 0)
return;
cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
cursor3dfx->vidProcCfg &= ~0x08000000;
}
static void
tdfxcurload(VGAscr* scr, Cursor* curs)
{
int y;
uchar *p;
Cursor3dfx *cursor3dfx;
if(scr->mmio == 0)
return;
cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
/*
* Disable the cursor then load the new image in
* the top-left of the 64x64 array.
* The cursor data is stored in memory as 128-bit
* words consisting of plane 0 in the least significant 64-bits
* and plane 1 in the most significant.
* The X11 cursor truth table is:
* p0 p1 colour
* 0 0 transparent
* 0 1 transparent
* 1 0 hwCurC0
* 1 1 hwCurC1
* Unused portions of the image have been initialised to be
* transparent.
*/
cursor3dfx->vidProcCfg &= ~0x08000000;
p = (uchar*)scr->vaddr + scr->storage;
for(y = 0; y < 16; y++){
*p++ = curs->clr[2*y]|curs->set[2*y];
*p++ = curs->clr[2*y+1]|curs->set[2*y+1];
p += 6;
*p++ = curs->set[2*y];
*p++ = curs->set[2*y+1];
p += 6;
}
/*
* Save the cursor hotpoint and enable the cursor.
* The 0,0 cursor point is bottom-right.
*/
scr->offset.x = 63+curs->offset.x;
scr->offset.y = 63+curs->offset.y;
cursor3dfx->vidProcCfg |= 0x08000000;
}
static int
tdfxcurmove(VGAscr* scr, Point p)
{
Cursor3dfx *cursor3dfx;
if(scr->mmio == 0)
return 1;
cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
return 0;
}
static void
tdfxcurenable(VGAscr* scr)
{
Cursor3dfx *cursor3dfx;
tdfxenable(scr);
if(scr->mmio == 0)
return;
cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
/*
* Cursor colours.
*/
cursor3dfx->hwCurC0 = 0xFFFFFFFF;
cursor3dfx->hwCurC1 = 0x00000000;
/*
* Initialise the 64x64 cursor to be transparent (X11 mode).
*/
cursor3dfx->hwCurPatAddr = scr->storage;
memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
/*
* Load, locate and enable the 64x64 cursor in X11 mode.
*/
tdfxcurload(scr, &arrow);
tdfxcurmove(scr, ZP);
cursor3dfx->vidProcCfg |= 0x08000002;
}
VGAdev vga3dfxdev = {
"3dfx",
tdfxenable,
nil,
nil,
nil,
};
VGAcur vga3dfxcur = {
"3dfxhwgc",
tdfxcurenable,
tdfxcurdisable,
tdfxcurload,
tdfxcurmove,
};
|