xref: /plan9/sys/src/cmd/gs/src/gdevs3ga.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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