📄 s3misc.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/s3/s3misc.c,v 3.68.2.2 1997/05/19 08:06:54 dawes Exp $ *//* * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Thomas Roell not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Thomas Roell makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * THOMAS ROELL AND KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, * IN NO EVENT SHALL THOMAS ROELL OR 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. * * Author: Thomas Roell, roell@informatik.tu-muenchen.de * * Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu) * * Header: /home/src/xfree86/mit/server/ddx/xf86/accel/s3/RCS/s3.c,v 2.0 * 1993/02/22 05:58:13 jon Exp * * Modified by Amancio Hasty and Jon Tombs * *//* $XConsortium: s3misc.c /main/36 1996/12/28 14:42:12 kaleb $ */#ifndef OSKIT#include "cfb.h"#include "cfb16.h"#include "cfb24.h"#include "cfb32.h"#include "pixmapstr.h"#include "fontstruct.h"#endif /* !OSKIT */#include "s3.h"#include "regs3.h"#include "xf86_HWlib.h"#include "ICD2061A.h"#define XCONFIG_FLAGS_ONLY#include "xf86_Config.h"#include "s3linear.h"#ifdef XFreeXDGA#include "X.h"#include "Xproto.h"#include "scrnintstr.h"#include "servermd.h"#define _XF86DGA_SERVER_#include "extensions/xf86dgastr.h"#endif#ifdef PC98#include "s3pc98.h"#endif extern char s3Mbanks;extern Bool s3Mmio928;extern Bool s3NewMmio;extern unsigned long s3MemBase;#ifndef OSKITextern miPointerScreenFuncRec xf86PointerScreenFuncs;#endif /* !OSKIT */static Bool s3TryAddress(#if NeedFunctionPrototypes long * /* addr */, long /* value */, long /* physaddr */, int /* stage */#endif);extern ScreenPtr s3savepScreen;#ifndef OSKITstatic PixmapPtr ppix = NULL;#endif /* !OSKIT */extern Bool s3Localbus;extern Bool s3VLB;extern Bool s3LinearAperture;extern int s3BankSize;extern int s3DisplayWidth;extern pointer vgaBase;extern pointer vgaBaseLow;extern pointer vgaBaseHigh;extern pointer s3VideoMem;extern pointer s3MmioMem;extern unsigned char s3Port59;extern unsigned char s3Port5A;extern unsigned char s3Port31;extern Bool xf86Exiting, xf86Resetting, xf86ProbeFailed;extern int xf86Verbose;static Bool AlreadyInited = FALSE;static Bool s3ModeSwitched = FALSE;#ifdef PC98extern int pc98BoardType;#endifstatic void s3WaitRetrace(){ while (inb(vgaIOBase + 0xA) & 0x08); while (!(inb(vgaIOBase + 0xA) & 0x08));}/* * s3Initialize -- Attempt to find and initialize a VGA framebuffer Most of * the elements of the ScreenRec are filled in. The video is enabled for the * frame buffer... */Bools3Initialize(scr_index, pScreen, argc, argv) int scr_index; /* The index of pScreen in the ScreenInfo */ ScreenPtr pScreen; /* The Screen to initialize */ int argc; /* The number of the Server's arguments. */ char **argv; /* The arguments themselves. Don't change! */{ int displayResolution = 75; /* default to 75dpi */ extern int monitorResolution; int i,j,k,ok; unsigned char *pat; unsigned short dash_test_pattern = 0xac00;#ifndef OSKIT Pixel blackPixel; if (xf86FlipPixels && s3Bpp == 1) blackPixel = (Pixel) 1; else blackPixel = (Pixel) 0;#endif /* !OSKIT */ s3Unlock(); /* for restarts */ /* for clips */ s3ScissB = ((s3InfoRec.videoRam * 1024) / s3BppDisplayWidth) - 1; s3ScissR = s3DisplayWidth - 1; /* * Initialize the screen, saving the original state for Save/Restore * function */ if (serverGeneration == 1) { unsigned long addr = 0; unsigned long base0 = 0xa0000; /* old default for s3Port59/s3Port5A */ s3BankSize = 0x10000; s3LinApOpt = 0x14; if ((OFLG_ISSET(OPTION_STB_PEGASUS, &s3InfoRec.options) || OFLG_ISSET(OPTION_MIRO_MAGIC_S4, &s3InfoRec.options)) && !OFLG_ISSET(OPTION_NOLINEAR_MODE, &s3InfoRec.options) && s3Mmio928) { vgaBaseLow = xf86MapVidMem(scr_index, VGA_REGION, (pointer)0xA0000, s3BankSize); vgaBaseHigh = xf86MapVidMem(scr_index, EXTENDED_REGION, (pointer)0x7C0A0000, s3BankSize); vgaBase = vgaBaseLow; } else { /* First, map the vga window -- it is always required */#ifndef PC98 vgaBase = xf86MapVidMem(scr_index, VGA_REGION, (pointer)0xA0000, s3BankSize);#else switch(pc98BoardType & 0xf0 ){ case PW: case PW805I: vgaBase = xf86MapVidMem(scr_index, VGA_REGION, (pointer)(PW_WinAdd << 16), s3BankSize); ErrorF(" PC98: PW mem-access\n"); break; case PCSKB: case PCHKB: vgaBase = xf86MapVidMem(scr_index, VGA_REGION, (pointer)(XKB_WinAdd << 16), s3BankSize); ErrorF(" PC98: SKB,HKB mem-access\n"); break; case PCSKB4: vgaBase = xf86MapVidMem(scr_index, VGA_REGION, (pointer)(SKB4_WinAdd << 16), s3BankSize); ErrorF(" PC98: SKB4 mem-access(not work,yet)\n"); break; case NECWAB: vgaBase = xf86MapVidMem(scr_index, VGA_REGION, (pointer)(NEC_WinAdd << 16), s3BankSize); ErrorF(" PC98: NEC-WAB(C Bus) mem-access\n"); break; case PWLB: vgaBase = xf86MapVidMem(scr_index, LINEAR_REGION, (pointer)((PWLB_WinAdd << 16) + 0xA0000), s3BankSize); ErrorF(" PC98: PW localbus mem-access\n"); break; default: vgaBase = xf86MapVidMem(scr_index, VGA_REGION, (pointer)0xA0000,s3BankSize); }#endif /* PC98 */ } /* s3Port59/s3Port5A need to be checked/initialized before s3Init() is called the first time */ if (S3_801_928_SERIES (s3ChipId) && s3Localbus && xf86LinearVidMem() && !OFLG_ISSET(OPTION_NOLINEAR_MODE, &s3InfoRec.options) && !OFLG_ISSET(OPTION_NO_MEM_ACCESS, &s3InfoRec.options)) { if (S3_x64_SERIES(s3ChipId)) if (s3InfoRec.MemBase != 0) { if ((s3InfoRec.MemBase & 0x3ffffff) && s3NewMmio) { ErrorF("%s %s: base address not correctly aligned to 64MB\n", XCONFIG_PROBED, s3InfoRec.name); ErrorF("\t\tbase address changed from 0x%08lx to 0x%08lx\n", s3InfoRec.MemBase, s3InfoRec.MemBase & ~0x3ffffff); s3InfoRec.MemBase &= ~0x3ffffff; } base0 = s3InfoRec.MemBase; } else if (s3MemBase != 0) /* checked in s3.c */ base0 = s3MemBase; else if (s3NewMmio) { unsigned long orig_base0; outb(vgaCRIndex, 0x59); base0 = inb(vgaCRReg) << 24; outb(vgaCRIndex, 0x5a); base0 |= inb(vgaCRReg) << 16; orig_base0 = base0; base0 &= 0xfc000000; if (base0 == 0 || base0 != orig_base0) { /* the aligned address may clash with other devices, so use a pretty random base address as last resort, 0x04000000 seems to be a necessary for some VLB boards but won't work with 128MB though :-( */ base0 = 0x04000000; ErrorF("%s %s: PCI: base address not correctly aligned\n", XCONFIG_PROBED, s3InfoRec.name); ErrorF("\t base address changed from 0x%08lx to 0x%08lx\n", orig_base0, base0); } } else base0 = 0xf3000000; /* old default, not good for newmmio */ else {#ifdef PC98_PWLB if (pc98BoardType == PWLB) base0 = 0x0; else#endif base0 = 0x03000000; } } s3Port59 = base0 >> 24; s3Port5A = base0 >> 16; s3Init(s3InfoRec.modes); if (xf86LinearVidMem() && !OFLG_ISSET(OPTION_NOLINEAR_MODE, &s3InfoRec.options)) { /* Now, see if we can map a high buffer */ if (s3Localbus && !S3_911_SERIES(s3ChipId) && !OFLG_ISSET(OPTION_NO_MEM_ACCESS, &s3InfoRec.options)) { long i2; long *poker; unsigned long pVal; Bool CachedFrameBuffer = FALSE; pVal = 0x12345678; s3InitEnvironment(); s3ImageWriteNoMem(0, 0, s3Bpp==3 ? 2 : 4 / s3Bpp, 1, (char *) &pVal, s3Bpp==3 ? 2 : 4 / s3Bpp, 0, 0, (short) s3alu[GXcopy], ~0); if (S3_801_928_SERIES (s3ChipId)) { outb(vgaCRIndex, 0x59); outb(vgaCRReg, s3Port59); outb(vgaCRIndex, 0x5a); outb(vgaCRReg, s3Port5A); if (s3InfoRec.videoRam <= 1024) { s3LinApOpt=0x15; } else if (s3InfoRec.videoRam <= 2048) { s3LinApOpt=0x16; } else { s3LinApOpt=0x17; } s3BankSize = s3InfoRec.videoRam * 1024; s3EnableLinear(); } /* * XXXX This is for debugging only. It attempts to find * which values of LAW are decoded (see s3TryAddress() below). */ if (OFLG_ISSET(OPTION_FB_DEBUG, &s3InfoRec.options) && !s3NewMmio) { /* don't poke around for newmmio */ for (i2 = 0xff; i2 >= 3; i2--) { /* 4080Mb..48Mb stepsize 16Mb */ addr = (i2 << 24); s3VideoMem = xf86MapVidMem(scr_index, LINEAR_REGION, (pointer)addr, 4096); poker = (long *) s3VideoMem; s3TryAddress(poker, pVal, addr, 0); xf86UnMapVidMem(scr_index, LINEAR_REGION, s3VideoMem, 4096); } } /* * If a MemBase value was given in the XF86Config, skip the LAW * probe and use the high 10 bits for the hw part of LAW. * Normally only 6 bits are set in hw, but the Diamond Stealth * Pro is different. */ if (s3InfoRec.MemBase != 0) { addr = (s3InfoRec.MemBase & 0xffc00000); s3VideoMem = xf86MapVidMem(scr_index, LINEAR_REGION, (pointer)addr, s3BankSize); if (s3NewMmio) s3MmioMem = xf86MapVidMem(scr_index, MMIO_REGION, (pointer)(addr+S3_NEWMMIO_REGBASE), S3_NEWMMIO_REGSIZE); s3DisableLinear(); outb(vgaCRIndex, 0x5a); if (S3_x64_SERIES(s3ChipId)) { outb(vgaCRReg, (addr >> 16) & 0xff); outb(vgaCRIndex, 0x59); outb(vgaCRReg, (addr >> 24) & 0xff); } else outb(vgaCRReg, 0xc0); s3EnableLinear(); s3LinearAperture = TRUE; ErrorF("%s %s: Local bus LAW is 0x%03lXxxxxx\n", XCONFIG_GIVEN, s3InfoRec.name, (addr >> 20)); } else { if (S3_x64_SERIES(s3ChipId) && !(S3_TRIO64_SERIES(s3ChipId) && /*s3InfoRec.videoRam > 1024 &&*/ s3VLB)) { /* So far, only tested for the PCI ELSA W2000Pro */ s3DisableLinear(); outb(vgaCRIndex, 0x59); addr = inb(vgaCRReg) << 8; outb(vgaCRIndex, 0x5a); addr |= inb(vgaCRReg); addr <<= 16; s3EnableLinear(); if (OFLG_ISSET(OPTION_FB_DEBUG, &s3InfoRec.options)) { ErrorF("Read LAW as 0x%08X \n", addr); } s3VideoMem = xf86MapVidMem(scr_index, LINEAR_REGION, (pointer)addr, s3BankSize); if (s3NewMmio) s3MmioMem = xf86MapVidMem(scr_index, MMIO_REGION, (pointer)(addr+S3_NEWMMIO_REGBASE), S3_NEWMMIO_REGSIZE); poker = (long *) s3VideoMem; if (s3TryAddress(poker, pVal, addr, 1)) { s3LinearAperture = TRUE; if (xf86Verbose) { ErrorF("%s %s: Local bus LAW is 0x%08lX\n", XCONFIG_PROBED, s3InfoRec.name, addr); } } else { s3LinearAperture = FALSE; CachedFrameBuffer = TRUE; if (xf86Verbose) { ErrorF("%s %s: Local bus LAW is 0x%08lX %s\n", XCONFIG_PROBED, s3InfoRec.name, addr, "but linear fb not usable"); } xf86UnMapVidMem(scr_index, LINEAR_REGION, s3VideoMem, s3BankSize); if (s3NewMmio) xf86UnMapVidMem(scr_index, MMIO_REGION, s3MmioMem, S3_NEWMMIO_REGSIZE); } } else {#ifdef PC98_PWLB if (pc98BoardType == PWLB) { unsigned long addr = (PWLB_WinAdd << 16) + 0x400000; s3VideoMem = xf86MapVidMem(scr_index, LINEAR_REGION, (pointer)addr, s3BankSize); if (s3NewMmio) s3MmioMem = xf86MapVidMem(scr_index, MMIO_REGION, (pointer)(addr+S3_NEWMMIO_REGBASE), S3_NEWMMIO_REGSIZE); poker = (long *) s3VideoMem; if (s3TryAddress(poker, pVal, addr, 1)) { ErrorF("%s %s: Local bus LAW is 0x%08X\n", XCONFIG_PROBED, s3InfoRec.name, addr); s3LinearAperture = TRUE; } } else {#endif for (i2 = 0xff; i2 >= 3; i2--) { /* 4080Mb..48Mb stepsize 16Mb */ addr = (i2 << 24); s3VideoMem = xf86MapVidMem(scr_index, LINEAR_REGION, (pointer)addr, s3BankSize); if (s3NewMmio) s3MmioMem = xf86MapVidMem(scr_index, MMIO_REGION, (pointer)(addr+S3_NEWMMIO_REGBASE), S3_NEWMMIO_REGSIZE); poker = (long *) s3VideoMem; if (s3TryAddress(poker, pVal, addr, 1)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -