📄 s3init.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/s3/s3init.c,v 3.110.2.6 1997/06/20 09:13:54 hohndel Exp $ *//* * Written by Jake Richter Copyright (c) 1989, 1990 Panacea Inc., * Londonderry, NH - All Rights Reserved * * This code may be freely incorporated in any program without royalty, as long * as the copyright notice stays intact. * * Additions by Kevin E. Martin (martin@cs.unc.edu) * * KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEVIN E. MARTIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * *//* * Modified by Amancio Hasty and Jon Tombs * *//* $XConsortium: s3init.c /main/28 1996/10/28 04:55:18 kaleb $ */#define USE_VGAHWINIT#include "X.h"#include "Xmd.h"#ifndef OSKIT#include "input.h"#include "servermd.h"#endif /* !OSKIT */#include "scrnintstr.h"#ifndef OSKIT#include "site.h"#endif /* !OSKIT */#include "xf86Procs.h"#include "xf86_OSlib.h"#include "xf86_HWlib.h"#include "vga.h"#include "s3.h"#include "regs3.h"#include "s3Bt485.h"#include "Ti302X.h"#include "IBMRGB.h"#define XCONFIG_FLAGS_ONLY #include "xf86_Config.h"typedef struct { vgaHWRec std; /* good old IBM VGA */ unsigned char s3reg[10]; /* Video Atribute (CR30-34, CR38-3C) */ unsigned char s3sysreg[46]; /* Video Atribute (CR40-6D)*/ unsigned char ColorStack[8]; /* S3 hw cursor color stack CR4A/CR4B */}vgaS3Rec, *vgaS3Ptr;extern int vgaIOBase;extern int vgaCRIndex;extern int vgaCRReg;int s3InitCursorFlag = TRUE;int s3HDisplay;extern xf86InfoRec xf86Info;static vgaS3Ptr oldS3 = NULL;static short savedVgaIOBase;pointer vgaNewVideoState = NULL;static LUTENTRY oldlut[256];static Bool LUTInited = FALSE;static short s3Initialised = 0;static int old_clock;extern Bool (*s3ClockSelectFunc) (#if NeedNestedPrototypes int /* clock */#endif );extern int s3DisplayWidth;extern Bool s3Localbus;extern Bool s3Mmio928;extern Bool s3NewMmio;extern Bool s3PixelMultiplexing;extern pointer vgaBase;extern pointer vgaBaseLow;extern pointer vgaBaseHigh;int currents3dac_border = 0xff;static void InitLUT(#if NeedFunctionPrototypes void#endif );#ifdef PC98extern void crtswitch(short);#endif#define new ((vgaHWPtr)vgaNewVideoState)unsigned short s3ChipId = 0;unsigned int s3ChipRev = 0;#define cebank() do { \ if (S3_801_928_SERIES(s3ChipId)) { \ unsigned char tmp2; \ outb(vgaCRIndex, 0x51); \ tmp2 = inb(vgaCRReg); \ outb(vgaCRReg, (tmp2 & 0xf3)); \ } \} while (1 == 0)/* * Registers to save/restore in the 0x50 - 0x5f control range */static short reg50_mask = 0x673b; /* was 0x6733; */ /* was 0x4023 */extern unsigned char s3Port54;extern unsigned char s3Port51;extern unsigned char s3Port40;extern unsigned char s3Port59;extern unsigned char s3Port5A;extern unsigned char s3Port31;voids3CleanUp(void){ int i; unsigned char tmp; UNLOCK_SYS_REGS; vgaProtect(TRUE); if (OFLG_ISSET(OPTION_STB_PEGASUS, &s3InfoRec.options) && !OFLG_ISSET(OPTION_NOLINEAR_MODE, &s3InfoRec.options) && s3Mmio928) { /* Clear bit 7 of CRTC register 5C to map video memory normally. */ int CR5C; outb(vgaCRIndex, 0x5C); CR5C = inb(vgaCRReg); outb(vgaCRIndex, 0x5C); outb(vgaCRReg, CR5C & ~0x80); vgaBase = vgaBaseLow; } /* BL */ if (s3NewMmio) { outb (vgaCRIndex, 0x58); outb (vgaCRReg, s3SAM256); /* disable linear mode */ } /* end BL */ WaitQueue(8); outb(vgaCRIndex, 0x35); tmp = inb(vgaCRReg); outb(vgaCRReg, (tmp & 0xf0)); cebank(); outw(ADVFUNC_CNTL, 0); if (s3Mmio928 || s3NewMmio) { outb(vgaCRIndex, 0x53); outb(vgaCRReg, 0x00); } /* (s3ClockSelectFunc)(restore->std.NoClock); */ /* Restore Ramdac registers */ (s3Ramdacs[s3RamdacType].DacRestore)(); if (DAC_IS_TI3025) { outb(vgaCRIndex, 0x5C); outb(vgaCRReg, oldS3->s3sysreg[0x0C + 16]); } /* restore s3 special bits */ if (S3_801_928_SERIES(s3ChipId)) { /* restore 801 specific registers */ for (i = 32; i < (S3_x64_SERIES(s3ChipId) ? 46 : S3_805_I_SERIES(s3ChipId) ? 40 : 38) ; i++) { outb(vgaCRIndex, 0x40 + i); outb(vgaCRReg, oldS3->s3sysreg[i]); } for (i = 0; i < 16; i++) { if (!((1 << i) & reg50_mask)) continue; outb(vgaCRIndex, 0x50 + i); outb(vgaCRReg, oldS3->s3sysreg[i + 16]); } } for (i = 0; i < 5; i++) { outb(vgaCRIndex, 0x30 + i); outb(vgaCRReg, oldS3->s3reg[i]); outb(vgaCRIndex, 0x38 + i); outb(vgaCRReg, oldS3->s3reg[5 + i]); } for (i = 0; i < 16; i++) { outb(vgaCRIndex, 0x40 + i); outb(vgaCRReg, oldS3->s3sysreg[i]); } outb(vgaCRIndex, 0x45); inb(vgaCRReg); /* reset color stack pointer */ outb(vgaCRIndex, 0x4A); for (i = 0; i < 4; i++) outb(vgaCRReg, oldS3->ColorStack[i]); outb(vgaCRIndex, 0x45); inb(vgaCRReg); /* reset color stack pointer */ outb(vgaCRIndex, 0x4B); for (i = 4; i < 8; i++) outb(vgaCRReg, oldS3->ColorStack[i]); if (OFLG_ISSET(CLOCK_OPTION_ICS2595, &s3InfoRec.clockOptions)){ outb(vgaCRIndex, 0x42); outb(vgaCRReg, (oldS3->s3sysreg[2] & 0xf0) | 0x01); outb(vgaCRIndex, 0x5c); /* switch back to 28MHz clock */ outb(vgaCRReg, 0x20); outb(vgaCRReg, 0x00); } vgaHWRestore((vgaHWPtr)oldS3); outb(0x3c2, old_clock); i = inb(0x3CC); if (savedVgaIOBase == 0x3B0) i &= 0xFE; else i |= 0x01; outb(0x3C2, i); vgaIOBase = savedVgaIOBase; vgaCRIndex = vgaIOBase + 4; vgaCRReg = vgaIOBase + 5; vgaProtect(FALSE);#ifdef PC98 crtswitch(0);#endif xf86DisableIOPorts(s3InfoRec.scrnIndex);}Bools3Init(mode) DisplayModePtr mode;{ short i, m, n; int interlacedived = mode->Flags & V_INTERLACE ? 2 : 1; unsigned char tmp, CR5C; unsigned int itmp; extern Bool s3DAC8Bit; int pixMuxShift = 0; s3HDisplay = mode->HDisplay; UNLOCK_SYS_REGS; /* Force use of colour I/O address */ if (!s3Initialised) { savedVgaIOBase = vgaIOBase; } i = inb(0x3CC); outb(0x3C2, i | 0x01); vgaIOBase = 0x3D0; vgaCRIndex = 0x3D4; vgaCRReg = 0x3D5; if (!s3Initialised) { /* blanket save of state */ /* unlock */ outb(vgaCRIndex, 0x38); outb(vgaCRReg, 0x48); old_clock = inb(0x3CC); outb(vgaCRIndex, 0x35); /* select segment 0 */ i = inb(vgaCRReg); outb(vgaCRReg, i & 0xf0); cebank(); oldS3 = vgaHWSave((vgaHWPtr)oldS3, sizeof(vgaS3Rec)); /* * Set up the Serial Access Mode 256 Words Control * (bit 6 in CR58) */ outb(vgaCRIndex, 0x58); s3SAM256 = inb(vgaCRReg) & 0x80; if (S3_968_SERIES(s3ChipId) || (S3_964_SERIES(s3ChipId) && !OFLG_ISSET(OPTION_NUMBER_NINE, &s3InfoRec.options))) s3SAM256 |= 0x40; else if ((OFLG_ISSET(OPTION_SPEA_MERCURY, &s3InfoRec.options) && S3_928_ONLY(s3ChipId)) || OFLG_ISSET(OPTION_STB_PEGASUS, &s3InfoRec.options)) s3SAM256 |= 0x80; /* set 6 MCLK cycles for R/W time on Mercury */ if (OFLG_ISSET(OPTION_EARLY_RAS_PRECHARGE, &s3InfoRec.options)) s3SAM256 |= 0x80; if (OFLG_ISSET(OPTION_LATE_RAS_PRECHARGE, &s3InfoRec.options)) s3SAM256 &= 0x7f; if (DAC_IS_TI3025) { outb(vgaCRIndex, 0x5C); CR5C = inb(vgaCRReg); }/* Save Ramdac registers */ (s3Ramdacs[s3RamdacType].DacSave)(); for (i = 0; i < 5; i++) { outb(vgaCRIndex, 0x30 + i); oldS3->s3reg[i] = inb(vgaCRReg);#ifdef REG_DEBUG ErrorF("CR%X = 0x%02x\n", 0x30 + i, oldS3->s3reg[i]);#endif outb(vgaCRIndex, 0x38 + i); oldS3->s3reg[5 + i] = inb(vgaCRReg);#ifdef REG_DEBUG ErrorF("CR%X = 0x%02x\n", 0x38 + i, oldS3->s3reg[i + 5]);#endif } outb(vgaCRIndex, 0x11); /* allow writting to CR0-7 */ tmp = inb(vgaCRReg); outb(vgaCRReg, tmp & 0x7f); for (i = 0; i < 16; i++) { outb(vgaCRIndex, 0x40 + i); oldS3->s3sysreg[i] = inb(vgaCRReg);#ifdef REG_DEBUG ErrorF("CR%X = 0x%02x\n", 0x40 + i, oldS3->s3sysreg[i]);#endif } outb(vgaCRIndex, 0x45); inb(vgaCRReg); /* reset color stack pointer */ outb(vgaCRIndex, 0x4A); for (i = 0; i < 4; i++) { oldS3->ColorStack[i] = inb(vgaCRReg); outb(vgaCRReg,oldS3->ColorStack[i]); /* advance stack pointer */ } outb(vgaCRIndex, 0x45); inb(vgaCRReg); /* reset color stack pointer */ outb(vgaCRIndex, 0x4B); for (i = 4; i < 8; i++) { oldS3->ColorStack[i] = inb(vgaCRReg); outb(vgaCRReg,oldS3->ColorStack[i]); /* advance stack pointer */ } if (S3_801_928_SERIES(s3ChipId)) for (i = 0; i < 16; i++) {#ifdef REG_DEBUG outb(vgaCRIndex, 0x50 + i); ErrorF("CR%X = 0x%02x\n", 0x50 + i, inb(vgaCRReg));#endif if (!((1 << i) & reg50_mask)) continue; outb(vgaCRIndex, 0x50 + i); oldS3->s3sysreg[i + 16] = inb(vgaCRReg); } if (DAC_IS_TI3025) /* restore 5C from above */ oldS3->s3sysreg[0x0C + 16] = CR5C; for (i = 32; i < (S3_x64_SERIES(s3ChipId) ? 46 : S3_805_I_SERIES(s3ChipId) ? 40 : 38); i++) { outb(vgaCRIndex, 0x40 + i); oldS3->s3sysreg[i] = inb(vgaCRReg);#ifdef REG_DEBUG ErrorF("CR%X = 0x%02x\n", 0x40 + i, oldS3->s3sysreg[i]);#endif } s3Initialised = 1; vgaNewVideoState = vgaHWSave(vgaNewVideoState, sizeof(vgaS3Rec)); outb(DAC_MASK, 0); } else if (DAC_IS_TI3025) { /* switch the ramdac from bt485 to ti3020 mode clearing RS4 */ outb(vgaCRIndex, 0x5C); CR5C = inb(vgaCRReg); outb(vgaCRReg, CR5C & 0xDF); /* clear TI_PLANAR_ACCESS bit */ s3OutTiIndReg(TI_CURS_CONTROL, 0x7F, 0x00); } if (s3UsingPixMux && (mode->Flags & V_PIXMUX)) s3PixelMultiplexing = TRUE; else s3PixelMultiplexing = FALSE; if (OFLG_ISSET(OPTION_ELSA_W2000PRO, &s3InfoRec.options)) pixMuxShift = s3InfoRec.clock[mode->Clock] > 120000 ? 2 : s3InfoRec.clock[mode->Clock] > 60000 ? 1 : 0 ; else if (OFLG_ISSET(OPTION_MIRO_80SV, &s3InfoRec.options)) pixMuxShift = ((mode->Flags & V_DBLCLK && s3Bpp == 1) || s3Bpp == 4) ? 1 : 0; else if (DAC_IS_IBMRGB528) pixMuxShift = (s3InfoRec.clock[mode->Clock] > 220000 && s3Bpp <= 2) ? 2 : s3InfoRec.clock[mode->Clock] > 110000 ? 1 : 0 ; else if ((mode->Flags & V_DBLCLK) && (DAC_IS_TI3026) && (OFLG_ISSET(CLOCK_OPTION_ICD2061A, &s3InfoRec.clockOptions))) pixMuxShift = (s3Bpp <= 2) ? 2 : 1; else if ((mode->Flags & V_DBLCLK) && DAC_IS_TI3030) pixMuxShift = 1; else if (S3_964_SERIES(s3ChipId) && DAC_IS_IBMRGB) pixMuxShift = mode->Flags & V_DBLCLK ? 1 : 0; else if (S3_964_SERIES(s3ChipId) && DAC_IS_TI3025) pixMuxShift = mode->Flags & V_DBLCLK ? 1 : 0; else if (S3_964_SERIES(s3ChipId) && DAC_IS_BT485_SERIES) /* Stealth64 and Miro Crystal 20SV */ pixMuxShift = mode->Flags & V_DBLCLK ? 1 : 0; else if (S3_801_928_SERIES(s3ChipId) && DAC_IS_SC15025) pixMuxShift = -(s3Bpp>>1); /* for 16/32 bpp */ else if (S3_864_SERIES(s3ChipId) || S3_805_I_SERIES(s3ChipId)) /* && (DAC_IS_ATT498 || DAC_IS_STG1700) */ pixMuxShift = -(s3Bpp>>1); /* for 16/32 bpp */ else if (S3_TRIOxx_SERIES(s3ChipId)) pixMuxShift = -(s3Bpp == 2); else if (S3_x64_SERIES(s3ChipId)) /* XXXX Better to test the DAC type? */ pixMuxShift = 0; else if ((S3_928_SERIES(s3ChipId) && (DAC_IS_TI3020 || DAC_IS_BT485_SERIES)) && s3PixelMultiplexing) { if (s3Bpp == 4) pixMuxShift = 0; /* 32 bit */ else if (s3Bpp == 2) pixMuxShift = 1; /* 16 bit */ else pixMuxShift = 2; /* 8 bit */ } else if (s3PixelMultiplexing) pixMuxShift = 2; /* old default for if (s3PixelMultiplexing) shifting */ else pixMuxShift = 0; if (!mode->CrtcHAdjusted) { if (s3Bpp == 3 && ( (S3_968_SERIES(s3ChipId) && DAC_IS_TI3026) || (S3_968_SERIES(s3ChipId) && DAC_IS_TI3030))) { mode->CrtcHTotal = (mode->CrtcHTotal * 3) / 4; mode->CrtcHDisplay = (mode->CrtcHDisplay * 3) / 4; mode->CrtcHSyncStart = (mode->CrtcHSyncStart * 3) / 4; mode->CrtcHSyncEnd = (mode->CrtcHSyncEnd * 3) / 4; mode->CrtcHSkew = (mode->CrtcHSkew * 3) / 4; } if (pixMuxShift > 0) { /* now divide the horizontal timing parameters as required */ mode->CrtcHTotal >>= pixMuxShift; mode->CrtcHDisplay >>= pixMuxShift; mode->CrtcHSyncStart >>= pixMuxShift; mode->CrtcHSyncEnd >>= pixMuxShift; mode->CrtcHSkew >>= pixMuxShift; } else if (pixMuxShift < 0) { /* now multiply the horizontal timing parameters as required */ mode->CrtcHTotal <<= -pixMuxShift; mode->CrtcHDisplay <<= -pixMuxShift; mode->CrtcHSyncStart <<= -pixMuxShift; mode->CrtcHSyncEnd <<= -pixMuxShift; mode->CrtcHSkew <<= -pixMuxShift; } mode->CrtcHAdjusted = TRUE; } /* * do some sanity checks on the horizontal timing parameters */ { Bool changed=FALSE; int oldCrtcHSyncStart, oldCrtcHSyncEnd, oldCrtcHTotal; int p24_fact = 4; oldCrtcHSyncStart = mode->CrtcHSyncStart; oldCrtcHSyncEnd = mode->CrtcHSyncEnd; oldCrtcHTotal = mode->CrtcHTotal; if (mode->CrtcHTotal > 4096) { /* CrtcHTotal/8 is a 9 bit value */ mode->CrtcHTotal = 4096; changed = TRUE; } if (mode->CrtcHSyncEnd >= mode->CrtcHTotal) { mode->CrtcHSyncEnd = mode->CrtcHTotal - 1; changed = TRUE; } if (mode->CrtcHSyncStart >= mode->CrtcHSyncEnd) { mode->CrtcHSyncStart = mode->CrtcHSyncEnd - 1; changed = TRUE; } if ((DAC_IS_TI3030 || DAC_IS_IBMRGB528) && s3Bpp==1) { /* for 128bit bus we need multiple of 16 8bpp pixels... */ if (mode->CrtcHTotal & 0x0f) { mode->CrtcHTotal = (mode->CrtcHTotal + 0x0f) & ~0x0f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -