// S3Graphics.cpp: implementation of the CS3Graphics class.
//
//////////////////////////////////////////////////////////////////////
#include "S3Graphics.h"
#include "driver.h"
#include <stdio.h>
#include <string.h>
MonitorModeTiming* current_timing;
#define CRT_C 24 /* 24 CRT Controller Registers */
#define ATT_C 21 /* 21 Attribute Controller Registers */
#define GRA_C 9 /* 9 Graphics Controller Registers */
#define SEQ_C 5 /* 5 Sequencer Registers */
#define MIS_C 1 /* 1 Misc Output Register */
#define VGA_TOTAL_REGS 60
#define CRT_IC 0x3D4 /* CRT Controller Index (mono: 0x3B4) */
#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
#define GRA_I 0x3CE /* Graphics Controller Index */
#define SEQ_I 0x3C4 /* Sequencer Index */
#define PEL_IW 0x3C8 /* PEL Write Index */
/* VGA registers saving indexes */
#define CRT 0 /* CRT Controller Registers start */
#define ATT (CRT+CRT_C) /* Attribute Controller Registers start */
#define GRA (ATT+ATT_C) /* Graphics Controller Registers start */
#define SEQ (GRA+GRA_C) /* Sequencer Registers */
#define MIS (SEQ+SEQ_C) /* General Registers */
#define EXT (MIS+MIS_C) /* SVGA Extended Registers */
#define CRT_D 0x3D5 /* CRT Controller Data Register (mono: 0x3B5) */
#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */
#define GRA_D 0x3CF /* Graphics Controller Data Register */
#define SEQ_D 0x3C5 /* Sequencer Data Register */
#define MIS_R 0x3CC /* Misc Output Read Register */
#define MIS_W 0x3C2 /* Misc Output Write Register */
#define IS1_R 0x3DA /* Input Status Register 1 (mono: 0x3BA) */
#define PEL_D 0x3C9 /* PEL Data Register */
#define VGA_CRTC_OFFSET 0 /* 24 registers */
#define VGA_ATC_OFFSET 24 /* 21 registers */
#define VGA_GRAPHICS_OFFSET 45 /* 9 registers. */
#define VGA_SEQUENCER_OFFSET 54 /* 5 registers. */
#define VGA_MISCOUTPUT 59 /* (single register) */
#define VGA_TOTAL_REGS 60
#define PaletteMask 0x3C6 // bit mask register
#define PaletteRegisterRead 0x3C7 // read index
#define PaletteRegisterWrite 0x3C8 // write index
#define PaletteData 0x3C9 // send/receive data here
#define __svgalib_CRT_D CRT_D
#define __svgalib_CRT_I CRT_IC
#define __svgalib_IS1_R IS1_R
#define __svgalib_driver_report 1
#define ADVFUNC_CNTL 0x4AE8 /* S3 */
int __svgalib_vga_inmisc(void)
{
return in(MIS_R);
}
void __svgalib_vga_outmisc(int i)
{
out(MIS_W,i);
}
int __svgalib_vga_incrtc(int i)
{
out(__svgalib_CRT_I,i);
return in(__svgalib_CRT_D);
}
void __svgalib_vga_outcrtc(int i, int d)
{
out16(__svgalib_CRT_I,i|(d<<8));
}
int __svgalib_vga_inseq(int index)
{
out(SEQ_I, index);
return in(SEQ_D);
}
void __svgalib_vga_outseq(int index, int val)
{
int v;
v = ((int) val << 8) + index;
out16(SEQ_I, v);
}
/*
* These are simple functions to write a value to a VGA Graphics
* Controller, CRTC Controller or Sequencer register.
* The idea is that drivers call these as a function call, making the
* code smaller and inserting small delays between I/O accesses when
* doing mode switches.
*/
void __svgalib_outGR(int index, unsigned char val)
{
int v;
v = ((int) val << 8) + index;
out16(GRA_I, v);
}
void __svgalib_outbGR(int index, unsigned char val)
{
out(GRA_I, index);
out(GRA_D, val);
}
void __svgalib_outCR(int index, unsigned char val)
{
int v;
v = ((int) val << 8) + index;
out16(CRT_IC, v);
}
void __svgalib_outbCR(int index, unsigned char val)
{
out(CRT_IC, index);
out(__svgalib_CRT_D, val);
}
void __svgalib_outSR(int index, unsigned char val)
{
int v;
v = ((int) val << 8) + index;
out16(SEQ_I, v);
}
void __svgalib_outbSR(int index, unsigned char val)
{
out(SEQ_I, index);
out(SEQ_D, val);
}
unsigned char __svgalib_inGR(int index)
{
out(GRA_I, index);
return in(GRA_D);
}
unsigned char __svgalib_inCR(int index)
{
out(CRT_IC, index);
return in(CRT_D);
}
unsigned char __svgalib_inSR(int index)
{
out(SEQ_I, index);
return in(SEQ_D);
}
enum {
S3_911, S3_924, S3_801, S3_805, S3_928, S3_864, S3_964, S3_TRIO32,
S3_TRIO64, S3_866, S3_868, S3_968, S3_765
};
void CS3Graphics::HwLock()
{
__svgalib_outCR(0x39, 0x00); /* Lock system control regs. */
__svgalib_outCR(0x38, 0x00); /* Lock special regs. */
}
void CS3Graphics::HwLockEnh()
{
if (s3_chiptype > S3_911)
__svgalib_outCR(0x40, __svgalib_inCR(0x40) & ~0x01); /* Lock enhanced command regs. */
HwLock();
}
/*
* Unlock S3's registers.
* There are more locks, but this should suffice.
*/
void CS3Graphics::HwUnlock()
{
__svgalib_outCR(0x38, 0x48); /* Unlock special regs. */
__svgalib_outCR(0x39, 0xA5); /* Unlock system control regs. */
}
void CS3Graphics::HwUnlockEnh()
{
Unlock();
if (s3_chiptype > S3_911)
__svgalib_outCR(0x40, __svgalib_inCR(0x40) | 0x01); /* Unlock enhanced command regs. */
}
static const wchar_t *s3_chipname[] =
{L"911", L"924", L"801", L"805", L"928",
L"864", L"964", L"Trio32", L"Trio64", L"866", L"868", L"968", L"Trio64V+"};
/* flags used by this driver */
#define S3_LOCALBUS 0x01
#define S3_CLUT8_8 0x02
#define S3_OLD_STEPPING 0x04
/* Card flags. */
/* The card has programmable clocks (matchProgrammableClock is valid). */
#define CLOCK_PROGRAMMABLE 0x1
/* For interlaced modes, the vertical timing must be divided by two. */
#define INTERLACE_DIVIDE_VERT 0x2
/* For modes with vertical timing greater or equal to 1024, vertical */
/* timing must be divided by two. */
#define GREATER_1024_DIVIDE_VERT 0x4
/* The DAC doesn't support 64K colors (5-6-5) at 16bpp, just 5-5-5. */
#define NO_RGB16_565 0x8
int CS3Graphics::Init(int force, int par1, int par2)
{
int id, rev, config;
HwUnlock();
s3_flags = 0; /* initialize */
id = __svgalib_inCR(0x30); /* Get chip id. */
rev = id & 0x0F;
if (id >= 0xE0) {
id |= __svgalib_inCR(0x2E) << 8;
rev |= __svgalib_inCR(0x2F) << 4;
}
if (force) {
s3_chiptype = par1; /* we already know the type */
s3_memory = par2;
/* ARI: can we really trust the user's specification, or should we ignore
it and probe ourselves ? */
if (s3_chiptype == S3_801 || s3_chiptype == S3_805) {
if ((rev & 0x0F) < 2)
s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
} else if (s3_chiptype == S3_928) {
if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */
s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
}
} else {
s3_chiptype = -1;
config = __svgalib_inCR(0x36); /* get configuration info */
switch (id & 0xf0) {
case 0x80:
if (rev == 1) {
s3_chiptype = S3_911;
break;
}
if (rev == 2) {
s3_chiptype = S3_924;
break;
}
break;
case 0xa0:
switch (config & 0x03) {
case 0x00:
case 0x01:
/* EISA or VLB - 805 */
s3_chiptype = S3_805;
/* ARI: Test stepping: 0:B, 1:unknown, 2,3,4:C, 8:I, >=5:D */
if ((rev & 0x0F) < 2)
s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
break;
case 0x03:
/* ISA - 801 */
s3_chiptype = S3_801;
/* Stepping same as 805, just ISA */
if ((rev & 0x0F) < 2)
s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
break;
}
break;
case 0x90:
s3_chiptype = S3_928;
if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */
s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
break;
case 0xB0:
/* 928P */
s3_chiptype = S3_928;
break;
case 0xC0:
s3_chiptype = S3_864;
break;
case 0xD0:
s3_chiptype = S3_964;
break;
case 0xE0:
switch (id & 0xFFF0) {
case 0x10E0:
s3_chiptype = S3_TRIO32;
break;
case 0x3DE0: /* ViRGE/VX ID */
case 0x31E0: /* ViRGE ID */
case 0x01E0: /* S3Trio64V2/DX ... any others? */
case 0x04E0:
case 0x11E0:
if (rev & 0x0400)
s3_chiptype = S3_765;
else
s3_chiptype = S3_TRIO64;
break;
case 0x80E0:
s3_chiptype = S3_866;
break;
case 0x90E0:
s3_chiptype = S3_868;
break;
case 0xF0E0: /* XXXX From data book; XF86 says 0xB0E0? */
s3_chiptype = S3_968;
break;
}
}
if (s3_chiptype == -1) {
wprintf(L"svgalib: S3: Unknown chip id %02x\n",
id);
return -1;
}
if (s3_chiptype <= S3_924) {
if ((config & 0x20) != 0)
s3_memory = 512;
else
s3_memory = 1024;
} else {
/* look at bits 5, 6 and 7 */
switch ((config & 0xE0) >> 5) {
case 0:
s3_memory = 4096;
break;
case 2:
s3_memory = 3072;
break;
case 3:
s3_memory = 8192;
break;
case 4:
s3_memory = 2048;
break;
case 5:
s3_memory = 6144;
break;
case 6:
s3_memory = 1024;
break;
case 7:
s3_memory = 512;
break; /* Trio32 */
}
}
if ((config & 0x03) < 3) /* XXXX 928P is ignored */
s3_flags |= S3_LOCALBUS;
}
if (__svgalib_driver_report) {
wprintf(L"svgalib: Using S3 driver (%s, %dK).\n", s3_chipname[s3_chiptype],
s3_memory);
if (s3_flags & S3_OLD_STEPPING)
wprintf(L"svgalib: Chip revision cannot handle modes with width 1152.\n");
if (s3_chiptype > S3_TRIO64) {
wprintf(L"svgalib: s3: chipsets newer than S3 Trio64 is not supported well yet.\n");
}
}
/* begin: Initialize cardspecs. */
/* If IOPERM is set, assume permissions have already been set by Olaf Titz' */
/* ioperm(1). */
/*if (getenv("IOPERM") == NULL) {
if (0 > iopl(3))
wprintf(L"svgalib: s3: cannot get I/O permissions for 8514.");
}*/
#ifdef S3_LINEAR_SUPPORT
if (s3_chiptype > S3_805) {
int found_pciconfig;
unsigned long pci_conf[64];
found_pciconfig = __svgalib_pci_find_vendor_vga(0x5333, pci_conf, 0);
if (!found_pciconfig)
s3_linear_base = pci_conf[4] & 0xFF800000;
}
s3_cr59 = s3_linear_base >> 24;
s3_cr5A = (s3_linear_base >> 16);
if (! (s3_cr59 | s3_cr5A)) {
s3_cr59 = __svgalib_inCR(0x59);
s3_cr5A = __svgalib_inCR(0x5A);
if (!s3_cr59) {
s3_cr59 = 0xF3000000 >> 24;
s3_cr5A = (0xF3000000 >> 16);
}
s3_linear_base = (s3_cr59 << 24) | (s3_cr5A << 16);
}
s3_linear_opt |= 0x10;
switch (s3_memory) {
case 512 :
case 1024 :
s3_linear_opt |= 0x01;
break;
case 2048 :
s3_linear_opt |= 0x02;
break;
case 3072 :
case 4096 :
case 6144 :
case 8192 :
s3_linear_opt |= 0x03;
break;
default :
s3_linear_opt = 0x14; /* like XFree */
}
#endif
cardspecs = (CardSpecs*) malloc(sizeof(CardSpecs));
cardspecs->videoMemory = s3_memory;
cardspecs->nClocks = 0;
/*cardspecs->maxHorizontalCrtc = 2040; SL: kills 800x600x32k and above */
cardspecs->maxHorizontalCrtc = 4088;
cardspecs->flags = INTERLACE_DIVIDE_VERT;
/* Process S3-specific config file options. */
//__svgalib_read_options(s3_config_options, s3_process_option);
#ifdef INCLUDE_S3_TRIO64_DAC
if ((s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) && dac_used == NULL)
dac_used = &__svgalib_Trio64_methods;
#endif
//if (dac_used == NULL)
//dac_used = __svgalib_probeDacs(dacs_to_probe);
//else
//dac_used->initialize();
//if (dac_used == NULL) {
/* Not supported. */
/*wprintf(L"svgalib: s3: Assuming normal VGA DAC.\n");
#ifdef INCLUDE_NORMAL_DAC
dac_used = &__svgalib_normal_dac_methods;
dac_used->initialize();
#else
wprintf(L"svgalib: Alas, normal VGA DAC support is not compiled in, goodbye.\n");
return 1;
#endif
}
if (clk_used)
clk_used->initialize(cardspecs, dac_used);*/
//dac_used->qualifyCardSpecs(cardspecs, dac_speed);
/* Initialize standard clocks for unknown DAC. */
if ((!(cardspecs->flags & CLOCK_PROGRAMMABLE))
&& cardspecs->nClocks == 0) {
/*
* Almost all cards have 25 and 28 MHz on VGA clocks 0 and 1,
* so use these for an unknown DAC, yielding 640x480x256.
*/
cardspecs->nClocks = 2;
cardspecs->clocks = (int*) malloc(sizeof(int) * 2);
cardspecs->clocks[0] = 25175;
cardspecs->clocks[1] = 28322;
}
/* Limit pixel clocks according to chip specifications. */
if (s3_chiptype == S3_864 || s3_chiptype == S3_868) {
/* Limit max clocks according to 95 MHz DCLK spec. */
/* SL: might just be 95000 for 4/8bpp since no pixmux'ing */
/*LIMIT(cardspecs->maxPixelClock4bpp, 95000 * 2);
LIMIT(cardspecs->maxPixelClock8bpp, 95000 * 2);
LIMIT(cardspecs->maxPixelClock16bpp, 95000);*/
/* see explanation below */
//LIMIT(cardspecs->maxPixelClock24bpp, 36000);
/*
* The official 32bpp limit is 47500, but we allow
* 50 MHz for VESA 800x600 timing (actually the
* S3-864 doesn't have the horizontal timing range
* to run unmodified VESA 800x600 72 Hz timings).
*/
//LIMIT(cardspecs->maxPixelClock32bpp, 50000);
}
#ifndef S3_16_COLORS
//cardspecs->maxPixelClock4bpp = 0; /* 16-color doesn't work. */
#endif
/* end: Initialize cardspecs. */
/*__svgalib_driverspecs = &__svgalib_s3_driverspecs;
__svgalib_banked_mem_base=0xa0000;
__svgalib_banked_mem_size=0x10000;
#ifdef S3_LINEAR_SUPPORT
__svgalib_linear_mem_base=s3_linear_base;
__svgalib_linear_mem_size=s3_memory*0x400;
#endif*/
return 0;
}
#define S3_CR(n) (EXT + (0x##n) - 0x30)
#define S3_CR30 S3_CR(30)
#define S3_CR31 S3_CR(31)
#define S3_CR32 S3_CR(32)
#define S3_CR33 S3_CR(33)
#define S3_CR34 S3_CR(34)
#define S3_CR35 S3_CR(35)
#define S3_CR3A S3_CR(3A)
#define S3_CR3B S3_CR(3B)
#define S3_CR3C S3_CR(3C)
#define S3_CR40 S3_CR(40)
#define S3_CR42 S3_CR(42)
#define S3_CR43 S3_CR(43)
#define S3_CR44 S3_CR(44)
#define S3_CR50 S3_CR(50) /* 801+ */
#define S3_CR51 S3_CR(51)
#define S3_CR53 S3_CR(53)
#define S3_CR54 S3_CR(54)
#define S3_CR55 S3_CR(55)
#define S3_CR58 S3_CR(58)
#define S3_CR59 S3_CR(59)
#define S3_CR5A S3_CR(5A)
#define S3_CR5D S3_CR(5D)
#define S3_CR5E S3_CR(5E)
#define S3_CR60 S3_CR(60)
#define S3_CR61 S3_CR(61)
#define S3_CR62 S3_CR(62)
#define S3_CR67 S3_CR(67)
#define S3_CR6A S3_CR(6A)
#define S3_CR6D S3_CR(6D)
/* For debugging, these (non-)registers are read also (but never written). */
#define S3_CR36 S3_CR(36)
#define S3_CR37 S3_CR(37)
#define S3_CR38 S3_CR(38)
#define S3_CR39 S3_CR(39)
#define S3_CR3D S3_CR(3D)
#define S3_CR3E S3_CR(3E)
#define S3_CR3F S3_CR(3F)
#define S3_CR45 S3_CR(45)
#define S3_CR46 S3_CR(46)
#define S3_CR47 S3_CR(47)
#define S3_CR48 S3_CR(48)
#define S3_CR49 S3_CR(49)
#define S3_CR4A S3_CR(4A)
#define S3_CR4B S3_CR(4B)
#define S3_CR4C S3_CR(4C)
#define S3_CR4D S3_CR(4D)
#define S3_CR4E S3_CR(4E)
#define S3_CR4F S3_CR(4F)
#define S3_CR52 S3_CR(52)
#define S3_CR56 S3_CR(56)
#define S3_CR57 S3_CR(57)
#define S3_CR5B S3_CR(5B)
#define S3_CR5C S3_CR(5C)
#define S3_CR5F S3_CR(5F)
#define S3_CR63 S3_CR(63)
#define S3_CR64 S3_CR(64)
#define S3_CR65 S3_CR(65)
#define S3_CR66 S3_CR(66)
#define S3_CR6E S3_CR(6E)
#define S3_CR6F S3_CR(6F)
/* Trio extended SR registers */
#define S3_SR(n) (S3_CR6F + 1 + (0x##n) - 0x08)
#define S3_SR08 S3_SR(08)
#define S3_SR09 S3_SR(09)
#define S3_SR0A S3_SR(0A)
#define S3_SR0D S3_SR(0D)
#define S3_SR10 S3_SR(10)
#define S3_SR11 S3_SR(11)
#define S3_SR12 S3_SR(12)
#define S3_SR13 S3_SR(13)
#define S3_SR15 S3_SR(15)
#define S3_SR18 S3_SR(18)
#define S3_SR1D S3_SR(1D)
#define S3_8514_OFFSET (S3_SR1D + 1)
#define S3_8514_COUNT (1) /* number of 2-byte words */
#define S3_DAC_OFFSET (S3_8514_OFFSET + (S3_8514_COUNT * 2))
#define S3_TOTAL_REGS (S3_DAC_OFFSET /*+ MAX_DAC_STATE*/)
/* 8514 regs */
#define S3_ADVFUNC_CNTL 0
static unsigned short s3_8514regs[S3_8514_COUNT] =
{
/* default assuming text mode */
0x0000U
};
/*
* save S3 registers. Lock registers receive special treatment
* so dumpreg will work under X.
*/
int CS3Graphics::SaveRegisters(unsigned char regs[])
{
unsigned char b, bmax;
unsigned char cr38, cr39, cr40;
cr38 = __svgalib_inCR(0x38);
__svgalib_outCR(0x38, 0x48); /* unlock S3 VGA regs (CR30-CR3B) */
cr39 = __svgalib_inCR(0x39);
__svgalib_outCR(0x39, 0xA5); /* unlock S3 system control (CR40-CR4F) */
/* and extended regs (CR50-CR6D) */
cr40 = __svgalib_inCR(0x40); /* unlock enhanced regs */
__svgalib_outCR(0x40, cr40 | 0x01);
/* retrieve values from private copy */
memcpy(regs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2);
/* get S3 VGA/Ext registers */
bmax = 0x4F;
if (s3_chiptype >= S3_801)
bmax = 0x66;
if (s3_chiptype >= S3_864)
bmax = 0x6D;
for (b = 0x30; b <= bmax; b++)
regs[EXT + b - 0x30] = __svgalib_inCR(b);
/* get S3 ext. SR registers */
/* if (s3_chiptype >= S3_864) { */
if (s3_chiptype == S3_TRIO32 || s3_chiptype == S3_TRIO64
|| s3_chiptype == S3_765) {/* SL: actually Trio32/64/V+ */
regs[S3_SR08] = __svgalib_inSR(0x08);
__svgalib_outSR(0x08, 0x06); /* unlock extended seq regs */
regs[S3_SR09] = __svgalib_inSR(0x09);
regs[S3_SR0A] = __svgalib_inSR(0x0A);
regs[S3_SR0D] = __svgalib_inSR(0x0D);
regs[S3_SR10] = __svgalib_inSR(0x10);
regs[S3_SR11] = __svgalib_inSR(0x11);
regs[S3_SR12] = __svgalib_inSR(0x12);
regs[S3_SR13] = __svgalib_inSR(0x13);
regs[S3_SR15] = __svgalib_inSR(0x15);
regs[S3_SR18] = __svgalib_inSR(0x18);
__svgalib_outSR(0x08, regs[S3_SR08]);
}
//dac_used->saveState(regs + S3_DAC_OFFSET);
/* leave the locks the way we found it */
__svgalib_outCR(0x40, regs[EXT + 0x40 - 0x30] = cr40);
__svgalib_outCR(0x39, regs[EXT + 0x39 - 0x30] = cr39);
__svgalib_outCR(0x38, regs[EXT + 0x38 - 0x30] = cr38);
#if 0
#include "ramdac/IBMRGB52x.h"
do {
unsigned char m, n, df;
printf("pix_fmt = 0x%02X, 8bpp = 0x%02X, 16bpp = 0x%02X, 24bpp = 0x%02X, 32bpp = 0x%02X,\n"
"CR58 = 0x%02X, CR66 = 0x%02X, CR67 = 0x%02X, CR6D = 0x%02X\n",
regs[S3_DAC_OFFSET + IBMRGB_pix_fmt],
regs[S3_DAC_OFFSET + IBMRGB_8bpp],
regs[S3_DAC_OFFSET + IBMRGB_16bpp],
regs[S3_DAC_OFFSET + IBMRGB_24bpp],
regs[S3_DAC_OFFSET + IBMRGB_32bpp],
regs[S3_CR58],
regs[S3_CR66],
regs[S3_CR67],
regs[S3_CR6D]);
m = regs[S3_DAC_OFFSET + IBMRGB_m0 + 4];
n = regs[S3_DAC_OFFSET + IBMRGB_n0 + 4];
df = m >> 6;
m &= ~0xC0;
printf("m = 0x%02X %d, n = 0x%02X %d, df = 0x%02X %d, freq = %.3f\n",
m, m, n, n, df, df, ((m + 65.0) / n) / (8 >> df) * 16.0);
} while (0);
#endif
return S3_DAC_OFFSET - VGA_TOTAL_REGS ;//+ dac_used->stateSize;
}
struct
{
int xdim;
int ydim;
int bytesperpixel;
int colors;
int xbytes;
} __svgalib_infotable[] =
{
{ 640, 480, 1, 256, 640 }
};
ModeInfo *
__svgalib_createModeInfoStructureForSvgalibMode(int mode)
{
ModeInfo *modeinfo;
/* Create the new ModeInfo structure. */
modeinfo = (ModeInfo*) malloc(sizeof(ModeInfo));
modeinfo->width = __svgalib_infotable[mode].xdim;
modeinfo->height = __svgalib_infotable[mode].ydim;
modeinfo->bytesPerPixel = __svgalib_infotable[mode].bytesperpixel;
switch (__svgalib_infotable[mode].colors) {
case 16:
modeinfo->colorBits = 4;
break;
case 256:
modeinfo->colorBits = 8;
break;
case 32768:
modeinfo->colorBits = 15;
modeinfo->blueOffset = 0;
modeinfo->greenOffset = 5;
modeinfo->redOffset = 10;
modeinfo->blueWeight = 5;
modeinfo->greenWeight = 5;
modeinfo->redWeight = 5;
break;
case 65536:
modeinfo->colorBits = 16;
modeinfo->blueOffset = 0;
modeinfo->greenOffset = 5;
modeinfo->redOffset = 11;
modeinfo->blueWeight = 5;
modeinfo->greenWeight = 6;
modeinfo->redWeight = 5;
break;
case 256 * 65536:
modeinfo->colorBits = 24;
modeinfo->blueOffset = 0;
modeinfo->greenOffset = 8;
modeinfo->redOffset = 16;
modeinfo->blueWeight = 8;
modeinfo->greenWeight = 8;
modeinfo->redWeight = 8;
break;
}
modeinfo->bitsPerPixel = modeinfo->bytesPerPixel * 8;
if (__svgalib_infotable[mode].colors == 16)
modeinfo->bitsPerPixel = 4;
modeinfo->lineWidth = __svgalib_infotable[mode].xbytes;
return modeinfo;
}
/*
* Clock allowance in 1/1000ths. 10 (1%) corresponds to a 250 kHz
* deviation at 25 MHz, 1 MHz at 100 MHz
*/
#define CLOCK_ALLOWANCE 10
#define PROGRAMMABLE_CLOCK_MAGIC_NUMBER 0x1234
static int findclock(int clock, CardSpecs * cardspecs)
{
int i;
/* Find a clock that is close enough. */
for (i = 0; i < cardspecs->nClocks; i++) {
int diff;
diff = cardspecs->clocks[i] - clock;
if (diff < 0)
diff = -diff;
if (diff * 1000 / clock < CLOCK_ALLOWANCE)
return i;
}
/* Try programmable clocks if available. */
if (cardspecs->flags & CLOCK_PROGRAMMABLE) {
int diff;
diff = cardspecs->matchProgrammableClock(clock) - clock;
if (diff < 0)
diff = -diff;
if (diff * 1000 / clock < CLOCK_ALLOWANCE)
return PROGRAMMABLE_CLOCK_MAGIC_NUMBER;
}
/* No close enough clock found. */
return -1;
}
typedef struct {
/* refresh ranges in Hz */
unsigned min;
unsigned max;
} RefreshRange;
RefreshRange __svgalib_horizsync =
{31500U, 0U}; /* horz. refresh (Hz) min, max */
RefreshRange __svgalib_vertrefresh =
{50U, 70U}; /* vert. refresh (Hz) min, max */
/*
* SYNC_ALLOWANCE is in percent
* 1% corresponds to a 315 Hz deviation at 31.5 kHz, 1 Hz at 100 Hz
*/
#define SYNC_ALLOWANCE 1
#define INRANGE(x,y) \
((x) > __svgalib_##y.min * (1.0f - SYNC_ALLOWANCE / 100.0f) && \
(x) < __svgalib_##y.max * (1.0f + SYNC_ALLOWANCE / 100.0f))
/*
* Check monitor spec.
*/
static int timing_within_monitor_spec(MonitorModeTiming * mmtp)
{
float hsf; /* Horz. sync freq in Hz */
float vsf; /* Vert. sync freq in Hz */
hsf = mmtp->pixelClock * 1000.0f / mmtp->HTotal;
vsf = hsf / mmtp->VTotal;
if ((mmtp->flags & INTERLACED))
vsf *= 2.0f;
if ((mmtp->flags & DOUBLESCAN))
vsf /= 2.0f;
#if 1
wprintf(L"hsf = %f (in:%d), vsf = %f (in:%d)\n",
hsf / 1000, (int) INRANGE(hsf, horizsync),
vsf, (int) INRANGE(vsf, vertrefresh));
#endif
return INRANGE(hsf, horizsync) && INRANGE(vsf, vertrefresh);
}
static MonitorModeTiming *search_mode(MonitorModeTiming * timings,
int maxclock,
ModeInfo * modeinfo,
CardSpecs * cardspecs)
{
int bestclock = 0;
MonitorModeTiming *besttiming = NULL, *t;
/*
* bestclock is the highest pixel clock found for the resolution
* in the mode timings, within the spec of the card and
* monitor.
* besttiming holds a pointer to timing with this clock.
*/
/* Search the timings for the best matching mode. */
for (t = timings; t; t = t->next)
if (t->HDisplay == modeinfo->width
&& t->VDisplay == modeinfo->height
&& timing_within_monitor_spec(t)
&& t->pixelClock <= maxclock
&& t->pixelClock > bestclock
&& cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
t->pixelClock,
t->HTotal)
<= cardspecs->maxHorizontalCrtc
/* Find the clock (possibly scaled by mapClock). */
&& findclock(cardspecs->mapClock(modeinfo->bitsPerPixel,
t->pixelClock), cardspecs) != -1
) {
bestclock = t->pixelClock;
besttiming = t;
}
return besttiming;
}
MonitorModeTiming __svgalib_standard_timings[] =
{
#define S __svgalib_standard_timings
/* 320x200 @ 70 Hz, 31.5 kHz hsync */
{12588, 320, 336, 384, 400, 200, 204, 206, 225, DOUBLESCAN, S + 1},
/* 320x200 @ 83 Hz, 37.5 kHz hsync */
{13333, 320, 336, 384, 400, 200, 204, 206, 225, DOUBLESCAN, S + 2},
/* 320x240 @ 60 Hz, 31.5 kHz hsync */
{12588, 320, 336, 384, 400, 240, 245, 247, 263, DOUBLESCAN, S + 3},
/* 320x240 @ 72Hz, 38.5 kHz hsync */
{15000, 320, 336, 384, 400, 240, 244, 246, 261, DOUBLESCAN, S + 4},
/* 320x400 @ 70 Hz, 31.5 kHz hsync */
{12588, 320, 336, 384, 400, 400, 408, 412, 450, 0, S + 5},
/* 320x400 @ 83 Hz, 37.5 kHz hsync */
{13333, 320, 336, 384, 400, 400, 408, 412, 450, 0, S + 6},
/* 320x480 @ 60 Hz, 31.5 kHz hsync */
{12588, 320, 336, 384, 400, 480, 490, 494, 526, 0, S + 7},
/* 320x480 @ 72Hz, 38.5 kHz hsync */
{15000, 320, 336, 384, 400, 480, 488, 492, 522, 0, S + 8},
/* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
{18000, 400, 416, 448, 512, 300, 301, 302, 312, DOUBLESCAN, S+9},
/* 400x300 @ 60 Hz, 37.8 kHz hsync */
{20000, 400, 416, 480, 528, 300, 301, 303, 314, DOUBLESCAN, S+10},
/* 400x300 @ 72 Hz, 48.0 kHz hsync*/
{25000, 400, 424, 488, 520, 300, 319, 322, 333, DOUBLESCAN, S+11},
/* 400x600 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
{18000, 400, 416, 448, 512, 600, 602, 604, 624, 0, S+12},
/* 400x600 @ 60 Hz, 37.8 kHz hsync */
{20000, 400, 416, 480, 528, 600, 602, 606, 628, 0, S+13},
/* 400x600 @ 72 Hz, 48.0 kHz hsync*/
{25000, 400, 424, 488, 520, 600, 639, 644, 666, 0, S+14},
/* 512x384 @ 67Hz */
{19600, 512, 522, 598, 646, 384, 418, 426, 454, 0, S+15 },
/* 512x384 @ 86Hz */
{25175, 512, 522, 598, 646, 384, 418, 426, 454,0, S+16},
/* 512x480 @ 55Hz */
{19600, 512, 522, 598, 646, 480, 500, 510, 550, 0, S+17},
/* 512x480 @ 71Hz */
{25175, 512, 522, 598, 646, 480, 500, 510, 550,0, S+18},
/* 640x400 at 70 Hz, 31.5 kHz hsync */
{25175, 640, 664, 760, 800, 400, 409, 411, 450, 0, S + 19},
/* 640x480 at 60 Hz, 31.5 kHz hsync */
{25175, 640, 664, 760, 800, 480, 491, 493, 525, 0, S + 20},
/* 640x480 at 72 Hz, 36.5 kHz hsync */
{31500, 640, 680, 720, 864, 480, 488, 491, 521, 0, S + 21},
/* 800x600 at 56 Hz, 35.15 kHz hsync */
{36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0, S + 22},
/* 800x600 at 60 Hz, 37.8 kHz hsync */
{40000, 800, 840, 968, 1056, 600, 601, 605, 628, PHSYNC | PVSYNC, S + 23},
/* 800x600 at 72 Hz, 48.0 kHz hsync */
{50000, 800, 856, 976, 1040, 600, 637, 643, 666, PHSYNC | PVSYNC, S + 24},
/* 960x720 @ 70Hz */
{66000, 960, 984, 1112, 1248, 720, 723, 729, 756, NHSYNC | NVSYNC, S+25},
/* 960x720* interlaced, 35.5 kHz hsync */
{40000, 960, 984, 1192, 1216, 720, 728, 784, 817, INTERLACED, S + 26},
/* 1024x768 at 87 Hz interlaced, 35.5 kHz hsync */
{44900, 1024, 1048, 1208, 1264, 768, 776, 784, 817, INTERLACED, S + 27},
/* 1024x768 at 100 Hz, 40.9 kHz hsync */
{55000, 1024, 1048, 1208, 1264, 768, 776, 784, 817, INTERLACED, S + 28},
/* 1024x768 at 60 Hz, 48.4 kHz hsync */
{65000, 1024, 1032, 1176, 1344, 768, 771, 777, 806, NHSYNC | NVSYNC, S + 29},
/* 1024x768 at 70 Hz, 56.6 kHz hsync */
{75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, NHSYNC | NVSYNC, S + 30},
/* 1152x864 at 59.3Hz */
{85000, 1152, 1214, 1326, 1600, 864, 870, 885, 895, 0, S+31},
/* 1280x1024 at 87 Hz interlaced, 51 kHz hsync */
{80000, 1280, 1296, 1512, 1568, 1024, 1025, 1037, 1165, INTERLACED, S + 32},
/* 1024x768 at 76 Hz, 62.5 kHz hsync */
{85000, 1024, 1032, 1152, 1360, 768, 784, 787, 823, 0, S + 33},
/* 1280x1024 at 60 Hz, 64.3 kHz hsync */
{110000, 1280, 1328, 1512, 1712, 1024, 1025, 1028, 1054, 0, S + 34},
/* 1280x1024 at 74 Hz, 78.9 kHz hsync */
{135000, 1280, 1312, 1456, 1712, 1024, 1027, 1030, 1064, 0, S + 35},
/* 1600x1200 at 68Hz */
{188500, 1600, 1792, 1856, 2208, 1200, 1202, 1205, 1256, 0, S + 36},
/* 1600x1200 at 75 Hz */
{198000, 1600, 1616, 1776, 2112, 1200, 1201, 1204, 1250, 0, S + 37},
/* 720x540 at 56 Hz, 35.15 kHz hsync */
{32400, 720, 744, 808, 920, 540, 541, 543, 563, 0, S + 38},
/* 720x540 at 60 Hz, 37.8 kHz hsync */
{36000, 720, 760, 872, 952, 540, 541, 545, 565, 0, S + 39},
/* 720x540 at 72 Hz, 48.0 kHz hsync */
{45000, 720, 768, 880, 936, 540, 552, 558, 599, 0, S + 40},
/* 1072x600 at 57 Hz interlaced, 35.5 kHz hsync */
{44900, 1072, 1096, 1208, 1264, 600, 602, 604, 625, 0, S + 41},
/* 1072x600 at 65 Hz, 40.9 kHz hsync */
{55000, 1072, 1096, 1208, 1264, 600, 602, 604, 625, 0, S + 42},
/* 1072x600 at 78 Hz, 48.4 kHz hsync */
{65000, 1072, 1088, 1184, 1344, 600, 603, 607, 625, NHSYNC | NVSYNC, S + 43},
/* 1072x600 at 90 Hz, 56.6 kHz hsync */
{75000, 1072, 1096, 1200, 1328, 768, 603, 607, 625, NHSYNC | NVSYNC, S + 44},
/* 1072x600 at 100 Hz, 62.5 kHz hsync */
{85000, 1072, 1088, 1160, 1360, 768, 603, 607, 625, 0, NULL},
#undef S
};
int __svgalib_getmodetiming(ModeTiming * modetiming, ModeInfo * modeinfo,
CardSpecs * cardspecs)
{
int maxclock, desiredclock;
MonitorModeTiming *besttiming=NULL;
/*if(force_timing){
if(timing_within_monitor_spec(force_timing) &&
force_timing->HDisplay == modeinfo->width &&
force_timing->VDisplay == modeinfo->height)
{
besttiming=force_timing;
};
};*/
/* Get the maximum pixel clock for the depth of the requested mode. */
if (modeinfo->bitsPerPixel == 4)
maxclock = cardspecs->maxPixelClock4bpp;
else if (modeinfo->bitsPerPixel == 8)
maxclock = cardspecs->maxPixelClock8bpp;
else if (modeinfo->bitsPerPixel == 16)
{
if ((cardspecs->flags & NO_RGB16_565)
&& modeinfo->greenWeight == 6)
return 1; /* No 5-6-5 RGB. */
maxclock = cardspecs->maxPixelClock16bpp;
}
else if (modeinfo->bitsPerPixel == 24)
maxclock = cardspecs->maxPixelClock24bpp;
else if (modeinfo->bitsPerPixel == 32)
maxclock = cardspecs->maxPixelClock32bpp;
else
maxclock = 0;
/*
* Check user defined timings first.
* If there is no match within these, check the standard timings.
*/
//if(!besttiming)
//besttiming = search_mode(user_timings, maxclock, modeinfo, cardspecs);
besttiming = __svgalib_standard_timings + 20;
if (!besttiming) {
besttiming = search_mode(__svgalib_standard_timings, maxclock, modeinfo, cardspecs);
if (!besttiming)
{
wprintf(L"besttiming == NULL\n");
return 1;
}
}
/*
* Copy the selected timings into the result, which may
* be adjusted for the chipset.
*/
modetiming->flags = besttiming->flags;
modetiming->pixelClock = besttiming->pixelClock; /* Formal clock. */
/*
* We know a close enough clock is available; the following is the
* exact clock that fits the mode. This is probably different
* from the best matching clock that will be programmed.
*/
desiredclock = cardspecs->mapClock(modeinfo->bitsPerPixel,
besttiming->pixelClock);
/* Fill in the best-matching clock that will be programmed. */
modetiming->selectedClockNo = findclock(desiredclock, cardspecs);
if (modetiming->selectedClockNo == PROGRAMMABLE_CLOCK_MAGIC_NUMBER) {
modetiming->programmedClock =
cardspecs->matchProgrammableClock(desiredclock);
modetiming->flags |= USEPROGRCLOCK;
} else
modetiming->programmedClock = cardspecs->clocks[
modetiming->selectedClockNo];
modetiming->HDisplay = besttiming->HDisplay;
modetiming->HSyncStart = besttiming->HSyncStart;
modetiming->HSyncEnd = besttiming->HSyncEnd;
modetiming->HTotal = besttiming->HTotal;
if (cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
modetiming->programmedClock,
besttiming->HTotal)
!= besttiming->HTotal) {
/* Horizontal CRTC timings are scaled in some way. */
modetiming->CrtcHDisplay =
cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
modetiming->programmedClock,
besttiming->HDisplay);
modetiming->CrtcHSyncStart =
cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
modetiming->programmedClock,
besttiming->HSyncStart);
modetiming->CrtcHSyncEnd =
cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
modetiming->programmedClock,
besttiming->HSyncEnd);
modetiming->CrtcHTotal =
cardspecs->mapHorizontalCrtc(modeinfo->bitsPerPixel,
modetiming->programmedClock,
besttiming->HTotal);
modetiming->flags |= HADJUSTED;
} else {
modetiming->CrtcHDisplay = besttiming->HDisplay;
modetiming->CrtcHSyncStart = besttiming->HSyncStart;
modetiming->CrtcHSyncEnd = besttiming->HSyncEnd;
modetiming->CrtcHTotal = besttiming->HTotal;
}
modetiming->VDisplay = besttiming->VDisplay;
modetiming->VSyncStart = besttiming->VSyncStart;
modetiming->VSyncEnd = besttiming->VSyncEnd;
modetiming->VTotal = besttiming->VTotal;
if (modetiming->flags & DOUBLESCAN){
modetiming->VDisplay <<= 1;
modetiming->VSyncStart <<= 1;
modetiming->VSyncEnd <<= 1;
modetiming->VTotal <<= 1;
}
modetiming->CrtcVDisplay = modetiming->VDisplay;
modetiming->CrtcVSyncStart = modetiming->VSyncStart;
modetiming->CrtcVSyncEnd = modetiming->VSyncEnd;
modetiming->CrtcVTotal = modetiming->VTotal;
if (((modetiming->flags & INTERLACED)
&& (cardspecs->flags & INTERLACE_DIVIDE_VERT))
|| (modetiming->VTotal >= 1024
&& (cardspecs->flags & GREATER_1024_DIVIDE_VERT))) {
/*
* Card requires vertical CRTC timing to be halved for
* interlaced modes, or for all modes with vertical
* timing >= 1024.
*/
modetiming->CrtcVDisplay /= 2;
modetiming->CrtcVSyncStart /= 2;
modetiming->CrtcVSyncEnd /= 2;
modetiming->CrtcVTotal /= 2;
modetiming->flags |= VADJUSTED;
}
current_timing=besttiming;
return 0; /* Succesful. */
}
/* Return non-zero if mode is available */
bool CS3Graphics::ModeAvailable(int mode)
{
//struct info *info;
ModeInfo *modeinfo;
ModeTiming *modetiming;
//if (mode < G640x480x256 || mode == G720x348x2)
//return __svgalib_vga_driverspecs.modeavailable(mode);
/* Enough memory? */
//info = &__svgalib_infotable[mode];
//if (s3_memory * 1024 < info->ydim * s3_adjlinewidth(info->xbytes))
//return 0;
modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
modetiming = (ModeTiming*) malloc(sizeof(ModeTiming));
if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs))
{
wprintf(L"__svgalib_getmodetiming failed\n");
free(modetiming);
free(modeinfo);
return 0;
}
free(modetiming);
free(modeinfo);
return true;
}
/*
* Adjust the display width. This is necessary for the graphics
* engine if acceleration is used. However it will require more
* memory making some modes unavailable.
*/
int CS3Graphics::AdjustLineWidth(int oldwidth)
{
if (s3_chiptype < S3_801)
return 1024;
#ifdef S3_USE_GRAPHIC_ENGINE
if (oldwidth <= 640)
return 640;
if (oldwidth <= 800)
return 800;
if (oldwidth <= 1024)
return 1024;
if (!(s3_flags & S3_OLD_STEPPING))
if (oldwidth <= 1152)
return 1152;
if (oldwidth <= 1280)
return 1280;
if (oldwidth <= 1600 && s3_chiptype >= S3_864)
return 1600;
return 2048;
#else
return oldwidth;
#endif
}
#define VGAREG_CR(i) (i)
#define VGAREG_AR(i) (i + VGA_ATC_OFFSET)
#define VGAREG_GR(i) (i + VGA_GRAPHICS_OFFSET)
#define VGAREG_SR(i) (i + VGA_SEQUENCER_OFFSET)
#define VGA_CR0 VGAREG_CR(0x00)
#define VGA_CR1 VGAREG_CR(0x01)
#define VGA_CR2 VGAREG_CR(0x02)
#define VGA_CR3 VGAREG_CR(0x03)
#define VGA_CR4 VGAREG_CR(0x04)
#define VGA_CR5 VGAREG_CR(0x05)
#define VGA_CR6 VGAREG_CR(0x06)
#define VGA_CR7 VGAREG_CR(0x07)
#define VGA_CR8 VGAREG_CR(0x08)
#define VGA_CR9 VGAREG_CR(0x09)
#define VGA_CRA VGAREG_CR(0x0A)
#define VGA_CRB VGAREG_CR(0x0B)
#define VGA_CRC VGAREG_CR(0x0C)
#define VGA_CRD VGAREG_CR(0x0D)
#define VGA_CRE VGAREG_CR(0x0E)
#define VGA_CRF VGAREG_CR(0x0F)
#define VGA_CR10 VGAREG_CR(0x10)
#define VGA_CR11 VGAREG_CR(0x11)
#define VGA_CR12 VGAREG_CR(0x12)
#define VGA_CR13 VGAREG_CR(0x13)
#define VGA_SCANLINEOFFSET VGAREG_CR(0x13)
#define VGA_CR14 VGAREG_CR(0x14)
#define VGA_CR15 VGAREG_CR(0x15)
#define VGA_CR16 VGAREG_CR(0x16)
#define VGA_CR17 VGAREG_CR(0x17)
#define VGA_CR18 VGAREG_CR(0x18)
#define VGA_AR0 VGAREG_AR(0x00)
#define VGA_AR10 VGAREG_AR(0x10)
#define VGA_AR11 VGAREG_AR(0x11)
#define VGA_AR12 VGAREG_AR(0x12)
#define VGA_AR13 VGAREG_AR(0x13)
#define VGA_AR14 VGAREG_AR(0x14)
#define VGA_GR0 VGAREG_GR(0x00)
#define VGA_GR1 VGAREG_GR(0x01)
#define VGA_GR2 VGAREG_GR(0x02)
#define VGA_GR3 VGAREG_GR(0x03)
#define VGA_GR4 VGAREG_GR(0x04)
#define VGA_GR5 VGAREG_GR(0x05)
#define VGA_GR6 VGAREG_GR(0x06)
#define VGA_GR7 VGAREG_GR(0x07)
#define VGA_GR8 VGAREG_GR(0x08)
#define VGA_SR0 VGAREG_SR(0x00)
#define VGA_SR1 VGAREG_SR(0x01)
#define VGA_SR2 VGAREG_SR(0x02)
#define VGA_SR3 VGAREG_SR(0x03)
#define VGA_SR4 VGAREG_SR(0x04)
/*
* Setup VGA registers for SVGA mode timing. Adapted from XFree86,
* vga256/vga/vgaHW.c vgaHWInit().
*
* Note that VGA registers are set up in a way that is common for
* SVGA modes. This is not particularly useful for standard VGA
* modes, since VGA does not have a clean packed-pixel mode.
*/
void __svgalib_setup_VGA_registers(unsigned char *moderegs, ModeTiming * modetiming,
ModeInfo * modeinfo)
{
int i;
/* Sync Polarities */
if ((modetiming->flags & (PHSYNC | NHSYNC)) &&
(modetiming->flags & (PVSYNC | NVSYNC))) {
/*
* If both horizontal and vertical polarity are specified,
* set them as specified.
*/
moderegs[VGA_MISCOUTPUT] = 0x23;
if (modetiming->flags & NHSYNC)
moderegs[VGA_MISCOUTPUT] |= 0x40;
if (modetiming->flags & NVSYNC)
moderegs[VGA_MISCOUTPUT] |= 0x80;
} else {
/*
* Otherwise, calculate the polarities according to
* monitor standards.
*/
if (modetiming->VDisplay < 400)
moderegs[VGA_MISCOUTPUT] = 0xA3;
else if (modetiming->VDisplay < 480)
moderegs[VGA_MISCOUTPUT] = 0x63;
else if (modetiming->VDisplay < 768)
moderegs[VGA_MISCOUTPUT] = 0xE3;
else
moderegs[VGA_MISCOUTPUT] = 0x23;
}
/* Sequencer */
moderegs[VGA_SR0] = 0x00;
if (modeinfo->bitsPerPixel == 4)
moderegs[VGA_SR0] = 0x02;
moderegs[VGA_SR1] = 0x01;
moderegs[VGA_SR2] = 0x0F; /* Bitplanes. */
moderegs[VGA_SR3] = 0x00;
moderegs[VGA_SR4] = 0x0E;
if (modeinfo->bitsPerPixel == 4)
moderegs[VGA_SR4] = 0x06;
/* CRTC Timing */
moderegs[VGA_CR0] = (modetiming->CrtcHTotal / 8) - 5;
moderegs[VGA_CR1] = (modetiming->CrtcHDisplay / 8) - 1;
moderegs[VGA_CR2] = (modetiming->CrtcHSyncStart / 8) - 1;
moderegs[VGA_CR3] = ((modetiming->CrtcHSyncEnd / 8) & 0x1F) | 0x80;
moderegs[VGA_CR4] = (modetiming->CrtcHSyncStart / 8);
moderegs[VGA_CR5] = (((modetiming->CrtcHSyncEnd / 8) & 0x20) << 2)
| ((modetiming->CrtcHSyncEnd / 8) & 0x1F);
moderegs[VGA_CR6] = (modetiming->CrtcVTotal - 2) & 0xFF;
moderegs[VGA_CR7] = (((modetiming->CrtcVTotal - 2) & 0x100) >> 8)
| (((modetiming->CrtcVDisplay - 1) & 0x100) >> 7)
| ((modetiming->CrtcVSyncStart & 0x100) >> 6)
| (((modetiming->CrtcVSyncStart) & 0x100) >> 5)
| 0x10
| (((modetiming->CrtcVTotal - 2) & 0x200) >> 4)
| (((modetiming->CrtcVDisplay - 1) & 0x200) >> 3)
| ((modetiming->CrtcVSyncStart & 0x200) >> 2);
moderegs[VGA_CR8] = 0x00;
moderegs[VGA_CR9] = ((modetiming->CrtcVSyncStart & 0x200) >> 4) | 0x40;
if (modetiming->flags & DOUBLESCAN)
moderegs[VGA_CR9] |= 0x80;
moderegs[VGA_CRA] = 0x00;
moderegs[VGA_CRB] = 0x00;
moderegs[VGA_CRC] = 0x00;
moderegs[VGA_CRD] = 0x00;
moderegs[VGA_CRE] = 0x00;
moderegs[VGA_CRF] = 0x00;
moderegs[VGA_CR10] = modetiming->CrtcVSyncStart & 0xFF;
moderegs[VGA_CR11] = (modetiming->CrtcVSyncEnd & 0x0F) | 0x20;
moderegs[VGA_CR12] = (modetiming->CrtcVDisplay - 1) & 0xFF;
moderegs[VGA_CR13] = modeinfo->lineWidth >> 4; /* Just a guess. */
moderegs[VGA_CR14] = 0x00;
moderegs[VGA_CR15] = modetiming->CrtcVSyncStart & 0xFF;
moderegs[VGA_CR16] = (modetiming->CrtcVSyncStart + 1) & 0xFF;
moderegs[VGA_CR17] = 0xC3;
if (modeinfo->bitsPerPixel == 4)
moderegs[VGA_CR17] = 0xE3;
moderegs[VGA_CR18] = 0xFF;
/* Graphics Controller */
moderegs[VGA_GR0] = 0x00;
moderegs[VGA_GR1] = 0x00;
moderegs[VGA_GR2] = 0x00;
moderegs[VGA_GR3] = 0x00;
moderegs[VGA_GR4] = 0x00;
moderegs[VGA_GR5] = 0x40;
if (modeinfo->bitsPerPixel == 4)
moderegs[VGA_GR5] = 0x02;
moderegs[VGA_GR6] = 0x05;
moderegs[VGA_GR7] = 0x0F;
moderegs[VGA_GR8] = 0xFF;
/* Attribute Controller */
for (i = 0; i < 16; i++)
moderegs[VGA_AR0 + i] = i;
moderegs[VGA_AR10] = 0x41;
if (modeinfo->bitsPerPixel == 4)
moderegs[VGA_AR10] = 0x01; /* was 0x81 */
/* Attribute register 0x11 is the overscan color. */
moderegs[VGA_AR12] = 0x0F;
moderegs[VGA_AR13] = 0x00;
moderegs[VGA_AR14] = 0x00;
}
/* Color modes. */
#define CLUT8_6 0
#define CLUT8_8 1
#define RGB16_555 2
#define RGB16_565 3
#define RGB24_888_B 4 /* 3 bytes per pixel, blue byte first. */
#define RGB32_888_B 5 /* 4 bytes per pixel. */
/*
* This function converts a number of significant color bits to a matching
* DAC mode type as defined in the RAMDAC interface.
*/
int __svgalib_colorbits_to_colormode(int bpp, int colorbits)
{
if (colorbits == 8)
return CLUT8_6;
if (colorbits == 15)
return RGB16_555;
if (colorbits == 16)
return RGB16_565;
if (colorbits == 24) {
if (bpp == 24)
return RGB24_888_B;
else
return RGB32_888_B;
}
return CLUT8_6;
}
/*
* Initialize register state for a mode.
*/
void CS3Graphics::InitializeMode(unsigned char *moderegs,
ModeTiming * modetiming, ModeInfo * modeinfo)
{
/* Get current values. */
SaveRegisters(moderegs);
/* Set up the standard VGA registers for a generic SVGA. */
__svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
/* Set up the extended register values, including modifications */
/* of standard VGA registers. */
moderegs[VGA_SR0] = 0x03;
moderegs[VGA_CR13] = modeinfo->lineWidth >> 3;
moderegs[VGA_CR17] = 0xE3;
if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 2048)
moderegs[S3_CR31] = 0x8F;
else
moderegs[S3_CR31] = 0x8D;
#ifdef S3_LINEAR_MODE_BANKING_864
if (s3_chiptype >= S3_864) {
/* moderegs[S3_ENHANCEDMODE] |= 0x01; */
/* Enable enhanced memory mode. */
moderegs[S3_CR31] |= 0x04;
/* Enable banking via CR6A in linear mode. */
moderegs[S3_CR31] |= 0x01;
}
#endif
moderegs[S3_CR32] = 0;
moderegs[S3_CR33] = 0x20;
moderegs[S3_CR34] = 0x10; /* 1024 */
moderegs[S3_CR35] = 0;
/* Call cebank() here when setting registers. */
if (modeinfo->bitsPerPixel >= 8) {
moderegs[S3_CR3A] = 0xB5;
if (s3_chiptype == S3_928)
/* ARI: Turn on CHAIN4 for 928, since __svgalib_setup_VGA_registers
initializes ModeX */
moderegs[VGA_CR14] = 0x60;
} else {
/* 16 color mode */
moderegs[VGA_CR13] = modeinfo->lineWidth >> 1;
moderegs[VGA_GR0] = 0x0F;
moderegs[VGA_GR1] = 0x0F;
moderegs[VGA_GR5] = 0x00; /* write mode 0 */
moderegs[VGA_AR11] = 0x00;
moderegs[S3_CR3A] = 0x85;
}
moderegs[S3_CR3B] = (moderegs[VGA_CR0] + moderegs[VGA_CR4] + 1) / 2;
moderegs[S3_CR3C] = moderegs[VGA_CR0] / 2;
if (s3_chiptype == S3_911) {
moderegs[S3_CR40] &= 0xF2;
moderegs[S3_CR40] |= 0x09;
} else if (s3_flags & S3_LOCALBUS) {
moderegs[S3_CR40] &= 0xF2;
/* Pegasus wants 0x01 for zero wait states. */
#ifdef S3_0_WAIT_805_864
moderegs[S3_CR40] |= 0x09; /* use fifo + 0 wait state */
#else
moderegs[S3_CR40] |= 0x05;
#endif
} else {
moderegs[S3_CR40] &= 0xF6;
moderegs[S3_CR40] |= 0x01;
}
if (modeinfo->bitsPerPixel >= 24) {
/* 24/32 bit color */
if (s3_chiptype == S3_864 || s3_chiptype == S3_964)
moderegs[S3_CR43] = 0x08;
else if (s3_chiptype == S3_928 /*&& dac_used->id == SIERRA_15025*/)
moderegs[S3_CR43] = 0x01; /* ELSA Winner 1000 */
} else if (modeinfo->bitsPerPixel >= 15) {
/* 15/16 bit color */
if (s3_chiptype <= S3_864 || s3_chiptype >= S3_866) { /* XXXX Trio? */
moderegs[S3_CR43] = 0x08;
//if (dac_used->id == IBMRGB52x)
//moderegs[S3_CR43] = 0x10;
//else
if (s3_chiptype == S3_928 /*&& dac_used->id == SIERRA_15025*/)
moderegs[S3_CR43] = 0x01;
if (s3_chiptype <= S3_924 /*&& dac_used->id != NORMAL_DAC*/)
moderegs[S3_CR43] = 0x01;
} else
/* XXXX some DAC might need this; XF86 source says... */
moderegs[S3_CR43] = 0x09;
} else {
/* 4/8 bit color */
moderegs[S3_CR43] = 0x00;
}
if (s3_chiptype >= S3_924 && s3_chiptype <= S3_928) { /* different for 864+ */
s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002;
if ((s3_chiptype == S3_928 && modeinfo->bitsPerPixel != 4) || !(s3_flags & S3_OLD_STEPPING))
s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001;
if (modeinfo->bitsPerPixel == 4)
s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004;
#if 0
/* 864 databook says it is for enhanced 4bpp */
if (modeinfo->lineWidth > 640)
s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004;
#endif
} else if (s3_chiptype == S3_968) {
s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002;
if (modeinfo->bitsPerPixel == 4)
s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004;
#ifdef PIXEL_MULTIPLEXING
else
s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001;
#endif
} else if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 1024)
s3_8514regs[S3_ADVFUNC_CNTL] = 0x0007;
else
s3_8514regs[S3_ADVFUNC_CNTL] = 0x0003;
moderegs[S3_CR44] = 0;
/* Skip CR45, 'hi/truecolor cursor color enable'. */
if (s3_chiptype >= S3_801) {
int m, n; /* for FIFO balancing */
/* XXXX Not all chips support all widths. */
moderegs[S3_CR50] &= ~0xF1;
switch (modeinfo->bitsPerPixel) {
case 16:
moderegs[S3_CR50] |= 0x10;
break;
case 24: /* XXXX 868/968 only */
if (s3_chiptype >= S3_868)
moderegs[S3_CR50] |= 0x20;
break;
case 32:
moderegs[S3_CR50] |= 0x30;
break;
}
switch (modeinfo->lineWidth / modeinfo->bytesPerPixel) {
case 640:
moderegs[S3_CR50] |= 0x40;
break;
case 800:
moderegs[S3_CR50] |= 0x80;
break;
case 1152:
if (!(s3_flags & S3_OLD_STEPPING)) {
moderegs[S3_CR50] |= 0x01;
break;
} /* else fall through */
case 1280:
moderegs[S3_CR50] |= 0xC0;
break;
case 1600:
moderegs[S3_CR50] |= 0x81;
break;
/* 1024/2048 no change. */
}
moderegs[S3_CR51] &= 0xC0;
moderegs[S3_CR51] |= (modeinfo->lineWidth >> 7) & 0x30;
/* moderegs[S3_CR53] |= 0x10; *//* Enable MMIO. */
/* moderegs[S3_CR53] |= 0x20; *//* DRAM interleaving for S3_805i with 2MB */
n = 0xFF;
if (s3_chiptype >= S3_864 ||
s3_chiptype == S3_801 || s3_chiptype == S3_805) {
/*
* CRT FIFO balancing for DRAM cards and 964/968
* in VGA mode.
*/
int clock, mclk;
if (modeinfo->bitsPerPixel < 8) {
clock = modetiming->pixelClock;
} else {
clock = modetiming->pixelClock *
modeinfo->bytesPerPixel;
}
if (s3_memory < 2048 || s3_chiptype == S3_TRIO32)
clock *= 2;
if (s3Mclk > 0)
mclk = s3Mclk;
else if (s3_chiptype == S3_801 || s3_chiptype == S3_805)
mclk = 50000; /* Assumption. */
else
mclk = 60000; /* Assumption. */
m = (int) ((mclk / 1000.0 * .72 + 16.867) * 89.736 / (clock / 1000.0 + 39) - 21.1543);
if (s3_memory < 2048 || s3_chiptype == S3_TRIO32)
m /= 2;
if (m > 31)
m = 31;
else if (m < 0) {
m = 0;
n = 16;
}
} else if (s3_memory == 512 || modetiming->HDisplay > 1200)
m = 0;
else if (s3_memory == 1024)
m = 2;
else
m = 20;
moderegs[S3_CR54] = m << 3;
moderegs[S3_CR60] = n;
moderegs[S3_CR55] &= 0x08;
moderegs[S3_CR55] |= 0x40;
#ifdef S3_LINEAR_MODE_BANKING_864
if (s3_chiptype >= S3_864) {
if (modeinfo->bitsPerPixel >= 8) {
/* Enable linear addressing. */
moderegs[S3_CR58] |= 0x10;
/* Set window size to 64K. */
moderegs[S3_CR58] &= ~0x03;
/* Assume CR59/5A are correctly set up for 0xA0000. */
/* Set CR6A linear bank to zero. */
moderegs[S3_CR6A] &= ~0x3F;
/* use alternate __svgalib_setpage() function */
__svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage864;
} else {
/* doesn't work for 4bpp. */
__svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage;
}
}
#endif
#ifdef S3_LINEAR_SUPPORT
moderegs[S3_CR59] = s3_cr59;
moderegs[S3_CR5A] = s3_cr5A;
#endif
/* Extended CRTC timing. */
moderegs[S3_CR5E] =
(((modetiming->CrtcVTotal - 2) & 0x400) >> 10) |
(((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) |
(((modetiming->CrtcVSyncStart) & 0x400) >> 8) |
(((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40;
{
int i, j;
i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) |
((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) |
((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) |
((modetiming->CrtcHSyncStart & 0x800) >> 7);
if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64)
i |= 0x08;
if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32)
i |= 0x20;
j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) +
moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2);
if (j - (moderegs[VGA_CR4] + ((i & 0x10) << 4)) < 4) {
if (moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4 <= moderegs[VGA_CR0] + ((i & 0x01) << 8))
j = moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4;
else
j = moderegs[VGA_CR0] + ((i & 0x01) << 8) + 1;
}
moderegs[S3_CR3B] = j & 0xFF;
i |= (j & 0x100) >> 2;
/* Interlace mode frame offset. */
moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2;
moderegs[S3_CR5D] = (moderegs[S3_CR5D] & 0x80) | i;
}
{
int i;
if (modeinfo->bitsPerPixel < 8)
i = modetiming->HDisplay / 4 + 1;
else
i = modetiming->HDisplay *
modeinfo->bytesPerPixel / 4 + 1;
moderegs[S3_CR61] = (i >> 8) | 0x80;
moderegs[S3_CR62] = i & 0xFF;
}
} /* 801+ */
if (modetiming->flags & INTERLACED)
moderegs[S3_CR42] |= 0x20;
/*
* Clock select works as follows:
* Clocks 0 and 1 (VGA 25 and 28 MHz) can be selected via the
* two VGA MiscOutput clock select bits.
* If 0x3 is written to these bits, the selected clock index
* is taken from the S3 clock select register at CR42. Clock
* indices 0 and 1 should correspond to the VGA ones above,
* and 3 is often 0 MHz, followed by extended clocks for a
* total of mostly 16.
*/
if (modetiming->flags & USEPROGRCLOCK)
moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */
else if (modetiming->selectedClockNo < 2) {
/* Program clock select bits 0 and 1. */
moderegs[VGA_MISCOUTPUT] &= ~0x0C;
moderegs[VGA_MISCOUTPUT] |=
(modetiming->selectedClockNo & 3) << 2;
} else if (modetiming->selectedClockNo >= 2) {
moderegs[VGA_MISCOUTPUT] |= 0x0C;
/* Program S3 clock select bits. */
moderegs[S3_CR42] &= ~0x1F;
moderegs[S3_CR42] |=
modetiming->selectedClockNo;
}
if (s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) {
moderegs[S3_CR33] &= ~0x08;
if (modeinfo->bitsPerPixel == 16)
moderegs[S3_CR33] |= 0x08;
/*
* The rest of the DAC/clocking is setup by the
* Trio64 code in the RAMDAC interface (ramdac.c).
*/
}
/*if (dac_used->id != NORMAL_DAC) {
int colormode;
colormode = __svgalib_colorbits_to_colormode(modeinfo->bitsPerPixel,
modeinfo->colorBits);
dac_used->initializeState(&moderegs[S3_DAC_OFFSET],
modeinfo->bitsPerPixel, colormode,
modetiming->pixelClock);
if (dac_used->id == ATT20C490) {
int pixmux, invert_vclk, blank_delay;
pixmux = 0;
invert_vclk = 0;
blank_delay = 2;
if (colormode == CLUT8_6
&& modetiming->pixelClock >= 67500) {
pixmux = 0x00;
invert_vclk = 1;
} else if (colormode == CLUT8_8)
pixmux = 0x02;
else if (colormode == RGB16_555)
pixmux = 0xa0;
else if (colormode == RGB16_565)
pixmux = 0xc0;
else if (colormode == RGB24_888_B)
pixmux = 0xe0;
moderegs[S3_CR67] = pixmux | invert_vclk;
moderegs[S3_CR6D] = blank_delay;
}*/
/*if (dac_used->id == S3_SDAC) {
int pixmux, invert_vclk, blank_delay;
pixmux = 0;
invert_vclk = 0;
blank_delay = 0;
if (colormode == CLUT8_6
&& modetiming->pixelClock >= 67500) {
#ifdef SDAC_8BPP_PIXMUX*/
/* x64 8bpp pixel multiplexing? */
/* pixmux = 0x10;
if (s3_chiptype != S3_866 && s3_chiptype != S3_868)
invert_vclk = 1;
blank_delay = 2;
#endif
} else if (colormode == RGB16_555) {
pixmux = 0x30;
blank_delay = 2;
} else if (colormode == RGB16_565) {
pixmux = 0x50;
blank_delay = 2;
} else if (colormode == RGB24_888_B) { // XXXX 868/968 only
pixmux = 0x90;
blank_delay = 2;
} else if (colormode == RGB32_888_B) {
pixmux = 0x70;
blank_delay = 2;
}
moderegs[S3_CR67] = pixmux | invert_vclk;
moderegs[S3_CR6D] = blank_delay;
// Clock select.
moderegs[S3_CR42] &= ~0x0F;
moderegs[S3_CR42] |= 0x02;
}*/
/* if (dac_used->id == IBMRGB52x) {
unsigned char pixmux, blank_delay, tmp;
tmp = 0;
pixmux = 0x11;
blank_delay = 0;
if (modeinfo->bitsPerPixel < 8 || colormode == RGB32_888_B)
pixmux = 0x00;
moderegs[S3_CR58] |= 0x40;
moderegs[S3_CR65] = 0;
moderegs[S3_CR66] &= 0xf8;
moderegs[S3_CR66] |= tmp;
#ifdef PIXEL_MULTIPLEXING
moderegs[S3_CR67] = pixmux;
#endif
moderegs[S3_CR6D] = blank_delay;
// Clock select.
moderegs[S3_CR42] &= ~0x0F;
moderegs[S3_CR42] |= 0x02;
}
}*/
#ifdef S3_LINEAR_SUPPORT
s3_cr58 = moderegs[S3_CR58];
s3_cr40 = moderegs[S3_CR40];
s3_cr54 = moderegs[S3_CR54];
#endif
/*if (clk_used == &__svgalib_I2061A_clockchip_methods &&
(modetiming->flags & USEPROGRCLOCK)) {
// Clock select.
moderegs[S3_CR42] &= ~0x0F;
moderegs[S3_CR42] |= 0x02;
}*/
/* update the 8514 regs */
memcpy(moderegs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2);
}
int __svgalib_setregs(const unsigned char *regs)
{
int i;
//if(__svgalib_novga) return 1;
//if (__svgalib_chipset == EGA) {
/* Enable graphics register modification */
//port_out(0x00, GRA_E0);
//port_out(0x01, GRA_E1);
//}
/* update misc output register */
__svgalib_vga_outmisc(regs[MIS]);
/* synchronous reset on */
__svgalib_vga_outseq(0x00,0x01);
/* write sequencer registers */
__svgalib_vga_outseq(0x01,regs[SEQ + 1] | 0x20);
out(SEQ_I, 1);
out(SEQ_D, regs[SEQ + 1] | 0x20);
for (i = 2; i < SEQ_C; i++) {
__svgalib_vga_outseq(i,regs[SEQ + i]);
}
/* synchronous reset off */
__svgalib_vga_outseq(0x00,0x03);
/*if (__svgalib_chipset != EGA) {
// deprotect CRT registers 0-7
__svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f);
}*/
/* write CRT registers */
for (i = 0; i < CRT_C; i++) {
__svgalib_vga_outcrtc(i,regs[CRT + i]);
}
/* write graphics controller registers */
for (i = 0; i < GRA_C; i++) {
out(GRA_I, i);
out(GRA_D, regs[GRA + i]);
}
/* write attribute controller registers */
for (i = 0; i < ATT_C; i++) {
in(__svgalib_IS1_R); /* reset flip-flop */
//__svgalib_delay();
msleep(1);
out(ATT_IW, i);
//__svgalib_delay();
msleep(1);
out(ATT_IW, regs[ATT + i]);
//__svgalib_delay();
msleep(1);
}
return 0;
}
/* Set chipset-specific registers */
void CS3Graphics::SetRegisters(const unsigned char regs[], int mode)
{
unsigned char b, bmax;
/*
* Right now, anything != 0x00 gets written in s3_setregs.
* May change this into a bitmask later.
*/
static unsigned char s3_regmask[] =
{
0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00, 0x00, /* CR30-CR37 */
0x00, 0x00, 0x3A, 0x3B, 0x3C, 0x00, 0x00, 0x00, /* CR38-CR3F */
0x00, 0x00, 0x42, 0x43, 0x44, 0x00, 0x00, 0x00, /* CR40-CR47 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR48-CR4F */
0x50, 0x51, 0x00, 0x00, 0x54, 0x55, 0x00, 0x00, /* CR50-CR57 */
0x58, 0x59, 0x5A, 0x00, 0x00, 0x5D, 0x5E, 0x00, /* CR58-CR5F */
0x60, 0x61, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR60-CR67 */
0x00, 0x00, 0x6A, 0x00, 0x00, 0x00 /* CR68-CR6D */
};
HwUnlockEnh();
/* save a private copy */
memcpy(s3_8514regs, regs + S3_8514_OFFSET, S3_8514_COUNT * 2);
/*
* set this first, so if we segfault on this (e.g. we didn't do a iopl(3))
* we don't get a screwed up display
*/
out16(ADVFUNC_CNTL, s3_8514regs[S3_ADVFUNC_CNTL]);
/* get S3 VGA/Ext registers */
bmax = 0x4F;
if (s3_chiptype >= S3_801)
bmax = 0x66;
if (s3_chiptype >= S3_864)
bmax = 0x6D;
for (b = 0x30; b <= bmax; b++) {
if (s3_regmask[b - 0x30])
__svgalib_outCR(b, regs[EXT + b - 0x30]);
}
/*if (dac_used->id != NORMAL_DAC) {
unsigned char CR1;
// Blank the screen.
CR1 = __svgalib_inCR(0x01);
__svgalib_outCR(0x01, CR1 | 0x20);
__svgalib_outbCR(0x55, __svgalib_inCR(0x55) | 1);
__svgalib_outCR(0x66, regs[S3_CR66]);
__svgalib_outCR(0x67, regs[S3_CR67]); // S3 pixmux.
dac_used->restoreState(regs + S3_DAC_OFFSET);
__svgalib_outCR(0x6D, regs[S3_CR6D]);
__svgalib_outbCR(0x55, __svgalib_inCR(0x55) & ~1);
__svgalib_outCR(0x01, CR1); // Unblank screen.
}*/
#ifdef S3_LINEAR_SUPPORT
if (mode == TEXT && s3_linear_addr)
s3_linear_disable(); /* make sure linear is off */
#endif
/* restore CR38/39 (may lock other regs) */
if (mode == 1) {
/* restore lock registers as well */
__svgalib_outCR(0x40, regs[S3_CR40]);
__svgalib_outCR(0x39, regs[S3_CR39]);
__svgalib_outCR(0x38, regs[S3_CR38]);
} else
HwLockEnh();
}
/* Set a mode */
int CS3Graphics::SetMode(int mode, int prv_mode)
{
ModeInfo *modeinfo;
ModeTiming *modetiming;
unsigned char moderegs[S3_TOTAL_REGS];
int res;
/*if (mode < G640x480x256 || mode == G720x348x2) {
// Let the standard VGA driver set standard VGA modes.
res = __svgalib_vga_driverspecs.setmode(mode, prv_mode);
if (res == 0 && s3_chiptype <= S3_928) */
/*
* ARI: Turn off virtual size of 1024 - this fixes all problems
* with standard modes, including 320x200x256.
*
* SL: Is this for 928 only? Doesn't matter for 805.
*/
/*HwUnlock();
__svgalib_outCR(0x34, __svgalib_inCR(0x34) & ~0x10);
HwLock();
}
return res;
}*/
if (!ModeAvailable(mode))
{
wprintf(L"Mode %d not available\n", mode);
return 1;
}
modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
wprintf(L"Mode: %ux%ux%u\n", modeinfo->width, modeinfo->height, modeinfo->bitsPerPixel);
modetiming = (ModeTiming*) malloc(sizeof(ModeTiming));
if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs))
{
wprintf(L"Unable to get mode timings\n");
free(modetiming);
free(modeinfo);
return 1;
}
/* Adjust the display width. */
modeinfo->lineWidth = AdjustLineWidth(modeinfo->lineWidth);
//CI.xbytes = modeinfo->lineWidth;
InitializeMode(moderegs, modetiming, modeinfo);
free(modeinfo);
free(modetiming);
__svgalib_setregs(moderegs); /* Set standard regs. */
SetRegisters(moderegs, mode); /* Set extended regs. */
return 0;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CS3Graphics::CS3Graphics()
{
s3Mclk = 0;
Init(0, 0, 0);
if (SetMode(0, 0))
wprintf(L"Unable to set mode\n");
}
CS3Graphics::~CS3Graphics()
{
}
HRESULT CS3Graphics::SetPalette(int nIndex, int red, int green, int blue)
{
return E_FAIL;
}
HRESULT CS3Graphics::Lock(surface_t* pDesc)
{
return E_FAIL;
}
HRESULT CS3Graphics::Unlock()
{
return E_FAIL;
}
HRESULT CS3Graphics::GetSurfaceDesc(surface_t* pDesc)
{
return E_FAIL;
}
pixel_t CS3Graphics::ColourMatch(colour_t clr)
{
return 0;
}
HRESULT CS3Graphics::SetPixel(int x, int y, pixel_t pix)
{
return E_FAIL;
}
pixel_t CS3Graphics::GetPixel(int x, int y)
{
return 0;
}
HRESULT CS3Graphics::Blt(ISurface* pSrc, int x, int y, int nWidth,
int nHeight, int nSrcX, int nSrcY, pixel_t pixTrans)
{
return E_FAIL;
}
HRESULT CS3Graphics::FillRect(const rectangle_t* rect, pixel_t pix)
{
return E_FAIL;
}
HRESULT CS3Graphics::AttachProcess()
{
return S_OK;
}