1 /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
2 /*                                                                 */
3 /* This library is free software; you can redistribute it and/or   */
4 /* modify it without any restrictions. This library is distributed */
5 /* in the hope that it will be useful, but without any warranty.   */
6 
7 /* Cirrus support Copyright (C) 1993 Harm Hanemaayer */
8 
9 /*
10  * Dec 1994:
11  *
12  * Mode setting rewritten with more SVGA generalization and increased
13  * flexibility. Supports 542x/543x.
14  * Uses interfaces in timing.h and vgaregs.h. Only saves/restores
15  * extended registers that are actually changed for SVGA modes.
16  */
17 
18 
19 #include <stdlib.h>
20 #include <stdio.h>		/* for printf */
21 #include <unistd.h>
22 #include <string.h>		/* for memset */
23 #include "vga.h"
24 #include "libvga.h"
25 #include "driver.h"
26 
27 
28 /* Enable support for > 85 MHz dot clocks on the 5434. */
29 #define SUPPORT_5434_PALETTE_CLOCK_DOUBLING
30 /* Use the special clocking mode for all dot clocks at 256 colors, not */
31 /* just those > 85 MHz, for debugging. */
32 /* #define ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING */
33 
34 
35 /* New style driver interface. */
36 #include "timing.h"
37 #include "vgaregs.h"
38 #include "interface.h"
39 #include "accel.h"
40 #include "vgapci.h"
41 
42 
43 #define CIRRUSREG_GR(i) (VGA_TOTAL_REGS + i - VGA_GRAPHICS_COUNT)
44 #define CIRRUSREG_SR(i) (VGA_TOTAL_REGS + 5 + i - VGA_SEQUENCER_COUNT)
45 #define CIRRUSREG_CR(i) (VGA_TOTAL_REGS + 5 + 27 + i - VGA_CRTC_COUNT)
46 #define CIRRUSREG_DAC (VGA_TOTAL_REGS + 5 + 27 + 15)
47 #define CIRRUS_TOTAL_REGS (VGA_TOTAL_REGS + 5 + 27 + 15 + 1)
48 
49 /* Indices into mode register array. */
50 #define CIRRUS_GRAPHICSOFFSET1	CIRRUSREG_GR(0x09)
51 #define CIRRUS_GRAPHICSOFFSET2	CIRRUSREG_GR(0x0A)
52 #define CIRRUS_GRB		CIRRUSREG_GR(0x0B)
53 #define CIRRUS_SR7		CIRRUSREG_SR(0x07)
54 #define CIRRUS_VCLK3NUMERATOR	CIRRUSREG_SR(0x0E)
55 #define CIRRUS_DRAMCONTROL	CIRRUSREG_SR(0x0F)
56 #define CIRRUS_PERFTUNING	CIRRUSREG_SR(0x16)
57 #define CIRRUS_SR17		CIRRUSREG_SR(0x17)
58 #define CIRRUS_VCLK3DENOMINATOR CIRRUSREG_SR(0x1E)
59 #define CIRRUS_MCLKREGISTER	CIRRUSREG_SR(0x1F)
60 #define CIRRUS_CR19		CIRRUSREG_CR(0x19)
61 #define CIRRUS_CR1A		CIRRUSREG_CR(0x1A)
62 #define CIRRUS_CR1B		CIRRUSREG_CR(0x1B)
63 #define CIRRUS_CR1D 		CIRRUSREG_CR(0x1D)
64 #define CIRRUS_HIDDENDAC	CIRRUSREG_DAC
65 
66 
67 /* Efficient chip type checks. */
68 
69 #define CHECKCHIP1(c1) ((1 << cirrus_chiptype) & (1 << c1))
70 #define CHECKCHIP2(c1, c2) ((1 << cirrus_chiptype) & ((1 << c1) | (1 << c2)))
71 #define CHECKCHIP3(c1, c2, c3) ((1 << cirrus_chiptype) & ((1 << c1) \
72 	| (1 << c2) | (1 << c3)))
73 #define CHECKCHIP4(c1, c2, c3, c4) ((1 << cirrus_chiptype) & ((1 << c1) \
74 	| (1 << c2) | (1 << c3) | (1 << c4)))
75 #define CHECKCHIP5(c1, c2, c3, c4, c5) ((1 << cirrus_chiptype) & \
76 	((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5)))
77 #define CHECKCHIP6(c1, c2, c3, c4, c5, c6) ((1 << cirrus_chiptype) & \
78 	((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
79 	| (1 << c6)))
80 #define CHECKCHIP7(c1, c2, c3, c4, c5, c6, c7) ((1 << cirrus_chiptype) & \
81 	((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
82 	| (1 << c6) | (1 << c7)))
83 #define CHECKCHIP8(c1, c2, c3, c4, c5, c6, c7, c8) ((1 << cirrus_chiptype) & \
84 	((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
85 	| (1 << c6) | (1 << c7) | (1 << c8)))
86 #define CHECKCHIP9(c1, c2, c3, c4, c5, c6, c7, c8, c9) ((1 << cirrus_chiptype) & \
87 	((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
88 	| (1 << c6) | (1 << c7) | (1 << c8) | (1 << c9)))
89 #define CHECKCHIPGREATEREQUAL(c) (cirrus_chiptype >= c)
90 #define CHECKCHIPNOTEQUAL(c) (cirrus_chiptype != c)
91 
92 #define CHIP_HAS_CR1D() \
93 	CHECKCHIP4(CLGD5429, CLGD5430, CLGD5434, CLGD5436)
94 #define CHIP_HAS_GRC_AND_GRD() \
95 	CHECKCHIP4(CLGD5424, CLGD5426, CLGD5428, CLGD5429)
96 #define CHIP_HAS_GRE() \
97 	CHECKCHIP5(CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)
98 #define CHIP_HAS_GR10_AND_GR11() \
99 	CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)
100 #define CHIP_HAS_BLTTRANSPARENTCOLOR() \
101 	CHECKCHIP2(CLGD5426, CLGD5428)
102 #define CHIP_HAS_PERFTUNINGREGISTER() \
103 	CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)
104 #define CHIP_HAS_MCLK_REGISTER() \
105 	CHECKCHIP9(CLGD5420B, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, \
106 		CLGD5429, CLGD5430, CLGD5434, CLGD5436)
107 #define CHIP_HAS_32BIT_DRAM_BUS() \
108 	CHECKCHIPGREATEREQUAL(CLGD5420B)
109 #define CHIP_HAS_64BIT_DRAM_BUS() \
110 	CHECKCHIP3(CLGD5434, CLGD5436, CLGD7548)
111 #define CHIP_HAS_HIDDENDAC() \
112 	CHECKCHIPGREATEREQUAL(CLGD5420B)
113 #define CHIP_HAS_ACCELERATION() \
114 	CHECKCHIPNOTEQUAL(CLGD5420B)
115 #define CHIP_HAS_SR17() \
116 	CHECKCHIPGREATEREQUAL(CLGD5422)
117 #define CHIP_USE_SR17() \
118 	CHECKCHIPGREATEREQUAL(CLGD5429)
119 
120 
121 /* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */
122 #define CLOCK_FACTOR 28636
123 
124 /* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */
125 #define CLOCKVAL(n, d) \
126      ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) >> ((d) & 1))
127 
128 
129 static int cirrus_init(int, int, int);
130 static void cirrus_unlock(void);
131 
132 void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);
133 
134 static int cirrus_memory;
135 static int cirrus_chiptype;
136 static int cirrus_chiprev;
137 static int cirrus_pci_linear = 0;
138 static unsigned char actualMCLK, programmedMCLK;
139 static int DRAMbandwidth, DRAMbandwidthLimit;
140 
141 
142 static CardSpecs *cardspecs;
143 
144 #define NU_FIXED_CLOCKS 21
145 
146 /* 12.588 clock (0x33, 0x3B) replaced with 12.599 (0x2C, 0x33). */
147 
148 static int cirrus_fixed_clocks[NU_FIXED_CLOCKS] =
149 {
150     12599, 18000, 19600,
151     25227, 28325, 31500, 36025, 37747, 39992, 41164,
152     45076, 49867, 64983, 72163, 75000, 80013, 85226, 89998,
153     95019, 100226, 108035
154 };
155 
156 static unsigned char fixed_clock_numerator[NU_FIXED_CLOCKS] =
157 {
158     0x2C, 0x27, 0x28,
159     0x4A, 0x5B, 0x42, 0x4E, 0x3A, 0x51, 0x45,
160     0x55, 0x65, 0x76, 0x7E, 0x6E, 0x5F, 0x7D, 0x58,
161     0x49, 0x46, 0x53
162 };
163 
164 static unsigned char fixed_clock_denominator[NU_FIXED_CLOCKS] =
165 {
166     0x33, 0x3e, 0x3a,
167     0x2B, 0x2F, 0x1F, 0x3E, 0x17, 0x3A, 0x30,
168     0x36, 0x3A, 0x34, 0x32, 0x2A, 0x22, 0x2A, 0x1C,
169     0x16, 0x14, 0x16
170 };
171 
172 /*
173  * It looks like the 5434 palette clock doubling mode doensn't like
174  * clocks like (0x7B, 0x20), whereas (0x53, 0x16) is OK.
175  */
176 
177 enum {
178     CLGD5420 = 0, CLGD7548, CLGD5420B, CLGD5422, CLGD5422C, CLGD5424, CLGD5426,
179     CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436
180 };
181 
182 
__svgalib_cirrus_inlinearmode(void)183 int __svgalib_cirrus_inlinearmode(void)
184 {
185     outb(SEQ_I, 0x07);
186     return (inb(SEQ_D) & 0xf0) != 0;
187 }
188 
189 /* Fill in chipset specific mode information */
190 
cirrus_getmodeinfo(int mode,vga_modeinfo * modeinfo)191 static void cirrus_getmodeinfo(int mode, vga_modeinfo * modeinfo)
192 {
193     if (modeinfo->bytesperpixel > 0)
194 	modeinfo->maxpixels = cirrus_memory * 1024 / modeinfo->bytesperpixel;
195     else
196 	/* 16-color SVGA mode */
197 	/* Value taken from the air. */
198 	modeinfo->maxpixels = cirrus_memory * 2048;
199     modeinfo->maxlogicalwidth = 4088;
200 #if 0
201     if (mode != G320x200x256) {
202 	/* No need to check for 320x200x256, we now have a special */
203 	/* SVGA-derived 320x200x256 mode that fully supports page */
204 	/* flipping etc. */
205 #endif
206 	modeinfo->startaddressrange = cirrus_memory * 1024 - 1;
207 	modeinfo->haveblit = 0;
208 #if 0
209     } else {
210 	modeinfo->startaddressrange = 0xffff;
211 	modeinfo->maxpixels = 65536;
212 	modeinfo->haveblit = 0;
213     }
214 #endif
215 #if 0				/* Who cares. */
216     if (cirrus_interlaced(mode))
217 	modeinfo->flags |= IS_INTERLACED;
218 #endif
219     modeinfo->flags &= ~HAVE_RWPAGE;
220 
221     if (modeinfo->bytesperpixel >= 1) {
222 	modeinfo->flags |= CAPABLE_LINEAR;
223 	if (__svgalib_cirrus_inlinearmode())
224 	    modeinfo->flags |= IS_LINEAR;
225     }
226 }
227 
228 
229 /* Read and save chipset-specific registers */
230 
cirrus_saveregs(unsigned char regs[])231 static int cirrus_saveregs(unsigned char regs[])
232 {
233 /*      int i; */
234 
235 /*      #ifdef DEBUG
236    printf("Saving Cirrus extended registers.\n");
237    #endif
238  */
239     cirrus_unlock();		/* May be locked again by other programs (e.g. X) */
240 
241 #if 0
242     /* Save extended CRTC registers. */
243     for (i = 0; i < 15; i++) {	/* was 4 */
244 	port_out(0x18 + i, __svgalib_CRT_I);
245 	regs[CIRRUSREG_CR(i)] = port_in(__svgalib_CRT_D);
246     }
247 
248     /* Save extended graphics registers */
249     for (i = 0; i < 5; i++) {	/* was 3 */
250 	port_out(0x09 + i, GRA_I);
251 	regs[CIRRUSREG_GR(i)] = port_in(GRA_D);
252     }
253 
254     /* Save extended sequencer registers. */
255     for (i = 0; i < 27; i++) {
256 	port_out(0x05 + i, SEQ_I);
257 	regs[CIRRUSREG_SR(i)] = port_in(SEQ_D);
258     }
259 #endif
260 
261     /* Save extended CRTC registers. */
262     regs[CIRRUSREG_CR(0x19)] = __svgalib_inCR(0x19);
263     regs[CIRRUSREG_CR(0x1A)] = __svgalib_inCR(0x1A);
264     regs[CIRRUSREG_CR(0x1B)] = __svgalib_inCR(0x1B);
265     if (CHIP_HAS_CR1D())
266 	regs[CIRRUSREG_CR(0x1D)] = __svgalib_inCR(0x1D);
267 
268     /* Save extended graphics registers. */
269     regs[CIRRUSREG_GR(0x09)] = __svgalib_inGR(0x09);
270     regs[CIRRUSREG_GR(0x0A)] = __svgalib_inGR(0x0A);
271     regs[CIRRUSREG_GR(0x0B)] = __svgalib_inGR(0x0B);
272 
273     /* Save extended sequencer registers. */
274     regs[CIRRUS_SR7] = __svgalib_inSR(0x07);
275     regs[CIRRUS_VCLK3NUMERATOR] = __svgalib_inSR(0x0E);
276     regs[CIRRUS_DRAMCONTROL] = __svgalib_inSR(0x0F);
277     if (CHIP_HAS_PERFTUNINGREGISTER())
278 	regs[CIRRUS_PERFTUNING] = __svgalib_inSR(0x16);
279     if (CHIP_HAS_SR17())
280 	regs[CIRRUS_SR17] = __svgalib_inSR(0x17);
281     regs[CIRRUS_VCLK3DENOMINATOR] = __svgalib_inSR(0x1E);
282     if (CHIP_HAS_MCLK_REGISTER())
283 	regs[CIRRUS_MCLKREGISTER] = __svgalib_inSR(0x1F);
284 
285     /* Save Hicolor DAC register. */
286     if (CHIP_HAS_HIDDENDAC()) {
287 	outb(0x3c6, 0);
288 	outb(0x3c6, 0xff);
289 	inb(0x3c6);
290 	inb(0x3c6);
291 	inb(0x3c6);
292 	inb(0x3c6);
293 	regs[CIRRUSREG_DAC] = inb(0x3c6);
294     }
295     return CIRRUS_TOTAL_REGS - VGA_TOTAL_REGS;
296 }
297 
writehicolordac(unsigned char c)298 static void writehicolordac(unsigned char c)
299 {
300     outb(0x3c6, 0);
301     outb(0x3c6, 0xff);
302     inb(0x3c6);
303     inb(0x3c6);
304     inb(0x3c6);
305     inb(0x3c6);
306     outb(0x3c6, c);
307     inb(0x3c8);
308 }
309 
310 
311 /* Set chipset-specific registers */
312 
cirrus_setregs(const unsigned char regs[],int mode)313 static void cirrus_setregs(const unsigned char regs[], int mode)
314 {
315 /*      #ifdef DEBUG
316    printf("Setting Cirrus extended registers.\n");
317    #endif
318  */
319     cirrus_unlock();		/* May be locked again by other programs (eg. X) */
320 
321     /* Write extended CRTC registers. */
322     __svgalib_outCR(0x19, regs[CIRRUSREG_CR(0x19)]);
323     __svgalib_outCR(0x1A, regs[CIRRUSREG_CR(0x1A)]);
324     __svgalib_outCR(0x1B, regs[CIRRUSREG_CR(0x1B)]);
325     if (CHIP_HAS_CR1D())
326 	__svgalib_outCR(0x1D, regs[CIRRUSREG_CR(0x1D)]);
327 
328     /* Write extended graphics registers. */
329     __svgalib_outGR(0x09, regs[CIRRUSREG_GR(0x09)]);
330     __svgalib_outGR(0x0A, regs[CIRRUSREG_GR(0x0A)]);
331     __svgalib_outGR(0x0B, regs[CIRRUSREG_GR(0x0B)]);
332 #ifdef SET_ALL
333     if (CHIP_HAS_GRC_AND_GRD()) {
334 	__svgalib_outGR(0x0C, regs[CIRRUSREG_GR(0x0C)]);
335 	__svgalib_outGR(0x0D, regs[CIRRUSREG_GR(0x0D)]);
336     }
337     if (CHIP_HAS_GRE())
338 	__svgalib_outGR(0x0E, regs[CIRRUSREG_GR(0x0E)]);
339     if (CHIP_HAS_GR10_AND_GR11()) {
340 	__svgalib_outGR(0x10, regs[CIRRUSREG_GR(0x10)]);
341 	__svgalib_outGR(0x11, regs[CIRRUSREG_GR(0x11)]);
342     }
343     if (CHIP_HAS_BLT_REGISTERS()) {
344 	int i;
345 
346 	for (i = 0x20; i <= 0x2A; i++)
347 	    __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]);
348 	for (i = 0x2C; i < 0x2E; i++)
349 	    __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]);
350 	if (CHIP_HAS_BLTWRITEMASK())
351 	    __svgalib_outGR(0x2D, regs[CIRRUSREG_GR(0x2D)]);
352 	__svgalib_outGR(0x30, regs[CIRRUSREG_GR(0x30)]);
353 	__svgalib_outGR(0x32, regs[CIRRUSREG_GR(0x32)]);
354 	if (CHIP_HAS_BLTTRANSPARENTCOLOR()) {
355 	    __svgalib_outGR(0x34, regs[CIRRUSREG_GR(0x34)]);
356 	    __svgalib_outGR(0x35, regs[CIRRUSREG_GR(0x35)]);
357 	    __svgalib_outGR(0x38, regs[CIRRUSREG_GR(0x38)]);
358 	    __svgalib_outGR(0x39, regs[CIRRUSREG_GR(0x39)]);
359 	}
360     }
361 #endif
362 
363     /* Write Truecolor DAC register. */
364     if (CHIP_HAS_HIDDENDAC())
365 	writehicolordac(regs[CIRRUS_HIDDENDAC]);
366 
367     /* Write extended sequencer registers. */
368 
369     /* Be careful to put the sequencer clocking mode in a safe state. */
370     __svgalib_outSR(0x07, (regs[CIRRUS_SR7] & ~0x0F) | 0x01);
371 
372     __svgalib_outSR(0x0E, regs[CIRRUS_VCLK3NUMERATOR]);
373     __svgalib_outSR(0x1E, regs[CIRRUS_VCLK3DENOMINATOR]);
374     __svgalib_outSR(0x07, regs[CIRRUS_SR7]);
375     __svgalib_outSR(0x0F, regs[CIRRUS_DRAMCONTROL]);
376     if (CHIP_HAS_PERFTUNINGREGISTER())
377 	__svgalib_outSR(0x16, regs[CIRRUS_PERFTUNING]);
378     if (CHIP_USE_SR17())
379 	__svgalib_outSR(0x17, regs[CIRRUS_SR17]);
380     if (CHIP_HAS_MCLK_REGISTER())
381 	__svgalib_outSR(0x1F, regs[CIRRUS_MCLKREGISTER]);
382 }
383 
384 
385 /* Return nonzero if mode is available */
386 
cirrus_modeavailable(int mode)387 static int cirrus_modeavailable(int mode)
388 {
389     struct info *info;
390     ModeTiming *modetiming;
391     ModeInfo *modeinfo;
392 
393     /* CLGD7548 mode 13 is broken. Remove this if when supported */
394     if (mode == G320x200x256 && cirrus_chiptype == CLGD7548)
395  return 0;
396 
397     if ((mode < G640x480x256 && mode != G320x200x256)
398 	|| mode == G720x348x2)
399 	return __svgalib_vga_driverspecs.modeavailable(mode);
400 
401     info = &__svgalib_infotable[mode];
402     if (cirrus_memory * 1024 < info->ydim * info->xbytes)
403 	return 0;
404 
405     modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
406 
407     modetiming = malloc(sizeof(ModeTiming));
408     if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
409 	free(modetiming);
410 	free(modeinfo);
411 	return 0;
412     }
413     free(modetiming);
414     free(modeinfo);
415 
416     return SVGADRV;
417 }
418 
419 
420 /* Set a mode */
421 
422 /* Local, called by cirrus_setmode(). */
423 
cirrus_initializemode(unsigned char * moderegs,ModeTiming * modetiming,ModeInfo * modeinfo)424 static void cirrus_initializemode(unsigned char *moderegs,
425 			    ModeTiming * modetiming, ModeInfo * modeinfo)
426 {
427 
428     /* Get current values. */
429     cirrus_saveregs(moderegs);
430 
431     /* Set up the standard VGA registers for a generic SVGA. */
432     __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
433 
434     /* Set up the extended register values, including modifications */
435     /* of standard VGA registers. */
436 
437 /* Graphics */
438     moderegs[CIRRUS_GRAPHICSOFFSET1] = 0;	/* Reset banks. */
439     moderegs[CIRRUS_GRAPHICSOFFSET2] = 0;
440     moderegs[CIRRUS_GRB] = 0;	/* 0x01 enables dual banking. */
441     if (cirrus_memory > 1024)
442 	/* Enable 16K granularity. */
443 	moderegs[CIRRUS_GRB] |= 0x20;
444     moderegs[VGA_SR2] = 0xFF;	/* Plane mask */
445 
446 /* CRTC */
447     if (modetiming->VTotal >= 1024 && !(modetiming->flags & INTERLACED))
448 	/*
449 	 * Double the vertical timing. Used for 1280x1024 NI.
450 	 * The CrtcVTimings have already been adjusted
451 	 * by __svgalib_getmodetiming() because of the GREATER_1024_DIVIDE_VERT
452 	 * flag.
453 	 */
454 	moderegs[VGA_CR17] |= 0x04;
455     moderegs[CIRRUS_CR1B] = 0x22;
456     if (cirrus_chiptype >= CLGD5434)
457 	/* Clear display start bit 19. */
458 	SETBITS(moderegs[CIRRUS_CR1D], 0x80, 0);
459     /* CRTC timing overflows. */
460     moderegs[CIRRUS_CR1A] = 0;
461     SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0xC0,
462 		     modetiming->CrtcVSyncStart + 1, 0x300);
463     SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0x30,
464 		     modetiming->CrtcHSyncEnd, (0xC0 << 3));
465     moderegs[CIRRUS_CR19] = 0;	/* Interlaced end. */
466     if (modetiming->flags & INTERLACED) {
467 	moderegs[CIRRUS_CR19] =
468 	    ((modetiming->CrtcHTotal / 8) - 5) / 2;
469 	moderegs[CIRRUS_CR1A] |= 0x01;
470     }
471 /* Scanline offset */
472     if (modeinfo->bytesPerPixel == 4) {
473 	/* At 32bpp the chip does an extra multiplication by two. */
474 	if (cirrus_chiptype >= CLGD5436) {
475 		/* Do these chipsets multiply by 4? */
476 		moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 5;
477 		SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
478 				 modeinfo->lineWidth, 0x2000);
479 	}
480 	else {
481 		moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 4;
482 		SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
483 				 modeinfo->lineWidth, 0x1000);
484 	}
485     } else if (modeinfo->bitsPerPixel == 4)
486 	/* 16 color mode (planar). */
487 	moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 1;
488     else {
489 	moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 3;
490 	SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
491 			 modeinfo->lineWidth, 0x800);
492     }
493 
494 /* Clocking */
495     moderegs[VGA_MISCOUTPUT] |= 0x0C;	/* Use VCLK3. */
496     moderegs[CIRRUS_VCLK3NUMERATOR] =
497 	fixed_clock_numerator[modetiming->selectedClockNo];
498     moderegs[CIRRUS_VCLK3DENOMINATOR] =
499 	fixed_clock_denominator[modetiming->selectedClockNo];
500 
501 /* DAC register and Sequencer Mode */
502     {
503 	unsigned char DAC, SR7;
504 	DAC = 0x00;
505 	SR7 = 0x00;
506 	if (modeinfo->bytesPerPixel > 0)
507 	    SR7 = 0x01;		/* Packed-pixel mode. */
508 	if (modeinfo->bytesPerPixel == 2) {
509 	    int rgbmode;
510 	    rgbmode = 0;	/* 5-5-5 RGB. */
511 	    if (modeinfo->colorBits == 16)
512 		rgbmode = 1;	/* Add one for 5-6-5 RGB. */
513 	    if (cirrus_chiptype >= CLGD5426) {
514 		/* Pixel clock (double edge) mode. */
515 		DAC = 0xD0 + rgbmode;
516 		SR7 = 0x07;
517 	    } else {
518 		/* Single-edge (double VCLK). */
519 		DAC = 0xF0 + rgbmode;
520 		SR7 = 0x03;
521 	    }
522 	}
523 	if (modeinfo->bytesPerPixel >= 3) {
524 	    /* Set 8-8-8 RGB mode. */
525 	    DAC = 0xE5;
526 	    SR7 = 0x05;
527 	    if (modeinfo->bytesPerPixel == 4)
528 		SR7 = 0x09;
529 	}
530 #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
531 	if (modeinfo->bytesPerPixel == 1 && (modetiming->flags & HADJUSTED)) {
532 	    /* Palette clock doubling mode on 5434 8bpp. */
533 	    DAC = 0x4A;
534 	    SR7 = 0x07;
535 	}
536 #endif
537 	moderegs[CIRRUS_HIDDENDAC] = DAC;
538 	moderegs[CIRRUS_SR7] = SR7;
539     }
540 
541 /* DRAM control and CRT FIFO */
542     if (cirrus_chiptype >= CLGD5422)
543 	/* Enable large CRT FIFO. */
544 	moderegs[CIRRUS_DRAMCONTROL] |= 0x20;
545     if (cirrus_memory == 2048 && cirrus_chiptype <= CLGD5429)
546 	/* Enable DRAM Bank Select. */
547 	moderegs[CIRRUS_DRAMCONTROL] |= 0x80;
548     if (cirrus_chiptype >= CLGD5424) {
549 	/* CRT FIFO threshold setting. */
550 	unsigned char threshold;
551 	threshold = 8;
552 /*	if (cirrus_chiptype >= CLGD5434)
553 	    threshold = 1;*/
554 	/* XXX Needs more elaborate setting. */
555 	SETBITS(moderegs[CIRRUS_PERFTUNING], 0x0F, threshold);
556     }
557     if (CHIP_HAS_MCLK_REGISTER())
558 	if (programmedMCLK != actualMCLK
559 	    && modeinfo->bytesPerPixel > 0)
560 	    /* Program higher MCLK for packed-pixel modes. */
561 	    moderegs[CIRRUS_MCLKREGISTER] = programmedMCLK;
562 }
563 
564 
565 /* This is the clock mapping function that is put in the CardSpecs. */
566 
cirrus_map_clock(int bpp,int pixelclock)567 static int cirrus_map_clock(int bpp, int pixelclock)
568 {
569     if (bpp == 24 && cirrus_chiptype < CLGD5436)
570 	/* Most chips need a tripled clock for 24bpp. */
571 	return pixelclock * 3;
572     if (bpp == 16 && cirrus_chiptype <= CLGD5424)
573 	/* The 5422/24 need to use a doubled clock. */
574 	return pixelclock * 2;
575     return pixelclock;
576 }
577 
578 /* This is the horizontal CRTC mapping function in the CardSpecs. */
579 
cirrus_map_horizontal_crtc(int bpp,int pixelclock,int htiming)580 static int cirrus_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
581 {
582 #ifdef ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING
583     if (bpp == 8 && cirrus_chiptype >= CLGD5434)
584 #else
585     if (bpp == 8 && cirrus_chiptype >= CLGD5434 && pixelclock > 86000)
586 #endif
587 	/* 5434 palette clock doubling mode; divide CRTC by 2. */
588 	return htiming / 2;
589     /* Otherwise, don't change. */
590     return htiming;
591 }
592 
593 static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp,
594 					     int width_in_pixels);
595 
cirrus_setmode(int mode,int prv_mode)596 static int cirrus_setmode(int mode, int prv_mode)
597 {
598     unsigned char *moderegs;
599     ModeTiming *modetiming;
600     ModeInfo *modeinfo;
601 
602     if ((mode < G640x480x256 && mode != G320x200x256)
603 	|| mode == G720x348x2) {
604 	__svgalib_clear_accelspecs(__svgalib_driverspecs->accelspecs);
605 	/* Let the standard VGA driver set standard VGA modes */
606 	/* But first reset an Cirrus extended register that */
607 	/* an old XFree86 Trident probe corrupts. */
608 	outw(CRT_IC, 0x4a0b);
609 	return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
610     }
611     if (!cirrus_modeavailable(mode))
612 	return 1;
613 
614     modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
615 
616     modetiming = malloc(sizeof(ModeTiming));
617     if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
618 	free(modetiming);
619 	free(modeinfo);
620 	return 1;
621     }
622     moderegs = malloc(CIRRUS_TOTAL_REGS);
623 
624     cirrus_initializemode(moderegs, modetiming, modeinfo);
625     free(modetiming);
626 
627     __svgalib_setregs(moderegs);	/* Set standard regs. */
628     cirrus_setregs(moderegs, mode);	/* Set extended regs. */
629     free(moderegs);
630 
631     __svgalib_InitializeAcceleratorInterface(modeinfo);
632 
633     init_acceleration_specs_for_mode(__svgalib_driverspecs->accelspecs,
634 				     modeinfo->bitsPerPixel,
635 			  modeinfo->lineWidth / modeinfo->bytesPerPixel);
636 
637     __svgalib_cirrusaccel_init(__svgalib_driverspecs->accelspecs,
638 		     modeinfo->bitsPerPixel,
639 		     modeinfo->lineWidth / modeinfo->bytesPerPixel);
640 
641     free(modeinfo);
642     return 0;
643 }
644 
645 
646 /* Unlock chipset-specific registers */
647 
cirrus_unlock(void)648 static void cirrus_unlock(void)
649 {
650     int vgaIOBase, temp;
651 
652     /* Are we Mono or Color? */
653     vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
654 
655     outb(SEQ_I, 0x06);
656     outb(SEQ_D, 0x12);		/* unlock cirrus special */
657 
658     /* Put the Vert. Retrace End Reg in temp */
659 
660     outb(vgaIOBase + 4, 0x11);
661     temp = inb(vgaIOBase + 5);
662 
663     /* Put it back with PR bit set to 0 */
664     /* This unprotects the 0-7 CRTC regs so */
665     /* they can be modified, i.e. we can set */
666     /* the timing. */
667 
668     outb(vgaIOBase + 5, temp & 0x7F);
669 }
670 
671 
672 /* Relock chipset-specific registers */
673 /* (currently not used) */
674 
cirrus_lock(void)675 static void cirrus_lock(void)
676 {
677     outb(SEQ_I, 0x06);
678     outb(SEQ_D, 0x0F);		/* relock cirrus special */
679 }
680 
681 
682 /* Indentify chipset, initialize and return non-zero if detected */
683 
cirrus_test(void)684 static int cirrus_test(void)
685 {
686     int oldlockreg;
687     int lockreg;
688 
689     outb(SEQ_I, 0x06);
690     oldlockreg = inb(SEQ_D);
691 
692     cirrus_unlock();
693 
694     /* If it's a Cirrus at all, we should be */
695     /* able to read back the lock register */
696 
697     outb(SEQ_I, 0x06);
698     lockreg = inb(SEQ_D);
699 
700     /* Ok, if it's not 0x12, we're not a Cirrus542X. */
701     if (lockreg != 0x12) {
702 	outb(SEQ_I, 0x06);
703 	outb(SEQ_D, oldlockreg);
704 	return 0;
705     }
706     /* The above check seems to be weak, so we also check the chip ID. */
707 
708     outb(__svgalib_CRT_I, 0x27);
709     switch (inb(__svgalib_CRT_D) >> 2) {
710     case 0x22:
711     case 0x23:
712     case 0x24:
713     case 0x25:
714     case 0x26:
715     case 0x27:			/* 5429 */
716     case 0x28:			/* 5430 */
717     case 0x2A:			/* 5434 */
718     case 0x2B:			/* 5436 */
719     case 0x2E:			/* 5446 */
720     case 0x0E:			/* 7548 */
721 	break;
722     default:
723 	outb(SEQ_I, 0x06);
724 	outb(SEQ_D, oldlockreg);
725 	return 0;
726     }
727 
728     if (cirrus_init(0, 0, 0))
729 	return 0;		/* failure */
730     return 1;
731 }
732 
733 
734 /* Bank switching function -- set 64K page number */
735 
cirrus_setpage_2M(int page)736 static void cirrus_setpage_2M(int page)
737 {
738     /* Cirrus banking register has been set to 16K granularity */
739     outw(GRA_I, (page << 10) + 0x09);
740 }
741 
cirrus_setpage(int page)742 static void cirrus_setpage(int page)
743 {
744     /* default 4K granularity */
745     outw(GRA_I, (page << 12) + 0x09);
746 }
747 
748 
749 /* No r/w paging */
cirrus_setrdpage(int page)750 static void cirrus_setrdpage(int page)
751 {
752 }
cirrus_setwrpage(int page)753 static void cirrus_setwrpage(int page)
754 {
755 }
756 
757 
758 /* Set display start address (not for 16 color modes) */
759 /* Cirrus supports any address in video memory (up to 2Mb) */
760 
cirrus_setdisplaystart(int address)761 static void cirrus_setdisplaystart(int address)
762 {
763     outw(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256);	/* sa2-sa9 */
764     outw(CRT_IC, 0x0c + ((address >> 2) & 0xff00));	/* sa10-sa17 */
765     inb(0x3da);			/* set ATC to addressing mode */
766     outb(ATT_IW, 0x13 + 0x20);	/* select ATC reg 0x13 */
767     /* Cirrus specific bits 0,1 and 18,19,20: */
768     outb(ATT_IW, (inb(ATT_R) & 0xf0) | (address & 3));
769     /* write sa0-1 to bits 0-1; other cards use bits 1-2 */
770     outb(CRT_IC, 0x1b);
771     outb(CRT_DC, (inb(CRT_DC) & 0xf2)
772 	 | ((address & 0x40000) >> 18)	/* sa18: write to bit 0 */
773 	 |((address & 0x80000) >> 17)	/* sa19: write to bit 2 */
774 	 |((address & 0x100000) >> 17));	/* sa20: write to bit 3 */
775     outb(CRT_IC, 0x1d);
776     if (cirrus_memory > 2048)
777 	outb(CRT_DC, (inb(CRT_DC) & 0x7f)
778 	     | ((address & 0x200000) >> 14));	/* sa21: write to bit 7 */
779 }
780 
781 
782 /* Set logical scanline length (usually multiple of 8) */
783 /* Cirrus supports multiples of 8, up to 4088 */
784 
cirrus_setlogicalwidth(int width)785 static void cirrus_setlogicalwidth(int width)
786 {
787     outw(CRT_IC, 0x13 + (width >> 3) * 256);	/* lw3-lw11 */
788     outb(CRT_IC, 0x1b);
789     outb(CRT_DC, (inb(CRT_DC) & 0xef) | ((width & 0x800) >> 7));
790     /* write lw12 to bit 4 of Sequencer reg. 0x1b */
791 }
792 
cirrus_setlinear(int addr)793 static void cirrus_setlinear(int addr)
794 {
795     int val;
796     outb(SEQ_I, 0x07);
797     val = inb(SEQ_D);
798     outb(SEQ_D, (val & 0x0f) | (addr << 4));
799 }
800 
cirrus_linear(int op,int param)801 static int cirrus_linear(int op, int param)
802 {
803     if (op == LINEAR_ENABLE) {
804 	cirrus_setlinear(0xE);
805 	return 0;
806     }
807     if (op == LINEAR_DISABLE) {
808 	cirrus_setlinear(0);
809 	return 0;
810     }
811     if (cirrus_chiptype >= CLGD5424 && cirrus_chiptype <= CLGD5429) {
812 	if (op == LINEAR_QUERY_BASE) {
813 	    if (param == 0)
814 		return 0xE00000;	/* 14MB */
815 	    /*
816 	     * Trying 64MB on a system with 16MB of memory is unsafe if the
817 	     * card maps at 14MB. 14 MB was not attempted because of the
818 	     * system memory check in vga_setlinearaddressing(). However,
819 	     * linear addressing is enabled when looking at 64MB, causing a
820 	     * clash between video card and system memory at 14MB.
821 	     */
822 	    if (__svgalib_physmem() <= 13 * 1024 * 1024) {
823 		if (param == 1)
824 		    return 0x4000000;	/* 64MB */
825 		if (param == 2)
826 		    return 0x4E00000;	/* 78MB */
827 		if (param == 3)
828 		    return 0x2000000;	/* 32MB */
829 		if (param == 4)
830 		    return 0x3E00000;	/* 62MB */
831 	    }
832 	    return -1;
833 	}
834     }
835     if (cirrus_chiptype >= CLGD5430) {
836 	if (op == LINEAR_QUERY_BASE) {
837             if(cirrus_pci_linear)return cirrus_pci_linear;
838 	    if (param == 0)
839 		return 0x04000000;	/* 64MB */
840 	    if (param == 1)
841 		return 0x80000000;	/* 2048MB */
842 	    if (param == 2)
843 		return 0x02000000;	/* 32MB */
844 	    if (param == 3)
845 		return 0x08000000;	/* 128MB */
846 	    /* While we're busy, try some common PCI */
847 	    /* motherboard-configured addresses as well. */
848 	    /* We only read, so should be safe. */
849 	    if (param == 4)
850 		return 0xA0000000;
851 	    if (param == 5)
852 		return 0xA8000000;
853 	    if (param == 6)
854 		return 0xE0000000;
855 	    if (param == 7)
856 		return 0XFE000000;
857 	    /*
858 	     * Some PCI/VL motherboards only seem to let the
859 	     * VL slave slot respond at addresses >= 2048MB.
860 	     */
861 	    if (param == 8)
862 		return 0x84000000;
863 	    if (param == 9)
864 		return 0x88000000;
865 	    return -1;
866 	}
867     }
868     if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY)
869 	return 0;		/* No granularity or range. */
870     else
871 	return -1;		/* Unknown function. */
872 }
873 
874 
875 /* Function table (exported) */
876 
877 DriverSpecs __svgalib_cirrus_driverspecs =
878 {
879     cirrus_saveregs,
880     cirrus_setregs,
881     cirrus_unlock,
882     cirrus_lock,
883     cirrus_test,
884     cirrus_init,
885     cirrus_setpage,
886     cirrus_setrdpage,
887     cirrus_setwrpage,
888     cirrus_setmode,
889     cirrus_modeavailable,
890     cirrus_setdisplaystart,
891     cirrus_setlogicalwidth,
892     cirrus_getmodeinfo,
893     0,				/* old blit funcs */
894     0,
895     0,
896     0,
897     0,
898     0,				/* ext_set */
899     0,				/* accel */
900     cirrus_linear,
901     NULL,                       /* Accelspecs */
902     NULL,                       /* Emulation */
903 };
904 
905 
906 /* Initialize chipset (called after detection) */
907 
908 static char *cirrus_chipname[] =
909 {
910     "5420", "7548", "5420-75QC-B", "5422", "5422-80QC-C", "5424", "5426",
911     "5428", "5429", "5430", "5434", "5436"
912 };
913 
914 static unsigned char fixedMCLK[4] =
915 {0x1c, 0x19, 0x17, 0x15};
916 
cirrus_init(int force,int par1,int par2)917 static int cirrus_init(int force, int par1, int par2)
918 {
919     unsigned char v;
920     cirrus_unlock();
921     if (force) {
922 	cirrus_memory = par1;
923 	cirrus_chiptype = par2;
924     } else {
925 	unsigned char partstatus;
926 	outb(__svgalib_CRT_I, 0x27);
927 	cirrus_chiptype = inb(__svgalib_CRT_D) >> 2;
928 	cirrus_chiprev = 0;
929 	partstatus = __svgalib_inCR(0x25);
930 	switch (cirrus_chiptype) {
931 	case 0x22:
932 	    cirrus_chiptype = CLGD5420;
933 #if 0
934 	    /* Check for CL-GD5420-75QC-B. */
935 	    /* It has a Hidden-DAC register. */
936 	    outb(0x3C6, 0x00);
937 	    outb(0x3C6, 0xFF);
938 	    inb(0x3C6);
939 	    inb(0x3c6);
940 	    inb(0x3C6);
941 	    inb(0x3C6);
942 	    if (inb(0x3C6) != 0xFF)
943 		cirrus_chiptype = CLGD5420B;
944 #endif
945 	    break;
946 	case 0x23:
947 	    cirrus_chiptype = CLGD5422;
948 	    break;
949 	case 0x24:
950 	    cirrus_chiptype = CLGD5426;
951 	    break;
952 	case 0x25:
953 	    cirrus_chiptype = CLGD5424;
954 	    /*
955 	     * Some CL-GD5422's ID as CL-GD5424.
956 	     * Check for writability of GRC.
957 	     */
958 	    v = __svgalib_inGR(0x0C);
959 	    __svgalib_outGR(0x0C, 0x55);
960 	    if (__svgalib_inGR(0x0C) != 0x55)
961 		cirrus_chiptype = CLGD5422;
962 	    __svgalib_outGR(0x0C, v);
963 	    break;
964 	case 0x26:
965 	    cirrus_chiptype = CLGD5428;
966 	    break;
967 	case 0x27:
968 	    cirrus_chiptype = CLGD5429;
969 	    break;
970 	case 0x28:
971 	    cirrus_chiptype = CLGD5430;
972 	    break;
973 	case 0x2A:
974 	    cirrus_chiptype = CLGD5434;
975 	    if ((partstatus & 0xC0) == 0xC0)
976 		/* Rev. E, can do 60 MHz MCLK. */
977 		cirrus_chiprev = 1;
978 	    break;
979 	case 0x2B:
980 	    cirrus_chiptype = CLGD5436;
981 	    break;
982 	case 0x2E:
983 	    /* Treat 5446 as 5436. */
984 	    cirrus_chiptype = CLGD5436;
985 	    break;
986 	case 0x0E:
987 	    cirrus_chiptype = CLGD7548;
988 	    break;
989 	default:
990 	    printf("Unknown Cirrus chip %2x.\n",
991 		   cirrus_chiptype);
992 	    return -1;
993 	}
994 
995 #if 0
996 	if (cirrus_chiptype == CLGD5422) {
997 	    /* Rev. C has programmable MCLK register; */
998 	    /* check for it. */
999 	    /* This check is wrong. */
1000 	    if (__svgalib_inSR(0x1F) != 0xFF)
1001 		cirrus_chiptype = CLGD5422C;
1002 	}
1003 #endif
1004 
1005 	/* Now determine the amount of memory. */
1006 	outb(SEQ_I, 0x0a);	/* read memory register */
1007 	/* This depends on the BIOS having set a scratch register. */
1008 	v = inb(SEQ_D);
1009 	cirrus_memory = 256 << ((v >> 3) & 3);
1010 
1011 	/* Determine memory the correct way for the 543x, and
1012 	 * for the 542x if the amount seems incorrect. */
1013 	if (cirrus_chiptype >= CLGD5430 || (cirrus_memory <= 256
1014 				       && cirrus_chiptype != CLGD5420)) {
1015 	    unsigned char SRF;
1016 	    cirrus_memory = 512;
1017 	    outb(SEQ_I, 0x0f);
1018 	    SRF = inb(SEQ_D);
1019 	    if (SRF & 0x10)
1020 		/* 32-bit DRAM bus. */
1021 		cirrus_memory *= 2;
1022 	    if ((SRF & 0x18) == 0x18)
1023 		/* 64-bit DRAM data bus width; assume 2MB. */
1024 		/* Also indicates 2MB memory on the 5430. */
1025 		cirrus_memory *= 2;
1026 	    if (cirrus_chiptype != CLGD5430 && (SRF & 0x80))
1027 		/* If DRAM bank switching is enabled, there */
1028 		/* must be twice as much memory installed. */
1029 		/* (4MB on the 5434) */
1030 		cirrus_memory *= 2;
1031 	}
1032     }
1033     if (__svgalib_driver_report) {
1034 	printf("Using Cirrus Logic GD542x/3x driver (%s, %dK).\n",
1035 	       cirrus_chipname[cirrus_chiptype], cirrus_memory);
1036     }
1037     if (CHIP_HAS_MCLK_REGISTER())
1038 	actualMCLK = __svgalib_inSR(0x1F) & 0x3F;
1039     else {
1040 	actualMCLK = fixedMCLK[__svgalib_inSR(0x0F) & 3];
1041     }
1042     programmedMCLK = actualMCLK;
1043     if (cirrus_chiptype == CLGD5434 && cirrus_chiprev > 0)
1044 	/* 5434 rev. E+ supports 60 MHz in graphics modes. */
1045 	programmedMCLK = 0x22;
1046     DRAMbandwidth = 14318 * (int) programmedMCLK / 16;
1047     if (cirrus_memory >= 512)
1048 	/* At least 16-bit DRAM bus. */
1049 	DRAMbandwidth *= 2;
1050     if (cirrus_memory >= 1024 && CHIP_HAS_32BIT_DRAM_BUS())
1051 	/* At least 32-bit DRAM bus. */
1052 	DRAMbandwidth *= 2;
1053     if (cirrus_memory >= 2048 && CHIP_HAS_64BIT_DRAM_BUS())
1054 	/* 64-bit DRAM bus. */
1055 	DRAMbandwidth *= 2;
1056     /*
1057      * Calculate highest acceptable DRAM bandwidth to be taken up
1058      * by screen refresh. Satisfies
1059      *     total bandwidth >= refresh bandwidth * 1.1
1060      */
1061     DRAMbandwidthLimit = (DRAMbandwidth * 10) / 11;
1062 
1063     if(cirrus_chiptype>=CLGD5430) {
1064        int i;
1065 
1066        i=(__svgalib_inSR(0x17)>>3)&7;
1067        if(i==4) {
1068           unsigned long buf[64];
1069           int found, _ioperm=0;
1070 
1071           if(getenv("IOPERM")==NULL) {
1072              _ioperm=1;
1073              iopl(3);
1074           };
1075           found=__svgalib_pci_find_vendor_vga(0x1013,buf,0);
1076           if(_ioperm)iopl(0);
1077           if(!found)cirrus_pci_linear=buf[4]&0xffff0000;
1078        };
1079     };
1080 /* begin: Initialize card specs. */
1081     cardspecs = malloc(sizeof(CardSpecs));
1082     cardspecs->videoMemory = cirrus_memory;
1083     /*
1084      * First determine clock limits for the chip (DAC), then
1085      * adjust them according to the available DRAM bandwidth.
1086      * For 32-bit DRAM cards the 16bpp clock limit is initially
1087      * set very high, but they are cut down by the DRAM bandwidth
1088      * check.
1089      */
1090     cardspecs->maxPixelClock4bpp = 75000;	/* 5420 */
1091     cardspecs->maxPixelClock8bpp = 45000;	/* 5420 */
1092     cardspecs->maxPixelClock16bpp = 0;	/* 5420 */
1093     cardspecs->maxPixelClock24bpp = 0;
1094     cardspecs->maxPixelClock32bpp = 0;
1095     if (cirrus_chiptype == CLGD5420B) {
1096 	/*
1097 	 * CL-GD5420-75QC-B
1098 	 * Deviating chip, may be used in cheap ISA cards.
1099 	 * 32-bit DRAM bus and Truecolor DAC but cannot do
1100 	 * LUT > 45 MHz, and maybe has less acceleration.
1101 	 */
1102 	cardspecs->maxPixelClock16bpp = 75000 / 2;
1103 	cardspecs->maxPixelClock24bpp = 25175;
1104     }
1105     if (cirrus_chiptype >= CLGD5422) {
1106 	/* 5422/24/26/28 have VCLK spec of 80 MHz. */
1107 	cardspecs->maxPixelClock4bpp = 80000;
1108 	cardspecs->maxPixelClock8bpp = 80000;
1109 	if (cirrus_chiptype >= CLGD5426)
1110 	    /* DRAM bandwidth will be limiting factor. */
1111 	    cardspecs->maxPixelClock16bpp = 80000;
1112 	else
1113 	    /* Clock / 2 16bpp requires 32-bit DRAM bus. */
1114 	if (cirrus_memory >= 1024)
1115 	    cardspecs->maxPixelClock16bpp = 80000 / 2;
1116 	/* Clock / 3 24bpp requires 32-bit DRAM bus. */
1117 	if (cirrus_memory >= 1024)
1118 	    cardspecs->maxPixelClock24bpp = 80000 / 3;
1119     }
1120     if (cirrus_chiptype >= CLGD5429) {
1121 	/* 5429, 5430, 5434 have VCLK spec of 86 MHz. */
1122 	cardspecs->maxPixelClock4bpp = 86000;
1123 	cardspecs->maxPixelClock8bpp = 86000;
1124 	cardspecs->maxPixelClock16bpp = 86000;
1125 	if (cirrus_memory >= 1024)
1126 	    cardspecs->maxPixelClock24bpp = 86000 / 3;
1127     }
1128     if (cirrus_chiptype == CLGD5434) {
1129 #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
1130 	cardspecs->maxPixelClock8bpp = 108300;
1131 	if (cirrus_chiprev > 0)
1132 	    /* 5434 rev E+ */
1133 	    cardspecs->maxPixelClock8bpp = 135300;
1134 #endif
1135 	if (cirrus_memory >= 2048)
1136 	    /* 32bpp requires 64-bit DRAM bus. */
1137 	    cardspecs->maxPixelClock32bpp = 86000;
1138     }
1139     if (cirrus_chiptype >=CLGD5436) {
1140 #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
1141         cardspecs->maxPixelClock8bpp = 135300;
1142 #endif
1143 	if (cirrus_memory >= 2048)
1144 	    /* 32bpp requires 64-bit DRAM bus. */
1145 	    cardspecs->maxPixelClock32bpp = 86000;
1146     }
1147 
1148     cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp,
1149 				       DRAMbandwidthLimit);
1150     cardspecs->maxPixelClock16bpp = min(cardspecs->maxPixelClock16bpp,
1151 					DRAMbandwidthLimit / 2);
1152     cardspecs->maxPixelClock24bpp = min(cardspecs->maxPixelClock24bpp,
1153 					DRAMbandwidthLimit / 3);
1154     cardspecs->maxPixelClock32bpp = min(cardspecs->maxPixelClock32bpp,
1155 					DRAMbandwidthLimit / 4);
1156     cardspecs->flags = INTERLACE_DIVIDE_VERT | GREATER_1024_DIVIDE_VERT;
1157     /* Initialize clocks (only fixed set for now). */
1158     cardspecs->nClocks = NU_FIXED_CLOCKS;
1159     cardspecs->clocks = cirrus_fixed_clocks;
1160     cardspecs->mapClock = cirrus_map_clock;
1161     cardspecs->mapHorizontalCrtc = cirrus_map_horizontal_crtc;
1162     cardspecs->maxHorizontalCrtc = 2040;
1163     /* Disable 16-color SVGA modes (don't work correctly). */
1164     cardspecs->maxPixelClock4bpp = 0;
1165 /* end: Initialize card specs. */
1166 
1167 #if 0
1168 /* begin: Initialize driver options. */
1169     register_option(5434 _VLB_ZERO_WAITSTATE);
1170     register_option(50 MHZ_MCLK);
1171     register_option(55 MHZ_MCLK);
1172     register_option(60 MHZ_MCLK);
1173     register_option(542 X_VLB_NORMAL_WAITSTATES);
1174     register_option(CRT_FIFO_CONSERVATIVE);
1175     register_option(CRT_FIFO_AGGRESSIVE);
1176     register_option(NO_ACCELERATION);
1177     register_option(NO_MMIO);
1178 /* end: Initialize driver options. */
1179 #endif
1180 
1181 /* Initialize accelspecs structure. */
1182     __svgalib_cirrus_driverspecs.accelspecs = malloc(sizeof(AccelSpecs));
1183     __svgalib_clear_accelspecs(__svgalib_cirrus_driverspecs.accelspecs);
1184     __svgalib_cirrus_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH;
1185     /* Set up the correct paging routine */
1186     if (cirrus_memory >= 2048)
1187 	__svgalib_cirrus_driverspecs.__svgalib_setpage =
1188 	    cirrus_setpage_2M;
1189 
1190     __svgalib_driverspecs = &__svgalib_cirrus_driverspecs;
1191 
1192     __svgalib_banked_mem_base=0xa0000;
1193     __svgalib_banked_mem_size=0x10000;
1194     __svgalib_linear_mem_base=cirrus_pci_linear;
1195     __svgalib_linear_mem_size=cirrus_memory*0x400;
1196     __svgalib_mmio_size=32768;
1197     __svgalib_mmio_base=0xb8000;
1198     return 0;
1199 }
1200 
1201 
1202 
1203 /*      Some information on the accelerated features of the 5426,
1204    derived from the Databook.
1205 
1206    port index
1207 
1208    Addresses have 21 bits (2Mb of memory).
1209    GRA_I,       0x28    bits 0-7 of the destination address
1210    GRA_I,  0x29 bits 8-15
1211    GRA_I,       0x2a    bits 16-20
1212 
1213    GRA_I,       0x2c    bits 0-7 of the source address
1214    GRA_I,       0x2d    bits 8-15
1215    GRA_I,       0x2e    bits 16-20
1216 
1217    Maximum pitch is 4095.
1218    GRA_I,       0x24    bits 0-7 of the destination pitch (screen width)
1219    GRA_I,       0x25    bits 8-11
1220 
1221    GRA_I,       0x26    bits 0-7 of the source pitch (screen width)
1222    GRA_I,       0x27    bits 8-11
1223 
1224    Maximum width is 2047.
1225    GRA_I,       0x20    bits 0-7 of the box width - 1
1226    GRA_I,       0x21    bits 8-10
1227 
1228    Maximum height is 1023.
1229    GRA_I,       0x22    bits 0-7 of the box height - 1
1230    GRA_I,       0x23    bits 8-9
1231 
1232    GRA_I,       0x30    BLT mode
1233    bit 0: direction (0 = down, 1 = up)
1234    bit 1: destination
1235    bit 2: source (0 = video memory, 1 = system memory)
1236    bit 3: enable transparency compare
1237    bit 4: 16-bit color expand/transparency
1238    bit 6: 8x8 pattern copy
1239    bit 7: enable color expand
1240 
1241    0x31 BLT status
1242    bit 0: busy
1243    bit 1: start operation (1)/suspend (0)
1244    bit 2: reset
1245    bit 3: set while blit busy/suspended
1246 
1247    0x32 BLT raster operation
1248    0x00 black
1249    0x01 white
1250    0x0d copy source
1251    0xd0 copy inverted source
1252    0x0b invert destination
1253    0x05 logical AND
1254    0x6d logical OR (paint)
1255    0x59 XOR
1256 
1257    0x34 BLT transparent color
1258    0x35 high byte
1259 
1260    GRA_I,  0x00 background color (for color expansion)
1261    GRA_I,  0x01 foreground color
1262    GRA_I,  0x10 high byte of background color for 16-bit pixels
1263    GRA_I,  0x11 high byte of foreground color
1264 
1265    GRA_I,       0x0b    bit 1: enable BY8 addressing
1266    SEQ_I,       0x02    8-bit plane mask for BY8 (corresponds to 8 pixels)
1267    (write mode 1, 4, 5)
1268    SEQ_D,  0x05 bits 0-2: VGA write mode
1269    extended write mode 4: write up to 8 pixels in
1270    foreground color (BY8)
1271    extended write mode 5: write 8 pixels in foreground/
1272    background color (BY8)
1273    This may also work in normal non-BY8 packed-pixel mode.
1274 
1275    When doing blits from system memory to video memory, pixel data
1276    can apparently be written to any video address in 16-bit words, with
1277    the each scanline padded to 4-byte alignment. This is handy because
1278    the chip handles line transitions and alignment automatically (and
1279    can do, for example, masking).
1280 
1281    The pattern copy requires an 8x8 pattern (64 pixels) at the source
1282    address in video memory, and fills a box with specified size and
1283    destination address with the pattern. This is in fact the way to do
1284    solid fills.
1285 
1286    mode                 pattern
1287    Color Expansion              8 bytes (monochrome bitmap)
1288    8-bit pixels         64 bytes
1289    16-bit pixels                128 bytes
1290 
1291  */
1292 
1293 
1294 
1295 /* Cirrus Logic acceleration functions implementation. */
1296 
1297 /* BitBLT modes. */
1298 
1299 #define FORWARDS		0x00
1300 #define BACKWARDS		0x01
1301 #define SYSTEMDEST		0x02
1302 #define SYSTEMSRC		0x04
1303 #define TRANSPARENCYCOMPARE	0x08
1304 #define PIXELWIDTH16		0x10
1305 #define PIXELWIDTH32		0x30	/* 543x only. */
1306 #define PATTERNCOPY		0x40
1307 #define COLOREXPAND		0x80
1308 
1309 /* Macros for normal I/O BitBLT register access. */
1310 
1311 #define SETSRCADDR(addr) \
1312 	outw(GRA_I, (((addr) & 0x000000FF) << 8) | 0x2C); \
1313 	outw(GRA_I, (((addr) & 0x0000FF00)) | 0x2D); \
1314 	outw(GRA_I, (((addr) & 0x003F0000) >> 8) | 0x2E);
1315 
1316 #define SETDESTADDR(addr) \
1317 	outw(GRA_I, (((addr) & 0x000000FF) << 8) | 0x28); \
1318 	outw(GRA_I, (((addr) & 0x0000FF00)) | 0x29); \
1319 	outw(GRA_I, (((addr) & 0x003F0000) >> 8) | 0x2A);
1320 
1321 /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
1322 
1323 #define SETDESTPITCH(pitch) \
1324 	outw(GRA_I, (((pitch) & 0x000000FF) << 8) | 0x24); \
1325 	outw(GRA_I, (((pitch) & 0x00001F00)) | 0x25);
1326 
1327 #define SETSRCPITCH(pitch) \
1328 	outw(GRA_I, (((pitch) & 0x000000FF) << 8) | 0x26); \
1329 	outw(GRA_I, (((pitch) & 0x00001F00)) | 0x27);
1330 
1331 /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
1332 
1333 #define SETWIDTH(width) \
1334 	outw(GRA_I, ((((width) - 1) & 0x000000FF) << 8) | 0x20); \
1335 	outw(GRA_I, ((((width) - 1) & 0x00001F00)) | 0x21);
1336 
1337 /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
1338 /* It appears many 5434's only go up to 1024. */
1339 
1340 #define SETHEIGHT(height) \
1341 	outw(GRA_I, ((((height) - 1) & 0x000000FF) << 8) | 0x22); \
1342 	outw(GRA_I, (((height) - 1) & 0x00000700) | 0x23);
1343 
1344 #define SETBLTMODE(m) \
1345 	outw(GRA_I, ((m) << 8) | 0x30);
1346 
1347 #define SETBLTWRITEMASK(m) \
1348 	outw(GRA_I, ((m) << 8) | 0x2F);
1349 
1350 #define SETTRANSPARENCYCOLOR(c) \
1351 	outw(GRA_I, ((c) << 8) | 0x34);
1352 
1353 #define SETTRANSPARENCYCOLOR16(c) \
1354 	outw(GRA_I, ((c) << 8) | 0x34); \
1355 	outw(GRA_I, (c & 0xFF00) | 0x35);
1356 
1357 #define SETTRANSPARENCYCOLORMASK16(m) \
1358 	outw(GRA_I, ((m) << 8) | 0x38); \
1359 	outw(GRA_I, ((m) & 0xFF00) | 0x39);
1360 
1361 #define SETROP(rop) \
1362 	outw(GRA_I, ((rop) << 8) | 0x32);
1363 
1364 #define SETFOREGROUNDCOLOR(c) \
1365 	outw(GRA_I, 0x01 + ((c) << 8));
1366 
1367 #define SETBACKGROUNDCOLOR(c) \
1368 	outw(GRA_I, 0x00 + ((c) << 8));
1369 
1370 #define SETFOREGROUNDCOLOR16(c) \
1371 	outw(GRA_I, 0x01 + ((c) << 8)); \
1372 	outw(GRA_I, 0x11 + ((c) & 0xFF00));
1373 
1374 #define SETBACKGROUNDCOLOR16(c) \
1375 	outw(GRA_I, 0x00 + ((c) << 8)); \
1376 	outw(GRA_I, 0x10 + ((c) & 0xFF00)); \
1377 
1378 #define SETFOREGROUNDCOLOR32(c) \
1379 	outw(GRA_I, 0x01 + ((c) << 8)); \
1380 	outw(GRA_I, 0x11 + ((c) & 0xFF00)); \
1381 	outw(GRA_I, 0x13 + (((c) & 0xFf0000) >> 8)); \
1382 	outw(GRA_I, 0x15 + (((unsigned int)(c) & 0xFF000000) >> 16));
1383 
1384 #define SETBACKGROUNDCOLOR32(c) \
1385 	outw(GRA_I, 0x00 + ((c) << 8)); \
1386 	outw(GRA_I, 0x10 + ((c) & 0xFF00)); \
1387 	outw(GRA_I, 0x12 + (((c) & 0xFF0000) >> 8)); \
1388 	outw(GRA_I, 0x14 + (((unsigned int)(c) & 0xFF000000) >> 16));
1389 
1390 #define STARTBLT() { \
1391 	unsigned char tmp; \
1392 	outb(GRA_I, 0x31); \
1393 	tmp = inb(GRA_D); \
1394 	outb(GRA_D, tmp | 0x02); \
1395 	}
1396 
1397 #define BLTBUSY(s) { \
1398 	outb(GRA_I, 0x31); \
1399 	s = inb(GRA_D) & 1; \
1400 	}
1401 
1402 #define WAITUNTILFINISHED() \
1403 	for (;;) { \
1404 		int busy; \
1405 		BLTBUSY(busy); \
1406 		if (!busy) \
1407 			break; \
1408 	}
1409 
1410 
1411 /* Macros for memory-mapped I/O BitBLT register access. */
1412 
1413 /* MMIO addresses (offset from 0xb8000). */
1414 
1415 #define MMIOBACKGROUNDCOLOR	0x00
1416 #define MMIOFOREGROUNDCOLOR	0x04
1417 #define MMIOWIDTH		0x08
1418 #define MMIOHEIGHT		0x0A
1419 #define MMIODESTPITCH		0x0C
1420 #define MMIOSRCPITCH		0x0E
1421 #define MMIODESTADDR		0x10
1422 #define MMIOSRCADDR		0x14
1423 #define MMIOBLTWRITEMASK	0x17
1424 #define MMIOBLTMODE		0x18
1425 #define MMIOROP			0x1A
1426 #define MMIOBLTSTATUS		0x40
1427 
1428 #define MMIOSETDESTADDR(addr) \
1429   *(unsigned int *)(MMIO_POINTER + MMIODESTADDR) = addr;
1430 
1431 #define MMIOSETSRCADDR(addr) \
1432   *(unsigned int *)(MMIO_POINTER + MMIOSRCADDR) = addr;
1433 
1434 /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
1435 
1436 #define MMIOSETDESTPITCH(pitch) \
1437   *(unsigned short *)(MMIO_POINTER + MMIODESTPITCH) = pitch;
1438 
1439 #define MMIOSETSRCPITCH(pitch) \
1440   *(unsigned short *)(MMIO_POINTER + MMIOSRCPITCH) = pitch;
1441 
1442 /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
1443 
1444 #define MMIOSETWIDTH(width) \
1445   *(unsigned short *)(MMIO_POINTER + MMIOWIDTH) = (width) - 1;
1446 
1447 /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
1448 
1449 #define MMIOSETHEIGHT(height) \
1450   *(unsigned short *)(MMIO_POINTER + MMIOHEIGHT) = (height) - 1;
1451 
1452 #define MMIOSETBLTMODE(m) \
1453   *(unsigned char *)(MMIO_POINTER + MMIOBLTMODE) = m;
1454 
1455 #define MMIOSETBLTWRITEMASK(m) \
1456   *(unsigned char *)(MMIO_POINTER + MMIOBLTWRITEMASK) = m;
1457 
1458 #define MMIOSETROP(rop) \
1459   *(unsigned char *)(MMIO_POINTER + MMIOROP) = rop;
1460 
1461 #define MMIOSTARTBLT() \
1462   *(unsigned char *)(MMIO_POINTER + MMIOBLTSTATUS) |= 0x02;
1463 
1464 #define MMIOBLTBUSY(s) \
1465   s = *(volatile unsigned char *)(MMIO_POINTER + MMIOBLTSTATUS) & 1;
1466 
1467 #define MMIOSETBACKGROUNDCOLOR(c) \
1468   *(unsigned char *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c;
1469 
1470 #define MMIOSETFOREGROUNDCOLOR(c) \
1471   *(unsigned char *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c;
1472 
1473 #define MMIOSETBACKGROUNDCOLOR16(c) \
1474   *(unsigned short *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c;
1475 
1476 #define MMIOSETFOREGROUNDCOLOR16(c) \
1477   *(unsigned short *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c;
1478 
1479 #define MMIOSETBACKGROUNDCOLOR32(c) \
1480   *(unsigned int *)(MMIO_POINTER + MMIOBACKGROUNDCOLOR) = c;
1481 
1482 #define MMIOSETFOREGROUNDCOLOR32(c) \
1483   *(unsigned int *)(MMIO_POINTER + MMIOFOREGROUNDCOLOR) = c;
1484 
1485 #define MMIOWAITUNTILFINISHED() \
1486 	for (;;) { \
1487 		int busy; \
1488 		MMIOBLTBUSY(busy); \
1489 		if (!busy) \
1490 			break; \
1491 	}
1492 
1493 static int cirrus_pattern_address;	/* Pattern with 1's (8 bytes) */
1494 static int cirrus_bitblt_pixelwidth;
1495 /* Foreground color is not preserved on 5420/2/4/6/8. */
1496 static int cirrus_accel_foreground_color;
1497 
__svgalib_cirrusaccel_init(AccelSpecs * accelspecs,int bpp,int width_in_pixels)1498 void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels)
1499 {
1500     /* [Setup accelerator screen pitch] */
1501     /* [Prepare any required off-screen space] */
1502     if (cirrus_chiptype < CLGD5426)
1503 	/* No BitBLT engine. */
1504 	return;
1505     if (bpp == 8)
1506 	cirrus_bitblt_pixelwidth = 0;
1507     if (bpp == 16)
1508 	cirrus_bitblt_pixelwidth = PIXELWIDTH16;
1509     if (bpp == 32)
1510 	cirrus_bitblt_pixelwidth = PIXELWIDTH32;
1511     SETSRCPITCH(__svgalib_accel_screenpitchinbytes);
1512     SETDESTPITCH(__svgalib_accel_screenpitchinbytes);
1513     SETROP(0x0D);
1514     cirrus_pattern_address = cirrus_memory * 1024 - 8;
1515     (*__svgalib_driverspecs->__svgalib_setpage) (cirrus_pattern_address / 65536);
1516     gr_writel(0xffffffff, cirrus_pattern_address & 0xffff);
1517     gr_writel(0xffffffff, (cirrus_pattern_address & 0xffff) + 4);
1518     (*__svgalib_driverspecs->__svgalib_setpage) (0);
1519     if (cirrus_chiptype >= CLGD5429)
1520 	/* Enable memory-mapped I/O. */
1521 	__svgalib_outSR(0x17, __svgalib_inSR(0x17) | 0x04);
1522 }
1523 
1524 
1525 /*
1526  * Note: The foreground color register must always be reset to 0
1527  * on the 542x to avoid problems in normal framebuffer operation.
1528  * This is not the case on chips that support memory-mapped I/O.
1529  */
1530 
1531 /*
1532  * These are two auxilliary functions to program the foreground
1533  * color depending on the current depth.
1534  */
1535 
set_foreground_color(int fg)1536 static void set_foreground_color(int fg)
1537 {
1538     if (__svgalib_accel_bytesperpixel == 1) {
1539 	SETFOREGROUNDCOLOR(fg);
1540 	return;
1541     }
1542     if (__svgalib_accel_bytesperpixel == 2) {
1543 	SETFOREGROUNDCOLOR16(fg);
1544 	return;
1545     }
1546     SETFOREGROUNDCOLOR32(fg);
1547 }
1548 
mmio_set_foreground_color(int fg)1549 static void mmio_set_foreground_color(int fg)
1550 {
1551     if (__svgalib_accel_bytesperpixel == 1) {
1552 	MMIOSETFOREGROUNDCOLOR(fg);
1553 	return;
1554     }
1555     if (__svgalib_accel_bytesperpixel == 2) {
1556 	MMIOSETFOREGROUNDCOLOR16(fg);
1557 	return;
1558     }
1559     MMIOSETFOREGROUNDCOLOR32(fg);
1560 }
1561 
1562 #define FINISHBACKGROUNDBLITS() \
1563 	if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \
1564 		WAITUNTILFINISHED();
1565 
1566 #define MMIOFINISHBACKGROUNDBLITS() \
1567 	if (__svgalib_accel_mode & BLITS_IN_BACKGROUND) \
1568 		MMIOWAITUNTILFINISHED();
1569 
__svgalib_cirrusaccel_FillBox(int x,int y,int width,int height)1570 void __svgalib_cirrusaccel_FillBox(int x, int y, int width, int height)
1571 {
1572     int destaddr;
1573     destaddr = BLTBYTEADDRESS(x, y);
1574     width *= __svgalib_accel_bytesperpixel;
1575     FINISHBACKGROUNDBLITS();
1576     SETSRCADDR(cirrus_pattern_address);
1577     SETDESTADDR(destaddr);
1578     SETWIDTH(width);
1579     SETHEIGHT(height);
1580     set_foreground_color(cirrus_accel_foreground_color);
1581     SETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
1582     STARTBLT();
1583     WAITUNTILFINISHED();
1584     /* Can't easily run in background because foreground color has */
1585     /* to be restored. */
1586     SETFOREGROUNDCOLOR(0x00);
1587 }
1588 
__svgalib_cirrusaccel_mmio_FillBox(int x,int y,int width,int height)1589 void __svgalib_cirrusaccel_mmio_FillBox(int x, int y, int width, int height)
1590 {
1591     int destaddr;
1592     destaddr = BLTBYTEADDRESS(x, y);
1593     width *= __svgalib_accel_bytesperpixel;
1594     MMIOFINISHBACKGROUNDBLITS();
1595     MMIOSETSRCADDR(cirrus_pattern_address);
1596     MMIOSETDESTADDR(destaddr);
1597     MMIOSETWIDTH(width);
1598     MMIOSETHEIGHT(height);
1599     MMIOSETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
1600     MMIOSTARTBLT();
1601     if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND))
1602 	MMIOWAITUNTILFINISHED();
1603 }
1604 
__svgalib_cirrusaccel_ScreenCopy(int x1,int y1,int x2,int y2,int width,int height)1605 void __svgalib_cirrusaccel_ScreenCopy(int x1, int y1, int x2, int y2, int width,
1606 			    int height)
1607 {
1608     int srcaddr, destaddr, dir;
1609     width *= __svgalib_accel_bytesperpixel;
1610     srcaddr = BLTBYTEADDRESS(x1, y1);
1611     destaddr = BLTBYTEADDRESS(x2, y2);
1612     dir = FORWARDS;
1613     if ((y1 < y2 || (y1 == y2 && x1 < x2))
1614 	&& y1 + height > y2) {
1615 	srcaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1616 	destaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1617 	dir = BACKWARDS;
1618     }
1619     FINISHBACKGROUNDBLITS();
1620     SETSRCADDR(srcaddr);
1621     SETDESTADDR(destaddr);
1622     SETWIDTH(width);
1623     SETHEIGHT(height);
1624     SETBLTMODE(dir);
1625     STARTBLT();
1626     if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND))
1627 	WAITUNTILFINISHED();
1628 }
1629 
__svgalib_cirrusaccel_mmio_ScreenCopy(int x1,int y1,int x2,int y2,int width,int height)1630 void __svgalib_cirrusaccel_mmio_ScreenCopy(int x1, int y1, int x2, int y2, int width,
1631 				 int height)
1632 {
1633     int srcaddr, destaddr, dir;
1634     width *= __svgalib_accel_bytesperpixel;
1635     srcaddr = BLTBYTEADDRESS(x1, y1);
1636     destaddr = BLTBYTEADDRESS(x2, y2);
1637     dir = FORWARDS;
1638     if ((y1 < y2 || (y1 == y2 && x1 < x2))
1639 	&& y1 + height > y2) {
1640 	srcaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1641 	destaddr += (height - 1) * __svgalib_accel_screenpitchinbytes + width - 1;
1642 	dir = BACKWARDS;
1643     }
1644     MMIOFINISHBACKGROUNDBLITS();
1645     MMIOSETSRCADDR(srcaddr);
1646     MMIOSETDESTADDR(destaddr);
1647     MMIOSETWIDTH(width);
1648     MMIOSETHEIGHT(height);
1649     MMIOSETBLTMODE(dir);
1650     MMIOSTARTBLT();
1651     if (!(__svgalib_accel_mode & BLITS_IN_BACKGROUND))
1652 	MMIOWAITUNTILFINISHED();
1653 }
1654 
__svgalib_cirrusaccel_SetFGColor(int fg)1655 void __svgalib_cirrusaccel_SetFGColor(int fg)
1656 {
1657     cirrus_accel_foreground_color = fg;
1658 }
1659 
__svgalib_cirrusaccel_mmio_SetFGColor(int fg)1660 void __svgalib_cirrusaccel_mmio_SetFGColor(int fg)
1661 {
1662     MMIOFINISHBACKGROUNDBLITS();
1663     mmio_set_foreground_color(fg);
1664 }
1665 
1666 static unsigned char cirrus_rop_map[] =
1667 {
1668     0x0D,			/* ROP_COPY */
1669     0x6D,			/* ROP_OR */
1670     0x05,			/* ROP_AND */
1671     0x59,			/* ROP_XOR */
1672     0x0B			/* ROP_INVERT */
1673 };
1674 
__svgalib_cirrusaccel_SetRasterOp(int rop)1675 void __svgalib_cirrusaccel_SetRasterOp(int rop)
1676 {
1677     FINISHBACKGROUNDBLITS();
1678     SETROP(cirrus_rop_map[rop]);
1679 }
1680 
__svgalib_cirrusaccel_mmio_SetRasterOp(int rop)1681 void __svgalib_cirrusaccel_mmio_SetRasterOp(int rop)
1682 {
1683     MMIOFINISHBACKGROUNDBLITS();
1684     MMIOSETROP(cirrus_rop_map[rop]);
1685 }
1686 
__svgalib_cirrusaccel_SetTransparency(int mode,int color)1687 void __svgalib_cirrusaccel_SetTransparency(int mode, int color)
1688 {
1689     FINISHBACKGROUNDBLITS();
1690     if (mode == DISABLE_TRANSPARENCY_COLOR) {
1691 	/* Disable. */
1692 	SETTRANSPARENCYCOLORMASK16(0xFFFF);
1693 	return;
1694     }
1695     if (mode == ENABLE_TRANSPARENCY_COLOR) {
1696 	if (__svgalib_accel_bytesperpixel == 1)
1697 	    color += color << 8;
1698 	SETTRANSPARENCYCOLORMASK16(0x0000);
1699 	SETTRANSPARENCYCOLOR16(color);
1700 	return;
1701     }
1702     if (mode == DISABLE_BITMAP_TRANSPARENCY) {
1703 	__svgalib_accel_bitmaptransparency = 0;
1704 	return;
1705     }
1706     /* mode == ENABLE_BITMAP_TRANSPARENCY */
1707     __svgalib_accel_bitmaptransparency = 1;
1708 }
1709 
__svgalib_cirrusaccel_Sync(void)1710 void __svgalib_cirrusaccel_Sync(void)
1711 {
1712     WAITUNTILFINISHED();
1713 }
1714 
__svgalib_cirrusaccel_mmio_Sync(void)1715 void __svgalib_cirrusaccel_mmio_Sync(void)
1716 {
1717     MMIOWAITUNTILFINISHED();
1718 }
1719 
1720 
1721 /*
1722  * Set up accelerator interface for pixels of size bpp and scanline width
1723  * of width_in_pixels.
1724  */
1725 
init_acceleration_specs_for_mode(AccelSpecs * accelspecs,int bpp,int width_in_pixels)1726 static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp,
1727 					     int width_in_pixels)
1728 {
1729     accelspecs->operations = 0;
1730     accelspecs->ropOperations = 0;
1731     accelspecs->transparencyOperations = 0;
1732     accelspecs->ropModes = 0;
1733     accelspecs->transparencyModes = 0;
1734     accelspecs->flags = ACCELERATE_ANY_LINEWIDTH;
1735 
1736     if (cirrus_chiptype >= CLGD5426) {
1737 	accelspecs->operations |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC;
1738 	if (bpp == 8 || bpp == 16) {
1739 	    /* BitBLT engine available. */
1740 	    accelspecs->operations |=
1741 		ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
1742 		ACCELFLAG_SCREENCOPY |
1743 		ACCELFLAG_SETRASTEROP |
1744 		ACCELFLAG_SETTRANSPARENCY;
1745 	    accelspecs->ropOperations =
1746 		ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
1747 	    accelspecs->transparencyOperations =
1748 		ACCELFLAG_SCREENCOPY;
1749     	    accelspecs->ropModes |= (1<<ROP_COPY) |
1750 		(1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1751 	    accelspecs->transparencyModes |=
1752 	 	(1<<ENABLE_TRANSPARENCY_COLOR) | (1<<ENABLE_BITMAP_TRANSPARENCY);
1753 	}
1754 	if (bpp == 24) {
1755 	    /* Depth-independent BitBLT functions. */
1756 	    accelspecs->operations |=
1757 		ACCELFLAG_SCREENCOPY;
1758 	    accelspecs->ropOperations =
1759 		ACCELFLAG_SCREENCOPY;
1760     	    accelspecs->ropModes |= (1<<ROP_COPY) |
1761 		(1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1762 	}
1763     }
1764     if (cirrus_chiptype >= CLGD5429)
1765 	if (bpp == 8 || bpp == 16) {
1766 	    /* Newer chips don't have true color-compare. */
1767 	    accelspecs->operations &= ~ACCELFLAG_SETTRANSPARENCY;
1768 	    accelspecs->transparencyOperations = 0;
1769     	    accelspecs->ropModes = 0;
1770     	    accelspecs->transparencyModes = 0;
1771 	}
1772     if (cirrus_chiptype >= CLGD5434)
1773 	if (bpp == 32) {
1774 	    /* BitBLT engine available for 32bpp. */
1775 	    accelspecs->operations |=
1776 		ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
1777 		ACCELFLAG_SCREENCOPY |
1778 		ACCELFLAG_SETRASTEROP |
1779 		ACCELFLAG_SETTRANSPARENCY;
1780 	    accelspecs->ropOperations =
1781 		ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
1782     	    accelspecs->ropModes |= (1<<ROP_COPY) |
1783 		(1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1784 	}
1785 #if 0				/* Full potential. */
1786     /* 5420 */
1787     if (bpp == 8)
1788 	/* Color-expand (extended write modes). */
1789 	accelspecs->operations =
1790 	    ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | ACCELFLAG_DRAWHLINE |
1791 	    ACCELFLAG_DRAWHLINELIST;
1792     if (cirrus_chiptype >= CLGD5422)
1793 	if (bpp == 16)
1794 	    /* Also for 16bpp. */
1795 	    accelspecs->operations =
1796 		ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
1797 		ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
1798     if (cirrus_chiptype >= CLGD5426 && cirrus_memory >= 1024) {
1799 	if (bpp == 8 || bpp == 16) {
1800 	    /* BitBLT engine available. */
1801 	    accelspecs->operations |=
1802 		ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
1803 		ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
1804 		ACCELFLAG_SETTRANSPARENCY |
1805 		ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
1806 		ACCELFLAG_SCREENCOPYBITMAP;
1807 	    accelspecs->ropOperations =
1808 		ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY |
1809 		ACCELFLAG_PUTIMAGE;
1810 	    accelspecs->transparencyOperations =
1811 		ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
1812 		ACCELFLAG_PUTBITMAP;
1813     	    accelspecs->ropModes |= (1<<ROP_COPY) |
1814 		(1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1815 	    accelspecs->transparencyModes |=
1816 	 	(1<<ENABLE_TRANSPARENCY_COLOR) | (1<<ENABLE_BITMAP_TRANSPARENCY);
1817 	}
1818 	if (bpp == 24) {
1819 	    /* Depth-independent BitBLT functions. */
1820 	    accelspecs->operations |=
1821 		ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
1822 	    accelspecs->ropOperations =
1823 		ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
1824     	    accelspecs->ropModes |= (1<<ROP_COPY) |
1825 		(1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1826 	    /*
1827 	     * Possible additions: FILLBOX in bands, and
1828 	     * weird PutBitmap with color 0x000000 (trippling
1829 	     * bits with 8bpp operation).
1830 	     */
1831 	}
1832     }
1833     if (cirrus_chiptype >= CLGD5429)
1834 	if (bpp == 8 || bpp == 16) {
1835 	    /* Newer chips don't have true color-compare. */
1836 	    accelspecs->transparencyOperations = ACCELFLAG_BITMAP;
1837 	}
1838     if (cirrus_chiptype >= CLGD5434)
1839 	if (bpp == 32) {
1840 	    /* BitBLT engine available for 32bpp. */
1841 	    accelspecs->operations |=
1842 		ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
1843 		ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
1844 		ACCELFLAG_SETTRANSPARENCY |
1845 		ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
1846 		ACCELFLAG_SCREENCOPYBITMAP |
1847 		ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
1848 	    accelspecs->ropOperations =
1849 		ACCELFLAG_FILLBOX |
1850 		ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
1851 	    accelspecs->transparencyOperations =
1852 		ACCELFLAG_PUTBITMAP;
1853     	    accelspecs->ropModes |= (1<<ROP_COPY) |
1854 		(1<<ROP_OR) | (1<<ROP_AND) | (1<<ROP_XOR) | (1<<ROP_INVERT);
1855 	    accelspecs->transparencyModes |=
1856 	 	(1<<ENABLE_TRANSPARENCY_COLOR) | (1<<ENABLE_BITMAP_TRANSPARENCY);
1857 	}
1858 #endif
1859     /* Set the function pointers; availability is handled by flags. */
1860     accelspecs->FillBox = __svgalib_cirrusaccel_FillBox;
1861     accelspecs->ScreenCopy = __svgalib_cirrusaccel_ScreenCopy;
1862     accelspecs->SetFGColor = __svgalib_cirrusaccel_SetFGColor;
1863     accelspecs->SetTransparency = __svgalib_cirrusaccel_SetTransparency;
1864     accelspecs->SetRasterOp = __svgalib_cirrusaccel_SetRasterOp;
1865     accelspecs->Sync = __svgalib_cirrusaccel_Sync;
1866     if (cirrus_chiptype >= CLGD5429) {
1867 	accelspecs->FillBox = __svgalib_cirrusaccel_mmio_FillBox;
1868 	accelspecs->ScreenCopy = __svgalib_cirrusaccel_mmio_ScreenCopy;
1869 	accelspecs->SetFGColor = __svgalib_cirrusaccel_mmio_SetFGColor;
1870 	/* No mmio-version of SetTransparency. */
1871 	accelspecs->SetRasterOp = __svgalib_cirrusaccel_mmio_SetRasterOp;
1872 	accelspecs->Sync = __svgalib_cirrusaccel_mmio_Sync;
1873     }
1874 }
1875