summaryrefslogtreecommitdiff
path: root/src/tga_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tga_driver.c')
-rw-r--r--src/tga_driver.c1766
1 files changed, 1766 insertions, 0 deletions
diff --git a/src/tga_driver.c b/src/tga_driver.c
new file mode 100644
index 0000000..3822dc9
--- /dev/null
+++ b/src/tga_driver.c
@@ -0,0 +1,1766 @@
+/*
+ * Copyright 1997,1998 by Alan Hourihane, Wigan, England.
+ *
+ * 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 Alan Hourihane not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Alan Hourihane makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ALAN HOURIHANE 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.
+ *
+ * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ * Matthew Grossman, <mattg@oz.net> - acceleration and misc fixes
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tga/tga_driver.c,v 1.58 2001/11/21 22:33:00 alanh Exp $ */
+
+/* everybody includes these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+
+/* PCI headers */
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+
+/* module versioning */
+#include "xf86Version.h"
+
+/* RAC stuff */
+#include "xf86Resources.h"
+
+/* #include "vgaHW.h" */
+
+/* software cursor */
+#include "mipointer.h"
+/* backing store */
+#include "mibstore.h"
+
+/* #include "mibank.h" */
+/* colormap manipulation */
+#include "micmap.h"
+
+#include "fb.h"
+
+/* more RAC stuff */
+#include "xf86RAC.h"
+
+/* Gamma Correction? */
+#include "xf86cmap.h"
+
+#include "tga_regs.h"
+#include "BT.h"
+#include "tga.h"
+
+#define _XF86DGA_SERVER_
+#include "extensions/xf86dgastr.h"
+
+#include "globals.h"
+#define DPMS_SERVER
+#include "extensions/dpms.h"
+
+#ifdef XvExtension
+#include "xf86xv.h"
+#include "Xv.h"
+#endif
+
+static const OptionInfoRec * TGAAvailableOptions(int chipid, int busid);
+static void TGAIdentify(int flags);
+static Bool TGAProbe(DriverPtr drv, int flags);
+static Bool TGAPreInit(ScrnInfoPtr pScrn, int flags);
+static Bool TGAScreenInit(int Index, ScreenPtr pScreen, int argc,
+ char **argv);
+static Bool TGAEnterVT(int scrnIndex, int flags);
+static void TGALeaveVT(int scrnIndex, int flags);
+static Bool TGACloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool TGASaveScreen(ScreenPtr pScreen, int mode);
+
+/* Required if the driver supports mode switching */
+static Bool TGASwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+/* Required if the driver supports moving the viewport */
+static void TGAAdjustFrame(int scrnIndex, int x, int y, int flags);
+
+/* Optional functions */
+static void TGAFreeScreen(int scrnIndex, int flags);
+static int TGAValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
+ int flags);
+
+/* Internally used functions */
+static Bool TGAMapMem(ScrnInfoPtr pScrn);
+static Bool TGAUnmapMem(ScrnInfoPtr pScrn);
+static void TGASave(ScrnInfoPtr pScrn);
+static void TGARestore(ScrnInfoPtr pScrn);
+static Bool TGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+
+static void TGARestoreHWCursor(ScrnInfoPtr pScrn);
+
+static void TGADisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode,
+ int flags);
+
+void TGASync(ScrnInfoPtr pScrn);
+
+#define VERSION 4000
+#define TGA_NAME "TGA"
+#define TGA_DRIVER_NAME "tga"
+#define TGA_MAJOR_VERSION 1
+#define TGA_MINOR_VERSION 0
+#define TGA_PATCHLEVEL 0
+
+/*
+ * This contains the functions needed by the server after loading the driver
+ * module. It must be supplied, and gets passed back by the SetupProc
+ * function in the dynamic case. In the static case, a reference to this
+ * is compiled in, and this requires that the name of this DriverRec be
+ * an upper-case version of the driver name.
+ */
+
+DriverRec TGA = {
+ VERSION,
+ TGA_DRIVER_NAME,
+ TGAIdentify,
+ TGAProbe,
+ TGAAvailableOptions,
+ NULL,
+ 0
+};
+
+static SymTabRec TGAChipsets[] = {
+ { PCI_CHIP_DEC21030, "tga" },
+ { PCI_CHIP_TGA2, "tga2" },
+ { -1, NULL }
+};
+
+static PciChipsets TGAPciChipsets[] = {
+ { PCI_CHIP_DEC21030, PCI_CHIP_DEC21030, NULL },
+ { PCI_CHIP_TGA2, PCI_CHIP_TGA2, NULL },
+ { -1, -1, RES_UNDEFINED }
+};
+
+typedef enum {
+ OPTION_SW_CURSOR,
+ OPTION_HW_CURSOR,
+ OPTION_PCI_RETRY,
+ OPTION_RGB_BITS,
+ OPTION_NOACCEL,
+ OPTION_SYNC_ON_GREEN,
+ OPTION_DAC_6_BIT,
+ OPTION_NOXAAPOLYSEGMENT
+} TGAOpts;
+
+static const OptionInfoRec TGAOptions[] = {
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SYNC_ON_GREEN, "SyncOnGreen", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DAC_6_BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NOXAAPOLYSEGMENT, "NoXaaPolySegment",OPTV_BOOLEAN,{0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+static RamDacSupportedInfoRec BTramdacs[] = {
+ { BT485_RAMDAC },
+ { -1 }
+};
+
+static const char *ramdacSymbols[] = {
+ "BTramdacProbe",
+ "RamDacCreateInfoRec",
+ "RamDacDestroyInfoRec",
+ "RamDacFreeRec",
+ "RamDacGetHWIndex",
+ "RamDacHandleColormaps",
+ "RamDacInit",
+ "xf86CreateCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAGCIndex",
+ "XAAInit",
+ "XAAScreenIndex",
+ NULL
+};
+
+static const char *fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(tgaSetup);
+
+static XF86ModuleVersionInfo tgaVersRec =
+{
+ "tga",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ TGA_MAJOR_VERSION, TGA_MINOR_VERSION, TGA_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV, /* This is a video driver */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0,0,0,0}
+};
+
+XF86ModuleData tgaModuleData = { &tgaVersRec, tgaSetup, NULL };
+
+pointer
+tgaSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&TGA, module, 0);
+
+ /*
+ * Modules that this driver always requires can be loaded here
+ * by calling LoadSubModule().
+ */
+
+ LoaderRefSymLists(ramdacSymbols, fbSymbols, xaaSymbols, NULL);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer)1;
+ } else {
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+#endif /* XFree86LOADER */
+
+static unsigned int fb_offset_presets[4] = {
+ TGA_8PLANE_FB_OFFSET,
+ TGA_24PLANE_FB_OFFSET,
+ 0xffffffff,
+ TGA_24PLUSZ_FB_OFFSET
+};
+
+static char *tga_cardnames[4] = {
+ "TGA 8 Plane",
+ "TGA 24 Plane",
+ NULL,
+ "TGA 24 Plane 3D"
+};
+
+static Bool
+TGAGetRec(ScrnInfoPtr pScrn)
+{
+ /*
+ * Allocate an TGARec, and hook it into pScrn->driverPrivate.
+ * pScrn->driverPrivate is initialised to NULL, so we can check if
+ * the allocation has already been done.
+ */
+ if (pScrn->driverPrivate != NULL)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(TGARec), 1);
+ /* Initialise it */
+
+
+ return TRUE;
+}
+
+static void
+TGAFreeRec(ScrnInfoPtr pScrn)
+{
+ TGAPtr pTga;
+
+ if (pScrn->driverPrivate == NULL)
+ return;
+
+ pTga = TGAPTR(pScrn);
+
+ if(pTga->buffers[0])
+ free(pTga->buffers[0]);
+
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+
+ return;
+}
+
+static const OptionInfoRec *
+TGAAvailableOptions(int chipid, int busid)
+{
+ return TGAOptions;
+}
+
+/* Mandatory */
+static void
+TGAIdentify(int flags)
+{
+ xf86PrintChipsets(TGA_NAME, "driver for Digital chipsets", TGAChipsets);
+ return;
+}
+
+
+/* Mandatory */
+static Bool
+TGAProbe(DriverPtr drv, int flags)
+{
+ int i;
+ GDevPtr *devSections;
+ int *usedChips;
+ int numDevSections;
+ int numUsed;
+ Bool foundScreen = FALSE;
+
+ /*
+ * The aim here is to find all cards that this driver can handle,
+ * and for the ones not already claimed by another driver, claim the
+ * slot, and allocate a ScrnInfoRec.
+ *
+ * This should be a minimal probe, and it should under no circumstances
+ * change the state of the hardware. Because a device is found, don't
+ * assume that it will be used. Don't do any initialisations other than
+ * the required ScrnInfoRec initialisations. Don't allocate any new
+ * data structures.
+ */
+
+ /*
+ * Next we check, if there has been a chipset override in the config file.
+ * For this we must find out if there is an active device section which
+ * is relevant, i.e., which has no driver specified or has THIS driver
+ * specified.
+ */
+
+ if ((numDevSections = xf86MatchDevice(TGA_DRIVER_NAME,
+ &devSections)) <= 0) {
+ /*
+ * There's no matching device section in the config file, so quit
+ * now.
+ */
+ return FALSE;
+ }
+
+ /*
+ * We need to probe the hardware first. We then need to see how this
+ * fits in with what is given in the config file, and allow the config
+ * file info to override any contradictions.
+ */
+
+ /*
+ * All of the cards this driver supports are PCI, so the "probing" just
+ * amounts to checking the PCI data that the server has already collected.
+ */
+ if (xf86GetPciVideoInfo() == NULL) {
+ /*
+ * We won't let anything in the config file override finding no
+ * PCI video cards at all. This seems reasonable now, but we'll see.
+ */
+ return FALSE;
+ }
+
+ numUsed = xf86MatchPciInstances(TGA_NAME, PCI_VENDOR_DIGITAL,
+ TGAChipsets, TGAPciChipsets, devSections, numDevSections,
+ drv, &usedChips);
+
+ xfree(devSections);
+ if (numUsed <= 0)
+ return FALSE;
+
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i = 0; i < numUsed; i++) {
+ /*
+ * Check that nothing else has claimed the slots.
+ */
+ ScrnInfoPtr pScrn = NULL;
+
+ /* Allocate a ScrnInfoRec and claim the slot */
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ TGAPciChipsets, NULL, NULL,
+ NULL, NULL, NULL))) {
+ /* Fill in what we can of the ScrnInfoRec */
+ pScrn->driverVersion = VERSION;
+ pScrn->driverName = TGA_DRIVER_NAME;
+ pScrn->name = TGA_NAME;
+ pScrn->Probe = TGAProbe;
+ pScrn->PreInit = TGAPreInit;
+ pScrn->ScreenInit = TGAScreenInit;
+ pScrn->SwitchMode = TGASwitchMode;
+ pScrn->AdjustFrame = TGAAdjustFrame;
+ pScrn->EnterVT = TGAEnterVT;
+ pScrn->LeaveVT = TGALeaveVT;
+ pScrn->FreeScreen = TGAFreeScreen;
+ pScrn->ValidMode = TGAValidMode;
+ foundScreen = TRUE;
+ }
+ }
+ xfree(usedChips);
+ return foundScreen;
+}
+
+#if 0
+/*
+ * GetAccelPitchValues -
+ *
+ * This function returns a list of display width (pitch) values that can
+ * be used in accelerated mode.
+ */
+static int *
+GetAccelPitchValues(ScrnInfoPtr pScrn)
+{
+ int *linePitches = NULL;
+ int i, n = 0;
+ int *linep = NULL;
+ /* TGAPtr pTga = TGAPTR(pScrn); */
+
+ for (i = 0; linep[i] != 0; i++) {
+ if (linep[i] != -1) {
+ n++;
+ linePitches = xnfrealloc(linePitches, n * sizeof(int));
+ linePitches[n - 1] = i << 5;
+ }
+ }
+
+ /* Mark the end of the list */
+ if (n > 0) {
+ linePitches = xnfrealloc(linePitches, (n + 1) * sizeof(int));
+ linePitches[n] = 0;
+ }
+ return linePitches;
+}
+#endif /* 0 */
+
+/* Mandatory */
+static Bool
+TGAPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ pciVideoPtr pciPtr;
+ TGAPtr pTga;
+ MessageType from;
+ int i;
+ ClockRangePtr clockRanges;
+ pointer Base;
+
+ if (flags & PROBE_DETECT) return FALSE;
+
+ /*
+ * Note: This function is only called once at server startup, and
+ * not at the start of each server generation. This means that
+ * only things that are persistent across server generations can
+ * be initialised here. xf86Screens[] is (pScrn is a pointer to one
+ * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex()
+ * are too, and should be used for data that must persist across
+ * server generations.
+ *
+ * Per-generation data should be allocated with
+ * AllocateScreenPrivateIndex() from the ScreenInit() function.
+ */
+
+ /* The ramdac module should be loaded here when needed */
+ if (!xf86LoadSubModule(pScrn, "ramdac"))
+ return FALSE;
+
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+
+ /* Allocate the TGARec driverPrivate */
+ if (!TGAGetRec(pScrn)) {
+ return FALSE;
+ }
+ pTga = TGAPTR(pScrn);
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /*********************
+ Handle pci and chipset stuff
+ *********************/
+
+
+ /* This driver doesn't expect more than one entity per screen */
+ if (pScrn->numEntities > 1)
+ return FALSE;
+ /* This is the general case */
+ for (i = 0; i < pScrn->numEntities; i++) {
+ pTga->pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
+ if (pTga->pEnt->resources) return FALSE;
+ pTga->Chipset = pTga->pEnt->chipset;
+ pScrn->chipset = (char *)xf86TokenToString(TGAChipsets,
+ pTga->pEnt->chipset);
+
+ /* TGA is purely PCI */
+ if (pTga->pEnt->location.type == BUS_PCI) {
+ pciPtr = xf86GetPciInfoForEntity(pTga->pEnt->index);
+ pTga->PciInfo = pciPtr;
+ pTga->PciTag = pciTag(pTga->PciInfo->bus,
+ pTga->PciInfo->device,
+ pTga->PciInfo->func);
+ }
+ else
+ return FALSE;
+ }
+
+ /*
+ * This shouldn't happen because such problems should be caught in
+ * TGAProbe(), but check it just in case.
+ */
+ if (pScrn->chipset == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ChipID 0x%04X is not recognised\n", pTga->Chipset);
+ return FALSE;
+ }
+ if (pTga->Chipset < 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Chipset \"%s\" is not recognised\n", pScrn->chipset);
+ return FALSE;
+ }
+
+ from = X_PROBED;
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
+
+ pTga->PciTag = pciTag(pTga->PciInfo->bus, pTga->PciInfo->device,
+ pTga->PciInfo->func);
+
+
+
+ /*********************
+ deal with depth and framebuffer size
+ *********************/
+
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
+ return FALSE;
+ } else {
+ /* Check that the returned depth is one we support */
+ switch (pScrn->depth) {
+ case 8:
+ case 24:
+ /* OK */
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* we can do option processing now */
+
+ /* Collect all of the relevant option flags (fill in pScrn->options) */
+ xf86CollectOptions(pScrn, NULL);
+ /* Process the options */
+ if (!(pTga->Options = xalloc(sizeof(TGAOptions))))
+ return FALSE;
+ memcpy(pTga->Options, TGAOptions, sizeof(TGAOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTga->Options);
+ if (xf86ReturnOptValBool(pTga->Options, OPTION_PCI_RETRY, FALSE)) {
+ pTga->UsePCIRetry = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
+ }
+
+ if(xf86ReturnOptValBool(pTga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
+ pTga->SyncOnGreen = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
+ }
+
+ if(xf86ReturnOptValBool(pTga->Options, OPTION_DAC_6_BIT, FALSE)) {
+ pTga->Dac6Bit = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "6 bit DAC enabled\n");
+ }
+
+ if(xf86ReturnOptValBool(pTga->Options, OPTION_NOXAAPOLYSEGMENT, FALSE)) {
+ pTga->NoXaaPolySegment = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "XAA PolySegment() disabled\n");
+ }
+
+ /* end option processing */
+
+ /*
+ * This must happen after pScrn->display has been set because
+ * xf86SetWeight references it.
+ */
+ if (pScrn->depth > 8) {
+ /* The defaults are OK for us */
+ rgb zeros = {0, 0, 0};
+
+ if (!xf86SetWeight(pScrn, zeros, zeros)) {
+ return FALSE;
+ } else {
+ /* XXX check that weight returned is supported */
+ ;
+ }
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ return FALSE;
+ } else {
+ /* We don't currently support DirectColor at > 8bpp */
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /*
+ * The new cmap code requires this to be initialised.
+ */
+
+ {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ /* Set the bits per RGB for 8bpp mode */
+ if (pScrn->depth == 8) {
+ /* Default to 8 */
+ pScrn->rgbBits = 8;
+ if(pTga->Dac6Bit)
+ pScrn->rgbBits = 6;
+ }
+ from = X_DEFAULT;
+
+ /* determine whether we use hardware or software cursor */
+
+ pTga->HWCursor = TRUE;
+ if (xf86GetOptValBool(pTga->Options, OPTION_HW_CURSOR, &pTga->HWCursor))
+ from = X_CONFIG;
+ if (xf86ReturnOptValBool(pTga->Options, OPTION_SW_CURSOR, FALSE)) {
+ from = X_CONFIG;
+ pTga->HWCursor = FALSE;
+ }
+
+ if(pScrn->depth != 8) {
+ pTga->HWCursor = FALSE;
+ from = X_WARNING;
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Hardware cursor currently only works with BT485 ramdac\n");
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
+ pTga->HWCursor ? "HW" : "SW");
+
+ if (xf86ReturnOptValBool(pTga->Options, OPTION_NOACCEL, FALSE)) {
+ pTga->NoAccel = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
+ }
+
+ if (pTga->pEnt->device->MemBase != 0) {
+ pTga->CardAddress = pTga->pEnt->device->MemBase;
+ from = X_CONFIG;
+ } else {
+ pTga->CardAddress = pTga->PciInfo->memBase[0] & 0xFFC00000;/*??*/
+ }
+
+ pTga->FbAddress = pTga->CardAddress;
+ /* Adjust MMIO region */
+ pTga->IOAddress = pTga->CardAddress + TGA_REGS_OFFSET;
+
+
+ /*********************
+ determine what sort of TGA card we have -- the only differences are
+ framebuffer size and ramdac type, all TGA cards use 21030 chips
+ *********************/
+
+ /* check what the user has specified in XF86Config */
+ if(pTga->pEnt->device->videoRam) {
+ switch(pTga->pEnt->device->videoRam) {
+ case 2048:
+ pTga->CardType = TYPE_TGA_8PLANE;
+ break;
+ case 8192:
+ pTga->CardType = TYPE_TGA_24PLANE;
+ break;
+ case 16384:
+ pTga->CardType = TYPE_TGA_24PLUSZ;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "%d KB video RAM specified, driver only supports 2048, 8192, or 16384 KB cards\n",
+ pTga->pEnt->device->videoRam);
+ return FALSE;
+ }
+ }
+ else { /* try to divine the amount of RAM */
+ switch (pTga->Chipset)
+ {
+ case PCI_CHIP_TGA2:
+ Base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
+ pTga->PciTag, pTga->IOAddress, 0x1000);
+ pTga->CardType = (*(unsigned int *)((char *)Base+TGA_REVISION_REG) >> 21) & 0x3;
+ pTga->CardType ^= (pTga->CardType == 1) ? 0 : 3;
+ xf86UnMapVidMem(pScrn->scrnIndex, Base, 0x1000);
+ break;
+ case PCI_CHIP_DEC21030:
+ Base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
+ pTga->PciTag, pTga->FbAddress, 4);
+ pTga->CardType = (*(unsigned int *)Base >> 12) & 0xf;
+ xf86UnMapVidMem(pScrn->scrnIndex, Base, 4);
+ break;
+ }
+ }
+
+ switch (pTga->CardType) {
+ case TYPE_TGA_8PLANE:
+ case TYPE_TGA_24PLANE:
+ case TYPE_TGA_24PLUSZ:
+ xf86DrvMsg(pScrn->scrnIndex, from, "Card Name: \"%s\"\n",
+ tga_cardnames[pTga->CardType]);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Card \"0x%02x\" is not recognised\n", pTga->CardType);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Assuming 8 plane TGA with 2MB frame buffer\n");
+ pTga->CardType = TYPE_TGA_8PLANE;
+ break;
+ }
+
+ /* Adjust framebuffer for card type */
+ pTga->FbAddress += fb_offset_presets[pTga->CardType];
+
+ if (!(((pScrn->depth == 8) && (pTga->CardType == TYPE_TGA_8PLANE)) ||
+ ((pScrn->depth == 24) && (pTga->CardType == TYPE_TGA_24PLANE)) ||
+ ((pScrn->depth == 24) && (pTga->CardType == TYPE_TGA_24PLUSZ)))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this card\n",
+ pScrn->depth);
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pTga->FbAddress);
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
+ (unsigned long)pTga->IOAddress);
+
+ /* RAC stuff: we don't have any resources we need to reserve,
+ but we should do this here anyway */
+ if (xf86RegisterResources(pTga->pEnt->index, NULL, ResExclusive)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "xf86RegisterResources() found resource conflicts\n");
+ TGAFreeRec(pScrn);
+ return FALSE;
+ }
+
+
+
+ /* HW bpp matches reported bpp */
+ pTga->HwBpp = pScrn->bitsPerPixel;
+
+ if (pTga->pEnt->device->videoRam != 0) {
+ pScrn->videoRam = pTga->pEnt->device->videoRam;
+ from = X_CONFIG;
+ } else {
+ switch (pTga->CardType) {
+ case TYPE_TGA_8PLANE:
+ pScrn->videoRam = 2*1024;
+ break;
+ case TYPE_TGA_24PLANE:
+ pScrn->videoRam = 8*1024;
+ break;
+ case TYPE_TGA_24PLUSZ:
+ pScrn->videoRam = 16*1024;
+ break;
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
+ pScrn->videoRam);
+
+ pTga->FbMapSize = pScrn->videoRam * 1024;
+
+ if (xf86LoadSubModule(pScrn, "fb") == NULL) {
+ TGAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+
+ /* Load XAA if needed */
+ if (!pTga->NoAccel || pTga->HWCursor) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ TGAFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+
+
+ /*********************
+ Let's check what type of DAC we have and reject if necessary
+ *********************/
+
+ pTga->RamDac = NULL;
+
+ if (pTga->CardType != TYPE_TGA_8PLANE) {
+ pTga->RamDacRec = NULL;
+ pTga->RamDac = NULL;
+ } else {
+
+ pTga->RamDacRec = RamDacCreateInfoRec();
+ switch (pTga->Chipset)
+ {
+ case PCI_CHIP_DEC21030:
+ pTga->RamDacRec->ReadDAC = tgaBTInIndReg;
+ pTga->RamDacRec->WriteDAC = tgaBTOutIndReg;
+ pTga->RamDacRec->ReadAddress = tgaBTReadAddress;
+ pTga->RamDacRec->WriteAddress = tgaBTWriteAddress;
+ pTga->RamDacRec->ReadData = tgaBTReadData;
+ pTga->RamDacRec->WriteData = tgaBTWriteData;
+ break;
+ case PCI_CHIP_TGA2:
+ pTga->RamDacRec->ReadDAC = tga2BTInIndReg;
+ pTga->RamDacRec->WriteDAC = tga2BTOutIndReg;
+ pTga->RamDacRec->ReadAddress = tga2BTReadAddress;
+ pTga->RamDacRec->WriteAddress = tga2BTWriteAddress;
+ pTga->RamDacRec->ReadData = tga2BTReadData;
+ pTga->RamDacRec->WriteData = tga2BTWriteData;
+ break;
+ }
+
+ if (!RamDacInit(pScrn, pTga->RamDacRec)) {
+ RamDacDestroyInfoRec(pTga->RamDacRec);
+ return FALSE;
+ }
+
+ TGAMapMem(pScrn);
+
+ pTga->RamDac = BTramdacProbe(pScrn, BTramdacs);
+
+ TGAUnmapMem(pScrn);
+
+ if (pTga->RamDac == NULL)
+ return FALSE;
+ }
+
+ /*********************
+ set up clock and mode stuff
+ *********************/
+
+ pScrn->progClock = TRUE;
+
+ /* Set the min pixel clock */
+ pTga->MinClock = 16250; /* XXX Guess, need to check this */
+ xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
+ pTga->MinClock / 1000);
+
+ /*
+ * If the user has specified ramdac speed in the XF86Config
+ * file, we respect that setting.
+ */
+ if (pTga->pEnt->device->dacSpeeds[0]) {
+ int speed = 0;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ speed = pTga->pEnt->device->dacSpeeds[DAC_BPP8];
+ break;
+ case 32:
+ speed = pTga->pEnt->device->dacSpeeds[DAC_BPP32];
+ break;
+ }
+ if (speed == 0)
+ pTga->MaxClock = pTga->pEnt->device->dacSpeeds[0];
+ else
+ pTga->MaxClock = speed;
+ from = X_CONFIG;
+ } else {
+ switch (pTga->Chipset) {
+ case PCI_CHIP_DEC21030:
+ pTga->MaxClock = 135000;
+ break;
+ case PCI_CHIP_TGA2:
+ pTga->MaxClock = 170000;
+ break;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
+ pTga->MaxClock / 1000);
+
+ /*
+ * Setup the ClockRanges, which describe what clock ranges are available,
+ * and what sort of modes they can be used for.
+ */
+ clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+ clockRanges->next = NULL;
+ clockRanges->minClock = pTga->MinClock;
+ clockRanges->maxClock = pTga->MaxClock;
+ clockRanges->clockIndex = -1; /* programmable */
+ clockRanges->interlaceAllowed = FALSE; /* XXX check this */
+ clockRanges->doubleScanAllowed = FALSE; /* XXX check this */
+
+ if(pScrn->display->virtualX || pScrn->display->virtualY) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "TGA does not support a virtual desktop\n");
+ pScrn->display->virtualX = 0;
+ pScrn->display->virtualY = 0;
+ }
+
+ /*
+ * xf86ValidateModes will check that the mode HTotal and VTotal values
+ * don't exceed the chipset's limit if pScrn->maxHValue and
+ * pScrn->maxVValue are set. Since our TGAValidMode() already takes
+ * care of this, we don't worry about setting them here.
+ */
+ /* Select valid modes from those available */
+ /*
+ * XXX Assuming min pitch 256, max 2048
+ * XXX Assuming min height 128, max 2048
+ */
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ NULL, 256, 2048,
+ pScrn->bitsPerPixel, 128, 2048,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pTga->FbMapSize,
+ LOOKUP_BEST_REFRESH);
+
+ if (i == -1) {
+ TGAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ /* Prune the modes marked as invalid */
+ xf86PruneDriverModes(pScrn);
+
+ if (i == 0 || pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ TGAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ if(i > 1) {
+ DisplayModePtr mp1 = NULL, mp2 = NULL;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "TGA only supports one mode, using first mode.\n");
+ mp1 = pScrn->modes->next;
+ mp2 = mp1;
+ while(mp1 && mp1->next != mp1) {
+ mp1 = mp1->next;
+ xf86DeleteMode(&(pScrn->modes), mp2);
+ mp2 = mp1;
+ }
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+ /* Set the current mode to the first in the list */
+ pScrn->currentMode = pScrn->modes;
+
+ /*
+ This is a bit of a hack; we seem to have to init
+ the TGA2 chipset knowing what the mode is, so we
+ do this now as soon as we know it...
+ */
+ if (pTga->Chipset == PCI_CHIP_TGA2) {
+ TGA2SetupMode(pScrn);
+ }
+
+ /* Print the list of modes being used */
+ xf86PrintModes(pScrn);
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ return TRUE;
+}
+
+
+/*
+ * Map the framebuffer and MMIO memory.
+ */
+
+static Bool
+TGAMapMem(ScrnInfoPtr pScrn)
+{
+ TGAPtr pTga;
+
+ pTga = TGAPTR(pScrn);
+
+ /*
+ * Map IO registers to virtual address space
+ */
+
+ /* TGA doesn't need a sparse memory mapping, because all register
+ accesses are doublewords */
+
+ pTga->IOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
+ pTga->PciTag,
+ pTga->IOAddress, 0x100000);
+ if (pTga->IOBase == NULL)
+ return FALSE;
+
+ pTga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pTga->PciTag,
+ (unsigned long)pTga->FbAddress,
+ pTga->FbMapSize);
+ if (pTga->FbBase == NULL)
+ return FALSE;
+
+ if (pTga->Chipset == PCI_CHIP_DEC21030)
+ return TRUE;
+
+ pTga->ClkBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
+ pTga->PciTag,
+ (unsigned long)pTga->CardAddress + TGA2_CLOCK_OFFSET,
+ 0x10000);
+ if (pTga->ClkBase == NULL)
+ return FALSE;
+
+ pTga->DACBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
+ pTga->PciTag,
+ (unsigned long)pTga->CardAddress + TGA2_RAMDAC_OFFSET,
+ 0x10000);
+ if (pTga->DACBase == NULL)
+ return FALSE;
+
+ /*
+ * This is a hack specifically for the TGA2 code, as it sometimes
+ * calculates/uses addresses in TGA2 memory which are NOT mmapped
+ * by the normal framebuffer code above. This most frequently occurs
+ * when displaying something close to the top-left corner (in the
+ * routines CopyLine{Forwards,Backwards}.
+ *
+ * This could most likely also be fixed by further modifying the
+ * code, but it (the code) is ugly enough already... ;-}
+ *
+ * So, the workaround is to simply mmap an additional PAGE of
+ * framebuffer memory in front of the normal mmap to prevent
+ * SEGVs from happening.
+ */
+ pTga->HACKBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pTga->PciTag,
+ (unsigned long)pTga->FbAddress - getpagesize(),
+ getpagesize());
+ if (pTga->HACKBase == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Unmap the framebuffer and MMIO memory.
+ */
+
+static Bool
+TGAUnmapMem(ScrnInfoPtr pScrn)
+{
+ TGAPtr pTga;
+
+ pTga = TGAPTR(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->IOBase, 0x100000);
+ pTga->IOBase = NULL;
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->FbBase, pTga->FbMapSize);
+ pTga->FbBase = NULL;
+
+ if (pTga->Chipset == PCI_CHIP_DEC21030)
+ return TRUE;
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->ClkBase, 0x10000);
+ pTga->ClkBase = NULL;
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->DACBase, 0x10000);
+ pTga->DACBase = NULL;
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->HACKBase, getpagesize());
+ pTga->HACKBase = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * This function saves the video state.
+ */
+static void
+TGASave(ScrnInfoPtr pScrn)
+{
+ TGAPtr pTga;
+ TGARegPtr tgaReg;
+ RamDacHWRecPtr pBT;
+ RamDacRegRecPtr BTreg;
+
+ pTga = TGAPTR(pScrn);
+ tgaReg = &pTga->SavedReg;
+
+ DEC21030Save(pScrn, tgaReg);
+ if (pTga->RamDac) { /* must be BT485... */
+ pBT = RAMDACHWPTR(pScrn);
+ BTreg = &pBT->SavedReg;
+ (*pTga->RamDac->Save)(pScrn, pTga->RamDacRec, BTreg);
+ } else switch (pTga->Chipset)
+ {
+ case PCI_CHIP_TGA2:
+ IBM561ramdacSave(pScrn, pTga->Ibm561saveReg);
+ break;
+ case PCI_CHIP_DEC21030:
+ BT463ramdacSave(pScrn, pTga->Bt463saveReg);
+ break;
+ }
+}
+
+
+/*
+ * Initialise a new mode. This is currently still using the old
+ * "initialise struct, restore/write struct to HW" model. That could
+ * be changed.
+ */
+
+static Bool
+TGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ int ret = -1;
+ TGAPtr pTga;
+ TGARegPtr tgaReg;
+ RamDacHWRecPtr pBT;
+ RamDacRegRecPtr BTreg;
+
+ pTga = TGAPTR(pScrn);
+
+ pScrn->vtSema = TRUE;
+
+ ret = DEC21030Init(pScrn, mode);
+
+ if (pTga->Chipset == PCI_CHIP_TGA2 && pTga->RamDac == NULL)
+ IBM561ramdacHWInit(pScrn);
+
+ if (!ret)
+ return FALSE;
+
+ /* Program the registers */
+ tgaReg = &pTga->ModeReg;
+
+ DEC21030Restore(pScrn, tgaReg);
+
+ if (pTga->RamDac != NULL) {
+ pBT = RAMDACHWPTR(pScrn);
+ BTreg = &pBT->ModeReg;
+ (*pTga->RamDac->Restore)(pScrn, pTga->RamDacRec, BTreg);
+ if (pTga->Chipset == PCI_CHIP_TGA2) {
+ pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0x00, 0x0c);
+ }
+ pTga->RamDacRec->WriteDAC(pScrn, BT_PIXEL_MASK, 0x00, 0xff);
+ } else {
+ switch (pTga->Chipset) {
+ case PCI_CHIP_TGA2:
+ IBM561ramdacRestore(pScrn, pTga->Ibm561modeReg);
+ break;
+ case PCI_CHIP_DEC21030:
+ BT463ramdacRestore(pScrn, pTga->Bt463modeReg);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Restore the initial (text) mode.
+ */
+static void
+TGARestore(ScrnInfoPtr pScrn)
+{
+ TGAPtr pTga;
+ TGARegPtr tgaReg;
+ RamDacHWRecPtr pBT;
+ RamDacRegRecPtr BTreg;
+
+ pTga = TGAPTR(pScrn);
+ tgaReg = &pTga->SavedReg;
+
+ /* Initial Text mode clock */
+ tgaReg->tgaRegs[0x0A] = 25175;
+
+ DEC21030Restore(pScrn, tgaReg);
+
+ if (pTga->RamDac != NULL) {
+ pBT = RAMDACHWPTR(pScrn);
+ BTreg = &pBT->SavedReg;
+ (*pTga->RamDac->Restore)(pScrn, pTga->RamDacRec, BTreg);
+ if (pTga->Chipset == PCI_CHIP_TGA2) {
+ pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0x00, 0x00);
+ }
+ pTga->RamDacRec->WriteDAC(pScrn, BT_PIXEL_MASK, 0x00, 0xff);
+ } else switch (pTga->Chipset) {
+ case PCI_CHIP_TGA2:
+ IBM561ramdacRestore(pScrn, pTga->Ibm561saveReg);
+ break;
+ case PCI_CHIP_DEC21030:
+ BT463ramdacRestore(pScrn, pTga->Bt463saveReg);
+ break;
+ }
+
+ if (pTga->HWCursor)
+ TGARestoreHWCursor(pScrn);
+}
+
+
+/* Mandatory */
+
+/* This gets called at the start of each server generation */
+
+static Bool
+TGAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn;
+ TGAPtr pTga;
+ int ret;
+ VisualPtr visual;
+
+ /*
+ * First get the ScrnInfoRec
+ */
+ pScrn = xf86Screens[pScreen->myNum];
+ pTga = TGAPTR(pScrn);
+
+ /* Map the TGA memory and MMIO areas */
+ if (!TGAMapMem(pScrn))
+ return FALSE;
+
+#if 1
+ /* dump original register contents */
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MODE 0x%x\n",
+ TGA_READ_REG(TGA_MODE_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VALID 0x%x\n",
+ TGA_READ_REG(TGA_VALID_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DEEP 0x%x\n",
+ TGA_READ_REG(TGA_DEEP_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PIXSH 0x%x\n",
+ TGA_READ_REG(TGA_PIXELSHIFT_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ROP 0x%x\n",
+ TGA_READ_REG(TGA_RASTEROP_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "HORIZ 0x%x\n",
+ TGA_READ_REG(TGA_HORIZ_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VERT 0x%x\n",
+ TGA_READ_REG(TGA_VERT_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PIXMSK 0x%x\n",
+ TGA_READ_REG(TGA_PIXELMASK_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "REV 0x%x\n",
+ TGA_READ_REG(TGA_REVISION_REG));
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VADDR 0x%x\n",
+ TGA_READ_REG(TGA_BASE_ADDR_REG));
+#endif
+
+ /* Save the current state */
+ TGASave(pScrn);
+
+ /* Initialise the first mode */
+ TGAModeInit(pScrn, pScrn->currentMode);
+
+ /* Darken the screen for aesthetic reasons and set the viewport */
+ TGASaveScreen(pScreen, SCREEN_SAVER_ON);
+
+ /*
+ * The next step is to setup the screen's visuals, and initialise the
+ * framebuffer code. In cases where the framebuffer's default
+ * choices for things like visual layouts and bits per RGB are OK,
+ * this may be as simple as calling the framebuffer's ScreenInit()
+ * function. If not, the visuals will need to be setup before calling
+ * a fb ScreenInit() function and fixed up after.
+ *
+ * For most PC hardware at depths >= 8, the defaults that fb uses
+ * are not appropriate. In this driver, we fixup the visuals after.
+ */
+
+ /*
+ * Reset visual list.
+ */
+ miClearVisualTypes();
+
+ /* Setup the visuals we support. */
+
+ /*
+ * For bpp > 8, the default visuals are not acceptable because we only
+ * support TrueColor and not DirectColor. To deal with this, call
+ * miSetVisualTypes for each visual supported.
+ */
+
+ if (pScrn->bitsPerPixel > 8) {
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
+ pScrn->defaultVisual))
+ return FALSE;
+ } else {
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+ }
+
+ miSetPixmapDepths ();
+
+ /*
+ * Call the framebuffer layer's ScreenInit function, and fill in other
+ * pScreen fields.
+ */
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 32:
+ ret = fbScreenInit(pScreen, pTga->FbBase, pScrn->virtualX,
+ pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth, pScrn->bitsPerPixel);
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Internal error: invalid bpp (%d) in TGAScrnInit\n",
+ pScrn->bitsPerPixel);
+ ret = FALSE;
+ break;
+ }
+ if (!ret)
+ return FALSE;
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8) {
+ /* Fixup RGB ordering */
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ /* must be after RGB ordering fixed */
+
+ fbPictureInit (pScreen, 0, 0);
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ /* we should ALWAYS do this */
+ if (pScrn->bitsPerPixel == 8) {
+ TGA_WRITE_REG(SIMPLE | X11 | BPP8PACKED, TGA_MODE_REG);
+ TGA_WRITE_REG(0x3 | BPP8PACKED, TGA_RASTEROP_REG);
+ if (pTga->Chipset == PCI_CHIP_TGA2)
+ TGA_WRITE_REG(2 << 28, TGA_DEEP_REG);
+ } else {
+ TGA_WRITE_REG(SIMPLE | X11 | BPP24, TGA_MODE_REG);
+ TGA_WRITE_REG(0x3 | BPP24, TGA_RASTEROP_REG);
+ if (pTga->Chipset == PCI_CHIP_TGA2)
+ TGA_WRITE_REG((7 << 2) | 1 | (2 << 28), TGA_DEEP_REG);
+ }
+ TGA_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
+ TGA_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
+
+ if (!pTga->NoAccel) {
+ switch (pTga->Chipset)
+ {
+ case PCI_CHIP_TGA2:
+ case PCI_CHIP_DEC21030:
+ if(DEC21030AccelInit(pScreen) == FALSE) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "XAA Initialization failed\n");
+ return(FALSE);
+ }
+ break;
+ }
+ }
+
+ /* Initialise cursor functions */
+ miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
+
+ /* Initialize HW cursor layer.
+ Must follow software cursor initialization*/
+ if (pTga->HWCursor) {
+ if(!TGAHWCursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ return(FALSE);
+ }
+ }
+
+
+ /* Initialise default colourmap */
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+
+ if ((pScrn->bitsPerPixel==8) &&
+ (!RamDacHandleColormaps(pScreen, 256, pScrn->rgbBits,
+ CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)))
+ return FALSE;
+
+ pTga->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = TGACloseScreen;
+ pScreen->SaveScreen = TGASaveScreen;
+
+ if(xf86DPMSInit(pScreen, TGADisplayPowerManagementSet, 0) == FALSE)
+ ErrorF("DPMS initialization failed!\n");
+
+#ifdef XvExtension
+ {
+ XF86VideoAdaptorPtr *ptr;
+ int n;
+
+ pScrn->memPhysBase = pTga->FbAddress;
+ pScrn->fbOffset = 0;
+
+ n = xf86XVListGenericAdaptors(pScrn,&ptr);
+
+ if(n) {
+ xf86XVScreenInit(pScreen, ptr, n);
+ }
+
+ }
+#endif
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1) {
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+ }
+
+ /* unblank the screen */
+ TGASaveScreen(pScreen, SCREEN_SAVER_OFF);
+
+ /* Done */
+ return TRUE;
+}
+
+
+/* Usually mandatory */
+static Bool
+TGASwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ return TGAModeInit(xf86Screens[scrnIndex], mode);
+}
+
+
+/*
+ * This function is used to initialize the Start Address - the first
+ * displayed location in the video memory.
+ */
+/* Usually mandatory */
+static void
+TGAAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ /* we don't support virtual desktops, because TGA doesn't have the
+ ability to set the start of the visible framebuffer at an arbitrary
+ pixel */
+ return;
+}
+
+/*
+ * This is called when VT switching back to the X server. Its job is
+ * to reinitialise the video mode.
+ *
+ * We may wish to unmap video/MMIO memory too.
+ */
+
+/* Mandatory */
+static Bool
+TGAEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ /* Should we re-save the text mode on each VT enter? */
+ if (!TGAModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * This is called when VT switching away from the X server. Its job is
+ * to restore the previous (text) mode.
+ *
+ * We may wish to remap video/MMIO memory too.
+ */
+
+/* Mandatory */
+static void
+TGALeaveVT(int scrnIndex, int flags)
+{
+ TGAPtr pTga;
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+
+ pTga = TGAPTR(pScrn);
+ TGARestore(pScrn);
+
+ /* no longer necessary with new VT switching code */
+/* memset(pTga->FbBase, 0, pTga->FbMapSize); */
+ return;
+}
+
+
+/*
+ * This is called at the end of each server generation. It restores the
+ * original (text) mode.
+ */
+
+/* Mandatory */
+static Bool
+TGACloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ TGAPtr pTga = TGAPTR(pScrn);
+
+ TGARestore(pScrn);
+ /* memset(pTga->FbBase, 0, pScrn->videoRam * 1024); */
+ TGASync(pScrn);
+ TGAUnmapMem(pScrn);
+
+ if(pTga->AccelInfoRec)
+ XAADestroyInfoRec(pTga->AccelInfoRec);
+ pScrn->vtSema = FALSE;
+
+ pScreen->CloseScreen = pTga->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
+/* Free up any per-generation data structures */
+
+/* Optional */
+static void
+TGAFreeScreen(int scrnIndex, int flags)
+{
+ RamDacFreeRec(xf86Screens[scrnIndex]);
+ TGAFreeRec(xf86Screens[scrnIndex]);
+}
+
+
+/* Checks if a mode is suitable for the selected chipset. */
+
+/* Optional */
+static int
+TGAValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ if (mode->Flags & V_INTERLACE)
+ return(MODE_BAD);
+
+ return(MODE_OK);
+}
+
+/* Do screen blanking */
+
+/* Mandatory */
+static Bool
+TGASaveScreen(ScreenPtr pScreen, int mode)
+ /* this function should blank the screen when unblank is FALSE and
+ unblank it when unblank is TRUE -- it doesn't actually seem to be
+ used for much though */
+{
+ TGAPtr pTga;
+ ScrnInfoPtr pScrn;
+ int valid_reg = 0;
+ Bool unblank;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pTga = TGAPTR(pScrn);
+ valid_reg = TGA_READ_REG(TGA_VALID_REG);
+ valid_reg &= 0xFFFFFFFC;
+
+ unblank = xf86IsUnblank(mode);
+
+ if(unblank == FALSE)
+ valid_reg |= 0x3;
+ else /* this function is sometimes called w/1 || 2 as TRUE */
+ valid_reg |= 0x1;
+
+ TGA_WRITE_REG(valid_reg, TGA_VALID_REG);
+
+/* ErrorF("TGASaveScreen called\n"); */
+
+ return TRUE;
+}
+
+
+/*
+ * TGADisplayPowerManagementSet --
+ *
+ * Sets VESA Display Power Management Signaling (DPMS) Mode.
+ */
+static void
+TGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ TGAPtr pTga;
+ int valid_reg = 0;
+
+ pTga = TGAPTR(pScrn);
+ valid_reg = TGA_READ_REG(TGA_VALID_REG);
+ valid_reg &= 0xFFFFFFFC;
+
+ switch(PowerManagementMode) {
+ case DPMSModeOn:
+ /* HSync: On, VSync: On */
+ valid_reg |= 0x1;
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ /* TGA gives us a function to blank the screen while maintaining sync...
+ I guess we can just use that here... */
+ valid_reg |= 0x3;
+ break;
+ case DPMSModeOff:
+ valid_reg |= 0x2;
+ break;
+ default:
+ ErrorF("Invalid PowerManagementMode %d passed to TGADisplayPowerManagementSet\n", PowerManagementMode);
+ break;
+ }
+
+ TGA_WRITE_REG(valid_reg, TGA_VALID_REG);
+ return;
+}
+
+static void
+TGARestoreHWCursor(ScrnInfoPtr pScrn)
+ /*
+ from tga.c in the linux kernel...may not work for BSD...
+ when the cursor is restored, it is one line down from where it should
+ be...this is disconcerting, but purely cosmetic. Unfortunately reading
+ in the cursor framebuffer doesn't seem to work, I get a bunch of junk
+ at the beginning...other than that, see tga_cursor.c
+ I believe this to be a problem with the linux kernel code.
+ Hmm...this seems to be a 2.0.* problem, 2.2 works ok
+ */
+{
+ unsigned char *p = NULL;
+ int i = 0;
+ TGAPtr pTga;
+
+ /* Making this static prevents EGCS from compiling memset code
+ to initialize it, which was causing a problem. */
+ static const CARD32 tga_cursor_source[128] = {
+ 0x000000ff, 0x00000000, 0x000000ff, 0x00000000, 0x000000ff,
+ 0x00000000, 0x000000ff, 0x00000000, 0x000000ff, 0x00000000,
+ 0x000000ff, 0x00000000, 0x000000ff, 0x00000000, 0x000000ff,
+ 0x00000000, 0x000000ff, 0x00000000, 0x000000ff, 0x00000000,
+ 0x000000ff, 0x00000000, 0x000000ff, 0x00000000, 0x000000ff,
+ 0x00000000, 0x000000ff, 0x00000000, 0x000000ff, 0x00000000,
+ 0x000000ff, 0x00000000,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ };
+
+ /* this is the linux console hw cursor...what about the bsd console? */
+ /* what about tgafb? */
+ pTga = TGAPTR(pScrn);
+
+ /* we want to move the cursor off the screen before we do anything with it
+ otherwise, there is a "ghost cursor" that shows up */
+
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_LOW, 0x00, 0);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_HIGH, 0xF0, 0);
+
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_LOW, 0x00, 0);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_HIGH, 0xF0, 0);
+
+
+ /* set a windows cursor -- oddly, this doesn't seem necessary */
+ pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_2, 0xFC, 0x02);
+
+ /* set a 64 bit cursor */
+/* pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_0, 0x7F, 0x80); */
+/* pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01); */
+/* pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0xF8, 0x04); */
+
+ /* set the colors */
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_WR_ADDR, 0xFC, 0x01);
+
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0xaa);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0xaa);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0xaa);
+
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
+
+
+ /* load the console cursor */
+ pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0xFC, 0x00);
+ p = (unsigned char *)tga_cursor_source;
+ for(i = 0; i < 512; i++)
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, *p++);
+ for(i = 0; i < 512; i++)
+ pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, 0xff);
+
+ return;
+}
+
+
+/*
+ * This is the implementation of the Sync() function.
+ */
+void
+TGASync(ScrnInfoPtr pScrn)
+{
+ TGAPtr pTga = TGAPTR(pScrn);
+ unsigned int stat;
+
+ switch (pTga->Chipset)
+ {
+ case PCI_CHIP_TGA2:
+ /* This code is weird, but then so is TGA2... ;-} */
+ mem_barrier();
+ while((stat = TGA_READ_REG(TGA_CMD_STAT_REG))) {
+ if (((stat >> 8) & 0xff) == ((stat >> 16) & 0xff)) {
+ TGA_WRITE_REG(0, TGA_CMD_STAT_REG);
+ mem_barrier();
+#if 0
+ErrorF("TGASync: writing CMD_STATUS\n");
+#endif
+ }
+ usleep(1000);
+ }
+ break;
+
+ case PCI_CHIP_DEC21030:
+#if 0
+ /* I'm experiencing lockups which could be due to this function.
+ We don't seem to need it anyway...
+ */
+ while (TGA_READ_REG(TGA_CMD_STAT_REG) & 0x01);
+#endif
+ break;
+ }
+
+ return;
+}
+