2 |
- |
1 |
/* Copyright (C) 1992, 1996, 1997 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gdevs3ga.c,v 1.5 2002/06/16 05:48:55 lpd Exp $ */
|
|
|
18 |
/* S3 86C911 driver */
|
|
|
19 |
#include "gx.h"
|
|
|
20 |
#include "gserrors.h"
|
|
|
21 |
#include "gxdevice.h"
|
|
|
22 |
#include "gdevpcfb.h"
|
|
|
23 |
#include "gdevsvga.h"
|
|
|
24 |
|
|
|
25 |
/* Shared routines from gdevsvga.c */
|
|
|
26 |
extern int vesa_get_mode(void);
|
|
|
27 |
extern void vesa_set_mode(int);
|
|
|
28 |
|
|
|
29 |
/* Macro for casting gx_device argument */
|
|
|
30 |
#define fb_dev ((gx_device_svga *)dev)
|
|
|
31 |
|
|
|
32 |
/* ------ The S3 86C911 device ------ */
|
|
|
33 |
|
|
|
34 |
private dev_proc_open_device(s3_open);
|
|
|
35 |
private dev_proc_fill_rectangle(s3_fill_rectangle);
|
|
|
36 |
private dev_proc_copy_mono(s3_copy_mono);
|
|
|
37 |
private const gx_device_procs s3_procs =
|
|
|
38 |
{
|
|
|
39 |
s3_open,
|
|
|
40 |
NULL, /* get_initial_matrix */
|
|
|
41 |
NULL, /* sync_output */
|
|
|
42 |
NULL, /* output_page */
|
|
|
43 |
svga_close,
|
|
|
44 |
svga_map_rgb_color,
|
|
|
45 |
svga_map_color_rgb,
|
|
|
46 |
s3_fill_rectangle,
|
|
|
47 |
NULL, /* tile_rectangle */
|
|
|
48 |
s3_copy_mono,
|
|
|
49 |
svga_copy_color,
|
|
|
50 |
/****** DOESN'T WORK ******/
|
|
|
51 |
NULL, /* draw_line */
|
|
|
52 |
svga_get_bits
|
|
|
53 |
/****** DOESN'T WORK ******/
|
|
|
54 |
};
|
|
|
55 |
gx_device_svga far_data gs_s3vga_device =
|
|
|
56 |
svga_device(s3_procs, "s3vga", vesa_get_mode, vesa_set_mode, NULL);
|
|
|
57 |
|
|
|
58 |
/* Keep track of the character bitmap cache in off-screen memory. */
|
|
|
59 |
#define log2_cell_width 5
|
|
|
60 |
#define cell_width (1 << log2_cell_width)
|
|
|
61 |
#define cache_x_bits (log2_cache_width_bits - log2_cell_width)
|
|
|
62 |
#define log2_cell_height 5
|
|
|
63 |
#define cell_height (1 << log2_cell_height)
|
|
|
64 |
#define cache_y_bits (log2_cache_height - log2_cell_height)
|
|
|
65 |
#define log2_cache_width_bits 10
|
|
|
66 |
#define log2_cache_width_bytes (log2_cache_width_bits - 3)
|
|
|
67 |
#define log2_cache_height 8
|
|
|
68 |
#define log2_cache_capacity (cache_x_bits + cache_y_bits)
|
|
|
69 |
#define cache_capacity (1 << log2_cache_capacity)
|
|
|
70 |
private gx_bitmap_id cache_ids[cache_capacity];
|
|
|
71 |
|
|
|
72 |
/* Define additional registers and I/O addresses. */
|
|
|
73 |
#define crtc_addr 0x3d4 /* (color) */
|
|
|
74 |
#define crt_lock 0x35
|
|
|
75 |
#define crt_s3_lock1 0x38
|
|
|
76 |
#define crt_s3_lock2 0x39
|
|
|
77 |
#define s3_y_pos 0x82e8
|
|
|
78 |
#define s3_x_pos 0x86e8
|
|
|
79 |
#define s3_y_dest 0x8ae8
|
|
|
80 |
#define s3_x_dest 0x8ee8
|
|
|
81 |
#define s3_width 0x96e8
|
|
|
82 |
#define s3_status 0x9ae8 /* read only */
|
|
|
83 |
#define s3_command 0x9ae8 /* write only */
|
|
|
84 |
#define s3_back_color 0xa2e8
|
|
|
85 |
#define s3_fore_color 0xa6e8
|
|
|
86 |
#define s3_write_mask 0xaae8
|
|
|
87 |
#define s3_read_mask 0xaee8
|
|
|
88 |
#define s3_back_mix 0xb6e8
|
|
|
89 |
#define s3_fore_mix 0xbae8
|
|
|
90 |
#define s3_height 0xbee8
|
|
|
91 |
#define s3_mf_control 0xbee8
|
|
|
92 |
# define mf_data_ones 0xa000
|
|
|
93 |
# define mf_data_cpu 0xa080
|
|
|
94 |
# define mf_data_display 0xa0c0
|
|
|
95 |
#define s3_pixel_data 0xe2e8
|
|
|
96 |
/* Wait for the command FIFO to empty. */
|
|
|
97 |
#define s3_wait_fifo()\
|
|
|
98 |
while ( inport(s3_status) & 0xff )
|
|
|
99 |
/* Load the parameters for a rectangle operation. */
|
|
|
100 |
#define out_s3_rect(x, y, w, h)\
|
|
|
101 |
(outport(s3_x_pos, x), outport(s3_y_pos, y),\
|
|
|
102 |
outport(s3_width, (w) - 1), outport(s3_height, (h) - 1))
|
|
|
103 |
|
|
|
104 |
private int
|
|
|
105 |
s3_open(gx_device * dev)
|
|
|
106 |
{
|
|
|
107 |
static const mode_info mode_table[] =
|
|
|
108 |
{
|
|
|
109 |
{640, 480, 0x201},
|
|
|
110 |
{800, 600, 0x203},
|
|
|
111 |
{1024, 768, 0x205},
|
|
|
112 |
{-1, -1, -1}
|
|
|
113 |
};
|
|
|
114 |
int code = svga_find_mode(dev, mode_table);
|
|
|
115 |
|
|
|
116 |
if (code < 0)
|
|
|
117 |
return_error(gs_error_rangecheck);
|
|
|
118 |
/* The enhanced modes all use a 1024-pixel raster. */
|
|
|
119 |
fb_dev->raster = 1024;
|
|
|
120 |
code = svga_open(dev);
|
|
|
121 |
if (code < 0)
|
|
|
122 |
return code;
|
|
|
123 |
/* Clear the cache */
|
|
|
124 |
{
|
|
|
125 |
int i;
|
|
|
126 |
|
|
|
127 |
for (i = 0; i < cache_capacity; i++)
|
|
|
128 |
cache_ids[i] = gx_no_bitmap_id;
|
|
|
129 |
}
|
|
|
130 |
return 0;
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
/* Fill a rectangle. */
|
|
|
134 |
int
|
|
|
135 |
s3_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
|
|
|
136 |
gx_color_index color)
|
|
|
137 |
{
|
|
|
138 |
fit_fill(dev, x, y, w, h);
|
|
|
139 |
s3_wait_fifo();
|
|
|
140 |
outport(s3_fore_mix, 0x27);
|
|
|
141 |
outport(s3_fore_color, (int)color);
|
|
|
142 |
outport(s3_mf_control, mf_data_ones);
|
|
|
143 |
out_s3_rect(x, y, w, h);
|
|
|
144 |
outport(s3_command, 0x40b3);
|
|
|
145 |
return 0;
|
|
|
146 |
}
|
|
|
147 |
|
|
|
148 |
/* Copy a monochrome bitmap. The colors are given explicitly. */
|
|
|
149 |
/* Color = gx_no_color_index means transparent (no effect on the image). */
|
|
|
150 |
private int
|
|
|
151 |
s3_copy_mono(gx_device * dev,
|
|
|
152 |
const byte * base, int sourcex, int raster, gx_bitmap_id id,
|
|
|
153 |
int x, int y, int w, int h, gx_color_index czero, gx_color_index cone)
|
|
|
154 |
{
|
|
|
155 |
int sbit;
|
|
|
156 |
const byte *sptr;
|
|
|
157 |
int run;
|
|
|
158 |
byte lmask;
|
|
|
159 |
byte lmerge = 0;
|
|
|
160 |
int cache_index, cache_x, cache_y;
|
|
|
161 |
int i, j;
|
|
|
162 |
|
|
|
163 |
fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
|
|
|
164 |
sbit = sourcex & 7;
|
|
|
165 |
sptr = base + (sourcex >> 3);
|
|
|
166 |
run = (sbit + w + 7) >> 3;
|
|
|
167 |
lmask = 0xff >> sbit;
|
|
|
168 |
/* See whether the cache is applicable. */
|
|
|
169 |
if (id != gx_no_bitmap_id && w <= cell_width - 7 &&
|
|
|
170 |
h <= cell_height
|
|
|
171 |
) {
|
|
|
172 |
cache_index = (int)(id & (cache_capacity - 1));
|
|
|
173 |
cache_x = ((cache_index & ((1 << cache_x_bits) - 1)) <<
|
|
|
174 |
log2_cell_width) + 7;
|
|
|
175 |
cache_y = ((cache_index >> cache_x_bits) <<
|
|
|
176 |
log2_cell_height) + 768;
|
|
|
177 |
if (cache_ids[cache_index] != id) {
|
|
|
178 |
cache_ids[cache_index] = id;
|
|
|
179 |
/* Copy the bitmap to the cache. */
|
|
|
180 |
s3_wait_fifo();
|
|
|
181 |
out_s3_rect(cache_x - sbit, cache_y, w + sbit, h);
|
|
|
182 |
outport(s3_fore_mix, 0x22); /* 1s */
|
|
|
183 |
outport(s3_back_mix, 0x01); /* 0s */
|
|
|
184 |
outport(s3_mf_control, mf_data_cpu);
|
|
|
185 |
outport(s3_command, 0x41b3);
|
|
|
186 |
{
|
|
|
187 |
const int skip = raster - run;
|
|
|
188 |
|
|
|
189 |
for (i = h; i > 0; i--, sptr += skip)
|
|
|
190 |
for (j = run; j > 0; j--, sptr++)
|
|
|
191 |
outportb(s3_pixel_data, *sptr);
|
|
|
192 |
}
|
|
|
193 |
}
|
|
|
194 |
s3_wait_fifo();
|
|
|
195 |
} else {
|
|
|
196 |
cache_index = -1;
|
|
|
197 |
if (lmask != 0xff) { /* The hardware won't do the masking for us. */
|
|
|
198 |
if (czero != gx_no_color_index) {
|
|
|
199 |
if (cone != gx_no_color_index) {
|
|
|
200 |
s3_fill_rectangle(dev, x, y, w, h, czero);
|
|
|
201 |
czero = gx_no_color_index;
|
|
|
202 |
} else {
|
|
|
203 |
lmerge = ~lmask;
|
|
|
204 |
}
|
|
|
205 |
}
|
|
|
206 |
}
|
|
|
207 |
s3_wait_fifo();
|
|
|
208 |
out_s3_rect(x - sbit, y, w + sbit, h);
|
|
|
209 |
}
|
|
|
210 |
/* Load the colors for the real transfer. */
|
|
|
211 |
if (cone != gx_no_color_index) {
|
|
|
212 |
outport(s3_fore_mix, 0x27);
|
|
|
213 |
outport(s3_fore_color, (int)cone);
|
|
|
214 |
} else
|
|
|
215 |
outport(s3_fore_mix, 0x63);
|
|
|
216 |
if (czero != gx_no_color_index) {
|
|
|
217 |
outport(s3_back_mix, 0x07);
|
|
|
218 |
outport(s3_back_color, (int)czero);
|
|
|
219 |
} else
|
|
|
220 |
outport(s3_back_mix, 0x63);
|
|
|
221 |
s3_wait_fifo();
|
|
|
222 |
if (cache_index < 0) { /* direct transfer */
|
|
|
223 |
outport(s3_mf_control, mf_data_cpu);
|
|
|
224 |
outport(s3_command, 0x41b3);
|
|
|
225 |
if (run == 1 && !lmerge) { /* special case for chars */
|
|
|
226 |
for (i = h; i > 0; i--, sptr += raster)
|
|
|
227 |
outportb(s3_pixel_data, *sptr & lmask);
|
|
|
228 |
} else {
|
|
|
229 |
const int skip = raster - run;
|
|
|
230 |
|
|
|
231 |
for (i = h; i > 0; i--, sptr += skip) {
|
|
|
232 |
outportb(s3_pixel_data, (*sptr++ & lmask) | lmerge);
|
|
|
233 |
for (j = run; j > 1; j--, sptr++)
|
|
|
234 |
outportb(s3_pixel_data, *sptr);
|
|
|
235 |
}
|
|
|
236 |
}
|
|
|
237 |
} else { /* Copy the character from the cache to the screen. */
|
|
|
238 |
out_s3_rect(cache_x, cache_y, w, h);
|
|
|
239 |
outport(s3_x_dest, x);
|
|
|
240 |
outport(s3_y_dest, y);
|
|
|
241 |
outport(s3_mf_control, mf_data_display);
|
|
|
242 |
outport(s3_command, 0xc0b3);
|
|
|
243 |
}
|
|
|
244 |
return 0;
|
|
|
245 |
}
|