tseng_driver.c revision d983712d
1d983712dSmrg/* 2d983712dSmrg * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tseng/tseng_driver.c,v 1.97tsi Exp $ 3d983712dSmrg * 4d983712dSmrg * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 5d983712dSmrg * 6d983712dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 7d983712dSmrg * documentation for any purpose is hereby granted without fee, provided that 8d983712dSmrg * the above copyright notice appear in all copies and that both that 9d983712dSmrg * copyright notice and this permission notice appear in supporting 10d983712dSmrg * documentation, and that the name of Thomas Roell not be used in 11d983712dSmrg * advertising or publicity pertaining to distribution of the software without 12d983712dSmrg * specific, written prior permission. Thomas Roell makes no representations 13d983712dSmrg * about the suitability of this software for any purpose. It is provided 14d983712dSmrg * "as is" without express or implied warranty. 15d983712dSmrg * 16d983712dSmrg * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17d983712dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18d983712dSmrg * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19d983712dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20d983712dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21d983712dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22d983712dSmrg * PERFORMANCE OF THIS SOFTWARE. 23d983712dSmrg * 24d983712dSmrg * Author: Thomas Roell, roell@informatik.tu-muenchen.de 25d983712dSmrg * ET6000 and ET4000W32 16/24/32 bpp and acceleration support by Koen Gadeyne 26d983712dSmrg * 27d983712dSmrg * Large parts rewritten for XFree86 4.0 by Koen Gadeyne. 28d983712dSmrg */ 29d983712dSmrg/* $XConsortium: et4_driver.c /main/27 1996/10/28 04:48:15 kaleb $ */ 30d983712dSmrg 31d983712dSmrg#ifdef HAVE_CONFIG_H 32d983712dSmrg#include "config.h" 33d983712dSmrg#endif 34d983712dSmrg 35d983712dSmrg/*** Generic includes ***/ 36d983712dSmrg 37d983712dSmrg#include "tseng.h" /* this includes most of the generic ones as well */ 38d983712dSmrg 39d983712dSmrg/* All drivers initialising the SW cursor need this */ 40d983712dSmrg#include "mipointer.h" 41d983712dSmrg 42d983712dSmrg/* All drivers implementing backing store need this */ 43d983712dSmrg#include "mibstore.h" 44d983712dSmrg 45d983712dSmrg#include "fb.h" 46d983712dSmrg 47d983712dSmrg#include "xf86RAC.h" 48d983712dSmrg#include "xf86Resources.h" 49d983712dSmrg#include "xf86int10.h" 50d983712dSmrg 51d983712dSmrg#include "xf86xv.h" 52d983712dSmrg#include <X11/extensions/Xv.h> 53d983712dSmrg 54d983712dSmrg/* 55d983712dSmrg * Forward definitions for the functions that make up the driver. 56d983712dSmrg */ 57d983712dSmrg 58d983712dSmrg/* Mandatory functions */ 59d983712dSmrgstatic const OptionInfoRec * TsengAvailableOptions(int chipid, int busid); 60d983712dSmrgstatic void TsengIdentify(int flags); 61d983712dSmrgstatic Bool TsengProbe(DriverPtr drv, int flags); 62d983712dSmrgstatic Bool TsengPreInit(ScrnInfoPtr pScrn, int flags); 63d983712dSmrgstatic Bool TsengScreenInit(int Index, ScreenPtr pScreen, int argc, 64d983712dSmrg char **argv); 65d983712dSmrgstatic Bool TsengEnterVT(int scrnIndex, int flags); 66d983712dSmrgstatic void TsengLeaveVT(int scrnIndex, int flags); 67d983712dSmrgstatic Bool TsengCloseScreen(int scrnIndex, ScreenPtr pScreen); 68d983712dSmrgstatic Bool TsengSaveScreen(ScreenPtr pScreen, int mode); 69d983712dSmrg 70d983712dSmrg/* Required if the driver supports mode switching */ 71d983712dSmrgstatic Bool TsengSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); 72d983712dSmrg 73d983712dSmrg/* Optional functions */ 74d983712dSmrgstatic void TsengFreeScreen(int scrnIndex, int flags); 75d983712dSmrg 76d983712dSmrg/* If driver-specific config file entries are needed, this must be defined */ 77d983712dSmrg/*static Bool TsengParseConfig(ParseInfoPtr raw); */ 78d983712dSmrg 79d983712dSmrg/* Internally used functions (some are defined in tseng.h) */ 80d983712dSmrgstatic Bool TsengMapMem(ScrnInfoPtr pScrn); 81d983712dSmrgstatic Bool TsengUnmapMem(ScrnInfoPtr pScrn); 82d983712dSmrgstatic void TsengUnlock(ScrnInfoPtr pScrn); 83d983712dSmrgstatic void TsengLock(ScrnInfoPtr pScrn); 84d983712dSmrg 85d983712dSmrg/* 86d983712dSmrg * This is intentionally screen-independent. It indicates the binding 87d983712dSmrg * choice made in the first PreInit. 88d983712dSmrg */ 89d983712dSmrgstatic int pix24bpp = 0; 90d983712dSmrg 91d983712dSmrg#define TSENG_NAME "TSENG" 92d983712dSmrg#define TSENG_DRIVER_NAME "tseng" 93d983712dSmrg#define TSENG_MAJOR_VERSION 1 94d983712dSmrg#define TSENG_MINOR_VERSION 1 95d983712dSmrg#define TSENG_PATCHLEVEL 0 96d983712dSmrg#define TSENG_VERSION (TSENG_MAJOR_VERSION << 24) | (TSENG_MINOR_VERSION << 16) | TSENG_PATCHLEVEL 97d983712dSmrg 98d983712dSmrg/* CRTC timing limits */ 99d983712dSmrg#define Tseng_HMAX (4096-8) 100d983712dSmrg#define Tseng_VMAX (2048-1) 101d983712dSmrg 102d983712dSmrg/* 103d983712dSmrg * This contains the functions needed by the server after loading the 104d983712dSmrg * driver module. It must be supplied, and gets added the driver list by 105d983712dSmrg * the Module Setup funtion in the dynamic case. In the static case a 106d983712dSmrg * reference to this is compiled in, and this requires that the name of 107d983712dSmrg * this DriverRec be an upper-case version of the driver name. 108d983712dSmrg */ 109d983712dSmrg 110d983712dSmrg_X_EXPORT DriverRec TSENG = 111d983712dSmrg{ 112d983712dSmrg TSENG_VERSION, 113d983712dSmrg TSENG_DRIVER_NAME, 114d983712dSmrg TsengIdentify, 115d983712dSmrg TsengProbe, 116d983712dSmrg TsengAvailableOptions, 117d983712dSmrg NULL, 118d983712dSmrg 0 119d983712dSmrg}; 120d983712dSmrg 121d983712dSmrg/* sub-revisions are now dealt with in the ChipRev variable */ 122d983712dSmrgstatic SymTabRec TsengChipsets[] = 123d983712dSmrg{ 124d983712dSmrg {ET4000, "ET4000W32p"}, 125d983712dSmrg {ET6000, "ET6000"}, 126d983712dSmrg {-1, NULL} 127d983712dSmrg}; 128d983712dSmrg 129d983712dSmrg/* Convert PCI ID to chipset name */ 130d983712dSmrgstatic PciChipsets TsengPciChipsets[] = 131d983712dSmrg{ 132d983712dSmrg {ET4000, PCI_CHIP_ET4000_W32P_A, RES_SHARED_VGA}, 133d983712dSmrg {ET4000, PCI_CHIP_ET4000_W32P_B, RES_SHARED_VGA}, 134d983712dSmrg {ET4000, PCI_CHIP_ET4000_W32P_C, RES_SHARED_VGA}, 135d983712dSmrg {ET4000, PCI_CHIP_ET4000_W32P_D, RES_SHARED_VGA}, 136d983712dSmrg {ET6000, PCI_CHIP_ET6000, RES_SHARED_VGA}, 137d983712dSmrg {-1, -1, RES_UNDEFINED} 138d983712dSmrg}; 139d983712dSmrg 140d983712dSmrgtypedef enum { 141d983712dSmrg OPTION_HIBIT_HIGH, 142d983712dSmrg OPTION_HIBIT_LOW, 143d983712dSmrg OPTION_SW_CURSOR, 144d983712dSmrg OPTION_HW_CURSOR, 145d983712dSmrg OPTION_PCI_BURST, 146d983712dSmrg OPTION_SLOW_DRAM, 147d983712dSmrg OPTION_MED_DRAM, 148d983712dSmrg OPTION_FAST_DRAM, 149d983712dSmrg OPTION_W32_INTERLEAVE, 150d983712dSmrg OPTION_NOACCEL, 151d983712dSmrg OPTION_SHOWCACHE, 152d983712dSmrg OPTION_PCI_RETRY 153d983712dSmrg} TsengOpts; 154d983712dSmrg 155d983712dSmrgstatic const OptionInfoRec TsengOptions[] = 156d983712dSmrg{ 157d983712dSmrg {OPTION_HIBIT_HIGH, "hibit_high", OPTV_BOOLEAN, 158d983712dSmrg {0}, FALSE}, 159d983712dSmrg {OPTION_HIBIT_LOW, "hibit_low", OPTV_BOOLEAN, 160d983712dSmrg {0}, FALSE}, 161d983712dSmrg {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, 162d983712dSmrg {0}, FALSE}, 163d983712dSmrg {OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, 164d983712dSmrg {0}, FALSE}, 165d983712dSmrg {OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, 166d983712dSmrg {0}, FALSE}, 167d983712dSmrg {OPTION_SLOW_DRAM, "slow_dram", OPTV_BOOLEAN, 168d983712dSmrg {0}, FALSE}, 169d983712dSmrg {OPTION_MED_DRAM, "med_dram", OPTV_BOOLEAN, 170d983712dSmrg {0}, FALSE}, 171d983712dSmrg {OPTION_FAST_DRAM, "fast_dram", OPTV_BOOLEAN, 172d983712dSmrg {0}, FALSE}, 173d983712dSmrg {OPTION_W32_INTERLEAVE, "w32_interleave", OPTV_BOOLEAN, 174d983712dSmrg {0}, FALSE}, 175d983712dSmrg {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, 176d983712dSmrg {0}, FALSE}, 177d983712dSmrg {OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, 178d983712dSmrg {0}, FALSE}, 179d983712dSmrg {OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, 180d983712dSmrg {0}, FALSE}, 181d983712dSmrg {-1, NULL, OPTV_NONE, 182d983712dSmrg {0}, FALSE} 183d983712dSmrg}; 184d983712dSmrg 185d983712dSmrgstatic const char *int10Symbols[] = { 186d983712dSmrg "xf86FreeInt10", 187d983712dSmrg "xf86InitInt10", 188d983712dSmrg NULL 189d983712dSmrg}; 190d983712dSmrg 191d983712dSmrgstatic const char *vgaHWSymbols[] = { 192d983712dSmrg "vgaHWFreeHWRec", 193d983712dSmrg "vgaHWGetHWRec", 194d983712dSmrg "vgaHWGetIOBase", 195d983712dSmrg "vgaHWGetIndex", 196d983712dSmrg "vgaHWHandleColormaps", 197d983712dSmrg "vgaHWInit", 198d983712dSmrg "vgaHWLock", 199d983712dSmrg "vgaHWMapMem", 200d983712dSmrg "vgaHWProtect", 201d983712dSmrg "vgaHWRestore", 202d983712dSmrg "vgaHWSave", 203d983712dSmrg "vgaHWSaveScreen", 204d983712dSmrg "vgaHWUnlock", 205d983712dSmrg "vgaHWUnmapMem", 206d983712dSmrg NULL 207d983712dSmrg}; 208d983712dSmrg 209d983712dSmrg#ifdef XFree86LOADER 210d983712dSmrgstatic const char* miscfbSymbols[] = { 211d983712dSmrg "xf1bppScreenInit", 212d983712dSmrg "xf4bppScreenInit", 213d983712dSmrg NULL 214d983712dSmrg}; 215d983712dSmrg#endif 216d983712dSmrg 217d983712dSmrgstatic const char* fbSymbols[] = { 218d983712dSmrg "fbPictureInit", 219d983712dSmrg "fbScreenInit", 220d983712dSmrg NULL 221d983712dSmrg}; 222d983712dSmrg 223d983712dSmrgstatic const char *ramdacSymbols[] = { 224d983712dSmrg "xf86CreateCursorInfoRec", 225d983712dSmrg "xf86DestroyCursorInfoRec", 226d983712dSmrg "xf86InitCursor", 227d983712dSmrg NULL 228d983712dSmrg}; 229d983712dSmrg 230d983712dSmrgstatic const char *xaaSymbols[] = { 231d983712dSmrg "XAACreateInfoRec", 232d983712dSmrg "XAADestroyInfoRec", 233d983712dSmrg "XAAInit", 234d983712dSmrg NULL 235d983712dSmrg}; 236d983712dSmrg 237d983712dSmrg#ifdef XFree86LOADER 238d983712dSmrg 239d983712dSmrgstatic MODULESETUPPROTO(tsengSetup); 240d983712dSmrg 241d983712dSmrgstatic XF86ModuleVersionInfo tsengVersRec = 242d983712dSmrg{ 243d983712dSmrg "tseng", 244d983712dSmrg MODULEVENDORSTRING, 245d983712dSmrg MODINFOSTRING1, 246d983712dSmrg MODINFOSTRING2, 247d983712dSmrg XORG_VERSION_CURRENT, 248d983712dSmrg TSENG_MAJOR_VERSION, TSENG_MINOR_VERSION, TSENG_PATCHLEVEL, 249d983712dSmrg ABI_CLASS_VIDEODRV, /* This is a video driver */ 250d983712dSmrg ABI_VIDEODRV_VERSION, 251d983712dSmrg MOD_CLASS_VIDEODRV, 252d983712dSmrg {0, 0, 0, 0} 253d983712dSmrg}; 254d983712dSmrg 255d983712dSmrg/* 256d983712dSmrg * This is the module init data for XFree86 modules. 257d983712dSmrg * 258d983712dSmrg * Its name has to be the driver name followed by ModuleData. 259d983712dSmrg */ 260d983712dSmrg_X_EXPORT XF86ModuleData tsengModuleData = { &tsengVersRec, tsengSetup, NULL }; 261d983712dSmrg 262d983712dSmrgstatic pointer 263d983712dSmrgtsengSetup(pointer module, pointer opts, int *errmaj, int *errmin) 264d983712dSmrg{ 265d983712dSmrg static Bool setupDone = FALSE; 266d983712dSmrg 267d983712dSmrg if (!setupDone) { 268d983712dSmrg setupDone = TRUE; 269d983712dSmrg xf86AddDriver(&TSENG, module, 0); 270d983712dSmrg 271d983712dSmrg /* 272d983712dSmrg * Modules that this driver always requires can be loaded here 273d983712dSmrg * by calling LoadSubModule(). 274d983712dSmrg */ 275d983712dSmrg /* 276d983712dSmrg * Tell the loader about symbols from other modules that this module 277d983712dSmrg * might refer to. 278d983712dSmrg */ 279d983712dSmrg LoaderRefSymLists(vgaHWSymbols, miscfbSymbols, fbSymbols, xaaSymbols, 280d983712dSmrg int10Symbols, ramdacSymbols, NULL); 281d983712dSmrg 282d983712dSmrg /* 283d983712dSmrg * The return value must be non-NULL on success even though there 284d983712dSmrg * is no TearDownProc. 285d983712dSmrg */ 286d983712dSmrg return (pointer) 1; 287d983712dSmrg } else { 288d983712dSmrg if (errmaj) 289d983712dSmrg *errmaj = LDR_ONCEONLY; 290d983712dSmrg return NULL; 291d983712dSmrg } 292d983712dSmrg} 293d983712dSmrg 294d983712dSmrg#endif /* XFree86LOADER */ 295d983712dSmrg 296d983712dSmrgstatic Bool 297d983712dSmrgTsengGetRec(ScrnInfoPtr pScrn) 298d983712dSmrg{ 299d983712dSmrg TsengPtr pTseng; 300d983712dSmrg 301d983712dSmrg PDEBUG(" TsengGetRec\n"); 302d983712dSmrg 303d983712dSmrg /* 304d983712dSmrg * Allocate an TsengRec, and hook it into pScrn->driverPrivate. 305d983712dSmrg * pScrn->driverPrivate is initialised to NULL, so we can check if 306d983712dSmrg * the allocation has already been done. 307d983712dSmrg */ 308d983712dSmrg if (pScrn->driverPrivate != NULL) 309d983712dSmrg return TRUE; 310d983712dSmrg 311d983712dSmrg pScrn->driverPrivate = xnfcalloc(sizeof(TsengRec), 1); 312d983712dSmrg 313d983712dSmrg 314d983712dSmrg /* Initialise it here when needed (or possible) */ 315d983712dSmrg pTseng = TsengPTR(pScrn); 316d983712dSmrg 317d983712dSmrg pTseng->SavedReg.RAMDAC = NULL; 318d983712dSmrg 319d983712dSmrg return TRUE; 320d983712dSmrg} 321d983712dSmrg 322d983712dSmrgstatic void 323d983712dSmrgTsengFreeRec(ScrnInfoPtr pScrn) 324d983712dSmrg{ 325d983712dSmrg TsengPtr pTseng; 326d983712dSmrg 327d983712dSmrg PDEBUG(" TsengFreeRec\n"); 328d983712dSmrg 329d983712dSmrg if (pScrn->driverPrivate == NULL) 330d983712dSmrg return; 331d983712dSmrg 332d983712dSmrg pTseng = TsengPTR(pScrn); 333d983712dSmrg 334d983712dSmrg if (pTseng->SavedReg.RAMDAC) 335d983712dSmrg xfree(pTseng->SavedReg.RAMDAC); 336d983712dSmrg 337d983712dSmrg xfree(pScrn->driverPrivate); 338d983712dSmrg pScrn->driverPrivate = NULL; 339d983712dSmrg} 340d983712dSmrg 341d983712dSmrgstatic const OptionInfoRec * 342d983712dSmrgTsengAvailableOptions(int chipid, int busid) 343d983712dSmrg{ 344d983712dSmrg return TsengOptions; 345d983712dSmrg} 346d983712dSmrg 347d983712dSmrgstatic void 348d983712dSmrgTsengIdentify(int flags) 349d983712dSmrg{ 350d983712dSmrg xf86Msg(X_INFO, TSENG_NAME ": driver for TsengLabs ET4000W32p, ET6000 and" 351d983712dSmrg " ET6100 chips.\n"); 352d983712dSmrg} 353d983712dSmrg 354d983712dSmrg/* unlock ET4000 using KEY register */ 355d983712dSmrgstatic void 356d983712dSmrgTsengUnlock(ScrnInfoPtr pScrn) 357d983712dSmrg{ 358d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 359d983712dSmrg CARD8 tmp; 360d983712dSmrg 361d983712dSmrg PDEBUG(" TsengUnlock\n"); 362d983712dSmrg 363d983712dSmrg vgaHWHerculesSecondPage(hwp, TRUE); 364d983712dSmrg vgaHWWriteModeControl(hwp, 0xA0); 365d983712dSmrg 366d983712dSmrg tmp = hwp->readCrtc(hwp, 0x11); 367d983712dSmrg hwp->writeCrtc(hwp, 0x11, tmp & 0x7F); 368d983712dSmrg} 369d983712dSmrg 370d983712dSmrg/* lock ET4000 using KEY register. FIXME: should restore old lock status instead */ 371d983712dSmrgstatic void 372d983712dSmrgTsengLock(ScrnInfoPtr pScrn) 373d983712dSmrg{ 374d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 375d983712dSmrg CARD8 tmp; 376d983712dSmrg 377d983712dSmrg PDEBUG(" TsengLock\n"); 378d983712dSmrg 379d983712dSmrg tmp = hwp->readCrtc(hwp, 0x11); 380d983712dSmrg hwp->writeCrtc(hwp, 0x11, tmp | 0x80); 381d983712dSmrg 382d983712dSmrg vgaHWWriteModeControl(hwp, 0x00); 383d983712dSmrg vgaHWWriteModeControl(hwp, 0x29); 384d983712dSmrg vgaHWHerculesSecondPage(hwp, FALSE); 385d983712dSmrg} 386d983712dSmrg 387d983712dSmrgstatic Bool 388d983712dSmrgTsengProbe(DriverPtr drv, int flags) 389d983712dSmrg{ 390d983712dSmrg int i; 391d983712dSmrg GDevPtr *devSections; 392d983712dSmrg int numDevSections; 393d983712dSmrg int numUsed; 394d983712dSmrg int *usedChips = NULL; 395d983712dSmrg Bool foundScreen = FALSE; 396d983712dSmrg 397d983712dSmrg 398d983712dSmrg PDEBUG(" TsengProbe\n"); 399d983712dSmrg /* 400d983712dSmrg * The aim here is to find all cards that this driver can handle, 401d983712dSmrg * and for the ones not already claimed by another driver, claim the 402d983712dSmrg * slot, and allocate a ScrnInfoRec. 403d983712dSmrg * 404d983712dSmrg * This should be a minimal probe, and it should under no circumstances 405d983712dSmrg * change the state of the hardware. Because a device is found, don't 406d983712dSmrg * assume that it will be used. Don't do any initialisations other than 407d983712dSmrg * the required ScrnInfoRec initialisations. Don't allocate any new 408d983712dSmrg * data structures. 409d983712dSmrg */ 410d983712dSmrg 411d983712dSmrg /* 412d983712dSmrg * Find the config file Device sections that match this 413d983712dSmrg * driver, and return if there are none. 414d983712dSmrg */ 415d983712dSmrg if ((numDevSections = xf86MatchDevice(TSENG_DRIVER_NAME, 416d983712dSmrg &devSections)) <= 0) { 417d983712dSmrg return FALSE; 418d983712dSmrg } 419d983712dSmrg 420d983712dSmrg /* PCI only driver now. */ 421d983712dSmrg if (!xf86GetPciVideoInfo()) 422d983712dSmrg return FALSE; 423d983712dSmrg 424d983712dSmrg /* XXX maybe this can go some time soon */ 425d983712dSmrg /* 426d983712dSmrg * for the Tseng server, there can only be one matching 427d983712dSmrg * device section. So issue a warning if more than one show up. 428d983712dSmrg * Multiple Tseng cards in the same machine are not possible. 429d983712dSmrg */ 430d983712dSmrg numUsed = xf86MatchPciInstances(TSENG_NAME, PCI_VENDOR_TSENG, 431d983712dSmrg TsengChipsets, TsengPciChipsets, 432d983712dSmrg devSections,numDevSections, drv, 433d983712dSmrg &usedChips); 434d983712dSmrg if (numUsed > 0) { 435d983712dSmrg if (flags & PROBE_DETECT) 436d983712dSmrg foundScreen = TRUE; 437d983712dSmrg else for (i = 0; i < numUsed; i++) { 438d983712dSmrg /* Allocate a ScrnInfoRec */ 439d983712dSmrg ScrnInfoPtr pScrn = NULL; 440d983712dSmrg if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], 441d983712dSmrg TsengPciChipsets,NULL, 442d983712dSmrg NULL,NULL,NULL,NULL))) { 443d983712dSmrg pScrn->driverVersion = TSENG_VERSION; 444d983712dSmrg pScrn->driverName = TSENG_DRIVER_NAME; 445d983712dSmrg pScrn->name = TSENG_NAME; 446d983712dSmrg pScrn->Probe = TsengProbe; 447d983712dSmrg pScrn->PreInit = TsengPreInit; 448d983712dSmrg pScrn->ScreenInit = TsengScreenInit; 449d983712dSmrg pScrn->SwitchMode = TsengSwitchMode; 450d983712dSmrg pScrn->AdjustFrame = TsengAdjustFrame; 451d983712dSmrg pScrn->EnterVT = TsengEnterVT; 452d983712dSmrg pScrn->LeaveVT = TsengLeaveVT; 453d983712dSmrg pScrn->FreeScreen = TsengFreeScreen; 454d983712dSmrg pScrn->ValidMode = TsengValidMode; 455d983712dSmrg 456d983712dSmrg foundScreen = TRUE; 457d983712dSmrg } 458d983712dSmrg } 459d983712dSmrg xfree(usedChips); 460d983712dSmrg } 461d983712dSmrg 462d983712dSmrg xfree(devSections); 463d983712dSmrg return foundScreen; 464d983712dSmrg} 465d983712dSmrg 466d983712dSmrg/* The PCI part of TsengPreInit() */ 467d983712dSmrgstatic Bool 468d983712dSmrgTsengPreInitPCI(ScrnInfoPtr pScrn) 469d983712dSmrg{ 470d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 471d983712dSmrg 472d983712dSmrg PDEBUG(" TsengPreInitPCI\n"); 473d983712dSmrg 474d983712dSmrg /* This is PCI, we should be able to trust it */ 475d983712dSmrg 476d983712dSmrg /* Set up ChipType, ChipRev and pScrn->chipset. 477d983712dSmrg * This last one is usually not done manually, but 478d983712dSmrg * it's for informative use only anyway. */ 479d983712dSmrg switch (pTseng->PciInfo->chipType) { 480d983712dSmrg case PCI_CHIP_ET4000_W32P_A: 481d983712dSmrg pTseng->ChipType = ET4000; 482d983712dSmrg pTseng->ChipRev = REV_A; 483d983712dSmrg pScrn->chipset = "ET4000/W32P (rev A)"; 484d983712dSmrg break; 485d983712dSmrg case PCI_CHIP_ET4000_W32P_B: 486d983712dSmrg pTseng->ChipType = ET4000; 487d983712dSmrg pTseng->ChipRev = REV_B; 488d983712dSmrg pScrn->chipset = "ET4000/W32P (rev B)"; 489d983712dSmrg break; 490d983712dSmrg case PCI_CHIP_ET4000_W32P_C: 491d983712dSmrg pTseng->ChipType = ET4000; 492d983712dSmrg pTseng->ChipRev = REV_C; 493d983712dSmrg pScrn->chipset = "ET4000/W32P (rev C)"; 494d983712dSmrg break; 495d983712dSmrg case PCI_CHIP_ET4000_W32P_D: 496d983712dSmrg pTseng->ChipType = ET4000; 497d983712dSmrg pTseng->ChipRev = REV_D; 498d983712dSmrg pScrn->chipset = "ET4000/W32P (rev D)"; 499d983712dSmrg break; 500d983712dSmrg case PCI_CHIP_ET6000: 501d983712dSmrg pTseng->ChipType = ET6000; 502d983712dSmrg 503d983712dSmrg if (pTseng->PciInfo->chipRev < 0x70) { 504d983712dSmrg pScrn->chipset = "ET6000"; 505d983712dSmrg pTseng->ChipRev = REV_ET6000; 506d983712dSmrg } else { 507d983712dSmrg pScrn->chipset = "ET6100"; 508d983712dSmrg pTseng->ChipRev = REV_ET6100; 509d983712dSmrg } 510d983712dSmrg break; 511d983712dSmrg default: 512d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown Tseng PCI ID: %X\n", 513d983712dSmrg pTseng->PciInfo->chipType); 514d983712dSmrg return FALSE; 515d983712dSmrg } 516d983712dSmrg 517d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chipset: \"%s\"\n", pScrn->chipset); 518d983712dSmrg 519d983712dSmrg pTseng->PciTag = pciTag(pTseng->PciInfo->bus, pTseng->PciInfo->device, 520d983712dSmrg pTseng->PciInfo->func); 521d983712dSmrg 522d983712dSmrg /* only the ET6000 implements a PCI IO address */ 523d983712dSmrg if (pTseng->ChipType == ET6000) { 524d983712dSmrg if (!pTseng->PciInfo->ioBase[1]) { 525d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 526d983712dSmrg "No valid PCI I/O address in PCI config space\n"); 527d983712dSmrg return FALSE; 528d983712dSmrg } 529d983712dSmrg 530d983712dSmrg pTseng->ET6000IOAddress = pTseng->PciInfo->ioBase[1]; 531d983712dSmrg 532d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ET6000 PCI I/O registers at 0x%lX\n", 533d983712dSmrg (unsigned long)pTseng->ET6000IOAddress); 534d983712dSmrg } 535d983712dSmrg 536d983712dSmrg return TRUE; 537d983712dSmrg} 538d983712dSmrg 539d983712dSmrg/* 540d983712dSmrg * The 8*32kb ET6000 MDRAM granularity causes the more general probe to 541d983712dSmrg * detect too much memory in some configurations, because that code has a 542d983712dSmrg * 8-bank (=256k) granularity. E.g. it fails to recognize 2.25 MB of memory 543d983712dSmrg * (detects 2.5 instead). This function goes to check if the RAM is actually 544d983712dSmrg * there. MDRAM comes in multiples of 4 banks (16, 24, 32, 36, 40, 64, 72, 545d983712dSmrg * 80, ... 32kb-banks), so checking each 64k block should be enough granularity. 546d983712dSmrg * 547d983712dSmrg * No more than the amount of refreshed RAM is checked. Non-refreshed RAM 548d983712dSmrg * won't work anyway. 549d983712dSmrg * 550d983712dSmrg * The same code could be used on other Tseng chips, or even on ANY 551d983712dSmrg * VGA board, but probably only in case of trouble. 552d983712dSmrg * 553d983712dSmrg * FIXME: this should be done using linear memory 554d983712dSmrg */ 555d983712dSmrg#define VIDMEM ((volatile CARD32*)check_vgabase) 556d983712dSmrg#define SEGSIZE (64) /* kb */ 557d983712dSmrg 558d983712dSmrg#define ET6K_SETSEG(seg) \ 559d983712dSmrg vgaHWWriteBank(hwp, ((seg) & 0x30) | ((seg) >> 4));\ 560d983712dSmrg vgaHWWriteSegment(hwp, ((seg) & 0x0f) | ((seg) << 4)); 561d983712dSmrg 562d983712dSmrgstatic int 563d983712dSmrget6000_check_videoram(ScrnInfoPtr pScrn, int ram) 564d983712dSmrg{ 565d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 566d983712dSmrg unsigned char oldSegSel1, oldSegSel2, oldGR5, oldGR6, oldSEQ2, oldSEQ4; 567d983712dSmrg int segment, i; 568d983712dSmrg int real_ram = 0; 569d983712dSmrg pointer check_vgabase; 570d983712dSmrg Bool fooled = FALSE; 571d983712dSmrg int save_vidmem; 572d983712dSmrg 573d983712dSmrg PDEBUG(" et6000_check_videoram\n"); 574d983712dSmrg if (ram > 4096) { 575d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 576d983712dSmrg "Detected more than 4096 kb of video RAM. Clipped to 4096kb\n"); 577d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 578d983712dSmrg " (Tseng VGA chips can only use 4096kb).\n"); 579d983712dSmrg ram = 4096; 580d983712dSmrg } 581d983712dSmrg if (!vgaHWMapMem(pScrn)) { 582d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 583d983712dSmrg "Could not map VGA memory to check for video memory.\n"); 584d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 585d983712dSmrg " Detected amount may be wrong.\n"); 586d983712dSmrg return ram; 587d983712dSmrg } 588d983712dSmrg check_vgabase = (VGAHWPTR(pScrn)->Base); 589d983712dSmrg 590d983712dSmrg /* 591d983712dSmrg * We need to set the VGA controller in VGA graphics mode, or else we won't 592d983712dSmrg * be able to access the full 4MB memory range. First, we save the 593d983712dSmrg * registers we modify, of course. 594d983712dSmrg */ 595d983712dSmrg 596d983712dSmrg oldSegSel1 = vgaHWReadSegment(hwp); 597d983712dSmrg oldSegSel2 = vgaHWReadBank(hwp); 598d983712dSmrg 599d983712dSmrg oldGR5 = hwp->readGr(hwp, 0x05); 600d983712dSmrg oldGR6 = hwp->readGr(hwp, 0x06); 601d983712dSmrg 602d983712dSmrg oldSEQ2 = hwp->readSeq(hwp, 0x02); 603d983712dSmrg oldSEQ4 = hwp->readSeq(hwp, 0x04); 604d983712dSmrg 605d983712dSmrg /* set graphics mode */ 606d983712dSmrg hwp->writeGr(hwp, 0x06, 0x05); 607d983712dSmrg hwp->writeGr(hwp, 0x05, 0x40); 608d983712dSmrg hwp->writeSeq(hwp, 0x02, 0x0F); 609d983712dSmrg hwp->writeSeq(hwp, 0x04, 0x0E); 610d983712dSmrg 611d983712dSmrg /* 612d983712dSmrg * count down from presumed amount of memory in SEGSIZE steps, and 613d983712dSmrg * look at each segment for real RAM. 614d983712dSmrg * 615d983712dSmrg * To select a segment, we cannot use ET4000W32SetReadWrite(), since 616d983712dSmrg * that requires the ScreenPtr, which we don't have here. 617d983712dSmrg */ 618d983712dSmrg 619d983712dSmrg for (segment = (ram / SEGSIZE) - 1; segment >= 0; segment--) { 620d983712dSmrg /* select the segment */ 621d983712dSmrg ET6K_SETSEG(segment); 622d983712dSmrg 623d983712dSmrg /* save contents of memory probing location */ 624d983712dSmrg save_vidmem = *(VIDMEM); 625d983712dSmrg 626d983712dSmrg /* test with pattern */ 627d983712dSmrg *VIDMEM = 0xAAAA5555; 628d983712dSmrg if (*VIDMEM != 0xAAAA5555) { 629d983712dSmrg *VIDMEM = save_vidmem; 630d983712dSmrg continue; 631d983712dSmrg } 632d983712dSmrg /* test with inverted pattern */ 633d983712dSmrg *VIDMEM = 0x5555AAAA; 634d983712dSmrg if (*VIDMEM != 0x5555AAAA) { 635d983712dSmrg *VIDMEM = save_vidmem; 636d983712dSmrg continue; 637d983712dSmrg } 638d983712dSmrg /* 639d983712dSmrg * If we get here, the memory seems to be writable/readable 640d983712dSmrg * Now check if we aren't fooled by address wrapping (mirroring) 641d983712dSmrg */ 642d983712dSmrg fooled = FALSE; 643d983712dSmrg for (i = segment - 1; i >= 0; i--) { 644d983712dSmrg /* select the segment */ 645d983712dSmrg ET6K_SETSEG(i); 646d983712dSmrg 647d983712dSmrg /* again? */ 648d983712dSmrg vgaHWWriteBank(hwp, (i & 0x30) | (i >> 4)); 649d983712dSmrg vgaHWWriteSegment(hwp, (i & 0x0f) | (i << 4)); 650d983712dSmrg 651d983712dSmrg if (*VIDMEM == 0x5555AAAA) { 652d983712dSmrg /* 653d983712dSmrg * Seems like address wrap, but there could of course be 654d983712dSmrg * 0x5555AAAA in here by accident, so we check with another 655d983712dSmrg * pattern again. 656d983712dSmrg */ 657d983712dSmrg ET6K_SETSEG(segment); 658d983712dSmrg /* test with other pattern again */ 659d983712dSmrg *VIDMEM = 0xAAAA5555; 660d983712dSmrg ET6K_SETSEG(i); 661d983712dSmrg if (*VIDMEM == 0xAAAA5555) { 662d983712dSmrg /* now we're sure: this is not real memory */ 663d983712dSmrg fooled = TRUE; 664d983712dSmrg break; 665d983712dSmrg } 666d983712dSmrg } 667d983712dSmrg } 668d983712dSmrg if (!fooled) { 669d983712dSmrg real_ram = (segment + 1) * SEGSIZE; 670d983712dSmrg break; 671d983712dSmrg } 672d983712dSmrg /* restore old contents again */ 673d983712dSmrg ET6K_SETSEG(segment); 674d983712dSmrg *VIDMEM = save_vidmem; 675d983712dSmrg } 676d983712dSmrg 677d983712dSmrg /* restore original register contents */ 678d983712dSmrg vgaHWWriteSegment(hwp, oldSegSel1); 679d983712dSmrg vgaHWWriteBank(hwp, oldSegSel2); 680d983712dSmrg 681d983712dSmrg hwp->writeGr(hwp, 0x05, oldGR5); 682d983712dSmrg hwp->writeGr(hwp, 0x06, oldGR6); 683d983712dSmrg hwp->writeSeq(hwp, 0x02, oldSEQ2); 684d983712dSmrg hwp->writeSeq(hwp, 0x04, oldSEQ4); 685d983712dSmrg 686d983712dSmrg vgaHWUnmapMem(pScrn); 687d983712dSmrg return real_ram; 688d983712dSmrg} 689d983712dSmrg 690d983712dSmrg/* 691d983712dSmrg * Handle amount of allowed memory: some combinations can't use all 692d983712dSmrg * available memory. Should we still allow the user to override this? 693d983712dSmrg * 694d983712dSmrg * This must be called AFTER the decision has been made to use linear mode 695d983712dSmrg * and/or acceleration, or the memory limit code won't be able to work. 696d983712dSmrg */ 697d983712dSmrg 698d983712dSmrgstatic int 699d983712dSmrgTsengDoMemLimit(ScrnInfoPtr pScrn, int ram, int limit, char *reason) 700d983712dSmrg{ 701d983712dSmrg if (ram > limit) { 702d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Only %d kb of memory can be used %s.\n", 703d983712dSmrg limit, reason); 704d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Reducing video memory to %d kb.\n", limit); 705d983712dSmrg ram = limit; 706d983712dSmrg } 707d983712dSmrg return ram; 708d983712dSmrg} 709d983712dSmrg 710d983712dSmrgstatic int 711d983712dSmrgTsengLimitMem(ScrnInfoPtr pScrn, int ram) 712d983712dSmrg{ 713d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 714d983712dSmrg 715d983712dSmrg if (pTseng->UseAccel) { 716d983712dSmrg if (pTseng->ChipType == ET4000) { 717d983712dSmrg /* <= W32p_ab : 718d983712dSmrg * 2 MB direct access + 2*512kb via apertures MBP0 and MBP1 719d983712dSmrg * == W32p_cd : 720d983712dSmrg * 2*1MB via apertures MBP0 and MBP1 721d983712dSmrg */ 722d983712dSmrg if ((pTseng->ChipRev == REV_C) || (pTseng->ChipRev == REV_D)) 723d983712dSmrg ram = TsengDoMemLimit(pScrn, ram, 2048, 724d983712dSmrg "in linear + accelerated mode " 725d983712dSmrg "on W32p rev c and d"); 726d983712dSmrg 727d983712dSmrg ram = TsengDoMemLimit(pScrn, ram, 2048 + 1024, 728d983712dSmrg "in linear + accelerated mode " 729d983712dSmrg "on W32/W32i/W32p"); 730d983712dSmrg 731d983712dSmrg /* 732d983712dSmrg * upper 516kb of 4MB linear map used for 733d983712dSmrg * "externally mapped registers" 734d983712dSmrg */ 735d983712dSmrg ram = TsengDoMemLimit(pScrn, ram, 4096 - 516, 736d983712dSmrg "in linear + accelerated mode " 737d983712dSmrg "on W32/W32i/W32p"); 738d983712dSmrg } else { 739d983712dSmrg /* 740d983712dSmrg * upper 8kb used for externally mapped and 741d983712dSmrg * memory mapped registers 742d983712dSmrg */ 743d983712dSmrg ram = TsengDoMemLimit(pScrn, ram, 4096 - 8, 744d983712dSmrg "in linear + accelerated mode " 745d983712dSmrg "on ET6000/6100"); 746d983712dSmrg } 747d983712dSmrg } 748d983712dSmrg ram = TsengDoMemLimit(pScrn, ram, 4096, "on any Tseng card"); 749d983712dSmrg return ram; 750d983712dSmrg} 751d983712dSmrg 752d983712dSmrg/* 753d983712dSmrg * TsengDetectMem -- 754d983712dSmrg * try to find amount of video memory installed. 755d983712dSmrg * 756d983712dSmrg */ 757d983712dSmrgstatic int 758d983712dSmrgTsengDetectMem(ScrnInfoPtr pScrn) 759d983712dSmrg{ 760d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 761d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 762d983712dSmrg unsigned char config; 763d983712dSmrg int ramtype = 0; 764d983712dSmrg int ram = 0; 765d983712dSmrg 766d983712dSmrg PDEBUG(" TsengDetectMem\n"); 767d983712dSmrg if (pTseng->ChipType == ET6000) { 768d983712dSmrg ramtype = hwp->readST00(hwp) & 0x03; 769d983712dSmrg switch (ramtype) { 770d983712dSmrg case 0x03: /* MDRAM */ 771d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 772d983712dSmrg "Video memory type: Multibank DRAM (MDRAM).\n"); 773d983712dSmrg ram = ((ET6000IORead(pTseng, 0x47) & 0x07) + 1) * 8 * 32; /* number of 8 32kb banks */ 774d983712dSmrg if (ET6000IORead(pTseng, 0x45) & 0x04) { 775d983712dSmrg ram <<= 1; 776d983712dSmrg } 777d983712dSmrg /* 778d983712dSmrg * 8*32kb MDRAM refresh control granularity in the ET6000 fails to 779d983712dSmrg * recognize 2.25 MB of memory (detects 2.5 instead) 780d983712dSmrg */ 781d983712dSmrg ram = et6000_check_videoram(pScrn, ram); 782d983712dSmrg break; 783d983712dSmrg case 0x00: /* DRAM -- VERY unlikely on ET6000 cards, IMPOSSIBLE on ET6100 */ 784d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 785d983712dSmrg "Video memory type: Standard DRAM.\n"); 786d983712dSmrg ram = 1024 << (ET6000IORead(pTseng, 0x45) & 0x03); 787d983712dSmrg break; 788d983712dSmrg default: /* unknown RAM type */ 789d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 790d983712dSmrg "Unknown ET6000 video memory type %d -- assuming 1 MB (unless specified)\n", 791d983712dSmrg ramtype); 792d983712dSmrg ram = 1024; 793d983712dSmrg } 794d983712dSmrg } else { 795d983712dSmrg config = hwp->readCrtc(hwp, 0x37); 796d983712dSmrg 797d983712dSmrg ram = 128 << (config & 0x03); 798d983712dSmrg 799d983712dSmrg if (config & 0x80) 800d983712dSmrg ram <<= 1; 801d983712dSmrg 802d983712dSmrg /* Check for interleaving on W32i/p. */ 803d983712dSmrg config = hwp->readCrtc(hwp, 0x32); 804d983712dSmrg if (config & 0x80) { 805d983712dSmrg ram <<= 1; 806d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 807d983712dSmrg "Video memory type: Interleaved DRAM.\n"); 808d983712dSmrg } else { 809d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 810d983712dSmrg "Video memory type: Standard DRAM.\n"); 811d983712dSmrg } 812d983712dSmrg } 813d983712dSmrg return ram; 814d983712dSmrg} 815d983712dSmrg 816d983712dSmrgstatic Bool 817d983712dSmrgTsengProcessHibit(ScrnInfoPtr pScrn) 818d983712dSmrg{ 819d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 820d983712dSmrg MessageType from = X_CONFIG; 821d983712dSmrg int hibit_mode_width; 822d983712dSmrg 823d983712dSmrg PDEBUG(" TsengProcessHibit\n"); 824d983712dSmrg if (xf86IsOptionSet(pTseng->Options, OPTION_HIBIT_HIGH)) { 825d983712dSmrg if (xf86IsOptionSet(pTseng->Options, OPTION_HIBIT_LOW)) { 826d983712dSmrg xf86Msg(X_ERROR, "\nOptions \"hibit_high\" and \"hibit_low\" are incompatible;\n"); 827d983712dSmrg xf86Msg(X_ERROR, " specify only one (not both) in X configuration file\n"); 828d983712dSmrg return FALSE; 829d983712dSmrg } 830d983712dSmrg pTseng->save_divide = 0x40; 831d983712dSmrg } else if (xf86IsOptionSet(pTseng->Options, OPTION_HIBIT_HIGH)) { 832d983712dSmrg pTseng->save_divide = 0; 833d983712dSmrg } else { 834d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 835d983712dSmrg 836d983712dSmrg from = X_PROBED; 837d983712dSmrg 838d983712dSmrg /* first check to see if hibit is probed from low-res mode */ 839d983712dSmrg hibit_mode_width = hwp->readCrtc(hwp, 0x01) + 1; 840d983712dSmrg 841d983712dSmrg if (hibit_mode_width > 82) { 842d983712dSmrg xf86Msg(X_WARNING, "Non-standard VGA text or graphics mode while probing for hibit:\n"); 843d983712dSmrg xf86Msg(X_WARNING, " probed 'hibit' value may be wrong.\n"); 844d983712dSmrg xf86Msg(X_WARNING, " Preferably run probe from 80x25 textmode,\n"); 845d983712dSmrg xf86Msg(X_WARNING, " or specify correct value in X configuration file.\n"); 846d983712dSmrg } 847d983712dSmrg 848d983712dSmrg /* Check for initial state of divide flag */ 849d983712dSmrg pTseng->save_divide = hwp->readSeq(hwp, 0x07) & 0x40; 850d983712dSmrg } 851d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Initial ET4000 hibit state: %s\n", 852d983712dSmrg pTseng->save_divide & 0x40 ? "high" : "low"); 853d983712dSmrg return TRUE; 854d983712dSmrg} 855d983712dSmrg 856d983712dSmrgstatic Bool 857d983712dSmrgTsengProcessOptions(ScrnInfoPtr pScrn) 858d983712dSmrg{ 859d983712dSmrg MessageType from; 860d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 861d983712dSmrg 862d983712dSmrg PDEBUG(" TsengProcessOptions\n"); 863d983712dSmrg 864d983712dSmrg /* Collect all of the relevant option flags (fill in pScrn->options) */ 865d983712dSmrg xf86CollectOptions(pScrn, NULL); 866d983712dSmrg 867d983712dSmrg /* Process the options */ 868d983712dSmrg if (!(pTseng->Options = xalloc(sizeof(TsengOptions)))) 869d983712dSmrg return FALSE; 870d983712dSmrg memcpy(pTseng->Options, TsengOptions, sizeof(TsengOptions)); 871d983712dSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTseng->Options); 872d983712dSmrg 873d983712dSmrg from = X_DEFAULT; 874d983712dSmrg pTseng->HWCursor = FALSE; /* default */ 875d983712dSmrg if (xf86GetOptValBool(pTseng->Options, OPTION_HW_CURSOR, &pTseng->HWCursor)) 876d983712dSmrg from = X_CONFIG; 877d983712dSmrg if (xf86ReturnOptValBool(pTseng->Options, OPTION_SW_CURSOR, FALSE)) { 878d983712dSmrg from = X_CONFIG; 879d983712dSmrg pTseng->HWCursor = FALSE; 880d983712dSmrg } 881d983712dSmrg if ((pTseng->ChipType == ET4000) && pTseng->HWCursor) { 882d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, from, 883d983712dSmrg "Hardware Cursor not supported on this chipset\n"); 884d983712dSmrg pTseng->HWCursor = FALSE; 885d983712dSmrg } 886d983712dSmrg 887d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 888d983712dSmrg pTseng->HWCursor ? "HW" : "SW"); 889d983712dSmrg 890d983712dSmrg if (pScrn->bitsPerPixel >= 8) { 891d983712dSmrg pTseng->UseAccel = TRUE; 892d983712dSmrg if (xf86ReturnOptValBool(pTseng->Options, OPTION_NOACCEL, FALSE)) { 893d983712dSmrg pTseng->UseAccel = FALSE; 894d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 895d983712dSmrg } 896d983712dSmrg } else 897d983712dSmrg pTseng->UseAccel = FALSE; /* 1bpp and 4bpp are always non-accelerated */ 898d983712dSmrg 899d983712dSmrg pTseng->SlowDram = FALSE; 900d983712dSmrg if (xf86IsOptionSet(pTseng->Options, OPTION_SLOW_DRAM)) { 901d983712dSmrg pTseng->SlowDram = TRUE; 902d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using slow DRAM access\n"); 903d983712dSmrg } 904d983712dSmrg pTseng->MedDram = FALSE; 905d983712dSmrg if (xf86IsOptionSet(pTseng->Options, OPTION_MED_DRAM)) { 906d983712dSmrg pTseng->MedDram = TRUE; 907d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using Medium-speed DRAM access\n"); 908d983712dSmrg } 909d983712dSmrg pTseng->FastDram = FALSE; 910d983712dSmrg if (xf86IsOptionSet(pTseng->Options, OPTION_FAST_DRAM)) { 911d983712dSmrg pTseng->FastDram = TRUE; 912d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using fast DRAM access\n"); 913d983712dSmrg } 914d983712dSmrg if ((pTseng->SetW32Interleave = 915d983712dSmrg xf86GetOptValBool(pTseng->Options, OPTION_W32_INTERLEAVE, &pTseng->W32Interleave)) ) 916d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing W32p memory interleave %s.\n", 917d983712dSmrg pTseng->W32Interleave ? "ON" : "OFF"); 918d983712dSmrg if ((pTseng->SetPCIBurst = 919d983712dSmrg xf86GetOptValBool(pTseng->Options, OPTION_PCI_BURST, &pTseng->PCIBurst)) ) 920d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing PCI burst mode %s.\n", 921d983712dSmrg pTseng->PCIBurst ? "ON" : "OFF"); 922d983712dSmrg 923d983712dSmrg pTseng->ShowCache = FALSE; 924d983712dSmrg if (xf86ReturnOptValBool(pTseng->Options, OPTION_SHOWCACHE, FALSE)) { 925d983712dSmrg pTseng->ShowCache = TRUE; 926d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "(for debugging only:) Visible off-screen memory\n"); 927d983712dSmrg } 928d983712dSmrg 929d983712dSmrg pTseng->UsePCIRetry = FALSE; 930d983712dSmrg if (xf86ReturnOptValBool(pTseng->Options, OPTION_PCI_RETRY, FALSE)) { 931d983712dSmrg pTseng->UsePCIRetry = TRUE; 932d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); 933d983712dSmrg } 934d983712dSmrg return TRUE; 935d983712dSmrg} 936d983712dSmrg 937d983712dSmrgstatic Bool 938d983712dSmrgTsengGetFbAddress(ScrnInfoPtr pScrn) 939d983712dSmrg{ 940d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 941d983712dSmrg 942d983712dSmrg PDEBUG(" TsengGetFbAddress\n"); 943d983712dSmrg 944d983712dSmrg /* base0 is the framebuffer and base1 is the PCI IO space. */ 945d983712dSmrg if (!pTseng->PciInfo->memBase[0]) { 946d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 947d983712dSmrg "No valid Framebuffer address in PCI config space;\n"); 948d983712dSmrg return FALSE; 949d983712dSmrg } else 950d983712dSmrg pTseng->FbAddress = pTseng->PciInfo->memBase[0]; 951d983712dSmrg 952d983712dSmrg 953d983712dSmrg if (xf86RegisterResources(pTseng->pEnt->index,NULL,ResNone)) { 954d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot register FB memory.\n"); 955d983712dSmrg return FALSE; 956d983712dSmrg } 957d983712dSmrg 958d983712dSmrg /* The W32 linear map address space is always 4Mb (mainly because the 959d983712dSmrg * memory-mapped registers are located near the top of the 4MB area). 960d983712dSmrg * The ET6000 maps out 16 Meg, but still uses only 4Mb of that. 961d983712dSmrg * However, since all mmap()-ed space is also reflected in the "ps" 962d983712dSmrg * listing for the Xserver, many users will be worried by a server that 963d983712dSmrg * always eats 16MB of memory, even if it's not "real" memory, just 964d983712dSmrg * address space. Not mapping all of the 16M may be a potential problem 965d983712dSmrg * though: if another board is mapped on top of the remaining part of 966d983712dSmrg * the 16M... Boom! 967d983712dSmrg */ 968d983712dSmrg if (pTseng->ChipType == ET6000) 969d983712dSmrg pTseng->FbMapSize = 16384 * 1024; 970d983712dSmrg else 971d983712dSmrg pTseng->FbMapSize = 4096 * 1024; 972d983712dSmrg 973d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer at 0x%lX\n", 974d983712dSmrg (unsigned long)pTseng->FbAddress); 975d983712dSmrg 976d983712dSmrg return TRUE; 977d983712dSmrg} 978d983712dSmrg 979d983712dSmrgstatic Bool 980d983712dSmrgTsengPreInit(ScrnInfoPtr pScrn, int flags) 981d983712dSmrg{ 982d983712dSmrg TsengPtr pTseng; 983d983712dSmrg MessageType from; 984d983712dSmrg int i; 985d983712dSmrg 986d983712dSmrg if (flags & PROBE_DETECT) return FALSE; 987d983712dSmrg 988d983712dSmrg PDEBUG(" TsengPreInit\n"); 989d983712dSmrg 990d983712dSmrg /* 991d983712dSmrg * Note: This function is only called once at server startup, and 992d983712dSmrg * not at the start of each server generation. This means that 993d983712dSmrg * only things that are persistent across server generations can 994d983712dSmrg * be initialised here. xf86Screens[] is (pScrn is a pointer to one 995d983712dSmrg * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 996d983712dSmrg * are too, and should be used for data that must persist across 997d983712dSmrg * server generations. 998d983712dSmrg * 999d983712dSmrg * Per-generation data should be allocated with 1000d983712dSmrg * AllocateScreenPrivateIndex() from the ScreenInit() function. 1001d983712dSmrg */ 1002d983712dSmrg 1003d983712dSmrg /* The vgahw module should be loaded here when needed */ 1004d983712dSmrg 1005d983712dSmrg /* This driver doesn't expect more than one entity per screen */ 1006d983712dSmrg if (pScrn->numEntities > 1) 1007d983712dSmrg return FALSE; 1008d983712dSmrg 1009d983712dSmrg /* Allocate the TsengRec driverPrivate */ 1010d983712dSmrg if (!TsengGetRec(pScrn)) { 1011d983712dSmrg return FALSE; 1012d983712dSmrg } 1013d983712dSmrg pTseng = TsengPTR(pScrn); 1014d983712dSmrg 1015d983712dSmrg /* This is the general case */ 1016d983712dSmrg pTseng->pEnt = xf86GetEntityInfo(*pScrn->entityList); 1017d983712dSmrg 1018d983712dSmrg#if 1 1019d983712dSmrg if (xf86LoadSubModule(pScrn, "int10")) { 1020d983712dSmrg xf86Int10InfoPtr pInt; 1021d983712dSmrg xf86LoaderReqSymLists(int10Symbols, NULL); 1022d983712dSmrg#if 1 1023d983712dSmrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 1024d983712dSmrg pInt = xf86InitInt10(pTseng->pEnt->index); 1025d983712dSmrg xf86FreeInt10(pInt); 1026d983712dSmrg#endif 1027d983712dSmrg } 1028d983712dSmrg#endif 1029d983712dSmrg 1030d983712dSmrg if (!xf86LoadSubModule(pScrn, "vgahw")) 1031d983712dSmrg return FALSE; 1032d983712dSmrg xf86LoaderReqSymLists(vgaHWSymbols, NULL); 1033d983712dSmrg /* 1034d983712dSmrg * Allocate a vgaHWRec 1035d983712dSmrg */ 1036d983712dSmrg if (!vgaHWGetHWRec(pScrn)) 1037d983712dSmrg return FALSE; 1038d983712dSmrg 1039d983712dSmrg vgaHWGetIOBase(VGAHWPTR(pScrn)); 1040d983712dSmrg /* 1041d983712dSmrg * Since, the capabilities are determined by the chipset, the very first 1042d983712dSmrg * thing to do is to figure out the chipset and its capabilities. 1043d983712dSmrg */ 1044d983712dSmrg 1045d983712dSmrg TsengUnlock(pScrn); 1046d983712dSmrg 1047d983712dSmrg pTseng->PciInfo = xf86GetPciInfoForEntity(pTseng->pEnt->index); 1048d983712dSmrg if (!TsengPreInitPCI(pScrn)) { 1049d983712dSmrg TsengFreeRec(pScrn); 1050d983712dSmrg return FALSE; 1051d983712dSmrg } 1052d983712dSmrg 1053d983712dSmrg if (!TsengRAMDACProbe(pScrn)) { 1054d983712dSmrg TsengFreeRec(pScrn); 1055d983712dSmrg return FALSE; 1056d983712dSmrg } 1057d983712dSmrg 1058d983712dSmrg pScrn->progClock = TRUE; 1059d983712dSmrg 1060d983712dSmrg /* 1061d983712dSmrg * Now we can check what depth we support. 1062d983712dSmrg */ 1063d983712dSmrg 1064d983712dSmrg /* Set pScrn->monitor */ 1065d983712dSmrg pScrn->monitor = pScrn->confScreen->monitor; 1066d983712dSmrg 1067d983712dSmrg /* 1068d983712dSmrg * The first thing we should figure out is the depth, bpp, etc. 1069d983712dSmrg * Our default depth is 8, so pass it to the helper function. 1070d983712dSmrg * Our preference for depth 24 is 24bpp, so tell it that too. 1071d983712dSmrg */ 1072d983712dSmrg if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | Support32bppFb | 1073d983712dSmrg SupportConvert32to24 | PreferConvert32to24)) { 1074d983712dSmrg return FALSE; 1075d983712dSmrg } else { 1076d983712dSmrg switch (pScrn->depth) { 1077d983712dSmrg case 8: 1078d983712dSmrg case 16: 1079d983712dSmrg case 24: 1080d983712dSmrg case 32: 1081d983712dSmrg /* OK */ 1082d983712dSmrg break; 1083d983712dSmrg default: 1084d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1085d983712dSmrg "Given depth (%d) is not supported by this driver\n", 1086d983712dSmrg pScrn->depth); 1087d983712dSmrg return FALSE; 1088d983712dSmrg } 1089d983712dSmrg } 1090d983712dSmrg xf86PrintDepthBpp(pScrn); 1091d983712dSmrg 1092d983712dSmrg /* Get the depth24 pixmap format */ 1093d983712dSmrg if (pScrn->depth == 24 && pix24bpp == 0) 1094d983712dSmrg pix24bpp = xf86GetBppFromDepth(pScrn, 24); 1095d983712dSmrg 1096d983712dSmrg if (pScrn->bitsPerPixel > 8) 1097d983712dSmrg pTseng->Bytesperpixel = pScrn->bitsPerPixel / 8; 1098d983712dSmrg else 1099d983712dSmrg pTseng->Bytesperpixel = 1; /* this is fake for < 8bpp, but simplifies other code */ 1100d983712dSmrg 1101d983712dSmrg /* hardware limits */ 1102d983712dSmrg pScrn->maxHValue = Tseng_HMAX; 1103d983712dSmrg pScrn->maxVValue = Tseng_VMAX; 1104d983712dSmrg 1105d983712dSmrg /* 1106d983712dSmrg * This must happen after pScrn->display has been set because 1107d983712dSmrg * xf86SetWeight references it. 1108d983712dSmrg */ 1109d983712dSmrg 1110d983712dSmrg /* Set weight/mask/offset for depth > 8 */ 1111d983712dSmrg if (pScrn->depth > 8) { 1112d983712dSmrg /* The defaults are OK for us */ 1113d983712dSmrg rgb zeros = {0, 0, 0}; 1114d983712dSmrg 1115d983712dSmrg if (!xf86SetWeight(pScrn, zeros, zeros)) { 1116d983712dSmrg return FALSE; 1117d983712dSmrg } else { 1118d983712dSmrg /* XXX check that weight returned is supported */ 1119d983712dSmrg ; 1120d983712dSmrg } 1121d983712dSmrg } 1122d983712dSmrg 1123d983712dSmrg /* Set the default visual. */ 1124d983712dSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 1125d983712dSmrg return FALSE; 1126d983712dSmrg 1127d983712dSmrg /* The gamma fields must be initialised when using the new cmap code */ 1128d983712dSmrg if (pScrn->depth > 1) { 1129d983712dSmrg Gamma zeros = {0.0, 0.0, 0.0}; 1130d983712dSmrg 1131d983712dSmrg if (!xf86SetGamma(pScrn, zeros)) { 1132d983712dSmrg return FALSE; 1133d983712dSmrg } 1134d983712dSmrg } 1135d983712dSmrg 1136d983712dSmrg /* Set the bits per RGB for 8bpp mode */ 1137d983712dSmrg if (pScrn->depth == 8) { 1138d983712dSmrg /* Default to 6, because most Tseng chips/RAMDACs don't support it */ 1139d983712dSmrg pScrn->rgbBits = 6; 1140d983712dSmrg } 1141d983712dSmrg if (!TsengProcessOptions(pScrn)) /* must be done _after_ we know what chip this is */ 1142d983712dSmrg return FALSE; 1143d983712dSmrg 1144d983712dSmrg if (!TsengGetFbAddress(pScrn)) 1145d983712dSmrg return FALSE; 1146d983712dSmrg 1147d983712dSmrg pScrn->memPhysBase = pTseng->FbAddress; 1148d983712dSmrg pScrn->fbOffset = 0; 1149d983712dSmrg 1150d983712dSmrg if (pTseng->UseAccel) 1151d983712dSmrg VGAHWPTR(pScrn)->MapSize = 0x20000; /* accelerator apertures and MMIO */ 1152d983712dSmrg else 1153d983712dSmrg VGAHWPTR(pScrn)->MapSize = 0x10000; 1154d983712dSmrg 1155d983712dSmrg /* 1156d983712dSmrg * XXX At least part of this range does appear to be disabled, 1157d983712dSmrg * but to play safe, it is marked as "unused" for now. 1158d983712dSmrg * Changed this to "disable". Otherwise it might interfere with DGA. 1159d983712dSmrg */ 1160d983712dSmrg xf86SetOperatingState(resVgaMem, pTseng->pEnt->index, ResDisableOpr); 1161d983712dSmrg 1162d983712dSmrg /* hibit processing (TsengProcessOptions() must have been called first) */ 1163d983712dSmrg pTseng->save_divide = 0x40; /* default */ 1164d983712dSmrg if (pTseng->ChipType == ET4000) { 1165d983712dSmrg if (!TsengProcessHibit(pScrn)) 1166d983712dSmrg return FALSE; 1167d983712dSmrg } 1168d983712dSmrg /* 1169d983712dSmrg * If the user has specified the amount of memory in the XF86Config 1170d983712dSmrg * file, we respect that setting. 1171d983712dSmrg */ 1172d983712dSmrg if (pTseng->pEnt->device->videoRam != 0) { 1173d983712dSmrg pScrn->videoRam = pTseng->pEnt->device->videoRam; 1174d983712dSmrg from = X_CONFIG; 1175d983712dSmrg } else { 1176d983712dSmrg from = X_PROBED; 1177d983712dSmrg pScrn->videoRam = TsengDetectMem(pScrn); 1178d983712dSmrg } 1179d983712dSmrg pScrn->videoRam = TsengLimitMem(pScrn, pScrn->videoRam); 1180d983712dSmrg 1181d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte.\n", 1182d983712dSmrg pScrn->videoRam); 1183d983712dSmrg 1184d983712dSmrg TsengSetupClockRange(pScrn); 1185d983712dSmrg 1186d983712dSmrg /* 1187d983712dSmrg * xf86ValidateModes will check that the mode HTotal and VTotal values 1188d983712dSmrg * don't exceed the chipset's limit if pScrn->maxHValue and 1189d983712dSmrg * pScrn->maxVValue are set. Since our TsengValidMode() already takes 1190d983712dSmrg * care of this, we don't worry about setting them here. 1191d983712dSmrg */ 1192d983712dSmrg 1193d983712dSmrg /* Select valid modes from those available */ 1194d983712dSmrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 1195d983712dSmrg pScrn->display->modes, &pTseng->clockRange, 1196d983712dSmrg NULL, 32, pScrn->maxHValue, 8*pTseng->Bytesperpixel, /* H limits */ 1197d983712dSmrg 0, pScrn->maxVValue, /* V limits */ 1198d983712dSmrg pScrn->display->virtualX, 1199d983712dSmrg pScrn->display->virtualY, 1200d983712dSmrg pTseng->FbMapSize, 1201d983712dSmrg LOOKUP_BEST_REFRESH); /* LOOKUP_CLOSEST_CLOCK | LOOKUP_CLKDIV2 when no programmable clock ? */ 1202d983712dSmrg 1203d983712dSmrg if (i == -1) { 1204d983712dSmrg TsengFreeRec(pScrn); 1205d983712dSmrg return FALSE; 1206d983712dSmrg } 1207d983712dSmrg /* Prune the modes marked as invalid */ 1208d983712dSmrg xf86PruneDriverModes(pScrn); 1209d983712dSmrg 1210d983712dSmrg if (i == 0 || pScrn->modes == NULL) { 1211d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1212d983712dSmrg TsengFreeRec(pScrn); 1213d983712dSmrg return FALSE; 1214d983712dSmrg } 1215d983712dSmrg /* 1216d983712dSmrg * Set the CRTC parameters for all of the modes based on the type 1217d983712dSmrg * of mode, and the chipset's interlace requirements. 1218d983712dSmrg * 1219d983712dSmrg * Calling this is required if the mode->Crtc* values are used by the 1220d983712dSmrg * driver and if the driver doesn't provide code to set them. They 1221d983712dSmrg * are not pre-initialised at all. 1222d983712dSmrg */ 1223d983712dSmrg xf86SetCrtcForModes(pScrn, 0); 1224d983712dSmrg 1225d983712dSmrg /* Set the current mode to the first in the list */ 1226d983712dSmrg pScrn->currentMode = pScrn->modes; 1227d983712dSmrg 1228d983712dSmrg /* Print the list of modes being used */ 1229d983712dSmrg xf86PrintModes(pScrn); 1230d983712dSmrg 1231d983712dSmrg /* Set display resolution */ 1232d983712dSmrg xf86SetDpi(pScrn, 0, 0); 1233d983712dSmrg 1234d983712dSmrg /* Load bpp-specific modules */ 1235d983712dSmrg switch (pScrn->bitsPerPixel) { 1236d983712dSmrg case 1: 1237d983712dSmrg if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) { 1238d983712dSmrg TsengFreeRec(pScrn); 1239d983712dSmrg return FALSE; 1240d983712dSmrg } 1241d983712dSmrg xf86LoaderReqSymbols("xf1bppScreenInit", NULL); 1242d983712dSmrg break; 1243d983712dSmrg case 4: 1244d983712dSmrg if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) { 1245d983712dSmrg TsengFreeRec(pScrn); 1246d983712dSmrg return FALSE; 1247d983712dSmrg } 1248d983712dSmrg xf86LoaderReqSymbols("xf4bppScreenInit", NULL); 1249d983712dSmrg break; 1250d983712dSmrg default: 1251d983712dSmrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 1252d983712dSmrg TsengFreeRec(pScrn); 1253d983712dSmrg return FALSE; 1254d983712dSmrg } 1255d983712dSmrg xf86LoaderReqSymLists(fbSymbols, NULL); 1256d983712dSmrg break; 1257d983712dSmrg } 1258d983712dSmrg 1259d983712dSmrg /* Load XAA if needed */ 1260d983712dSmrg if (pTseng->UseAccel) { 1261d983712dSmrg if (!xf86LoadSubModule(pScrn, "xaa")) { 1262d983712dSmrg TsengFreeRec(pScrn); 1263d983712dSmrg return FALSE; 1264d983712dSmrg } 1265d983712dSmrg xf86LoaderReqSymLists(xaaSymbols, NULL); 1266d983712dSmrg } 1267d983712dSmrg /* Load ramdac if needed */ 1268d983712dSmrg if (pTseng->HWCursor) { 1269d983712dSmrg if (!xf86LoadSubModule(pScrn, "ramdac")) { 1270d983712dSmrg TsengFreeRec(pScrn); 1271d983712dSmrg return FALSE; 1272d983712dSmrg } 1273d983712dSmrg xf86LoaderReqSymLists(ramdacSymbols, NULL); 1274d983712dSmrg } 1275d983712dSmrg/* TsengLock(pScrn); */ 1276d983712dSmrg 1277d983712dSmrg return TRUE; 1278d983712dSmrg} 1279d983712dSmrg 1280d983712dSmrgstatic void 1281d983712dSmrgTsengSetupAccelMemory(int scrnIndex, ScreenPtr pScreen) 1282d983712dSmrg{ 1283d983712dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1284d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1285d983712dSmrg int offscreen_videoram, videoram_end, req_videoram; 1286d983712dSmrg int i; 1287d983712dSmrg int v; 1288d983712dSmrg 1289d983712dSmrg /* XXX Hack to suppress messages in subsequent generations. */ 1290d983712dSmrg if (serverGeneration == 1) 1291d983712dSmrg v = 1; 1292d983712dSmrg else 1293d983712dSmrg v = 100; 1294d983712dSmrg /* 1295d983712dSmrg * The accelerator requires free off-screen video memory to operate. The 1296d983712dSmrg * more there is, the more it can accelerate. 1297d983712dSmrg */ 1298d983712dSmrg 1299d983712dSmrg videoram_end = pScrn->videoRam * 1024; 1300d983712dSmrg offscreen_videoram = videoram_end - 1301d983712dSmrg pScrn->displayWidth * pScrn->virtualY * pTseng->Bytesperpixel; 1302d983712dSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, v, "Available off-screen memory: %d bytes.\n", 1303d983712dSmrg offscreen_videoram); 1304d983712dSmrg 1305d983712dSmrg /* 1306d983712dSmrg * The HW cursor requires 1kb of off-screen memory, aligned to 1kb 1307d983712dSmrg * (256 DWORDS). Setting up its memory first ensures the alignment. 1308d983712dSmrg */ 1309d983712dSmrg if (pTseng->HWCursor) { 1310d983712dSmrg req_videoram = 1024; 1311d983712dSmrg if (offscreen_videoram < req_videoram) { 1312d983712dSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, v, 1313d983712dSmrg "Hardware Cursor disabled. It requires %d bytes of free video memory\n", 1314d983712dSmrg req_videoram); 1315d983712dSmrg pTseng->HWCursor = FALSE; 1316d983712dSmrg pTseng->HWCursorBufferOffset = 0; 1317d983712dSmrg } else { 1318d983712dSmrg offscreen_videoram -= req_videoram; 1319d983712dSmrg videoram_end -= req_videoram; 1320d983712dSmrg pTseng->HWCursorBufferOffset = videoram_end; 1321d983712dSmrg } 1322d983712dSmrg } else { 1323d983712dSmrg pTseng->HWCursorBufferOffset = 0; 1324d983712dSmrg } 1325d983712dSmrg 1326d983712dSmrg /* 1327d983712dSmrg * Acceleration memory setup. Do this only if acceleration is enabled. 1328d983712dSmrg */ 1329d983712dSmrg if (!pTseng->UseAccel) return; 1330d983712dSmrg 1331d983712dSmrg /* 1332d983712dSmrg * Basic acceleration needs storage for FG, BG and PAT colors in 1333d983712dSmrg * off-screen memory. Each color requires 2(ping-pong)*8 bytes. 1334d983712dSmrg */ 1335d983712dSmrg req_videoram = 2 * 8 * 3; 1336d983712dSmrg if (offscreen_videoram < req_videoram) { 1337d983712dSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, v, 1338d983712dSmrg "Acceleration disabled. It requires AT LEAST %d bytes of free video memory\n", 1339d983712dSmrg req_videoram); 1340d983712dSmrg pTseng->UseAccel = FALSE; 1341d983712dSmrg pTseng->AccelColorBufferOffset = 0; 1342d983712dSmrg goto end_memsetup; /* no basic acceleration means none at all */ 1343d983712dSmrg } else { 1344d983712dSmrg offscreen_videoram -= req_videoram; 1345d983712dSmrg videoram_end -= req_videoram; 1346d983712dSmrg pTseng->AccelColorBufferOffset = videoram_end; 1347d983712dSmrg } 1348d983712dSmrg 1349d983712dSmrg /* 1350d983712dSmrg * Color expansion (using triple buffering) requires 3 non-expanded 1351d983712dSmrg * scanlines, DWORD padded. 1352d983712dSmrg */ 1353d983712dSmrg req_videoram = 3 * ((pScrn->virtualX + 31) / 32) * 4; 1354d983712dSmrg if (offscreen_videoram < req_videoram) { 1355d983712dSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, v, 1356d983712dSmrg "Accelerated color expansion disabled (%d more bytes of free video memory required)\n", 1357d983712dSmrg req_videoram - offscreen_videoram); 1358d983712dSmrg pTseng->AccelColorExpandBufferOffsets[0] = 0; 1359d983712dSmrg } else { 1360d983712dSmrg offscreen_videoram -= req_videoram; 1361d983712dSmrg for (i = 0; i < 3; i++) { 1362d983712dSmrg videoram_end -= req_videoram / 3; 1363d983712dSmrg pTseng->AccelColorExpandBufferOffsets[i] = videoram_end; 1364d983712dSmrg } 1365d983712dSmrg } 1366d983712dSmrg 1367d983712dSmrg /* 1368d983712dSmrg * XAA ImageWrite support needs two entire line buffers. The 1369d983712dSmrg * current code assumes buffer 1 lies in the same 8kb aperture as 1370d983712dSmrg * buffer 0. 1371d983712dSmrg * 1372d983712dSmrg * [ FIXME: aren't we forgetting the DWORD padding here ? ] 1373d983712dSmrg * [ FIXME: why here double-buffering and in colexp triple-buffering? ] 1374d983712dSmrg */ 1375d983712dSmrg req_videoram = 2 * (pScrn->virtualX * pTseng->Bytesperpixel); 1376d983712dSmrg 1377d983712dSmrg if (offscreen_videoram < req_videoram) { 1378d983712dSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, v, 1379d983712dSmrg "Accelerated ImageWrites disabled (%d more bytes of free video memory required)\n", 1380d983712dSmrg req_videoram - offscreen_videoram); 1381d983712dSmrg pTseng->AccelImageWriteBufferOffsets[0] = 0; 1382d983712dSmrg } else { 1383d983712dSmrg offscreen_videoram -= req_videoram; 1384d983712dSmrg for (i = 0; i < 2; i++) { 1385d983712dSmrg videoram_end -= req_videoram / 2; 1386d983712dSmrg pTseng->AccelImageWriteBufferOffsets[i] = videoram_end; 1387d983712dSmrg } 1388d983712dSmrg } 1389d983712dSmrg 1390d983712dSmrg xf86DrvMsgVerb(scrnIndex, X_INFO, v, 1391d983712dSmrg "Remaining off-screen memory available for pixmap cache: %d bytes.\n", 1392d983712dSmrg offscreen_videoram); 1393d983712dSmrg 1394d983712dSmrgend_memsetup: 1395d983712dSmrg pScrn->videoRam = videoram_end / 1024; 1396d983712dSmrg} 1397d983712dSmrg 1398d983712dSmrgstatic Bool 1399d983712dSmrgTsengScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1400d983712dSmrg{ 1401d983712dSmrg ScrnInfoPtr pScrn; 1402d983712dSmrg TsengPtr pTseng; 1403d983712dSmrg int ret; 1404d983712dSmrg VisualPtr visual; 1405d983712dSmrg 1406d983712dSmrg PDEBUG(" TsengScreenInit\n"); 1407d983712dSmrg 1408d983712dSmrg /* 1409d983712dSmrg * First get the ScrnInfoRec 1410d983712dSmrg */ 1411d983712dSmrg pScrn = xf86Screens[pScreen->myNum]; 1412d983712dSmrg 1413d983712dSmrg pTseng = TsengPTR(pScrn); 1414d983712dSmrg /* Map the Tseng memory areas */ 1415d983712dSmrg if (!TsengMapMem(pScrn)) 1416d983712dSmrg return FALSE; 1417d983712dSmrg 1418d983712dSmrg /* Save the current state */ 1419d983712dSmrg TsengSave(pScrn); 1420d983712dSmrg 1421d983712dSmrg /* Initialise the first mode */ 1422d983712dSmrg TsengModeInit(pScrn, pScrn->currentMode); 1423d983712dSmrg 1424d983712dSmrg /* Darken the screen for aesthetic reasons and set the viewport */ 1425d983712dSmrg TsengSaveScreen(pScreen, SCREEN_SAVER_ON); 1426d983712dSmrg 1427d983712dSmrg TsengAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1428d983712dSmrg /* XXX Fill the screen with black */ 1429d983712dSmrg 1430d983712dSmrg /* 1431d983712dSmrg * Reset visual list. 1432d983712dSmrg */ 1433d983712dSmrg miClearVisualTypes(); 1434d983712dSmrg 1435d983712dSmrg /* Setup the visuals we support. */ 1436d983712dSmrg 1437d983712dSmrg /* 1438d983712dSmrg * For bpp > 8, the default visuals are not acceptable because we only 1439d983712dSmrg * support TrueColor and not DirectColor. To deal with this, call 1440d983712dSmrg * miSetVisualTypes for each visual supported. 1441d983712dSmrg */ 1442d983712dSmrg if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 1443d983712dSmrg pScrn->rgbBits, pScrn->defaultVisual)) 1444d983712dSmrg return FALSE; 1445d983712dSmrg 1446d983712dSmrg miSetPixmapDepths (); 1447d983712dSmrg 1448d983712dSmrg /* 1449d983712dSmrg * Call the framebuffer layer's ScreenInit function, and fill in other 1450d983712dSmrg * pScreen fields. 1451d983712dSmrg */ 1452d983712dSmrg 1453d983712dSmrg switch (pScrn->bitsPerPixel) { 1454d983712dSmrg case 1: 1455d983712dSmrg ret = xf1bppScreenInit(pScreen, pTseng->FbBase, 1456d983712dSmrg pScrn->virtualX, pScrn->virtualY, 1457d983712dSmrg pScrn->xDpi, pScrn->yDpi, 1458d983712dSmrg pScrn->displayWidth); 1459d983712dSmrg break; 1460d983712dSmrg case 4: 1461d983712dSmrg ret = xf4bppScreenInit(pScreen, pTseng->FbBase, 1462d983712dSmrg pScrn->virtualX, pScrn->virtualY, 1463d983712dSmrg pScrn->xDpi, pScrn->yDpi, 1464d983712dSmrg pScrn->displayWidth); 1465d983712dSmrg break; 1466d983712dSmrg default: 1467d983712dSmrg ret = fbScreenInit(pScreen, pTseng->FbBase, 1468d983712dSmrg pScrn->virtualX, pScrn->virtualY, 1469d983712dSmrg pScrn->xDpi, pScrn->yDpi, 1470d983712dSmrg pScrn->displayWidth, pScrn->bitsPerPixel); 1471d983712dSmrg break; 1472d983712dSmrg } 1473d983712dSmrg 1474d983712dSmrg if (!ret) 1475d983712dSmrg return FALSE; 1476d983712dSmrg 1477d983712dSmrg xf86SetBlackWhitePixels(pScreen); 1478d983712dSmrg 1479d983712dSmrg if (pScrn->bitsPerPixel > 8) { 1480d983712dSmrg /* Fixup RGB ordering */ 1481d983712dSmrg visual = pScreen->visuals + pScreen->numVisuals; 1482d983712dSmrg while (--visual >= pScreen->visuals) { 1483d983712dSmrg if ((visual->class | DynamicClass) == DirectColor) { 1484d983712dSmrg visual->offsetRed = pScrn->offset.red; 1485d983712dSmrg visual->offsetGreen = pScrn->offset.green; 1486d983712dSmrg visual->offsetBlue = pScrn->offset.blue; 1487d983712dSmrg visual->redMask = pScrn->mask.red; 1488d983712dSmrg visual->greenMask = pScrn->mask.green; 1489d983712dSmrg visual->blueMask = pScrn->mask.blue; 1490d983712dSmrg } 1491d983712dSmrg } 1492d983712dSmrg } 1493d983712dSmrg 1494d983712dSmrg /* must be after RGB ordering fixed */ 1495d983712dSmrg if (pScrn->bitsPerPixel > 4) 1496d983712dSmrg fbPictureInit(pScreen, 0, 0); 1497d983712dSmrg 1498d983712dSmrg if (pScrn->depth >= 8) 1499d983712dSmrg TsengDGAInit(pScreen); 1500d983712dSmrg 1501d983712dSmrg /* 1502d983712dSmrg * Initialize the acceleration interface. 1503d983712dSmrg */ 1504d983712dSmrg TsengSetupAccelMemory(scrnIndex, pScreen); 1505d983712dSmrg if (pTseng->UseAccel) { 1506d983712dSmrg tseng_init_acl(pScrn); /* set up accelerator */ 1507d983712dSmrg if (!TsengXAAInit(pScreen)) { /* set up XAA interface */ 1508d983712dSmrg return FALSE; 1509d983712dSmrg } 1510d983712dSmrg } 1511d983712dSmrg 1512d983712dSmrg miInitializeBackingStore(pScreen); 1513d983712dSmrg xf86SetSilkenMouse(pScreen); 1514d983712dSmrg /* Initialise cursor functions */ 1515d983712dSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1516d983712dSmrg 1517d983712dSmrg /* Hardware Cursor layer */ 1518d983712dSmrg if (pTseng->HWCursor) { 1519d983712dSmrg if (!TsengHWCursorInit(pScreen)) 1520d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1521d983712dSmrg "Hardware cursor initialization failed\n"); 1522d983712dSmrg } 1523d983712dSmrg 1524d983712dSmrg /* Initialise default colourmap */ 1525d983712dSmrg if (!miCreateDefColormap(pScreen)) 1526d983712dSmrg return FALSE; 1527d983712dSmrg 1528d983712dSmrg if (pScrn->depth == 4 || pScrn->depth == 8) { /* fb and xf4bpp */ 1529d983712dSmrg vgaHWHandleColormaps(pScreen); 1530d983712dSmrg } 1531d983712dSmrg pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 1532d983712dSmrg pScrn->racMemFlags = pScrn->racIoFlags; 1533d983712dSmrg 1534d983712dSmrg /* Wrap the current CloseScreen and SaveScreen functions */ 1535d983712dSmrg pScreen->SaveScreen = TsengSaveScreen; 1536d983712dSmrg 1537d983712dSmrg /* Support for DPMS, the ET4000W32Pc and newer uses a different and 1538d983712dSmrg * simpler method than the older cards. 1539d983712dSmrg */ 1540d983712dSmrg if ((pTseng->ChipType == ET4000) && 1541d983712dSmrg ((pTseng->ChipRev == REV_A) || (pTseng->ChipRev == REV_B))) 1542d983712dSmrg xf86DPMSInit(pScreen, (DPMSSetProcPtr)TsengHVSyncDPMSSet, 0); 1543d983712dSmrg else 1544d983712dSmrg xf86DPMSInit(pScreen, (DPMSSetProcPtr)TsengCrtcDPMSSet, 0); 1545d983712dSmrg 1546d983712dSmrg pTseng->CloseScreen = pScreen->CloseScreen; 1547d983712dSmrg pScreen->CloseScreen = TsengCloseScreen; 1548d983712dSmrg 1549d983712dSmrg /* Report any unused options (only for the first generation) */ 1550d983712dSmrg if (serverGeneration == 1) { 1551d983712dSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1552d983712dSmrg } 1553d983712dSmrg /* Done */ 1554d983712dSmrg return TRUE; 1555d983712dSmrg} 1556d983712dSmrg 1557d983712dSmrgstatic Bool 1558d983712dSmrgTsengEnterVT(int scrnIndex, int flags) 1559d983712dSmrg{ 1560d983712dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1561d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1562d983712dSmrg 1563d983712dSmrg PDEBUG(" TsengEnterVT\n"); 1564d983712dSmrg 1565d983712dSmrg vgaHWUnlock(VGAHWPTR(pScrn)); 1566d983712dSmrg TsengUnlock(pScrn); 1567d983712dSmrg 1568d983712dSmrg if (!TsengModeInit(pScrn, pScrn->currentMode)) 1569d983712dSmrg return FALSE; 1570d983712dSmrg if (pTseng->UseAccel) { 1571d983712dSmrg tseng_init_acl(pScrn); /* set up accelerator */ 1572d983712dSmrg } 1573d983712dSmrg return TRUE; 1574d983712dSmrg} 1575d983712dSmrg 1576d983712dSmrgstatic void 1577d983712dSmrgTsengLeaveVT(int scrnIndex, int flags) 1578d983712dSmrg{ 1579d983712dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1580d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1581d983712dSmrg 1582d983712dSmrg PDEBUG(" TsengLeaveVT\n"); 1583d983712dSmrg TsengRestore(pScrn, &(VGAHWPTR(pScrn)->SavedReg), 1584d983712dSmrg &pTseng->SavedReg,VGA_SR_ALL); 1585d983712dSmrg 1586d983712dSmrg TsengLock(pScrn); 1587d983712dSmrg vgaHWLock(VGAHWPTR(pScrn)); 1588d983712dSmrg} 1589d983712dSmrg 1590d983712dSmrgstatic Bool 1591d983712dSmrgTsengCloseScreen(int scrnIndex, ScreenPtr pScreen) 1592d983712dSmrg{ 1593d983712dSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1594d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1595d983712dSmrg 1596d983712dSmrg PDEBUG(" TsengCloseScreen\n"); 1597d983712dSmrg 1598d983712dSmrg if (pScrn->vtSema) { 1599d983712dSmrg TsengRestore(pScrn, &(VGAHWPTR(pScrn)->SavedReg), 1600d983712dSmrg &(pTseng->SavedReg),VGA_SR_ALL); 1601d983712dSmrg TsengUnmapMem(pScrn); 1602d983712dSmrg } 1603d983712dSmrg if (pTseng->AccelInfoRec) 1604d983712dSmrg XAADestroyInfoRec(pTseng->AccelInfoRec); 1605d983712dSmrg if (pTseng->CursorInfoRec) 1606d983712dSmrg xf86DestroyCursorInfoRec(pTseng->CursorInfoRec); 1607d983712dSmrg 1608d983712dSmrg pScrn->vtSema = FALSE; 1609d983712dSmrg 1610d983712dSmrg pScreen->CloseScreen = pTseng->CloseScreen; 1611d983712dSmrg return (*pScreen->CloseScreen) (scrnIndex, pScreen); 1612d983712dSmrg} 1613d983712dSmrg 1614d983712dSmrg/* 1615d983712dSmrg * SaveScreen -- 1616d983712dSmrg * 1617d983712dSmrg * perform a sequencer reset. 1618d983712dSmrg * 1619d983712dSmrg * The ET4000 "Video System Configuration 1" register (CRTC index 0x36), 1620d983712dSmrg * which is used to set linear memory mode and MMU-related stuff, is 1621d983712dSmrg * partially reset to "0" when TS register index 0 bit 1 is set (synchronous 1622d983712dSmrg * reset): bits 3..5 are reset during a sync. reset. 1623d983712dSmrg * 1624d983712dSmrg * We therefor do _not_ call vgaHWSaveScreen here, since it does a sequencer 1625d983712dSmrg * reset. Instead, we do the same as in vgaHWSaveScreen except for the seq. reset. 1626d983712dSmrg * 1627d983712dSmrg * If this is not done, the higher level code will not be able to access the 1628d983712dSmrg * framebuffer (because it is temporarily in banked mode instead of linear 1629d983712dSmrg * mode) as long as SaveScreen is active (=in between a 1630d983712dSmrg * SaveScreen(FALSE)/SaveScreen(TRUE) pair) 1631d983712dSmrg */ 1632d983712dSmrg 1633d983712dSmrgstatic Bool 1634d983712dSmrgTsengSaveScreen(ScreenPtr pScreen, int mode) 1635d983712dSmrg{ 1636d983712dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1637d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 1638d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1639d983712dSmrg Bool unblank; 1640d983712dSmrg 1641d983712dSmrg PDEBUG(" TsengSaveScreen\n"); 1642d983712dSmrg 1643d983712dSmrg unblank = xf86IsUnblank(mode); 1644d983712dSmrg 1645d983712dSmrg if (pTseng->ChipType == ET6000) { 1646d983712dSmrg return vgaHWSaveScreen(pScreen, unblank); 1647d983712dSmrg } else { 1648d983712dSmrg if (unblank) 1649d983712dSmrg SetTimeSinceLastInputEvent(); 1650d983712dSmrg 1651d983712dSmrg if (pScrn->vtSema) { 1652d983712dSmrg /* vgaHWBlankScreen without seq reset */ 1653d983712dSmrg CARD8 scrn; 1654d983712dSmrg 1655d983712dSmrg scrn = hwp->readSeq(hwp, 0x01); 1656d983712dSmrg 1657d983712dSmrg if (unblank) 1658d983712dSmrg scrn &= 0xDF; /* enable screen */ 1659d983712dSmrg else 1660d983712dSmrg scrn |= 0x20; /* blank screen */ 1661d983712dSmrg 1662d983712dSmrg hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ 1663d983712dSmrg } 1664d983712dSmrg return (TRUE); 1665d983712dSmrg } 1666d983712dSmrg} 1667d983712dSmrg 1668d983712dSmrgstatic Bool 1669d983712dSmrgTsengMapMem(ScrnInfoPtr pScrn) 1670d983712dSmrg{ 1671d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1672d983712dSmrg 1673d983712dSmrg PDEBUG(" TsengMapMem\n"); 1674d983712dSmrg 1675d983712dSmrg /* Map the VGA memory */ 1676d983712dSmrg 1677d983712dSmrg if (!vgaHWMapMem(pScrn)) { 1678d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1679d983712dSmrg "Could not mmap standard VGA memory aperture.\n"); 1680d983712dSmrg return FALSE; 1681d983712dSmrg } 1682d983712dSmrg 1683d983712dSmrg pTseng->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1684d983712dSmrg pTseng->PciTag, 1685d983712dSmrg (unsigned long)pTseng->FbAddress, 1686d983712dSmrg pTseng->FbMapSize); 1687d983712dSmrg if (pTseng->FbBase == NULL) { 1688d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1689d983712dSmrg "Could not mmap linear video memory.\n"); 1690d983712dSmrg return FALSE; 1691d983712dSmrg } 1692d983712dSmrg 1693d983712dSmrg /* need some sanity here */ 1694d983712dSmrg if (pTseng->UseAccel) { 1695d983712dSmrg pTseng->MMioBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1696d983712dSmrg pTseng->PciTag, 1697d983712dSmrg (unsigned long)pTseng->FbAddress, 1698d983712dSmrg pTseng->FbMapSize); 1699d983712dSmrg if (!pTseng->MMioBase) { 1700d983712dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1701d983712dSmrg "Could not mmap mmio memory.\n"); 1702d983712dSmrg return FALSE; 1703d983712dSmrg } 1704d983712dSmrg pTseng->MMioBase += 0x3FFF00L; 1705d983712dSmrg } 1706d983712dSmrg 1707d983712dSmrg if (pTseng->FbBase == NULL) 1708d983712dSmrg return FALSE; 1709d983712dSmrg 1710d983712dSmrg return TRUE; 1711d983712dSmrg} 1712d983712dSmrg 1713d983712dSmrgstatic Bool 1714d983712dSmrgTsengUnmapMem(ScrnInfoPtr pScrn) 1715d983712dSmrg{ 1716d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 1717d983712dSmrg 1718d983712dSmrg PDEBUG(" TsengUnmapMem\n"); 1719d983712dSmrg 1720d983712dSmrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pTseng->FbBase, pTseng->FbMapSize); 1721d983712dSmrg 1722d983712dSmrg vgaHWUnmapMem(pScrn); 1723d983712dSmrg 1724d983712dSmrg pTseng->FbBase = NULL; 1725d983712dSmrg 1726d983712dSmrg return TRUE; 1727d983712dSmrg} 1728d983712dSmrg 1729d983712dSmrgstatic void 1730d983712dSmrgTsengFreeScreen(int scrnIndex, int flags) 1731d983712dSmrg{ 1732d983712dSmrg PDEBUG(" TsengFreeScreen\n"); 1733d983712dSmrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1734d983712dSmrg vgaHWFreeHWRec(xf86Screens[scrnIndex]); 1735d983712dSmrg TsengFreeRec(xf86Screens[scrnIndex]); 1736d983712dSmrg} 1737d983712dSmrg 1738d983712dSmrgstatic Bool 1739d983712dSmrgTsengSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 1740d983712dSmrg{ 1741d983712dSmrg PDEBUG(" TsengSwitchMode\n"); 1742d983712dSmrg return TsengModeInit(xf86Screens[scrnIndex], mode); 1743d983712dSmrg} 1744