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
s3_open(gx_device * dev)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
s3_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)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
s3_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index czero,gx_color_index cone)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 }
246