2 |
- |
1 |
#include "u.h"
|
|
|
2 |
#include "../port/lib.h"
|
|
|
3 |
#include "mem.h"
|
|
|
4 |
#include "dat.h"
|
|
|
5 |
#include "fns.h"
|
|
|
6 |
#include "io.h"
|
|
|
7 |
#include "../port/error.h"
|
|
|
8 |
|
|
|
9 |
#define Image IMAGE
|
|
|
10 |
#include <draw.h>
|
|
|
11 |
#include <memdraw.h>
|
|
|
12 |
#include <cursor.h>
|
|
|
13 |
#include "screen.h"
|
|
|
14 |
|
|
|
15 |
enum {
|
|
|
16 |
PCIS3 = 0x5333, /* PCI VID */
|
|
|
17 |
|
|
|
18 |
SAVAGE3D = 0x8A20, /* PCI DID */
|
|
|
19 |
SAVAGE3DMV = 0x8A21,
|
|
|
20 |
SAVAGE4 = 0x8A22,
|
|
|
21 |
PROSAVAGEP = 0x8A25,
|
|
|
22 |
PROSAVAGEK = 0x8A26,
|
|
|
23 |
PROSAVAGE8 = 0x8D04,
|
|
|
24 |
SAVAGEMXMV = 0x8C10,
|
|
|
25 |
SAVAGEMX = 0x8C11,
|
|
|
26 |
SAVAGEIXMV = 0x8C12,
|
|
|
27 |
SAVAGEIX = 0x8C13,
|
|
|
28 |
SUPERSAVAGEIXC16 = 0x8C2E,
|
|
|
29 |
SAVAGE2000 = 0x9102,
|
|
|
30 |
|
|
|
31 |
VIRGE = 0x5631,
|
|
|
32 |
VIRGEGX2 = 0x8A10,
|
|
|
33 |
VIRGEDXGX = 0x8A01,
|
|
|
34 |
VIRGEVX = 0x883D,
|
|
|
35 |
VIRGEMX = 0x8C01,
|
|
|
36 |
VIRGEMXP = 0x8C03,
|
|
|
37 |
|
|
|
38 |
AURORA64VPLUS = 0x8812,
|
|
|
39 |
};
|
|
|
40 |
|
|
|
41 |
/*
|
|
|
42 |
* Savage4 et al. acceleration.
|
|
|
43 |
*
|
|
|
44 |
* This is based only on the Savage4 documentation.
|
|
|
45 |
* It is expected to work on other Savage cards as well,
|
|
|
46 |
* but has not been tried.
|
|
|
47 |
*
|
|
|
48 |
* There are five ways to access the 2D graphics engine registers:
|
|
|
49 |
* - Old MMIO non-packed format
|
|
|
50 |
* - Old MMIO packed format
|
|
|
51 |
* - New MMIO non-packed format
|
|
|
52 |
* - New MMIO packed format
|
|
|
53 |
* - Burst Command Interface (BCI)
|
|
|
54 |
*
|
|
|
55 |
* Of these, the manual hints that the first three are deprecated,
|
|
|
56 |
* and it does not document any of those three well enough to use.
|
|
|
57 |
*
|
|
|
58 |
* I have tried for many hours with no success to understand the BCI
|
|
|
59 |
* interface well enough to use it. It is not well documented, and the
|
|
|
60 |
* XFree86 driver seems to completely contradict what little documentation
|
|
|
61 |
* there is.
|
|
|
62 |
*
|
|
|
63 |
* This leaves the packed new MMIO.
|
|
|
64 |
* The manual contradicts itself here, claming that the registers
|
|
|
65 |
* start at 0x2008100 as well as at 0x0008100 from the base of the
|
|
|
66 |
* mmio segment. Since the segment is only 512k, we assume that
|
|
|
67 |
* the latter is the correct offset.
|
|
|
68 |
*
|
|
|
69 |
* According to the manual, only 16-bit reads of the 2D registers
|
|
|
70 |
* are supported: 32-bit reads will return garbage in the upper word.
|
|
|
71 |
* 32-bit writes must be enabled explicitly.
|
|
|
72 |
*
|
|
|
73 |
* 32-bit reads of the status registers seem just fine.
|
|
|
74 |
*/
|
|
|
75 |
|
|
|
76 |
/* 2D graphics engine registers for Savage4; others appear to be mostly the same */
|
|
|
77 |
enum {
|
|
|
78 |
SubsystemStatus = 0x8504, /* Subsystem Status: read only */
|
|
|
79 |
/* read only: whether we get interrupts on various events */
|
|
|
80 |
VsyncInt = 1<<0, /* vertical sync */
|
|
|
81 |
GeBusyInt = 1<<1, /* 2D graphics engine busy */
|
|
|
82 |
BfifoFullInt = 1<<2, /* BIU FIFO full */
|
|
|
83 |
BfifoEmptyInt = 1<<3, /* BIU FIFO empty */
|
|
|
84 |
CfifoFullInt = 1<<4, /* command FIFO full */
|
|
|
85 |
CfifoEmptyInt = 1<<5, /* command FIFO empty */
|
|
|
86 |
BciInt = 1<<6, /* BCI */
|
|
|
87 |
LpbInt = 1<<7, /* LPB */
|
|
|
88 |
CbHiInt = 1<<16, /* COB upper threshold */
|
|
|
89 |
CbLoInt = 1<<17, /* COB lower threshold */
|
|
|
90 |
|
|
|
91 |
SubsystemCtl = 0x8504, /* Subsystem Control: write only */
|
|
|
92 |
/* clear interrupts for various events */
|
|
|
93 |
VsyncClr = 1<<0,
|
|
|
94 |
GeBusyClr = 1<<1,
|
|
|
95 |
BfifoFullClr = 1<<2,
|
|
|
96 |
BfifoEmptyClr = 1<<3,
|
|
|
97 |
CfifoFullClr = 1<<4,
|
|
|
98 |
CfifoEmptyClr = 1<<5,
|
|
|
99 |
BciClr = 1<<6,
|
|
|
100 |
LpbClr = 1<<7,
|
|
|
101 |
CbHiClr = 1<<16,
|
|
|
102 |
CbLoClr = 1<<17,
|
|
|
103 |
|
|
|
104 |
/* enable interrupts for various events */
|
|
|
105 |
VsyncEna = 1<<8,
|
|
|
106 |
Busy2DEna = 1<<9,
|
|
|
107 |
BfifoFullEna = 1<<10,
|
|
|
108 |
BfifoEmptyEna = 1<<11,
|
|
|
109 |
CfifoFullEna = 1<<12,
|
|
|
110 |
CfifoEmptyEna = 1<<13,
|
|
|
111 |
SubsysBciEna = 1<<14,
|
|
|
112 |
CbHiEna = 1<<24,
|
|
|
113 |
CbLoEna = 1<<25,
|
|
|
114 |
|
|
|
115 |
/* 2D graphics engine software reset */
|
|
|
116 |
GeSoftReset = 1<<15,
|
|
|
117 |
|
|
|
118 |
FifoStatus = 0x8508, /* FIFO status: read only */
|
|
|
119 |
CwbEmpty = 1<<0, /* command write buffer empty */
|
|
|
120 |
CrbEmpty = 1<<1, /* command read buffer empty */
|
|
|
121 |
CobEmpty = 1<<2, /* command overflow buffer empty */
|
|
|
122 |
CfifoEmpty = 1<<3, /* command FIFO empty */
|
|
|
123 |
CwbFull = 1<<8, /* command write buffer full */
|
|
|
124 |
CrbFull = 1<<9, /* command read buffer full */
|
|
|
125 |
CobFull = 1<<10, /* command overflow buffer full */
|
|
|
126 |
CfifoFull = 1<<11, /* command FIFO full */
|
|
|
127 |
|
|
|
128 |
AdvFunCtl = 0x850C, /* Advanced Function Control: read/write */
|
|
|
129 |
GeEna = 1<<0, /* enable 2D/3D engine */
|
|
|
130 |
/*
|
|
|
131 |
* according to the manual, BigPixel should be
|
|
|
132 |
* set when bpp >= 8 (bpp != 4), and then CR50_5-4 are
|
|
|
133 |
* used to figure out bpp example. however, it does bad things
|
|
|
134 |
* to the screen in 8bpp mode.
|
|
|
135 |
*/
|
|
|
136 |
BigPixel = 1<<2, /* 8 or more bpp enhanced mode */
|
|
|
137 |
LaEna = 1<<3, /* linear addressing ena: or'ed with CR58_4 */
|
|
|
138 |
Mclk_2 = 0<<8, /* 2D engine clock divide: MCLK/2 */
|
|
|
139 |
Mclk_4 = 1<<8, /* " MCLK/4 */
|
|
|
140 |
Mclk = 2<<8, /* " MCLK */
|
|
|
141 |
/* Mclk = 3<<8, /* " MCLK */
|
|
|
142 |
Ic33mhz = 1<<16, /* Internal clock 33 MHz (instead of 66) */
|
|
|
143 |
|
|
|
144 |
WakeupReg = 0x8510, /* Wakeup: read/write */
|
|
|
145 |
WakeupBit = 1<<0, /* wake up: or'ed with 3C3_0 */
|
|
|
146 |
|
|
|
147 |
SourceY = 0x8100, /* UL corner of bitblt source */
|
|
|
148 |
SourceX = 0x8102, /* " */
|
|
|
149 |
RectY = 0x8100, /* UL corner of rectangle fill */
|
|
|
150 |
RectX = 0x8102, /* " */
|
|
|
151 |
DestY = 0x8108, /* UL corner of bitblt dest */
|
|
|
152 |
DestX = 0x810A, /* " */
|
|
|
153 |
Height = 0x8148, /* bitblt, image xfer rectangle height */
|
|
|
154 |
Width = 0x814A, /* bitblt, image xfer rectangle width */
|
|
|
155 |
|
|
|
156 |
StartY = 0x8100, /* Line draw: first point*/
|
|
|
157 |
StartX = 0x8102, /* " */
|
|
|
158 |
/*
|
|
|
159 |
* For line draws, the following must be programmed:
|
|
|
160 |
* axial step constant = 2*min(|dx|,|dy|)
|
|
|
161 |
* diagonal step constant = 2*[min(|dx|,|dy|) - max(|dx|,|dy|)]
|
|
|
162 |
* error term = 2*min(|dx|,|dy|) - max(|dx|,|dy| - 1
|
|
|
163 |
* [sic] when start X < end X
|
|
|
164 |
* error term = 2*min(|dx|,|dy|) - max(|dx|,|dy|
|
|
|
165 |
* [sic] when start X >= end X
|
|
|
166 |
*/
|
|
|
167 |
AxialStep = 0x8108,
|
|
|
168 |
DiagonalStep = 0x810A,
|
|
|
169 |
LineError = 0x8110,
|
|
|
170 |
MinorLength = 0x8148, /* pixel count along minor axis */
|
|
|
171 |
MajorLength = 0x814A, /* pixel count along major axis */
|
|
|
172 |
|
|
|
173 |
DrawCmd = 0x8118, /* Drawing Command: write only */
|
|
|
174 |
CmdMagic = 0<<1,
|
|
|
175 |
AcrossPlane = 1<<1, /* across the plane mode */
|
|
|
176 |
LastPixelOff = 1<<2, /* last pixel of line or vector draw not drawn */
|
|
|
177 |
Radial = 1<<3, /* enable radial direction (else axial) */
|
|
|
178 |
DoDraw = 1<<4, /* draw pixels (else only move current pos) */
|
|
|
179 |
|
|
|
180 |
DrawRight = 1<<5, /* axial drawing direction: left to right */
|
|
|
181 |
/* DrawLeft = 0<<5, */
|
|
|
182 |
MajorY = 1<<6,
|
|
|
183 |
/* MajorX = 0<<6, */
|
|
|
184 |
DrawDown = 1<<7,
|
|
|
185 |
/* DrawUp = 0<<7, */
|
|
|
186 |
Degree0 = 0<<5, /* drawing direction when Radial */
|
|
|
187 |
Degree45 = 1<<5,
|
|
|
188 |
/* ... */
|
|
|
189 |
Degree315 = 7<<5,
|
|
|
190 |
|
|
|
191 |
UseCPUData = 1<<8,
|
|
|
192 |
|
|
|
193 |
/* image write bus transfer width */
|
|
|
194 |
Bus8 = 0<<9,
|
|
|
195 |
Bus16 = 1<<9,
|
|
|
196 |
/*
|
|
|
197 |
* in Bus32 mode, doubleword bits beyond the image rect width are
|
|
|
198 |
* discarded. each line starts on a new doubleword.
|
|
|
199 |
* Bus32AP is intended for across-the-plane mode and
|
|
|
200 |
* rounds to byte boundaries instead.
|
|
|
201 |
*/
|
|
|
202 |
Bus32 = 2<<9,
|
|
|
203 |
Bus32AP = 3<<9,
|
|
|
204 |
|
|
|
205 |
CmdNop = 0<<13, /* nop */
|
|
|
206 |
CmdLine = 1<<13, /* draw line */
|
|
|
207 |
CmdFill = 2<<13, /* fill rectangle */
|
|
|
208 |
CmdBitblt = 6<<13, /* bitblt */
|
|
|
209 |
CmdPatblt = 7<<13, /* 8x8 pattern blt */
|
|
|
210 |
|
|
|
211 |
SrcGBD = 0<<16,
|
|
|
212 |
SrcPBD = 1<<16,
|
|
|
213 |
SrcSBD = 2<<16,
|
|
|
214 |
|
|
|
215 |
DstGBD = 0<<18,
|
|
|
216 |
DstPBD = 1<<18,
|
|
|
217 |
DstSBD = 2<<18,
|
|
|
218 |
|
|
|
219 |
/* color sources, controls */
|
|
|
220 |
BgColor = 0x8120, /* Background Color: read/write */
|
|
|
221 |
FgColor = 0x8124, /* Foreground Color: read/write */
|
|
|
222 |
BitplaneWmask = 0x8128, /* Bitplane Write Mask: read/write */
|
|
|
223 |
BitplaneRmask = 0x812C, /* Bitplane Read Mask: read/write */
|
|
|
224 |
CmpColor = 0x8130, /* Color Compare: read/write */
|
|
|
225 |
BgMix = 0x8134,
|
|
|
226 |
FgMix = 0x8136,
|
|
|
227 |
MixNew = 7,
|
|
|
228 |
SrcBg = 0<<5,
|
|
|
229 |
SrcFg = 1<<5,
|
|
|
230 |
SrcCPU = 2<<5,
|
|
|
231 |
SrcDisp = 3<<5,
|
|
|
232 |
|
|
|
233 |
/* clipping rectangle */
|
|
|
234 |
TopScissors = 0x8138, /* Top Scissors: write only */
|
|
|
235 |
LeftScissors = 0x813A, /* Left Scissors: write only */
|
|
|
236 |
BottomScissors = 0x813C, /* Bottom Scissors: write only */
|
|
|
237 |
RightScissors = 0x813E, /* Right Scissors: write only */
|
|
|
238 |
|
|
|
239 |
/*
|
|
|
240 |
* Registers with Magic were indirectly accessed in older modes.
|
|
|
241 |
* It is not clear whether the Magic is necessary.
|
|
|
242 |
* In the older modes, writes to these registers were pipelined,
|
|
|
243 |
* so that you had to issue an engine command and wait for engine
|
|
|
244 |
* idle before reading a write back. It is not clear if this is
|
|
|
245 |
* still the case either.
|
|
|
246 |
*/
|
|
|
247 |
PixCtl = 0x8140, /* Pixel Control: write only */
|
|
|
248 |
PixMagic = 0xA<<12,
|
|
|
249 |
PixMixFg = 0<<6, /* foreground mix register always */
|
|
|
250 |
PixMixCPU = 2<<6, /* CPU data determines mix register */
|
|
|
251 |
PixMixDisp = 3<<6, /* display data determines mix register */
|
|
|
252 |
|
|
|
253 |
MfMisc2Ctl = 0x8142, /* Multifunction Control Misc. 2: write only */
|
|
|
254 |
MfMisc2Magic = 0xD<<12,
|
|
|
255 |
DstShift = 0, /* 3 bits: destination base address in MB */
|
|
|
256 |
SrcShift = 4, /* 3 bits: source base address in MB */
|
|
|
257 |
WaitFifoEmpty = 2<<8, /* wait for write FIFO empty between draws */
|
|
|
258 |
|
|
|
259 |
MfMiscCtl = 0x8144, /* Multifunction Control Misc: write only */
|
|
|
260 |
MfMiscMagic = 0xE<<12,
|
|
|
261 |
UseHighBits = 1<<4, /* select upper 16 bits for 32-bit reg access */
|
|
|
262 |
ClipInvert = 1<<5, /* only touch pixels outside clip rectangle */
|
|
|
263 |
SkipSame = 0<<6, /* ignore pixels with color CmpColor */
|
|
|
264 |
SkipDifferent = 1<<7, /* ignore pixels not color CmpColor */
|
|
|
265 |
CmpEna = 1<<8, /* enable color compare */
|
|
|
266 |
W32Ena = 1<<9, /* enable 32-bit register write */
|
|
|
267 |
ClipDis = 1<<11, /* disable clipping */
|
|
|
268 |
|
|
|
269 |
/*
|
|
|
270 |
* The bitmap descriptor 1 registers contain the starting
|
|
|
271 |
* address of the bitmap (in bytes).
|
|
|
272 |
* The bitmap descriptor 2 registesr contain stride (in pixels)
|
|
|
273 |
* in the lower 16 bits, depth (in bits) in the next 8 bits,
|
|
|
274 |
* and whether block write is disabled.
|
|
|
275 |
*/
|
|
|
276 |
GBD1 = 0x8168, /* Global Bitmap Descriptor 1: read/write */
|
|
|
277 |
GBD2 = 0x816C, /* Global Bitmap Descriptor 2: read/write */
|
|
|
278 |
/* GBD2-only bits */
|
|
|
279 |
BDS64 = 1<<0, /* bitmap descriptor size 64 bits */
|
|
|
280 |
GBDBciEna = 1<<3, /* BCI enable */
|
|
|
281 |
/* generic BD2 bits */
|
|
|
282 |
BlockWriteDis = 1<<28,
|
|
|
283 |
StrideShift = 0,
|
|
|
284 |
DepthShift = 16,
|
|
|
285 |
|
|
|
286 |
PBD1 = 0x8170, /* Primary Bitmap Descriptor: read/write */
|
|
|
287 |
PBD2 = 0x8174,
|
|
|
288 |
SBD1 = 0x8178, /* Secondary Bitmap Descriptor: read/write */
|
|
|
289 |
SBD2 = 0x817C,
|
|
|
290 |
};
|
|
|
291 |
|
|
|
292 |
/* mastered data transfer registers */
|
|
|
293 |
|
|
|
294 |
/* configuration/status registers */
|
|
|
295 |
enum {
|
|
|
296 |
XStatus0 = 0x48C00, /* Status Word 0: read only */
|
|
|
297 |
/* rev. A silicon differs from rev. B; use AltStatus0 */
|
|
|
298 |
CBEMaskA = 0x1FFFF, /* filled command buffer entries */
|
|
|
299 |
CBEShiftA = 0,
|
|
|
300 |
BciIdleA = 1<<17, /* BCI idle */
|
|
|
301 |
Ge3IdleA = 1<<18, /* 3D engine idle */
|
|
|
302 |
Ge2IdleA = 1<<19, /* 2D engine idle */
|
|
|
303 |
McpIdleA = 1<<20, /* motion compensation processor idle */
|
|
|
304 |
MeIdleA = 1<<22, /* master engine idle */
|
|
|
305 |
PfPendA = 1<<23, /* page flip pending */
|
|
|
306 |
|
|
|
307 |
CBEMaskB = 0x1FFFFF,
|
|
|
308 |
CBEShiftB = 0,
|
|
|
309 |
BciIdleB = 1<<25,
|
|
|
310 |
Ge3IdleB = 1<<26,
|
|
|
311 |
Ge2IdleB = 1<<27,
|
|
|
312 |
McpIdleB = 1<<28,
|
|
|
313 |
MeIdleB = 1<<30,
|
|
|
314 |
PfPendB = 1<<31,
|
|
|
315 |
|
|
|
316 |
AltStatus0 = 0x48C60, /* Alternate Status Word 0: read only */
|
|
|
317 |
CBEMask = 0x1FFFF,
|
|
|
318 |
CBEShift = 0,
|
|
|
319 |
/* the Savage4 manual says bits 17..23 for these, like Status0 */
|
|
|
320 |
/* empirically, they are bits 21..26 */
|
|
|
321 |
BciIdle = 1<<21,
|
|
|
322 |
Ge3Idle = 1<<22,
|
|
|
323 |
Ge2Idle = 1<<23,
|
|
|
324 |
McpIdle = 1<<24,
|
|
|
325 |
MeIdle = 1<<25,
|
|
|
326 |
PfPend = 1<<26,
|
|
|
327 |
|
|
|
328 |
XStatus1 = 0x48C04, /* Status Word 1: read only */
|
|
|
329 |
/* contains event tag 1, event tag 0, both 16 bits */
|
|
|
330 |
|
|
|
331 |
XStatus2 = 0x48C08, /* Status Word 2: read only */
|
|
|
332 |
ScanMask = 0x3FF, /* current scan line */
|
|
|
333 |
ScanShift = 0,
|
|
|
334 |
VRTMask = 0x7F100, /* vert retrace count */
|
|
|
335 |
VRTShift = 11,
|
|
|
336 |
|
|
|
337 |
CbThresh = 0x48C10, /* Command Buffer Thresholds: read/write */
|
|
|
338 |
CobOff = 0x48C14, /* Command Overflow Buffer: read/write */
|
|
|
339 |
|
|
|
340 |
CobPtr = 0x48C18, /* Command Overflow Buffer Pointers: read/write */
|
|
|
341 |
CobEna = 1<<2, /* command overflow buffer enable */
|
|
|
342 |
CobBciEna = 1<<3, /* BCI function enable */
|
|
|
343 |
CbeMask = 0xFFFF8000, /* no. of entries in command buffer */
|
|
|
344 |
CbeShift = 15,
|
|
|
345 |
|
|
|
346 |
AltStatus1 = 0x48C64, /* Alternate Status Word 1: read onnly */
|
|
|
347 |
/* contains current texture surface tag, vertex buffer tag */
|
|
|
348 |
|
|
|
349 |
};
|
|
|
350 |
|
|
|
351 |
struct {
|
|
|
352 |
ulong idletimeout;
|
|
|
353 |
ulong tostatw[16];
|
|
|
354 |
} savagestats;
|
|
|
355 |
|
|
|
356 |
enum {
|
|
|
357 |
Maxloop = 1<<20
|
|
|
358 |
};
|
|
|
359 |
|
|
|
360 |
static void
|
|
|
361 |
savagewaitidle(VGAscr *scr)
|
|
|
362 |
{
|
|
|
363 |
long x;
|
|
|
364 |
ulong *statw, mask, goal;
|
|
|
365 |
|
|
|
366 |
switch(scr->id){
|
|
|
367 |
case SAVAGE4:
|
|
|
368 |
case PROSAVAGEP:
|
|
|
369 |
case PROSAVAGEK:
|
|
|
370 |
case PROSAVAGE8:
|
|
|
371 |
/* wait for engine idle and FIFO empty */
|
|
|
372 |
statw = (ulong*)((uchar*)scr->mmio+AltStatus0);
|
|
|
373 |
mask = CBEMask | Ge2Idle;
|
|
|
374 |
goal = Ge2Idle;
|
|
|
375 |
break;
|
|
|
376 |
/* case SAVAGEMXMV: ? */
|
|
|
377 |
/* case SAVAGEMX: ? */
|
|
|
378 |
/* case SAVAGEIX: ? */
|
|
|
379 |
case SUPERSAVAGEIXC16:
|
|
|
380 |
case SAVAGEIXMV:
|
|
|
381 |
case SAVAGEMXMV:
|
|
|
382 |
/* wait for engine idle and FIFO empty */
|
|
|
383 |
statw = (ulong*)((uchar*)scr->mmio+XStatus0);
|
|
|
384 |
mask = CBEMaskA | Ge2IdleA;
|
|
|
385 |
goal = Ge2IdleA;
|
|
|
386 |
break;
|
|
|
387 |
default:
|
|
|
388 |
/*
|
|
|
389 |
* best we can do: can't print or we'll call ourselves.
|
|
|
390 |
* savageinit is supposed to not let this happen.
|
|
|
391 |
*/
|
|
|
392 |
return;
|
|
|
393 |
}
|
|
|
394 |
|
|
|
395 |
for(x=0; x<Maxloop; x++)
|
|
|
396 |
if((*statw & mask) == goal)
|
|
|
397 |
return;
|
|
|
398 |
|
|
|
399 |
savagestats.tostatw[savagestats.idletimeout++&15] = *statw;
|
|
|
400 |
savagestats.tostatw[savagestats.idletimeout++&15] = (ulong)statw;
|
|
|
401 |
}
|
|
|
402 |
|
|
|
403 |
static int
|
|
|
404 |
savagefill(VGAscr *scr, Rectangle r, ulong sval)
|
|
|
405 |
{
|
|
|
406 |
uchar *mmio;
|
|
|
407 |
|
|
|
408 |
mmio = (uchar*)scr->mmio;
|
|
|
409 |
|
|
|
410 |
*(ulong*)(mmio+FgColor) = sval;
|
|
|
411 |
*(ulong*)(mmio+BgColor) = sval;
|
|
|
412 |
*(ulong*)(mmio+BgMix) = SrcFg|MixNew;
|
|
|
413 |
*(ulong*)(mmio+FgMix) = SrcFg|MixNew;
|
|
|
414 |
*(ushort*)(mmio+RectY) = r.min.y;
|
|
|
415 |
*(ushort*)(mmio+RectX) = r.min.x;
|
|
|
416 |
*(ushort*)(mmio+Width) = Dx(r)-1;
|
|
|
417 |
*(ushort*)(mmio+Height) = Dy(r)-1;
|
|
|
418 |
*(ulong*)(mmio+DrawCmd) = CmdMagic | DoDraw | CmdFill | DrawRight | DrawDown;
|
|
|
419 |
savagewaitidle(scr);
|
|
|
420 |
return 1;
|
|
|
421 |
}
|
|
|
422 |
|
|
|
423 |
static int
|
|
|
424 |
savagescroll(VGAscr *scr, Rectangle r, Rectangle sr)
|
|
|
425 |
{
|
|
|
426 |
uchar *mmio;
|
|
|
427 |
ulong cmd;
|
|
|
428 |
Point dp, sp;
|
|
|
429 |
|
|
|
430 |
cmd = CmdMagic | DoDraw | CmdBitblt | SrcPBD | DstGBD;
|
|
|
431 |
|
|
|
432 |
if(r.min.x <= sr.min.x){
|
|
|
433 |
cmd |= DrawRight;
|
|
|
434 |
dp.x = r.min.x;
|
|
|
435 |
sp.x = sr.min.x;
|
|
|
436 |
}else{
|
|
|
437 |
dp.x = r.max.x-1;
|
|
|
438 |
sp.x = sr.max.x-1;
|
|
|
439 |
}
|
|
|
440 |
|
|
|
441 |
if(r.min.y <= sr.min.y){
|
|
|
442 |
cmd |= DrawDown;
|
|
|
443 |
dp.y = r.min.y;
|
|
|
444 |
sp.y = sr.min.y;
|
|
|
445 |
}else{
|
|
|
446 |
dp.y = r.max.y-1;
|
|
|
447 |
sp.y = sr.max.y-1;
|
|
|
448 |
}
|
|
|
449 |
|
|
|
450 |
mmio = (uchar*)scr->mmio;
|
|
|
451 |
|
|
|
452 |
*(ushort*)(mmio+SourceX) = sp.x;
|
|
|
453 |
*(ushort*)(mmio+SourceY) = sp.y;
|
|
|
454 |
*(ushort*)(mmio+DestX) = dp.x;
|
|
|
455 |
*(ushort*)(mmio+DestY) = dp.y;
|
|
|
456 |
*(ushort*)(mmio+Width) = Dx(r)-1;
|
|
|
457 |
*(ushort*)(mmio+Height) = Dy(r)-1;
|
|
|
458 |
*(ulong*)(mmio+BgMix) = SrcDisp|MixNew;
|
|
|
459 |
*(ulong*)(mmio+FgMix) = SrcDisp|MixNew;
|
|
|
460 |
*(ulong*)(mmio+DrawCmd) = cmd;
|
|
|
461 |
savagewaitidle(scr);
|
|
|
462 |
return 1;
|
|
|
463 |
}
|
|
|
464 |
|
|
|
465 |
static void
|
|
|
466 |
savageblank(VGAscr*, int blank)
|
|
|
467 |
{
|
|
|
468 |
uchar seqD;
|
|
|
469 |
|
|
|
470 |
/*
|
|
|
471 |
* Will handle DPMS to monitor
|
|
|
472 |
*/
|
|
|
473 |
vgaxo(Seqx, 8, vgaxi(Seqx,8)|0x06);
|
|
|
474 |
seqD = vgaxi(Seqx, 0xD);
|
|
|
475 |
seqD &= 0x03;
|
|
|
476 |
if(blank)
|
|
|
477 |
seqD |= 0x50;
|
|
|
478 |
vgaxo(Seqx, 0xD, seqD);
|
|
|
479 |
|
|
|
480 |
/*
|
|
|
481 |
* Will handle LCD
|
|
|
482 |
*/
|
|
|
483 |
if(blank)
|
|
|
484 |
vgaxo(Seqx, 0x31, vgaxi(Seqx, 0x31) & ~0x10);
|
|
|
485 |
else
|
|
|
486 |
vgaxo(Seqx, 0x31, vgaxi(Seqx, 0x31) | 0x10);
|
|
|
487 |
}
|
|
|
488 |
|
|
|
489 |
|
|
|
490 |
void
|
|
|
491 |
savageinit(VGAscr *scr)
|
|
|
492 |
{
|
|
|
493 |
uchar *mmio;
|
|
|
494 |
ulong bd;
|
|
|
495 |
|
|
|
496 |
/* if you add chip IDs here be sure to update savagewaitidle */
|
|
|
497 |
switch(scr->id){
|
|
|
498 |
case SAVAGE4:
|
|
|
499 |
case PROSAVAGEP:
|
|
|
500 |
case PROSAVAGEK:
|
|
|
501 |
case PROSAVAGE8:
|
|
|
502 |
case SAVAGEIXMV:
|
|
|
503 |
case SUPERSAVAGEIXC16:
|
|
|
504 |
case SAVAGEMXMV:
|
|
|
505 |
break;
|
|
|
506 |
default:
|
|
|
507 |
print("unknown savage %.4lux\n", scr->id);
|
|
|
508 |
return;
|
|
|
509 |
}
|
|
|
510 |
|
|
|
511 |
mmio = (uchar*)scr->mmio;
|
|
|
512 |
if(mmio == nil) {
|
|
|
513 |
print("savageinit: no mmio\n");
|
|
|
514 |
return;
|
|
|
515 |
}
|
|
|
516 |
|
|
|
517 |
/* 2D graphics engine software reset */
|
|
|
518 |
*(ushort*)(mmio+SubsystemCtl) = GeSoftReset;
|
|
|
519 |
delay(2);
|
|
|
520 |
*(ushort*)(mmio+SubsystemCtl) = 0;
|
|
|
521 |
savagewaitidle(scr);
|
|
|
522 |
|
|
|
523 |
/* disable BCI as much as possible */
|
|
|
524 |
*(ushort*)(mmio+CobPtr) &= ~CobBciEna;
|
|
|
525 |
*(ushort*)(mmio+GBD2) &= ~GBDBciEna;
|
|
|
526 |
savagewaitidle(scr);
|
|
|
527 |
|
|
|
528 |
/* enable 32-bit writes, disable clipping */
|
|
|
529 |
*(ushort*)(mmio+MfMiscCtl) = MfMiscMagic|W32Ena|ClipDis;
|
|
|
530 |
savagewaitidle(scr);
|
|
|
531 |
|
|
|
532 |
/* enable all read, write planes */
|
|
|
533 |
*(ulong*)(mmio+BitplaneRmask) = ~0;
|
|
|
534 |
*(ulong*)(mmio+BitplaneWmask) = ~0;
|
|
|
535 |
savagewaitidle(scr);
|
|
|
536 |
|
|
|
537 |
/* turn on linear access, 2D engine */
|
|
|
538 |
*(ulong*)(mmio+AdvFunCtl) |= GeEna|LaEna;
|
|
|
539 |
savagewaitidle(scr);
|
|
|
540 |
|
|
|
541 |
/* set bitmap descriptors */
|
|
|
542 |
bd = (scr->gscreen->depth<<DepthShift) |
|
|
|
543 |
(Dx(scr->gscreen->r)<<StrideShift) | BlockWriteDis
|
|
|
544 |
| BDS64;
|
|
|
545 |
|
|
|
546 |
*(ulong*)(mmio+GBD1) = 0;
|
|
|
547 |
*(ulong*)(mmio+GBD2) = bd;
|
|
|
548 |
|
|
|
549 |
*(ulong*)(mmio+PBD1) = 0;
|
|
|
550 |
*(ulong*)(mmio+PBD2) = bd;
|
|
|
551 |
|
|
|
552 |
*(ulong*)(mmio+SBD1) = 0;
|
|
|
553 |
*(ulong*)(mmio+SBD2) = bd;
|
|
|
554 |
|
|
|
555 |
/*
|
|
|
556 |
* For some reason, the GBD needs to get programmed twice,
|
|
|
557 |
* once before the PBD, SBD, and once after.
|
|
|
558 |
* This empirically makes it get set right.
|
|
|
559 |
* I would like to better understand the ugliness
|
|
|
560 |
* going on here.
|
|
|
561 |
*/
|
|
|
562 |
*(ulong*)(mmio+GBD1) = 0;
|
|
|
563 |
*(ulong*)(mmio+GBD2) = bd;
|
|
|
564 |
*(ushort*)(mmio+GBD2+2) = bd>>16;
|
|
|
565 |
savagewaitidle(scr);
|
|
|
566 |
|
|
|
567 |
scr->fill = savagefill;
|
|
|
568 |
scr->scroll = savagescroll;
|
|
|
569 |
scr->blank = savageblank;
|
|
|
570 |
hwblank = 0;
|
|
|
571 |
}
|