1
/* Copyright (C) 2001-2007 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gdevsvga.c 8468 2007-12-31 18:07:59Z giles $ */
15
/* SuperVGA display drivers */
19
#include "gxarith.h" /* for ...log2 */
26
/* The color map for dynamically assignable colors. */
27
#define first_dc_index 64
28
static int next_dc_index;
30
#define dc_hash_size 293 /* prime, >num_dc */
34
static dc_entry dynamic_colors[dc_hash_size + 1];
36
#define num_colors 255
38
/* Macro for casting gx_device argument */
39
#define fb_dev ((gx_device_svga *)dev)
41
/* Procedure records */
42
#define svga_procs(open) {\
43
open, NULL /*get_initial_matrix*/,\
44
NULL /*sync_output*/, NULL /*output_page*/, svga_close,\
45
svga_map_rgb_color, svga_map_color_rgb,\
46
svga_fill_rectangle, NULL /*tile_rectangle*/,\
47
svga_copy_mono, svga_copy_color, NULL /*draw_line*/,\
48
svga_get_bits, NULL /*get_params*/, svga_put_params,\
49
NULL /*map_cmyk_color*/, NULL /*get_xfont_procs*/,\
50
NULL /*get_xfont_device*/, NULL /*map_rgb_alpha_color*/,\
51
gx_page_device_get_page_device, NULL /*get_alpha_bits*/,\
55
/* Save the controller mode */
56
static int svga_save_mode = -1;
58
/* ------ Internal routines ------ */
62
/* Construct a pointer for writing a pixel. */
63
/* Assume 64K pages, 64K granularity. */
64
/* We know that y is within bounds. */
65
#define set_pixel_ptr(ptr, fbdev, x, y, wnum)\
66
{ ulong index = (ulong)(y) * fbdev->raster + (uint)(x);\
67
if ( (uint)(index >> 16) != fbdev->current_page )\
68
{ (*fbdev->set_page)(fbdev, (fbdev->current_page = index >> 16), wnum);\
70
ptr = (fb_ptr)MK_PTR(regen, (ushort)index);\
72
#define set_pixel_write_ptr(ptr, fbdev, x, y)\
73
set_pixel_ptr(ptr, fbdev, x, y, fbdev->wnum_write)
74
#define set_pixel_read_ptr(ptr, fbdev, x, y)\
75
set_pixel_ptr(ptr, fbdev, x, y, fbdev->wnum_read)
77
/* Find the graphics mode for a desired width and height. */
78
/* Set the mode in the device structure and return 0, */
79
/* or return an error code. */
81
svga_find_mode(gx_device * dev, const mode_info * mip)
84
if (mip->width >= fb_dev->width &&
85
mip->height >= fb_dev->height ||
89
gx_device_adjust_resolution(dev, mip->width, mip->height, 1);
90
fb_dev->raster = fb_dev->width;
94
return_error(gs_error_rangecheck);
97
/* Set the index for writing into the color DAC. */
98
#define svga_dac_set_write_index(i) outportb(0x3c8, i)
100
/* Write 6-bit R,G,B values into the color DAC. */
101
#define svga_dac_write(r, g, b)\
102
(outportb(0x3c9, r), outportb(0x3c9, g), outportb(0x3c9, b))
104
/* ------ Common procedures ------ */
106
#define cv_bits(v,n) (v >> (gx_color_value_bits - n))
108
/* Initialize the dynamic color table, if any. */
110
svga_init_colors(gx_device * dev)
112
if (fb_dev->fixed_colors)
113
next_dc_index = num_colors;
115
memset(dynamic_colors, 0,
116
(dc_hash_size + 1) * sizeof(dc_entry));
117
next_dc_index = first_dc_index;
121
/* Load the color DAC with the predefined colors. */
123
svga_load_colors(gx_device * dev)
127
svga_dac_set_write_index(0);
128
if (fb_dev->fixed_colors)
129
for (ci = 0; ci < num_colors; ci++) {
130
gx_color_value rgb[3];
132
pc_8bit_map_color_rgb(dev, (gx_color_index) ci, rgb);
133
svga_dac_write(cv_bits(rgb[0], 6), cv_bits(rgb[1], 6),
136
for (ci = 0; ci < 64; ci++) {
137
static const byte c2[10] =
138
{0, 42, 0, 0, 0, 0, 0, 0, 21, 63};
140
svga_dac_write(c2[(ci >> 2) & 9], c2[(ci >> 1) & 9],
145
/* Initialize the device structure and the DACs. */
147
svga_open(gx_device * dev)
149
fb_dev->x_pixels_per_inch =
150
fb_dev->y_pixels_per_inch =
151
fb_dev->height / PAGE_HEIGHT_INCHES;
152
/* Set the display mode. */
153
if (svga_save_mode < 0)
154
svga_save_mode = (*fb_dev->get_mode) ();
155
(*fb_dev->set_mode) (fb_dev->mode->mode);
156
svga_init_colors(dev);
157
svga_load_colors(dev);
158
fb_dev->current_page = -1;
162
/* Close the device; reinitialize the display for text mode. */
164
svga_close(gx_device * dev)
166
if (svga_save_mode >= 0)
167
(*fb_dev->set_mode) (svga_save_mode);
172
/* Map a r-g-b color to a palette index. */
173
/* The first 64 entries of the color map are set */
174
/* for compatibility with the older display modes: */
175
/* these are indexed as 0.0.R0.G0.B0.R1.G1.B1. */
177
svga_map_rgb_color(gx_device * dev, const gx_color_value cv[])
180
gx_color_value r = cv[0], g = cv[1], b = cv[2];
182
if (fb_dev->fixed_colors) {
183
gx_color_index ci = pc_8bit_map_rgb_color(dev, cv);
185
/* Here is where we should permute the index to match */
186
/* the old color map... but we don't yet. */
189
ushort r5 = cv_bits(r, 5), g5 = cv_bits(g, 5), b5 = cv_bits(b, 5);
190
static const byte cube_bits[32] =
191
{0, 128, 128, 128, 128, 128, 128, 128, 128, 128,
192
8, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
193
1, 128, 128, 128, 128, 128, 128, 128, 128, 128,
196
uint cx = ((uint) cube_bits[r5] << 2) +
197
((uint) cube_bits[g5] << 1) +
198
(uint) cube_bits[b5];
200
/* Check for a color on the cube. */
202
return (gx_color_index) cx;
203
/* Not on the cube, check the dynamic color table. */
204
rgb = (r5 << 10) + (g5 << 5) + b5;
207
register dc_entry *pdc;
209
for (pdc = &dynamic_colors[rgb % dc_hash_size];
213
return (gx_color_index) (pdc->index);
214
if (pdc == &dynamic_colors[dc_hash_size]) { /* Wraparound */
215
for (pdc = &dynamic_colors[0]; pdc->rgb != 0; pdc++)
217
return (gx_color_index) (pdc->index);
219
if (next_dc_index == num_colors) { /* No space left, report failure. */
220
return gx_no_color_index;
222
/* Not on the cube, and not in the dynamic table. */
223
/* Put in the dynamic table if space available. */
225
int i = next_dc_index++;
229
svga_dac_set_write_index(i);
230
svga_dac_write(cv_bits(r, 6), cv_bits(g, 6),
232
return (gx_color_index) i;
237
/* Map a color code to r-g-b. */
238
/* This routine must invert the transformation of the one above. */
239
/* Since this is practically never used, we just read the DAC. */
241
svga_map_color_rgb(gx_device * dev, gx_color_index color,
242
gx_color_value prgb[3])
246
outportb(0x3c7, (byte) color);
247
#define dacin() (cval = inportb(0x3c9) >> 1,\
248
((cval << 11) + (cval << 6) + (cval << 1) + (cval >> 4)) >>\
249
(16 - gx_color_value_bits))
257
/* Fill a rectangle. */
259
svga_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
260
gx_color_index color)
262
uint raster = fb_dev->raster;
263
ushort limit = (ushort) - raster;
267
fit_fill(dev, x, y, w, h);
268
set_pixel_write_ptr(ptr, fb_dev, x, y);
269
/* Most fills are very small and don't cross a page boundary. */
273
return 0; /* no-op */
275
while (--yi >= 0 && PTR_OFF(ptr) < limit)
276
ptr[0] = (byte) color,
282
while (--yi >= 0 && PTR_OFF(ptr) < limit)
283
ptr[0] = ptr[1] = (byte) color,
289
while (--yi >= 0 && PTR_OFF(ptr) < limit)
290
ptr[0] = ptr[1] = ptr[2] = (byte) color,
296
while (--yi >= 0 && PTR_OFF(ptr) < limit)
297
ptr[0] = ptr[1] = ptr[2] = ptr[3] = (byte) color,
305
/* Check for erasepage. */
306
if (w == dev->width && h == dev->height &&
307
color < first_dc_index
309
svga_init_colors(dev);
312
if (PTR_OFF(ptr) < limit) {
313
memset(ptr, (byte) color, w);
315
} else if (PTR_OFF(ptr) <= (ushort) (-w)) {
316
memset(ptr, (byte) color, w);
318
set_pixel_write_ptr(ptr, fb_dev, x, y + h - yi);
320
uint left = (uint) 0x10000 - PTR_OFF(ptr);
322
memset(ptr, (byte) color, left);
323
set_pixel_write_ptr(ptr, fb_dev, x + left, y + h - 1 - yi);
324
memset(ptr, (byte) color, w - left);
325
ptr += raster - left;
331
/* Copy a monochrome bitmap. The colors are given explicitly. */
332
/* Color = gx_no_color_index means transparent (no effect on the image). */
334
svga_copy_mono(gx_device * dev,
335
const byte * base, int sourcex, int sraster, gx_bitmap_id id,
336
int x, int y, int w, int h, gx_color_index czero, gx_color_index cone)
338
uint raster = fb_dev->raster;
343
register fb_ptr ptr = (fb_ptr) 0;
347
fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
348
limit = (ushort) - w;
349
skip = raster - w + 1;
350
srow = base + (sourcex >> 3);
351
#define izero (int)czero
352
#define ione (int)cone
353
if (ione == no_color) {
356
if (izero == no_color)
357
return 0; /* no-op */
364
/* Pre-filling saves us a test in the loop, */
365
/* and since tiling is uncommon, we come out ahead. */
366
if (izero != no_color)
367
svga_fill_rectangle(dev, x, y, w, h, czero);
368
for (yi = 0; yi < h; yi++) {
369
const byte *sptr = srow;
371
int bitno = sourcex & 7;
374
if (PTR_OFF(ptr) <= skip) {
375
set_pixel_write_ptr(ptr, fb_dev, x, y + yi);
376
} else if (PTR_OFF(ptr) > limit) { /* We're crossing a page boundary. */
377
/* This is extremely rare, so it doesn't matter */
378
/* how slow it is. */
379
int xi = (ushort) - PTR_OFF(ptr);
381
svga_copy_mono(dev, srow, sourcex & 7, sraster,
382
gx_no_bitmap_id, x, y + yi, xi, 1,
383
gx_no_color_index, cone);
384
set_pixel_write_ptr(ptr, fb_dev, x + xi, y + yi);
385
sptr = srow - (sourcex >> 3) + ((sourcex + xi) >> 3);
386
bitno = (sourcex + xi) & 7;
389
bits = *sptr ^ invert;
392
if ( bits & msk ) *ptr = (byte)ione;\
393
if ( !--wi ) break; ptr++
411
bits = *++sptr ^ invert;
422
/* Copy a color pixelmap. This is just like a bitmap, */
423
/* except that each pixel takes 8 bits instead of 1. */
425
svga_copy_color(gx_device * dev,
426
const byte * base, int sourcex, int sraster, gx_bitmap_id id,
427
int x, int y, int w, int h)
434
fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
436
sptr = base + sourcex;
437
for (yi = y; yi - y < h; yi++) {
439
for (xi = x; xi - x < w; xi++) {
440
if (PTR_OFF(ptr) == 0)
441
set_pixel_write_ptr(ptr, fb_dev, xi, yi);
449
/* Put parameters. */
451
svga_put_params(gx_device * dev, gs_param_list * plist)
455
const char *param_name;
457
if ((code = ecode) < 0 ||
458
(code = gx_default_put_params(dev, plist)) < 0
464
/* Read scan lines back from the frame buffer. */
466
svga_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
468
uint bytes_per_row = dev->width;
469
ushort limit = (ushort) - bytes_per_row;
472
if (y < 0 || y >= dev->height)
473
return gs_error_rangecheck;
474
set_pixel_read_ptr(src, fb_dev, 0, y);
475
/* The logic here is similar to fill_rectangle. */
476
if (PTR_OFF(src) <= limit)
477
memcpy(data, src, bytes_per_row);
479
uint left = (uint) 0x10000 - PTR_OFF(src);
481
memcpy(data, src, left);
482
set_pixel_read_ptr(src, fb_dev, left, y);
483
memcpy(data + left, src, bytes_per_row - left);
485
if (actual_data != 0)
490
/* Copy an alpha-map to the screen. */
491
/* Depth is 1, 2, or 4. */
493
svga_copy_alpha(gx_device * dev, const byte * base, int sourcex,
494
int sraster, gx_bitmap_id id, int x, int y, int w, int h,
495
gx_color_index color, int depth)
503
/* We fake alpha by interpreting it as saturation, i.e., */
504
/* alpha = 0 is white, alpha = 1 is the full color. */
506
gx_color_value rgb[3];
507
int log2_depth = depth >> 1; /* works for 1,2,4 */
508
int n1 = (1 << depth) - 1;
510
fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
511
shades[0] = (byte) svga_map_rgb_color(dev, gx_max_color_value,
514
shades[n1] = (byte) color;
516
memset(shades + 1, 255, n1 - 1);
517
svga_map_color_rgb(dev, color, rgb);
519
skip = sraster - ((w * depth) >> 3);
520
sptr = base + (sourcex >> (3 - log2_depth));
522
ishift = (~sourcex & (7 >> log2_depth)) << log2_depth;
523
for (yi = y; yi - y < h; yi++) {
527
for (xi = x; xi - x < w; xi++, ptr++) {
528
uint a = (*sptr >> shift) & mask;
530
if (PTR_OFF(ptr) == 0)
531
set_pixel_write_ptr(ptr, fb_dev, xi, yi);
535
if (ci == 255) { /* Map the color now. */
536
#define make_shade(v, alpha, n1)\
537
(gx_max_color_value -\
538
((ulong)(gx_max_color_value - (v)) * (alpha) / (n1)))
540
make_shade(rgb[0], a, n1);
542
make_shade(rgb[1], a, n1);
544
make_shade(rgb[2], a, n1);
546
svga_map_rgb_color(dev, r, g, b);
548
if (sci == gx_no_color_index) {
549
a += (n1 + 1 - a) >> 1;
552
shades[a] = ci = (byte) sci;
557
shift = 8 - depth, sptr++;
566
/* ------ The VESA device ------ */
568
static dev_proc_open_device(vesa_open);
569
static const gx_device_procs vesa_procs = svga_procs(vesa_open);
570
int vesa_get_mode(void);
571
void vesa_set_mode(int);
572
static void vesa_set_page(gx_device_svga *, int, int);
573
gx_device_svga far_data gs_vesa_device =
574
svga_device(vesa_procs, "vesa", vesa_get_mode, vesa_set_mode, vesa_set_page);
576
/* Define the structures for information returned by the BIOS. */
577
#define bits_include(a, m) !(~(a) & (m))
578
/* Information about the BIOS capabilities. */
580
byte vesa_signature[4]; /* "VESA" */
582
char *product_info; /* product name string */
583
byte capabilities[4]; /* (undefined) */
584
ushort *mode_list; /* supported video modes, -1 ends */
587
/* Information about an individual VESA mode. */
598
ushort mode_attributes;
599
byte win_a_attributes;
600
byte win_b_attributes;
601
ushort win_granularity;
603
ushort win_a_segment;
604
ushort win_b_segment;
605
void (*win_func_ptr) (int, int);
606
ushort bytes_per_line;
607
/* Optional information */
612
byte number_of_planes;
614
byte number_of_banks;
617
/* Padding to 256 bytes */
618
byte _padding[256 - 29];
621
/* Read the device mode */
629
int86(0x10, ®s, ®s);
630
return regs.rshort.bx;
633
/* Set the device mode */
635
vesa_set_mode(int mode)
641
regs.rshort.bx = mode;
642
int86(0x10, ®s, ®s);
645
/* Read information about a device mode */
647
vesa_get_info(int mode, vesa_info _ss * info)
654
regs.rshort.cx = mode;
657
regs.rshort.di = PTR_OFF(info);
658
int86x(0x10, ®s, ®s, &sregs);
660
if (regs.h.ah == 0 && regs.h.al == 0x4f)
661
dlprintf8("vesa_get_info(%x): ma=%x wa=%x/%x wg=%x ws=%x wseg=%x/%x\n",
662
mode, info->mode_attributes,
663
info->win_a_attributes, info->win_b_attributes,
664
info->win_granularity, info->win_size,
665
info->win_a_segment, info->win_b_segment);
667
dlprintf3("vesa_get_info(%x) failed: ah=%x al=%x\n",
668
mode, regs.h.ah, regs.h.al);
670
return (regs.h.ah == 0 && regs.h.al == 0x4f ? 0 : -1);
673
/* Initialize the graphics mode. */
674
/* Shared routine to look up a VESA-compatible BIOS mode. */
676
vesa_find_mode(gx_device * dev, const mode_info * mode_table)
677
{ /* Select the proper video mode */
679
const mode_info *mip;
681
for (mip = mode_table; mip->mode >= 0; mip++) {
682
if (mip->width >= fb_dev->width &&
683
mip->height >= fb_dev->height &&
684
vesa_get_info(mip->mode, &info) >= 0 &&
685
bits_include(info.mode_attributes,
686
m_supported | m_graphics) &&
687
info.win_granularity <= 64 &&
688
(info.win_granularity & (info.win_granularity - 1)) == 0 &&
689
info.win_size == 64 &&
690
bits_include(info.win_a_attributes,
692
info.win_a_segment == regen
693
) { /* Make sure we can both read & write. */
694
/* Initialize for the default case. */
695
fb_dev->wnum_read = 0;
696
fb_dev->wnum_write = 0;
697
if (bits_include(info.win_a_attributes,
698
w_readable | w_writable)
701
else if (info.win_b_segment == regen &&
702
bits_include(info.win_b_attributes,
704
bits_include(info.win_a_attributes |
705
info.win_b_attributes,
706
w_readable | w_writable)
707
) { /* Two superimposed windows. */
708
if (!bits_include(info.win_a_attributes,
711
fb_dev->wnum_write = 1;
713
fb_dev->wnum_read = 1;
719
return_error(gs_error_rangecheck); /* mode not available */
721
gx_device_adjust_resolution(dev, mip->width, mip->height, 1);
722
fb_dev->info.vesa.bios_set_page = info.win_func_ptr;
723
fb_dev->info.vesa.pn_shift = ilog2(64 / info.win_granularity);
724
/* Reset the raster per the VESA info. */
725
fb_dev->raster = info.bytes_per_line;
729
vesa_open(gx_device * dev)
731
static const mode_info mode_table[] =
740
int code = vesa_find_mode(dev, mode_table);
744
return svga_open(dev);
747
/* Set the current display page. */
749
vesa_set_page(gx_device_svga * dev, int pn, int wnum)
753
regs.rshort.dx = pn << dev->info.vesa.pn_shift;
756
regs.rshort.bx = wnum;
757
int86(0x10, ®s, ®s);
760
/* ------ The ATI Wonder device ------ */
762
static dev_proc_open_device(atiw_open);
763
static const gx_device_procs atiw_procs = svga_procs(atiw_open);
764
static int atiw_get_mode(void);
765
static void atiw_set_mode(int);
766
static void atiw_set_page(gx_device_svga *, int, int);
767
gx_device_svga far_data gs_atiw_device =
768
svga_device(atiw_procs, "atiw", atiw_get_mode, atiw_set_mode, atiw_set_page);
770
/* Read the device mode */
777
int86(0x10, ®s, ®s);
781
/* Set the device mode */
783
atiw_set_mode(int mode)
789
int86(0x10, ®s, ®s);
792
/* Initialize the graphics mode. */
794
atiw_open(gx_device * dev)
795
{ /* Select the proper video mode */
797
static const mode_info mode_table[] =
805
int code = svga_find_mode(dev, mode_table);
808
return code; /* mode not available */
809
fb_dev->info.atiw.select_reg = *(int *)MK_PTR(0xc000, 0x10);
810
return svga_open(dev);
814
/* Set the current display page. */
816
atiw_set_page(gx_device_svga * dev, int pn, int wnum)
818
int select_reg = dev->info.atiw.select_reg;
822
outportb(select_reg, 0xb2);
823
reg = inportb(select_reg + 1);
824
outportb(select_reg, 0xb2);
825
outportb(select_reg + 1, (reg & 0xe1) + (pn << 1));
829
/* ------ The Trident device ------ */
831
static dev_proc_open_device(tvga_open);
832
static const gx_device_procs tvga_procs = svga_procs(tvga_open);
834
/* We can use the atiw_get/set_mode procedures. */
835
static void tvga_set_page(gx_device_svga *, int, int);
836
gx_device_svga far_data gs_tvga_device =
837
svga_device(tvga_procs, "tvga", atiw_get_mode, atiw_set_mode, tvga_set_page);
839
/* Initialize the graphics mode. */
841
tvga_open(gx_device * dev)
843
fb_dev->wnum_read = 1;
844
fb_dev->wnum_write = 0;
845
/* Select the proper video mode */
847
static const mode_info mode_table[] =
855
int code = svga_find_mode(dev, mode_table);
858
return code; /* mode not available */
859
return svga_open(dev);
863
/* Set the current display page. */
865
tvga_set_page(gx_device_svga * dev, int pn, int wnum)
868
outportb(0x3c4, 0x0b);
871
outportb(0x3c4, 0x0e);
872
outportb(0x3c5, pn ^ 2);
875
/* ------ The Tseng Labs ET3000/4000 devices ------ */
877
static dev_proc_open_device(tseng_open);
878
static const gx_device_procs tseng_procs =
879
svga_procs(tseng_open);
881
/* We can use the atiw_get/set_mode procedures. */
882
static void tseng_set_page(gx_device_svga *, int, int);
884
/* The 256-color Tseng device */
885
gx_device_svga far_data gs_tseng_device =
886
svga_device(tseng_procs, "tseng", atiw_get_mode, atiw_set_mode, tseng_set_page);
888
/* Initialize the graphics mode. */
890
tseng_open(gx_device * dev)
892
fb_dev->wnum_read = 1;
893
fb_dev->wnum_write = 0;
894
/* Select the proper video mode */
896
static const mode_info mode_table[] =
904
int code = svga_find_mode(dev, mode_table);
905
volatile_fb_ptr p0 = (volatile_fb_ptr) MK_PTR(regen, 0);
908
return code; /* mode not available */
909
code = svga_open(dev);
912
/* Figure out whether we have an ET3000 or an ET4000 */
913
/* by playing with the segment register. */
914
outportb(0x3cd, 0x44);
915
*p0 = 4; /* byte 0, page 4 */
916
outportb(0x3cd, 0x40);
917
*p0 = 3; /* byte 0, page 0 */
918
fb_dev->info.tseng.et_model = *p0;
919
/* read page 0 if ET3000, */
920
/* page 4 if ET4000 */
925
/* Set the current display page. */
927
tseng_set_page(gx_device_svga * dev, int pn, int wnum)
928
{ /* The ET3000 has read page = 5:3, write page = 2:0; */
929
/* the ET4000 has read page = 7:4, write page = 3:0. */
930
int shift = dev->info.tseng.et_model;
931
int mask = (1 << shift) - 1;
934
pn <<= shift, mask <<= shift;
935
outportb(0x3cd, (inportb(0x3cd) & ~mask) + pn);
937
/* ------ The Cirrus device (CL-GD54XX) ------ */
938
/* Written by Piotr Strzelczyk, BOP s.c., Gda\'nsk, Poland, */
939
/* e-mail contact via B.Jackowski@GUST.org.pl */
941
static dev_proc_open_device(cirr_open);
942
static gx_device_procs cirr_procs = svga_procs(cirr_open);
944
/* We can use the atiw_get/set_mode procedures. */
945
static void cirr_set_page(gx_device_svga *, int, int);
946
gx_device_svga gs_cirr_device =
947
svga_device(cirr_procs, "cirr", atiw_get_mode, atiw_set_mode, cirr_set_page);
949
/* Initialize the graphics mode. */
951
cirr_open(gx_device * dev)
953
fb_dev->wnum_read = 1;
954
fb_dev->wnum_write = 0;
955
/* Select the proper video mode */
957
static const mode_info mode_table[] =
965
int code = svga_find_mode(dev, mode_table);
968
return code; /* mode not available */
969
outportb(0x3c4, 0x06);
970
outportb(0x3c5, 0x12);
971
outportb(0x3ce, 0x0b);
972
outportb(0x3cf, (inportb(0x3cf) & 0xde));
973
return svga_open(dev);
977
/* Set the current display page. */
979
cirr_set_page(gx_device_svga * dev, int pn, int wnum)
981
outportb(0x3ce, 0x09);
982
outportb(0x3cf, pn << 4);
985
/* ------ The Avance Logic device (mostly experimental) ------ */
986
/* For questions about this device, please contact Stefan Freund */
987
/* <freund@ikp.uni-koeln.de>. */
989
static dev_proc_open_device(ali_open);
990
static const gx_device_procs ali_procs = svga_procs(ali_open);
992
/* We can use the atiw_get/set_mode procedures. */
993
static void ali_set_page(gx_device_svga *, int, int);
995
/* The 256-color Avance Logic device */
996
gx_device_svga gs_ali_device =
997
svga_device(ali_procs, "ali", atiw_get_mode, atiw_set_mode,
1000
/* Initialize the graphics mode. */
1002
ali_open(gx_device * dev)
1004
fb_dev->wnum_read = 1;
1005
fb_dev->wnum_write = 0;
1006
/* Select the proper video mode */
1008
static const mode_info mode_table[] =
1016
int code = svga_find_mode(dev, mode_table);
1019
return code; /* mode not available */
1020
return svga_open(dev);
1025
/* Set the current display page. */
1027
ali_set_page(gx_device_svga * dev, int pn, int wnum)
1029
outportb(0x3d6, pn); /* read */
1030
outportb(0x3d7, pn); /* write */