tga_driver.c revision b92e825a
17706df26Smrg/*
27706df26Smrg * Copyright 1997,1998 by Alan Hourihane, Wigan, England.
37706df26Smrg *
47706df26Smrg * Permission to use, copy, modify, distribute, and sell this software and its
57706df26Smrg * documentation for any purpose is hereby granted without fee, provided that
67706df26Smrg * the above copyright notice appear in all copies and that both that
77706df26Smrg * copyright notice and this permission notice appear in supporting
87706df26Smrg * documentation, and that the name of Alan Hourihane not be used in
97706df26Smrg * advertising or publicity pertaining to distribution of the software without
107706df26Smrg * specific, written prior permission.  Alan Hourihane makes no representations
117706df26Smrg * about the suitability of this software for any purpose.  It is provided
127706df26Smrg * "as is" without express or implied warranty.
137706df26Smrg *
147706df26Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
157706df26Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
167706df26Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
177706df26Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
187706df26Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
197706df26Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
207706df26Smrg * PERFORMANCE OF THIS SOFTWARE.
217706df26Smrg *
227706df26Smrg * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
237706df26Smrg *           Matthew Grossman, <mattg@oz.net> - acceleration and misc fixes
247706df26Smrg */
257706df26Smrg
267706df26Smrg#ifdef HAVE_CONFIG_H
277706df26Smrg#include "config.h"
287706df26Smrg#endif
297706df26Smrg
307706df26Smrg#include <string.h>
317ae0a258Smrg#include <unistd.h>
327706df26Smrg
337706df26Smrg/* everybody includes these */
347706df26Smrg#include "xf86.h"
357706df26Smrg#include "xf86_OSproc.h"
367706df26Smrg
377706df26Smrg/* PCI headers */
387706df26Smrg#include "xf86PciInfo.h"
397706df26Smrg#include "xf86Pci.h"
407706df26Smrg
417ae0a258Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
427706df26Smrg#include "xf86Resources.h"
437ae0a258Smrg#include "xf86RAC.h"
447ae0a258Smrg#endif
457706df26Smrg/*  #include "vgaHW.h" */
467706df26Smrg
477706df26Smrg/* software cursor */
487706df26Smrg#include "mipointer.h"
497706df26Smrg/* backing store */
507706df26Smrg#include "mibstore.h"
517706df26Smrg
527706df26Smrg/*  #include "mibank.h" */
537706df26Smrg/* colormap manipulation */
547706df26Smrg#include "micmap.h"
557706df26Smrg
567706df26Smrg#include "fb.h"
577706df26Smrg
587706df26Smrg/* Gamma Correction? */
597706df26Smrg#include "xf86cmap.h"
607706df26Smrg
617706df26Smrg#include "tga_regs.h"
627706df26Smrg#include "BT.h"
637706df26Smrg#include "tga.h"
647706df26Smrg
657706df26Smrg#ifdef XFreeXDGA
66b92e825aSmrg#include <X11/extensions/xf86dgaproto.h>
677706df26Smrg#endif
687706df26Smrg
697706df26Smrg#include "globals.h"
707ae0a258Smrg#ifdef HAVE_XEXTPROTO_71
717ae0a258Smrg#include <X11/extensions/dpmsconst.h>
727ae0a258Smrg#else
737706df26Smrg#define DPMS_SERVER
747706df26Smrg#include <X11/extensions/dpms.h>
757ae0a258Smrg#endif
767ae0a258Smrg
777706df26Smrg
787706df26Smrg#include "xf86xv.h"
797706df26Smrg#include <X11/extensions/Xv.h>
807706df26Smrg
817706df26Smrgstatic const OptionInfoRec * TGAAvailableOptions(int chipid, int busid);
827706df26Smrgstatic void	TGAIdentify(int flags);
837706df26Smrgstatic Bool	TGAProbe(DriverPtr drv, int flags);
847706df26Smrgstatic Bool	TGAPreInit(ScrnInfoPtr pScrn, int flags);
85b92e825aSmrgstatic Bool	TGAScreenInit(SCREEN_INIT_ARGS_DECL);
86b92e825aSmrgstatic Bool	TGAEnterVT(VT_FUNC_ARGS_DECL);
87b92e825aSmrgstatic void	TGALeaveVT(VT_FUNC_ARGS_DECL);
88b92e825aSmrgstatic Bool	TGACloseScreen(CLOSE_SCREEN_ARGS_DECL);
897706df26Smrgstatic Bool	TGASaveScreen(ScreenPtr pScreen, int mode);
907706df26Smrg
917706df26Smrg/* Required if the driver supports mode switching */
92b92e825aSmrgstatic Bool	TGASwitchMode(SWITCH_MODE_ARGS_DECL);
937706df26Smrg/* Required if the driver supports moving the viewport */
94b92e825aSmrgstatic void	TGAAdjustFrame(ADJUST_FRAME_ARGS_DECL);
957706df26Smrg
967706df26Smrg/* Optional functions */
97b92e825aSmrgstatic void	TGAFreeScreen(FREE_SCREEN_ARGS_DECL);
98b92e825aSmrgstatic ModeStatus TGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
997706df26Smrg			       Bool verbose, int flags);
1007706df26Smrg
1017706df26Smrg/* Internally used functions */
1027706df26Smrgstatic Bool	TGAMapMem(ScrnInfoPtr pScrn);
1037706df26Smrgstatic Bool	TGAUnmapMem(ScrnInfoPtr pScrn);
1047706df26Smrgstatic void	TGASave(ScrnInfoPtr pScrn);
1057706df26Smrgstatic void	TGARestore(ScrnInfoPtr pScrn);
1067706df26Smrgstatic Bool	TGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
1077706df26Smrg
1087706df26Smrgstatic void     TGARestoreHWCursor(ScrnInfoPtr pScrn);
1097706df26Smrg
1107706df26Smrgstatic void TGADisplayPowerManagementSet(ScrnInfoPtr pScrn,
1117706df26Smrg					 int PowerManagementMode,
1127706df26Smrg					 int flags);
1137706df26Smrg
1147706df26Smrgvoid TGASync(ScrnInfoPtr pScrn);
1157706df26Smrg
1167706df26Smrg#define TGA_VERSION 4000
1177706df26Smrg#define TGA_NAME "TGA"
1187706df26Smrg#define TGA_DRIVER_NAME "tga"
119047944f3Smrg#define TGA_MAJOR_VERSION PACKAGE_VERSION_MAJOR
120047944f3Smrg#define TGA_MINOR_VERSION PACKAGE_VERSION_MINOR
121047944f3Smrg#define TGA_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
1227706df26Smrg
1237706df26Smrg/*
1247706df26Smrg * This contains the functions needed by the server after loading the driver
1257706df26Smrg * module.  It must be supplied, and gets passed back by the SetupProc
1267706df26Smrg * function in the dynamic case.  In the static case, a reference to this
1277706df26Smrg * is compiled in, and this requires that the name of this DriverRec be
1287706df26Smrg * an upper-case version of the driver name.
1297706df26Smrg */
1307706df26Smrg
1317706df26Smrg_X_EXPORT DriverRec TGA = {
1327706df26Smrg    TGA_VERSION,
1337706df26Smrg    TGA_DRIVER_NAME,
1347706df26Smrg    TGAIdentify,
1357706df26Smrg    TGAProbe,
1367706df26Smrg    TGAAvailableOptions,
1377706df26Smrg    NULL,
1387706df26Smrg    0
1397706df26Smrg};
1407706df26Smrg
1417706df26Smrgstatic SymTabRec TGAChipsets[] = {
1427706df26Smrg    { PCI_CHIP_DEC21030,		"tga" },
1437706df26Smrg    { PCI_CHIP_TGA2,			"tga2" },
1447706df26Smrg    { -1,				NULL }
1457706df26Smrg};
1467706df26Smrg
1477706df26Smrgstatic PciChipsets TGAPciChipsets[] = {
1487706df26Smrg    { PCI_CHIP_DEC21030,	PCI_CHIP_DEC21030,	NULL },
1497706df26Smrg    { PCI_CHIP_TGA2,		PCI_CHIP_TGA2,		NULL },
1507706df26Smrg    { -1,			-1,			RES_UNDEFINED }
1517706df26Smrg};
1527706df26Smrg
1537706df26Smrgtypedef enum {
1547706df26Smrg    OPTION_SW_CURSOR,
1557706df26Smrg    OPTION_HW_CURSOR,
1567706df26Smrg    OPTION_PCI_RETRY,
1577706df26Smrg    OPTION_RGB_BITS,
1587706df26Smrg    OPTION_NOACCEL,
1597706df26Smrg    OPTION_SYNC_ON_GREEN,
1607706df26Smrg    OPTION_DAC_6_BIT,
1617706df26Smrg    OPTION_NOXAAPOLYSEGMENT
1627706df26Smrg} TGAOpts;
1637706df26Smrg
1647706df26Smrgstatic const OptionInfoRec TGAOptions[] = {
1657706df26Smrg    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
1667706df26Smrg    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
1677706df26Smrg    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
1687706df26Smrg    { OPTION_RGB_BITS,		"RGBbits",	OPTV_INTEGER,	{0}, FALSE },
1697706df26Smrg    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
1707706df26Smrg    { OPTION_SYNC_ON_GREEN,     "SyncOnGreen",  OPTV_BOOLEAN,   {0}, FALSE },
1717706df26Smrg    { OPTION_DAC_6_BIT,         "Dac6Bit",      OPTV_BOOLEAN,   {0}, FALSE },
1727706df26Smrg    { OPTION_NOXAAPOLYSEGMENT,  "NoXaaPolySegment",OPTV_BOOLEAN,{0}, FALSE },
1737706df26Smrg    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
1747706df26Smrg};
1757706df26Smrg
1767706df26Smrgstatic RamDacSupportedInfoRec BTramdacs[] = {
1777706df26Smrg    { BT485_RAMDAC },
1787706df26Smrg    { -1 }
1797706df26Smrg};
1807706df26Smrg
1817706df26Smrg#ifdef XFree86LOADER
1827706df26Smrg
1837706df26Smrgstatic MODULESETUPPROTO(tgaSetup);
1847706df26Smrg
1857706df26Smrgstatic XF86ModuleVersionInfo tgaVersRec =
1867706df26Smrg{
1877706df26Smrg	"tga",
1887706df26Smrg	MODULEVENDORSTRING,
1897706df26Smrg	MODINFOSTRING1,
1907706df26Smrg	MODINFOSTRING2,
1917706df26Smrg	XORG_VERSION_CURRENT,
1927706df26Smrg	TGA_MAJOR_VERSION, TGA_MINOR_VERSION, TGA_PATCHLEVEL,
1937706df26Smrg	ABI_CLASS_VIDEODRV,			/* This is a video driver */
1947706df26Smrg	ABI_VIDEODRV_VERSION,
1957706df26Smrg	MOD_CLASS_VIDEODRV,
1967706df26Smrg	{0,0,0,0}
1977706df26Smrg};
1987706df26Smrg
1997706df26Smrg_X_EXPORT XF86ModuleData tgaModuleData = { &tgaVersRec, tgaSetup, NULL };
2007706df26Smrg
2017706df26Smrgpointer
2027706df26SmrgtgaSetup(pointer module, pointer opts, int *errmaj, int *errmin)
2037706df26Smrg{
2047706df26Smrg    static Bool setupDone = FALSE;
2057706df26Smrg
2067706df26Smrg    if (!setupDone) {
2077706df26Smrg	setupDone = TRUE;
2087706df26Smrg	xf86AddDriver(&TGA, module, 0);
2097706df26Smrg
2107706df26Smrg	/*
2117706df26Smrg	 * The return value must be non-NULL on success even though there
2127706df26Smrg	 * is no TearDownProc.
2137706df26Smrg	 */
2147706df26Smrg	return (pointer)1;
2157706df26Smrg    } else {
2167706df26Smrg	if (errmaj) *errmaj = LDR_ONCEONLY;
2177706df26Smrg	return NULL;
2187706df26Smrg    }
2197706df26Smrg}
2207706df26Smrg
2217706df26Smrg#endif /* XFree86LOADER */
2227706df26Smrg
2237706df26Smrgstatic unsigned int fb_offset_presets[4] = {
2247706df26Smrg	TGA_8PLANE_FB_OFFSET,
2257706df26Smrg	TGA_24PLANE_FB_OFFSET,
2267706df26Smrg	0xffffffff,
2277706df26Smrg	TGA_24PLUSZ_FB_OFFSET
2287706df26Smrg};
2297706df26Smrg
2307706df26Smrgstatic char *tga_cardnames[4] = {
2317706df26Smrg	"TGA 8 Plane",
2327706df26Smrg	"TGA 24 Plane",
2337706df26Smrg	NULL,
2347706df26Smrg	"TGA 24 Plane 3D"
2357706df26Smrg};
2367706df26Smrg
2377706df26Smrgstatic Bool
2387706df26SmrgTGAGetRec(ScrnInfoPtr pScrn)
2397706df26Smrg{
2407706df26Smrg    /*
2417706df26Smrg     * Allocate an TGARec, and hook it into pScrn->driverPrivate.
2427706df26Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
2437706df26Smrg     * the allocation has already been done.
2447706df26Smrg     */
2457706df26Smrg    if (pScrn->driverPrivate != NULL)
2467706df26Smrg	return TRUE;
2477706df26Smrg
2487706df26Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(TGARec), 1);
2497706df26Smrg    /* Initialise it */
2507706df26Smrg
2517706df26Smrg
2527706df26Smrg    return TRUE;
2537706df26Smrg}
2547706df26Smrg
2557706df26Smrgstatic void
2567706df26SmrgTGAFreeRec(ScrnInfoPtr pScrn)
2577706df26Smrg{
2587706df26Smrg    TGAPtr pTga;
2597706df26Smrg
2607706df26Smrg    if (pScrn->driverPrivate == NULL)
2617706df26Smrg	return;
2627706df26Smrg
2637706df26Smrg    pTga = TGAPTR(pScrn);
2647706df26Smrg
2657706df26Smrg    if(pTga->buffers[0])
2667706df26Smrg      free(pTga->buffers[0]);
2677706df26Smrg
268b92e825aSmrg    free(pScrn->driverPrivate);
2697706df26Smrg    pScrn->driverPrivate = NULL;
2707706df26Smrg
2717706df26Smrg    return;
2727706df26Smrg}
2737706df26Smrg
2747706df26Smrgstatic const OptionInfoRec *
2757706df26SmrgTGAAvailableOptions(int chipid, int busid)
2767706df26Smrg{
2777706df26Smrg    return TGAOptions;
2787706df26Smrg}
2797706df26Smrg
2807706df26Smrg/* Mandatory */
2817706df26Smrgstatic void
2827706df26SmrgTGAIdentify(int flags)
2837706df26Smrg{
2847706df26Smrg    xf86PrintChipsets(TGA_NAME, "driver for Digital chipsets", TGAChipsets);
2857706df26Smrg    return;
2867706df26Smrg}
2877706df26Smrg
2887706df26Smrg
2897706df26Smrg/* Mandatory */
2907706df26Smrgstatic Bool
2917706df26SmrgTGAProbe(DriverPtr drv, int flags)
2927706df26Smrg{
2937706df26Smrg    int i;
2947706df26Smrg    GDevPtr *devSections;
2957706df26Smrg    int *usedChips;
2967706df26Smrg    int numDevSections;
2977706df26Smrg    int numUsed;
2987706df26Smrg    Bool foundScreen = FALSE;
2997706df26Smrg
3007706df26Smrg    /*
3017706df26Smrg     * The aim here is to find all cards that this driver can handle,
3027706df26Smrg     * and for the ones not already claimed by another driver, claim the
3037706df26Smrg     * slot, and allocate a ScrnInfoRec.
3047706df26Smrg     *
3057706df26Smrg     * This should be a minimal probe, and it should under no circumstances
3067706df26Smrg     * change the state of the hardware.  Because a device is found, don't
3077706df26Smrg     * assume that it will be used.  Don't do any initialisations other than
3087706df26Smrg     * the required ScrnInfoRec initialisations.  Don't allocate any new
3097706df26Smrg     * data structures.
3107706df26Smrg     */
3117706df26Smrg
3127706df26Smrg    /*
3137706df26Smrg     * Next we check, if there has been a chipset override in the config file.
3147706df26Smrg     * For this we must find out if there is an active device section which
3157706df26Smrg     * is relevant, i.e., which has no driver specified or has THIS driver
3167706df26Smrg     * specified.
3177706df26Smrg     */
3187706df26Smrg
3197706df26Smrg    if ((numDevSections = xf86MatchDevice(TGA_DRIVER_NAME,
3207706df26Smrg					  &devSections)) <= 0) {
3217706df26Smrg	/*
3227706df26Smrg	 * There's no matching device section in the config file, so quit
3237706df26Smrg	 * now.
3247706df26Smrg	 */
3257706df26Smrg	return FALSE;
3267706df26Smrg    }
3277706df26Smrg
3287706df26Smrg    /*
3297706df26Smrg     * We need to probe the hardware first.  We then need to see how this
3307706df26Smrg     * fits in with what is given in the config file, and allow the config
3317706df26Smrg     * file info to override any contradictions.
3327706df26Smrg     */
3337706df26Smrg
3347706df26Smrg    /*
3357706df26Smrg     * All of the cards this driver supports are PCI, so the "probing" just
3367706df26Smrg     * amounts to checking the PCI data that the server has already collected.
3377706df26Smrg     */
338047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
3397706df26Smrg    if (xf86GetPciVideoInfo() == NULL) {
3407706df26Smrg	/*
3417706df26Smrg	 * We won't let anything in the config file override finding no
3427706df26Smrg	 * PCI video cards at all.  This seems reasonable now, but we'll see.
3437706df26Smrg	 */
3447706df26Smrg	return FALSE;
3457706df26Smrg    }
346047944f3Smrg#endif
3477706df26Smrg
3487706df26Smrg    numUsed = xf86MatchPciInstances(TGA_NAME, PCI_VENDOR_DIGITAL,
3497706df26Smrg		   TGAChipsets, TGAPciChipsets, devSections, numDevSections,
3507706df26Smrg		   drv, &usedChips);
3517706df26Smrg
352b92e825aSmrg    free(devSections);
3537706df26Smrg    if (numUsed <= 0)
3547706df26Smrg	return FALSE;
3557706df26Smrg
3567706df26Smrg    if (flags & PROBE_DETECT)
3577706df26Smrg	foundScreen = TRUE;
3587706df26Smrg    else for (i = 0; i < numUsed; i++) {
3597706df26Smrg	/*
3607706df26Smrg	 * Check that nothing else has claimed the slots.
3617706df26Smrg	 */
3627706df26Smrg	ScrnInfoPtr pScrn = NULL;
3637706df26Smrg
3647706df26Smrg	/* Allocate a ScrnInfoRec and claim the slot */
3657706df26Smrg	if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
3667706df26Smrg					       TGAPciChipsets, NULL, NULL,
3677706df26Smrg					       NULL, NULL, NULL))) {
3687706df26Smrg	    /* Fill in what we can of the ScrnInfoRec */
3697706df26Smrg	    pScrn->driverVersion = TGA_VERSION;
3707706df26Smrg	    pScrn->driverName	 = TGA_DRIVER_NAME;
3717706df26Smrg	    pScrn->name		 = TGA_NAME;
3727706df26Smrg	    pScrn->Probe	 = TGAProbe;
3737706df26Smrg	    pScrn->PreInit	 = TGAPreInit;
3747706df26Smrg	    pScrn->ScreenInit	 = TGAScreenInit;
3757706df26Smrg  	    pScrn->SwitchMode	 = TGASwitchMode;
3767706df26Smrg  	    pScrn->AdjustFrame	 = TGAAdjustFrame;
3777706df26Smrg	    pScrn->EnterVT	 = TGAEnterVT;
3787706df26Smrg	    pScrn->LeaveVT	 = TGALeaveVT;
3797706df26Smrg	    pScrn->FreeScreen	 = TGAFreeScreen;
3807706df26Smrg	    pScrn->ValidMode	 = TGAValidMode;
3817706df26Smrg	    foundScreen = TRUE;
3827706df26Smrg	}
3837706df26Smrg    }
384b92e825aSmrg    free(usedChips);
3857706df26Smrg    return foundScreen;
3867706df26Smrg}
3877706df26Smrg
3887706df26Smrg#if 0
3897706df26Smrg/*
3907706df26Smrg * GetAccelPitchValues -
3917706df26Smrg *
3927706df26Smrg * This function returns a list of display width (pitch) values that can
3937706df26Smrg * be used in accelerated mode.
3947706df26Smrg */
3957706df26Smrgstatic int *
3967706df26SmrgGetAccelPitchValues(ScrnInfoPtr pScrn)
3977706df26Smrg{
3987706df26Smrg    int *linePitches = NULL;
3997706df26Smrg    int i, n = 0;
4007706df26Smrg    int *linep = NULL;
4017706df26Smrg    /*     TGAPtr pTga = TGAPTR(pScrn); */
4027706df26Smrg
4037706df26Smrg    for (i = 0; linep[i] != 0; i++) {
4047706df26Smrg	if (linep[i] != -1) {
4057706df26Smrg	    n++;
4067706df26Smrg	    linePitches = xnfrealloc(linePitches, n * sizeof(int));
4077706df26Smrg	    linePitches[n - 1] = i << 5;
4087706df26Smrg	}
4097706df26Smrg    }
4107706df26Smrg
4117706df26Smrg    /* Mark the end of the list */
4127706df26Smrg    if (n > 0) {
4137706df26Smrg	linePitches = xnfrealloc(linePitches, (n + 1) * sizeof(int));
4147706df26Smrg	linePitches[n] = 0;
4157706df26Smrg    }
4167706df26Smrg    return linePitches;
4177706df26Smrg}
4187706df26Smrg#endif /* 0 */
4197706df26Smrg
4207706df26Smrg/* Mandatory */
4217706df26Smrgstatic Bool
4227706df26SmrgTGAPreInit(ScrnInfoPtr pScrn, int flags)
4237706df26Smrg{
4247706df26Smrg    pciVideoPtr pciPtr;
4257706df26Smrg    TGAPtr pTga;
4267706df26Smrg    MessageType from;
4277706df26Smrg    int i;
4287706df26Smrg    ClockRangePtr clockRanges;
4297706df26Smrg    pointer Base;
4307706df26Smrg
4317706df26Smrg    if (flags & PROBE_DETECT) return FALSE;
4327706df26Smrg
4337706df26Smrg    /*
4347706df26Smrg     * Note: This function is only called once at server startup, and
4357706df26Smrg     * not at the start of each server generation.  This means that
4367706df26Smrg     * only things that are persistent across server generations can
4377706df26Smrg     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
4387706df26Smrg     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
4397706df26Smrg     * are too, and should be used for data that must persist across
4407706df26Smrg     * server generations.
4417706df26Smrg     *
4427706df26Smrg     * Per-generation data should be allocated with
4437706df26Smrg     * AllocateScreenPrivateIndex() from the ScreenInit() function.
4447706df26Smrg     */
4457706df26Smrg
4467706df26Smrg    /* The ramdac module should be loaded here when needed */
4477706df26Smrg    if (!xf86LoadSubModule(pScrn, "ramdac"))
4487706df26Smrg	return FALSE;
4497706df26Smrg
4507706df26Smrg    /* Allocate the TGARec driverPrivate */
4517706df26Smrg    if (!TGAGetRec(pScrn)) {
4527706df26Smrg	return FALSE;
4537706df26Smrg    }
4547706df26Smrg    pTga = TGAPTR(pScrn);
4557706df26Smrg
4567706df26Smrg    /* Set pScrn->monitor */
4577706df26Smrg    pScrn->monitor = pScrn->confScreen->monitor;
4587706df26Smrg
4597706df26Smrg    /*********************
4607706df26Smrg    Handle pci and chipset stuff
4617706df26Smrg    *********************/
4627706df26Smrg
4637706df26Smrg
4647706df26Smrg    /* This driver doesn't expect more than one entity per screen */
4657706df26Smrg    if (pScrn->numEntities > 1)
4667706df26Smrg	return FALSE;
4677706df26Smrg    /* This is the general case */
4687706df26Smrg    for (i = 0; i < pScrn->numEntities; i++) {
4697706df26Smrg	pTga->pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
4707ae0a258Smrg#ifndef XSERVER_LIBPCIACCESS
4717706df26Smrg	if (pTga->pEnt->resources) return FALSE;
4727ae0a258Smrg#endif
4737706df26Smrg	pTga->Chipset = pTga->pEnt->chipset;
4747706df26Smrg	pScrn->chipset = (char *)xf86TokenToString(TGAChipsets,
4757706df26Smrg						   pTga->pEnt->chipset);
4767706df26Smrg
4777706df26Smrg	/* TGA is purely PCI */
4787706df26Smrg	if (pTga->pEnt->location.type == BUS_PCI) {
4797706df26Smrg	    pciPtr = xf86GetPciInfoForEntity(pTga->pEnt->index);
4807706df26Smrg	    pTga->PciInfo = pciPtr;
481047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
4827706df26Smrg	    pTga->PciTag = pciTag(pTga->PciInfo->bus,
4837706df26Smrg				  pTga->PciInfo->device,
4847706df26Smrg				  pTga->PciInfo->func);
485047944f3Smrg#endif
4867706df26Smrg	}
4877706df26Smrg	else
4887706df26Smrg	    return FALSE;
4897706df26Smrg    }
4907706df26Smrg
4917706df26Smrg    /*
4927706df26Smrg     * This shouldn't happen because such problems should be caught in
4937706df26Smrg     * TGAProbe(), but check it just in case.
4947706df26Smrg     */
4957706df26Smrg    if (pScrn->chipset == NULL) {
4967706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4977706df26Smrg		   "ChipID 0x%04X is not recognised\n", pTga->Chipset);
4987706df26Smrg	return FALSE;
4997706df26Smrg    }
5007706df26Smrg    if (pTga->Chipset < 0) {
5017706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
5027706df26Smrg		   "Chipset \"%s\" is not recognised\n", pScrn->chipset);
5037706df26Smrg	return FALSE;
5047706df26Smrg    }
5057706df26Smrg
5067706df26Smrg    from = X_PROBED;
5077706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
5087706df26Smrg
509047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
5107706df26Smrg    pTga->PciTag = pciTag(pTga->PciInfo->bus, pTga->PciInfo->device,
5117706df26Smrg			  pTga->PciInfo->func);
512047944f3Smrg#endif
5137706df26Smrg
5147706df26Smrg
5157706df26Smrg
5167706df26Smrg    /*********************
5177706df26Smrg    deal with depth and framebuffer size
5187706df26Smrg    *********************/
5197706df26Smrg
5207706df26Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
5217706df26Smrg	return FALSE;
5227706df26Smrg    } else {
5237706df26Smrg	/* Check that the returned depth is one we support */
5247706df26Smrg	switch (pScrn->depth) {
5257706df26Smrg	case 8:
5267706df26Smrg	case 24:
5277706df26Smrg	    /* OK */
5287706df26Smrg	    break;
5297706df26Smrg	default:
5307706df26Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
5317706df26Smrg		       "Given depth (%d) is not supported by this driver\n",
5327706df26Smrg		       pScrn->depth);
5337706df26Smrg	    return FALSE;
5347706df26Smrg	}
5357706df26Smrg    }
5367706df26Smrg
5377706df26Smrg    /* we can do option processing now */
5387706df26Smrg
5397706df26Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
5407706df26Smrg    xf86CollectOptions(pScrn, NULL);
5417706df26Smrg    /* Process the options */
542b92e825aSmrg    if (!(pTga->Options = malloc(sizeof(TGAOptions))))
5437706df26Smrg	return FALSE;
5447706df26Smrg    memcpy(pTga->Options, TGAOptions, sizeof(TGAOptions));
5457706df26Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTga->Options);
5467706df26Smrg    if (xf86ReturnOptValBool(pTga->Options, OPTION_PCI_RETRY, FALSE)) {
5477706df26Smrg	pTga->UsePCIRetry = TRUE;
5487706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
5497706df26Smrg    }
5507706df26Smrg
5517706df26Smrg    if(xf86ReturnOptValBool(pTga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
5527706df26Smrg	pTga->SyncOnGreen = TRUE;
5537706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
5547706df26Smrg    }
5557706df26Smrg
5567706df26Smrg    if(xf86ReturnOptValBool(pTga->Options, OPTION_DAC_6_BIT, FALSE)) {
5577706df26Smrg	pTga->Dac6Bit = TRUE;
5587706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "6 bit DAC enabled\n");
5597706df26Smrg    }
5607706df26Smrg
5617706df26Smrg    if(xf86ReturnOptValBool(pTga->Options, OPTION_NOXAAPOLYSEGMENT, FALSE)) {
5627706df26Smrg	pTga->NoXaaPolySegment = TRUE;
5637706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "XAA PolySegment() disabled\n");
5647706df26Smrg    }
5657706df26Smrg
5667706df26Smrg    /* end option processing */
5677706df26Smrg
5687706df26Smrg    /*
5697706df26Smrg     * This must happen after pScrn->display has been set because
5707706df26Smrg     * xf86SetWeight references it.
5717706df26Smrg     */
5727706df26Smrg    if (pScrn->depth > 8) {
5737706df26Smrg	/* The defaults are OK for us */
5747706df26Smrg	rgb zeros = {0, 0, 0};
5757706df26Smrg
5767706df26Smrg	if (!xf86SetWeight(pScrn, zeros, zeros)) {
5777706df26Smrg	    return FALSE;
5787706df26Smrg	} else {
5797706df26Smrg	    /* XXX check that weight returned is supported */
5807706df26Smrg            ;
5817706df26Smrg        }
5827706df26Smrg    }
5837706df26Smrg
5847706df26Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) {
5857706df26Smrg	return FALSE;
5867706df26Smrg    } else {
5877706df26Smrg	/* We don't currently support DirectColor at > 8bpp */
5887706df26Smrg	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
5897706df26Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
5907706df26Smrg		       " (%s) is not supported at depth %d\n",
5917706df26Smrg		       xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
5927706df26Smrg	    return FALSE;
5937706df26Smrg	}
5947706df26Smrg    }
5957706df26Smrg
5967706df26Smrg    /*
5977706df26Smrg     * The new cmap code requires this to be initialised.
5987706df26Smrg     */
5997706df26Smrg
6007706df26Smrg    {
6017706df26Smrg	Gamma zeros = {0.0, 0.0, 0.0};
6027706df26Smrg
6037706df26Smrg	if (!xf86SetGamma(pScrn, zeros)) {
6047706df26Smrg	    return FALSE;
6057706df26Smrg	}
6067706df26Smrg    }
6077706df26Smrg
6087706df26Smrg    /* Set the bits per RGB for 8bpp mode */
6097706df26Smrg    if (pScrn->depth == 8) {
6107706df26Smrg	/* Default to 8 */
6117706df26Smrg	pScrn->rgbBits = 8;
6127706df26Smrg	if(pTga->Dac6Bit)
6137706df26Smrg	    pScrn->rgbBits = 6;
6147706df26Smrg    }
6157706df26Smrg    from = X_DEFAULT;
6167706df26Smrg
6177706df26Smrg    /* determine whether we use hardware or software cursor */
6187706df26Smrg
6197706df26Smrg    pTga->HWCursor = TRUE;
6207706df26Smrg    if (xf86GetOptValBool(pTga->Options, OPTION_HW_CURSOR, &pTga->HWCursor))
6217706df26Smrg	from = X_CONFIG;
6227706df26Smrg    if (xf86ReturnOptValBool(pTga->Options, OPTION_SW_CURSOR, FALSE)) {
6237706df26Smrg	from = X_CONFIG;
6247706df26Smrg	pTga->HWCursor = FALSE;
6257706df26Smrg    }
6267706df26Smrg
6277706df26Smrg    if(pScrn->depth != 8) {
6287706df26Smrg      pTga->HWCursor = FALSE;
6297706df26Smrg      from = X_WARNING;
6307706df26Smrg      xf86DrvMsg(pScrn->scrnIndex, from,
6317706df26Smrg		 "Hardware cursor currently only works with BT485 ramdac\n");
6327706df26Smrg    }
6337706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
6347706df26Smrg		pTga->HWCursor ? "HW" : "SW");
6357706df26Smrg
6367706df26Smrg    if (xf86ReturnOptValBool(pTga->Options, OPTION_NOACCEL, FALSE)) {
6377706df26Smrg	pTga->NoAccel = TRUE;
6387706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
6397706df26Smrg    }
6407706df26Smrg
6417706df26Smrg    if (pTga->pEnt->device->MemBase != 0) {
6427706df26Smrg	pTga->CardAddress = pTga->pEnt->device->MemBase;
6437706df26Smrg	from = X_CONFIG;
6447706df26Smrg    } else {
645047944f3Smrg      pTga->CardAddress = PCI_REGION_BASE(pTga->PciInfo, 0, REGION_MEM) & 0xFFC00000;/*??*/
6467706df26Smrg    }
6477706df26Smrg
6487706df26Smrg    pTga->FbAddress = pTga->CardAddress;
6497706df26Smrg    /* Adjust MMIO region */
6507706df26Smrg    pTga->IOAddress = pTga->CardAddress + TGA_REGS_OFFSET;
6517706df26Smrg
6527706df26Smrg
6537706df26Smrg    /*********************
6547706df26Smrg    determine what sort of TGA card we have -- the only differences are
6557706df26Smrg    framebuffer size and ramdac type, all TGA cards use 21030 chips
6567706df26Smrg    *********************/
6577706df26Smrg
6587706df26Smrg    /* check what the user has specified in XF86Config */
6597706df26Smrg    if(pTga->pEnt->device->videoRam) {
6607706df26Smrg      switch(pTga->pEnt->device->videoRam) {
6617706df26Smrg      case 2048:
6627706df26Smrg	pTga->CardType = TYPE_TGA_8PLANE;
6637706df26Smrg	break;
6647706df26Smrg      case 8192:
6657706df26Smrg	pTga->CardType = TYPE_TGA_24PLANE;
6667706df26Smrg	break;
6677706df26Smrg      case 16384:
6687706df26Smrg	pTga->CardType = TYPE_TGA_24PLUSZ;
6697706df26Smrg	break;
6707706df26Smrg      default:
6717706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
6727706df26Smrg		   "%d KB video RAM specified, driver only supports 2048, 8192, or 16384 KB cards\n",
6737706df26Smrg		   pTga->pEnt->device->videoRam);
6747706df26Smrg	return FALSE;
6757706df26Smrg      }
6767706df26Smrg    }
6777706df26Smrg    else { /* try to divine the amount of RAM */
6787706df26Smrg      switch (pTga->Chipset)
6797706df26Smrg	{
6807706df26Smrg	case PCI_CHIP_TGA2:
681047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
6827706df26Smrg	  Base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
6837706df26Smrg			       pTga->PciTag, pTga->IOAddress, 0x1000);
684047944f3Smrg
685047944f3Smrg#else
686047944f3Smrg	  {
687047944f3Smrg	      void** result = (void**)&Base;
688047944f3Smrg	      int err = pci_device_map_range(pTga->PciInfo,
689047944f3Smrg					     pTga->IOAddress,
690047944f3Smrg					     0x1000,
691047944f3Smrg					     PCI_DEV_MAP_FLAG_WRITABLE,
692047944f3Smrg					     result);
693047944f3Smrg	      if (err)
694047944f3Smrg		  return FALSE;
695047944f3Smrg	  }
696047944f3Smrg#endif
6977706df26Smrg	  pTga->CardType = (*(unsigned int *)((char *)Base+TGA_REVISION_REG) >> 21) & 0x3;
6987706df26Smrg	  pTga->CardType ^= (pTga->CardType == 1) ? 0 : 3;
699047944f3Smrg
700047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
7017706df26Smrg	  xf86UnMapVidMem(pScrn->scrnIndex, Base, 0x1000);
702047944f3Smrg#else
703047944f3Smrg	  pci_device_unmap_range(pTga->PciInfo, Base, 0x1000);
704047944f3Smrg#endif
7057706df26Smrg	  break;
7067706df26Smrg	case PCI_CHIP_DEC21030:
707047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
7087706df26Smrg	  Base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
7097706df26Smrg			       pTga->PciTag, pTga->FbAddress, 4);
710047944f3Smrg#else
711047944f3Smrg	  {
712047944f3Smrg	      void** result = (void**)&Base;
713047944f3Smrg	      int err = pci_device_map_range(pTga->PciInfo,
714047944f3Smrg					     pTga->FbAddress,
715047944f3Smrg					     0x4,
716047944f3Smrg					     PCI_DEV_MAP_FLAG_WRITABLE,
717047944f3Smrg					     result);
718047944f3Smrg	      if (err)
719047944f3Smrg		  return FALSE;
720047944f3Smrg	  }
721047944f3Smrg#endif
7227706df26Smrg	  pTga->CardType = (*(unsigned int *)Base >> 12) & 0xf;
723047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
7247706df26Smrg	  xf86UnMapVidMem(pScrn->scrnIndex, Base, 4);
725047944f3Smrg#else
726047944f3Smrg	  pci_device_unmap_range(pTga->PciInfo, Base, 4);
727047944f3Smrg#endif
7287706df26Smrg	  break;
7297706df26Smrg	}
7307706df26Smrg    }
7317706df26Smrg
7327706df26Smrg    switch (pTga->CardType) {
7337706df26Smrg        case TYPE_TGA_8PLANE:
7347706df26Smrg        case TYPE_TGA_24PLANE:
7357706df26Smrg        case TYPE_TGA_24PLUSZ:
7367706df26Smrg            xf86DrvMsg(pScrn->scrnIndex, from, "Card Name: \"%s\"\n",
7377706df26Smrg			tga_cardnames[pTga->CardType]);
7387706df26Smrg	    break;
7397706df26Smrg	default:
7407706df26Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
7417706df26Smrg                 "Card \"0x%02x\" is not recognised\n", pTga->CardType);
7427706df26Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
7437706df26Smrg		       "Assuming 8 plane TGA with 2MB frame buffer\n");
7447706df26Smrg	    pTga->CardType = TYPE_TGA_8PLANE;
7457706df26Smrg	    break;
7467706df26Smrg    }
7477706df26Smrg
7487706df26Smrg    /* Adjust framebuffer for card type */
7497706df26Smrg    pTga->FbAddress += fb_offset_presets[pTga->CardType];
7507706df26Smrg
7517706df26Smrg    if (!(((pScrn->depth ==  8) && (pTga->CardType == TYPE_TGA_8PLANE)) ||
7527706df26Smrg	  ((pScrn->depth == 24) && (pTga->CardType == TYPE_TGA_24PLANE)) ||
7537706df26Smrg	  ((pScrn->depth == 24) && (pTga->CardType == TYPE_TGA_24PLUSZ)))) {
7547706df26Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
7557706df26Smrg		   "Given depth (%d) is not supported by this card\n",
7567706df26Smrg		   pScrn->depth);
7577706df26Smrg	return FALSE;
7587706df26Smrg    }
7597706df26Smrg
7607706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
7617706df26Smrg	       (unsigned long)pTga->FbAddress);
7627706df26Smrg
7637706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
7647706df26Smrg	       (unsigned long)pTga->IOAddress);
7657706df26Smrg
7667ae0a258Smrg#ifndef XSERVER_LIBPCIACCESS
7677706df26Smrg    /* RAC stuff: we don't have any resources we need to reserve,
7687706df26Smrg       but we should do this here anyway */
7697706df26Smrg    if (xf86RegisterResources(pTga->pEnt->index, NULL, ResExclusive)) {
7707706df26Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
7717706df26Smrg		 "xf86RegisterResources() found resource conflicts\n");
7727706df26Smrg      TGAFreeRec(pScrn);
7737706df26Smrg      return FALSE;
7747706df26Smrg    }
7757ae0a258Smrg#endif
7767706df26Smrg
7777706df26Smrg    /* HW bpp matches reported bpp */
7787706df26Smrg    pTga->HwBpp = pScrn->bitsPerPixel;
7797706df26Smrg
7807706df26Smrg    if (pTga->pEnt->device->videoRam != 0) {
7817706df26Smrg	pScrn->videoRam = pTga->pEnt->device->videoRam;
7827706df26Smrg	from = X_CONFIG;
7837706df26Smrg    } else {
7847706df26Smrg      switch (pTga->CardType) {
7857706df26Smrg      case TYPE_TGA_8PLANE:
7867706df26Smrg	pScrn->videoRam = 2*1024;
7877706df26Smrg	break;
7887706df26Smrg      case TYPE_TGA_24PLANE:
7897706df26Smrg	pScrn->videoRam = 8*1024;
7907706df26Smrg	break;
7917706df26Smrg      case TYPE_TGA_24PLUSZ:
7927706df26Smrg	pScrn->videoRam = 16*1024;
7937706df26Smrg	break;
7947706df26Smrg      }
7957706df26Smrg    }
7967706df26Smrg
7977706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
7987706df26Smrg               pScrn->videoRam);
7997706df26Smrg
8007706df26Smrg    pTga->FbMapSize = pScrn->videoRam * 1024;
8017706df26Smrg
8027706df26Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
8037706df26Smrg	TGAFreeRec(pScrn);
8047706df26Smrg	return FALSE;
8057706df26Smrg    }
8067706df26Smrg
8077706df26Smrg    /* Load XAA if needed */
8087706df26Smrg    if (!pTga->NoAccel || pTga->HWCursor) {
8097706df26Smrg	if (!xf86LoadSubModule(pScrn, "xaa")) {
8107706df26Smrg	    TGAFreeRec(pScrn);
8117706df26Smrg	    return FALSE;
8127706df26Smrg	}
8137706df26Smrg    }
8147706df26Smrg
8157706df26Smrg
8167706df26Smrg    /*********************
8177706df26Smrg    Let's check what type of DAC we have and reject if necessary
8187706df26Smrg    *********************/
8197706df26Smrg
8207706df26Smrg    pTga->RamDac = NULL;
8217706df26Smrg
8227706df26Smrg    if (pTga->CardType != TYPE_TGA_8PLANE) {
8237706df26Smrg        pTga->RamDacRec = NULL;
8247706df26Smrg	pTga->RamDac = NULL;
8257706df26Smrg    } else {
8267706df26Smrg
8277706df26Smrg        pTga->RamDacRec = RamDacCreateInfoRec();
8287706df26Smrg        switch (pTga->Chipset)
8297706df26Smrg	{
8307706df26Smrg	case PCI_CHIP_DEC21030:
8317706df26Smrg	    pTga->RamDacRec->ReadDAC = tgaBTInIndReg;
8327706df26Smrg	    pTga->RamDacRec->WriteDAC = tgaBTOutIndReg;
8337706df26Smrg	    pTga->RamDacRec->ReadAddress = tgaBTReadAddress;
8347706df26Smrg	    pTga->RamDacRec->WriteAddress = tgaBTWriteAddress;
8357706df26Smrg	    pTga->RamDacRec->ReadData = tgaBTReadData;
8367706df26Smrg	    pTga->RamDacRec->WriteData = tgaBTWriteData;
8377706df26Smrg	    break;
8387706df26Smrg	case PCI_CHIP_TGA2:
8397706df26Smrg	    pTga->RamDacRec->ReadDAC = tga2BTInIndReg;
8407706df26Smrg	    pTga->RamDacRec->WriteDAC = tga2BTOutIndReg;
8417706df26Smrg	    pTga->RamDacRec->ReadAddress = tga2BTReadAddress;
8427706df26Smrg	    pTga->RamDacRec->WriteAddress = tga2BTWriteAddress;
8437706df26Smrg	    pTga->RamDacRec->ReadData = tga2BTReadData;
8447706df26Smrg	    pTga->RamDacRec->WriteData = tga2BTWriteData;
8457706df26Smrg	    break;
8467706df26Smrg	}
8477706df26Smrg
8487706df26Smrg	if (!RamDacInit(pScrn, pTga->RamDacRec)) {
8497706df26Smrg	    RamDacDestroyInfoRec(pTga->RamDacRec);
8507706df26Smrg	    return FALSE;
8517706df26Smrg	}
8527706df26Smrg
8537706df26Smrg	TGAMapMem(pScrn);
8547706df26Smrg
8557706df26Smrg	pTga->RamDac = BTramdacProbe(pScrn, BTramdacs);
8567706df26Smrg
8577706df26Smrg	TGAUnmapMem(pScrn);
8587706df26Smrg
8597706df26Smrg	if (pTga->RamDac == NULL)
8607706df26Smrg	    return FALSE;
8617706df26Smrg    }
8627706df26Smrg
8637706df26Smrg    /*********************
8647706df26Smrg    set up clock and mode stuff
8657706df26Smrg    *********************/
8667706df26Smrg
8677706df26Smrg    pScrn->progClock = TRUE;
8687706df26Smrg
8697706df26Smrg    /* Set the min pixel clock */
8707706df26Smrg    pTga->MinClock = 16250;	/* XXX Guess, need to check this */
8717706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
8727706df26Smrg	       pTga->MinClock / 1000);
8737706df26Smrg
8747706df26Smrg    /*
8757706df26Smrg     * If the user has specified ramdac speed in the XF86Config
8767706df26Smrg     * file, we respect that setting.
8777706df26Smrg     */
8787706df26Smrg    if (pTga->pEnt->device->dacSpeeds[0]) {
8797706df26Smrg	int speed = 0;
8807706df26Smrg
8817706df26Smrg	switch (pScrn->bitsPerPixel) {
8827706df26Smrg	case 8:
8837706df26Smrg	   speed = pTga->pEnt->device->dacSpeeds[DAC_BPP8];
8847706df26Smrg	   break;
8857706df26Smrg	case 32:
8867706df26Smrg	   speed = pTga->pEnt->device->dacSpeeds[DAC_BPP32];
8877706df26Smrg	   break;
8887706df26Smrg	}
8897706df26Smrg	if (speed == 0)
8907706df26Smrg	    pTga->MaxClock = pTga->pEnt->device->dacSpeeds[0];
8917706df26Smrg	else
8927706df26Smrg	    pTga->MaxClock = speed;
8937706df26Smrg	from = X_CONFIG;
8947706df26Smrg    } else {
8957706df26Smrg	switch (pTga->Chipset) {
8967706df26Smrg	case PCI_CHIP_DEC21030:
8977706df26Smrg		pTga->MaxClock = 135000;
8987706df26Smrg		break;
8997706df26Smrg	case PCI_CHIP_TGA2:
9007706df26Smrg		pTga->MaxClock = 170000;
9017706df26Smrg		break;
9027706df26Smrg	}
9037706df26Smrg    }
9047706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
9057706df26Smrg	       pTga->MaxClock / 1000);
9067706df26Smrg
9077706df26Smrg    /*
9087706df26Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
9097706df26Smrg     * and what sort of modes they can be used for.
9107706df26Smrg     */
9117706df26Smrg    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
9127706df26Smrg    clockRanges->next = NULL;
9137706df26Smrg    clockRanges->minClock = pTga->MinClock;
9147706df26Smrg    clockRanges->maxClock = pTga->MaxClock;
9157706df26Smrg    clockRanges->clockIndex = -1;		/* programmable */
9167706df26Smrg    clockRanges->interlaceAllowed = FALSE;	/* XXX check this */
9177706df26Smrg    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
9187706df26Smrg
9197706df26Smrg    if(pScrn->display->virtualX || pScrn->display->virtualY) {
9207706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
9217706df26Smrg		   "TGA does not support a virtual desktop\n");
9227706df26Smrg	pScrn->display->virtualX = 0;
9237706df26Smrg	pScrn->display->virtualY = 0;
9247706df26Smrg    }
9257706df26Smrg
9267706df26Smrg    /*
9277706df26Smrg     * xf86ValidateModes will check that the mode HTotal and VTotal values
9287706df26Smrg     * don't exceed the chipset's limit if pScrn->maxHValue and
9297706df26Smrg     * pScrn->maxVValue are set.  Since our TGAValidMode() already takes
9307706df26Smrg     * care of this, we don't worry about setting them here.
9317706df26Smrg     */
9327706df26Smrg    /* Select valid modes from those available */
9337706df26Smrg    /*
9347706df26Smrg     * XXX Assuming min pitch 256, max 2048
9357706df26Smrg     * XXX Assuming min height 128, max 2048
9367706df26Smrg     */
9377706df26Smrg    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
9387706df26Smrg			  pScrn->display->modes, clockRanges,
9397706df26Smrg			  NULL, 256, 2048,
9407706df26Smrg			  pScrn->bitsPerPixel, 128, 2048,
9417706df26Smrg			  pScrn->display->virtualX,
9427706df26Smrg			  pScrn->display->virtualY,
9437706df26Smrg			  pTga->FbMapSize,
9447706df26Smrg			  LOOKUP_BEST_REFRESH);
9457706df26Smrg
9467706df26Smrg    if (i == -1) {
9477706df26Smrg	TGAFreeRec(pScrn);
9487706df26Smrg	return FALSE;
9497706df26Smrg    }
9507706df26Smrg
9517706df26Smrg    /* Prune the modes marked as invalid */
9527706df26Smrg    xf86PruneDriverModes(pScrn);
9537706df26Smrg
9547706df26Smrg    if (i == 0 || pScrn->modes == NULL) {
9557706df26Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
9567706df26Smrg	TGAFreeRec(pScrn);
9577706df26Smrg	return FALSE;
9587706df26Smrg    }
9597706df26Smrg
9607706df26Smrg    if(i > 1) {
9617706df26Smrg	DisplayModePtr mp1 = NULL, mp2 = NULL;
9627706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
9637706df26Smrg		   "TGA only supports one mode, using first mode.\n");
9647706df26Smrg	mp1 = pScrn->modes->next;
9657706df26Smrg	mp2 = mp1;
9667706df26Smrg	while(mp1 && mp1->next != mp1) {
9677706df26Smrg	    mp1 = mp1->next;
9687706df26Smrg	    xf86DeleteMode(&(pScrn->modes), mp2);
9697706df26Smrg	    mp2 = mp1;
9707706df26Smrg	}
9717706df26Smrg    }
9727706df26Smrg
9737706df26Smrg    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
9747706df26Smrg
9757706df26Smrg    /* Set the current mode to the first in the list */
9767706df26Smrg    pScrn->currentMode = pScrn->modes;
9777706df26Smrg
9787706df26Smrg    /*
9797706df26Smrg     This is a bit of a hack; we seem to have to init
9807706df26Smrg     the TGA2 chipset knowing what the mode is, so we
9817706df26Smrg     do this now as soon as we know it...
9827706df26Smrg    */
9837706df26Smrg    if (pTga->Chipset == PCI_CHIP_TGA2) {
9847706df26Smrg      TGA2SetupMode(pScrn);
9857706df26Smrg    }
9867706df26Smrg
9877706df26Smrg    /* Print the list of modes being used */
9887706df26Smrg    xf86PrintModes(pScrn);
9897706df26Smrg
9907706df26Smrg    /* Set display resolution */
9917706df26Smrg    xf86SetDpi(pScrn, 0, 0);
9927706df26Smrg
9937706df26Smrg    return TRUE;
9947706df26Smrg}
9957706df26Smrg
9967706df26Smrg
9977706df26Smrg/*
9987706df26Smrg * Map the framebuffer and MMIO memory.
9997706df26Smrg */
10007706df26Smrg
10017706df26Smrgstatic Bool
10027706df26SmrgTGAMapMem(ScrnInfoPtr pScrn)
10037706df26Smrg{
10047706df26Smrg    TGAPtr pTga;
10057706df26Smrg
10067706df26Smrg    pTga = TGAPTR(pScrn);
10077706df26Smrg
10087706df26Smrg    /*
10097706df26Smrg     * Map IO registers to virtual address space
10107706df26Smrg     */
10117706df26Smrg
10127706df26Smrg    /* TGA doesn't need a sparse memory mapping, because all register
10137706df26Smrg       accesses are doublewords */
1014047944f3Smrg
1015047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
10167706df26Smrg    pTga->IOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
10177706df26Smrg				      pTga->PciTag,
10187706df26Smrg				      pTga->IOAddress, 0x100000);
1019047944f3Smrg#else
1020047944f3Smrg    {
1021047944f3Smrg	void** result = (void**)&pTga->IOBase;
1022047944f3Smrg	int err = pci_device_map_range(pTga->PciInfo,
1023047944f3Smrg				       pTga->IOAddress,
1024047944f3Smrg				       0x100000,
1025047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE,
1026047944f3Smrg				       result);
1027047944f3Smrg	if (err)
1028047944f3Smrg	    return FALSE;
1029047944f3Smrg    }
1030047944f3Smrg#endif
10317706df26Smrg    if (pTga->IOBase == NULL)
10327706df26Smrg	return FALSE;
10337706df26Smrg
1034047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
10357706df26Smrg    pTga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
10367706df26Smrg				 pTga->PciTag,
10377706df26Smrg				 (unsigned long)pTga->FbAddress,
10387706df26Smrg				 pTga->FbMapSize);
1039047944f3Smrg#else
1040047944f3Smrg    {
1041047944f3Smrg	void** result = (void**)&pTga->FbBase;
1042047944f3Smrg	int err = pci_device_map_range(pTga->PciInfo,
1043047944f3Smrg				       pTga->FbAddress,
1044047944f3Smrg				       pTga->FbMapSize,
1045047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE |
1046047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1047047944f3Smrg				       result);
1048047944f3Smrg	if (err)
1049047944f3Smrg	    return FALSE;
1050047944f3Smrg    }
1051047944f3Smrg#endif
10527706df26Smrg    if (pTga->FbBase == NULL)
10537706df26Smrg	return FALSE;
10547706df26Smrg
10557706df26Smrg    if (pTga->Chipset == PCI_CHIP_DEC21030)
10567706df26Smrg	return TRUE;
10577706df26Smrg
1058047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
10597706df26Smrg    pTga->ClkBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
10607706df26Smrg			pTga->PciTag,
10617706df26Smrg			(unsigned long)pTga->CardAddress + TGA2_CLOCK_OFFSET,
10627706df26Smrg			0x10000);
1063047944f3Smrg#else
1064047944f3Smrg    {
1065047944f3Smrg	void** result = (void**)&pTga->ClkBase;
1066047944f3Smrg	int err = pci_device_map_range(pTga->PciInfo,
1067047944f3Smrg				       pTga->CardAddress + TGA2_CLOCK_OFFSET,
1068047944f3Smrg				       0x10000,
1069047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE,
1070047944f3Smrg				       result);
1071047944f3Smrg	if (err)
1072047944f3Smrg	    return FALSE;
1073047944f3Smrg    }
1074047944f3Smrg#endif
10757706df26Smrg    if (pTga->ClkBase == NULL)
10767706df26Smrg	return FALSE;
10777706df26Smrg
1078047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
10797706df26Smrg    pTga->DACBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,
10807706df26Smrg			pTga->PciTag,
10817706df26Smrg			(unsigned long)pTga->CardAddress + TGA2_RAMDAC_OFFSET,
10827706df26Smrg			0x10000);
1083047944f3Smrg#else
1084047944f3Smrg    {
1085047944f3Smrg	void** result = (void**)&pTga->DACBase;
1086047944f3Smrg	int err = pci_device_map_range(pTga->PciInfo,
1087047944f3Smrg				       pTga->CardAddress + TGA2_RAMDAC_OFFSET,
1088047944f3Smrg				       0x10000,
1089047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE,
1090047944f3Smrg				       result);
1091047944f3Smrg	if (err)
1092047944f3Smrg	    return FALSE;
1093047944f3Smrg    }
1094047944f3Smrg#endif
10957706df26Smrg    if (pTga->DACBase == NULL)
10967706df26Smrg	return FALSE;
10977706df26Smrg
10987706df26Smrg    /*
10997706df26Smrg     * This is a hack specifically for the TGA2 code, as it sometimes
11007706df26Smrg     * calculates/uses addresses in TGA2 memory which are NOT mmapped
11017706df26Smrg     * by the normal framebuffer code above. This most frequently occurs
11027706df26Smrg     * when displaying something close to the top-left corner (in the
11037706df26Smrg     * routines CopyLine{Forwards,Backwards}.
11047706df26Smrg     *
11057706df26Smrg     * This could most likely also be fixed by further modifying the
11067706df26Smrg     * code, but it (the code) is ugly enough already... ;-}
11077706df26Smrg     *
11087706df26Smrg     * So, the workaround is to simply mmap an additional PAGE of
11097706df26Smrg     * framebuffer memory in front of the normal mmap to prevent
11107706df26Smrg     * SEGVs from happening.
11117706df26Smrg     */
1112047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
11137706df26Smrg    pTga->HACKBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
11147706df26Smrg				 pTga->PciTag,
11157706df26Smrg				 (unsigned long)pTga->FbAddress - getpagesize(),
11167706df26Smrg				 getpagesize());
1117047944f3Smrg#else
1118047944f3Smrg    {
1119047944f3Smrg	void** result = (void**)&pTga->DACBase;
1120047944f3Smrg	int err = pci_device_map_range(pTga->PciInfo,
1121047944f3Smrg				       pTga->FbAddress - getpagesize(),
1122047944f3Smrg				       getpagesize(),
1123047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE |
1124047944f3Smrg				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1125047944f3Smrg				       result);
1126047944f3Smrg	if (err)
1127047944f3Smrg	    return FALSE;
1128047944f3Smrg    }
1129047944f3Smrg#endif
1130047944f3Smrg
11317706df26Smrg    if (pTga->HACKBase == NULL)
11327706df26Smrg	return FALSE;
11337706df26Smrg
11347706df26Smrg    return TRUE;
11357706df26Smrg}
11367706df26Smrg
11377706df26Smrg
11387706df26Smrg/*
11397706df26Smrg * Unmap the framebuffer and MMIO memory.
11407706df26Smrg */
11417706df26Smrg
11427706df26Smrgstatic Bool
11437706df26SmrgTGAUnmapMem(ScrnInfoPtr pScrn)
11447706df26Smrg{
11457706df26Smrg    TGAPtr pTga;
11467706df26Smrg
11477706df26Smrg    pTga = TGAPTR(pScrn);
11487706df26Smrg
1149047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
11507706df26Smrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->IOBase, 0x100000);
1151047944f3Smrg#else
1152047944f3Smrg    pci_device_unmap_range(pTga->PciInfo, pTga->IOBase, 0x100000);
1153047944f3Smrg#endif
11547706df26Smrg    pTga->IOBase = NULL;
11557706df26Smrg
1156047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
11577706df26Smrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->FbBase, pTga->FbMapSize);
1158047944f3Smrg#else
1159047944f3Smrg    pci_device_unmap_range(pTga->PciInfo, pTga->FbBase, pTga->FbMapSize);
1160047944f3Smrg#endif
11617706df26Smrg    pTga->FbBase = NULL;
11627706df26Smrg
11637706df26Smrg    if (pTga->Chipset == PCI_CHIP_DEC21030)
11647706df26Smrg	return TRUE;
11657706df26Smrg
1166047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
11677706df26Smrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->ClkBase, 0x10000);
1168047944f3Smrg#else
1169047944f3Smrg    pci_device_unmap_range(pTga->PciInfo, pTga->ClkBase, 0x10000);
1170047944f3Smrg#endif
11717706df26Smrg    pTga->ClkBase = NULL;
11727706df26Smrg
1173047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
11747706df26Smrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->DACBase, 0x10000);
1175047944f3Smrg#else
1176047944f3Smrg    pci_device_unmap_range(pTga->PciInfo, pTga->DACBase, 0x10000);
1177047944f3Smrg#endif
11787706df26Smrg    pTga->DACBase = NULL;
11797706df26Smrg
1180047944f3Smrg#ifndef XSERVER_LIBPCIACCESS
11817706df26Smrg    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTga->HACKBase, getpagesize());
1182047944f3Smrg#else
1183047944f3Smrg    pci_device_unmap_range(pTga->PciInfo, pTga->HACKBase, getpagesize());
1184047944f3Smrg#endif
11857706df26Smrg    pTga->HACKBase = NULL;
11867706df26Smrg
11877706df26Smrg    return TRUE;
11887706df26Smrg}
11897706df26Smrg
11907706df26Smrg
11917706df26Smrg/*
11927706df26Smrg * This function saves the video state.
11937706df26Smrg */
11947706df26Smrgstatic void
11957706df26SmrgTGASave(ScrnInfoPtr pScrn)
11967706df26Smrg{
11977706df26Smrg    TGAPtr pTga;
11987706df26Smrg    TGARegPtr tgaReg;
11997706df26Smrg    RamDacHWRecPtr pBT;
12007706df26Smrg    RamDacRegRecPtr BTreg;
12017706df26Smrg
12027706df26Smrg    pTga = TGAPTR(pScrn);
12037706df26Smrg    tgaReg = &pTga->SavedReg;
12047706df26Smrg
12057706df26Smrg    DEC21030Save(pScrn, tgaReg);
12067706df26Smrg    if (pTga->RamDac) { /* must be BT485... */
12077706df26Smrg        pBT = RAMDACHWPTR(pScrn);
12087706df26Smrg	BTreg = &pBT->SavedReg;
12097706df26Smrg	(*pTga->RamDac->Save)(pScrn, pTga->RamDacRec, BTreg);
12107706df26Smrg    } else switch (pTga->Chipset)
12117706df26Smrg    {
12127706df26Smrg    case PCI_CHIP_TGA2:
12137706df26Smrg        IBM561ramdacSave(pScrn, pTga->Ibm561saveReg);
12147706df26Smrg	break;
12157706df26Smrg    case PCI_CHIP_DEC21030:
12167706df26Smrg        BT463ramdacSave(pScrn, pTga->Bt463saveReg);
12177706df26Smrg	break;
12187706df26Smrg    }
12197706df26Smrg}
12207706df26Smrg
12217706df26Smrg
12227706df26Smrg/*
12237706df26Smrg * Initialise a new mode.  This is currently still using the old
12247706df26Smrg * "initialise struct, restore/write struct to HW" model.  That could
12257706df26Smrg * be changed.
12267706df26Smrg */
12277706df26Smrg
12287706df26Smrgstatic Bool
12297706df26SmrgTGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
12307706df26Smrg{
12317706df26Smrg    int ret = -1;
12327706df26Smrg    TGAPtr pTga;
12337706df26Smrg    TGARegPtr tgaReg;
12347706df26Smrg    RamDacHWRecPtr pBT;
12357706df26Smrg    RamDacRegRecPtr BTreg;
12367706df26Smrg
12377706df26Smrg    pTga = TGAPTR(pScrn);
12387706df26Smrg
12397706df26Smrg    pScrn->vtSema = TRUE;
12407706df26Smrg
12417706df26Smrg    ret = DEC21030Init(pScrn, mode);
12427706df26Smrg
12437706df26Smrg    if (pTga->Chipset == PCI_CHIP_TGA2 && pTga->RamDac == NULL)
12447706df26Smrg        IBM561ramdacHWInit(pScrn);
12457706df26Smrg
12467706df26Smrg    if (!ret)
12477706df26Smrg	return FALSE;
12487706df26Smrg
12497706df26Smrg    /* Program the registers */
12507706df26Smrg    tgaReg = &pTga->ModeReg;
12517706df26Smrg
12527706df26Smrg    DEC21030Restore(pScrn, tgaReg);
12537706df26Smrg
12547706df26Smrg    if (pTga->RamDac != NULL) {
12557706df26Smrg        pBT = RAMDACHWPTR(pScrn);
12567706df26Smrg	BTreg = &pBT->ModeReg;
12577706df26Smrg	(*pTga->RamDac->Restore)(pScrn, pTga->RamDacRec, BTreg);
12587706df26Smrg	if (pTga->Chipset == PCI_CHIP_TGA2) {
12597706df26Smrg	    pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01);
12607706df26Smrg	    pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0x00, 0x0c);
12617706df26Smrg	}
12627706df26Smrg	pTga->RamDacRec->WriteDAC(pScrn, BT_PIXEL_MASK, 0x00, 0xff);
12637706df26Smrg    } else {
12647706df26Smrg        switch (pTga->Chipset) {
12657706df26Smrg	case PCI_CHIP_TGA2:
12667706df26Smrg	    IBM561ramdacRestore(pScrn, pTga->Ibm561modeReg);
12677706df26Smrg	    break;
12687706df26Smrg	case PCI_CHIP_DEC21030:
12697706df26Smrg	    BT463ramdacRestore(pScrn, pTga->Bt463modeReg);
12707706df26Smrg	    break;
12717706df26Smrg	}
12727706df26Smrg    }
12737706df26Smrg    return TRUE;
12747706df26Smrg}
12757706df26Smrg
12767706df26Smrg/*
12777706df26Smrg * Restore the initial (text) mode.
12787706df26Smrg */
12797706df26Smrgstatic void
12807706df26SmrgTGARestore(ScrnInfoPtr pScrn)
12817706df26Smrg{
12827706df26Smrg    TGAPtr pTga;
12837706df26Smrg    TGARegPtr tgaReg;
12847706df26Smrg    RamDacHWRecPtr pBT;
12857706df26Smrg    RamDacRegRecPtr BTreg;
12867706df26Smrg
12877706df26Smrg    pTga = TGAPTR(pScrn);
12887706df26Smrg    tgaReg = &pTga->SavedReg;
12897706df26Smrg
12907706df26Smrg    /* Initial Text mode clock */
12917706df26Smrg    tgaReg->tgaRegs[0x0A] = 25175;
12927706df26Smrg
12937706df26Smrg    DEC21030Restore(pScrn, tgaReg);
12947706df26Smrg
12957706df26Smrg    if (pTga->RamDac != NULL) {
12967706df26Smrg        pBT = RAMDACHWPTR(pScrn);
12977706df26Smrg	BTreg = &pBT->SavedReg;
12987706df26Smrg	(*pTga->RamDac->Restore)(pScrn, pTga->RamDacRec, BTreg);
12997706df26Smrg	if (pTga->Chipset == PCI_CHIP_TGA2) {
13007706df26Smrg	    pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01);
13017706df26Smrg	    pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0x00, 0x00);
13027706df26Smrg	}
13037706df26Smrg	pTga->RamDacRec->WriteDAC(pScrn, BT_PIXEL_MASK, 0x00, 0xff);
13047706df26Smrg    } else switch (pTga->Chipset) {
13057706df26Smrg    case PCI_CHIP_TGA2:
13067706df26Smrg        IBM561ramdacRestore(pScrn, pTga->Ibm561saveReg);
13077706df26Smrg	break;
13087706df26Smrg    case PCI_CHIP_DEC21030:
13097706df26Smrg        BT463ramdacRestore(pScrn, pTga->Bt463saveReg);
13107706df26Smrg	break;
13117706df26Smrg    }
13127706df26Smrg
13137706df26Smrg if (pTga->HWCursor)
13147706df26Smrg     TGARestoreHWCursor(pScrn);
13157706df26Smrg}
13167706df26Smrg
13177706df26Smrg
13187706df26Smrg/* Mandatory */
13197706df26Smrg
13207706df26Smrg/* This gets called at the start of each server generation */
13217706df26Smrg
13227706df26Smrgstatic Bool
1323b92e825aSmrgTGAScreenInit(SCREEN_INIT_ARGS_DECL)
13247706df26Smrg{
13257706df26Smrg    ScrnInfoPtr pScrn;
13267706df26Smrg    TGAPtr pTga;
13277706df26Smrg    int ret;
13287706df26Smrg    VisualPtr visual;
13297706df26Smrg
13307706df26Smrg    /*
13317706df26Smrg     * First get the ScrnInfoRec
13327706df26Smrg     */
1333b92e825aSmrg    pScrn = xf86ScreenToScrn(pScreen);
13347706df26Smrg    pTga = TGAPTR(pScrn);
13357706df26Smrg
13367706df26Smrg    /* Map the TGA memory and MMIO areas */
13377706df26Smrg    if (!TGAMapMem(pScrn))
13387706df26Smrg	return FALSE;
13397706df26Smrg
13407706df26Smrg#if 1
13417706df26Smrg    /* dump original register contents */
13427706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MODE 0x%x\n",
13437706df26Smrg	       TGA_READ_REG(TGA_MODE_REG));
13447706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VALID 0x%x\n",
13457706df26Smrg	       TGA_READ_REG(TGA_VALID_REG));
13467706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DEEP 0x%x\n",
13477706df26Smrg	       TGA_READ_REG(TGA_DEEP_REG));
13487706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PIXSH 0x%x\n",
13497706df26Smrg	       TGA_READ_REG(TGA_PIXELSHIFT_REG));
13507706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ROP 0x%x\n",
13517706df26Smrg	       TGA_READ_REG(TGA_RASTEROP_REG));
13527706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "HORIZ 0x%x\n",
13537706df26Smrg	       TGA_READ_REG(TGA_HORIZ_REG));
13547706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VERT 0x%x\n",
13557706df26Smrg	       TGA_READ_REG(TGA_VERT_REG));
13567706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PIXMSK 0x%x\n",
13577706df26Smrg	       TGA_READ_REG(TGA_PIXELMASK_REG));
13587706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "REV 0x%x\n",
13597706df26Smrg	       TGA_READ_REG(TGA_REVISION_REG));
13607706df26Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VADDR 0x%x\n",
13617706df26Smrg	       TGA_READ_REG(TGA_BASE_ADDR_REG));
13627706df26Smrg#endif
13637706df26Smrg
13647706df26Smrg    /* Save the current state */
13657706df26Smrg    TGASave(pScrn);
13667706df26Smrg
13677706df26Smrg    /* Initialise the first mode */
13687706df26Smrg    TGAModeInit(pScrn, pScrn->currentMode);
13697706df26Smrg
13707706df26Smrg    /* Darken the screen for aesthetic reasons and set the viewport */
13717706df26Smrg    TGASaveScreen(pScreen, SCREEN_SAVER_ON);
13727706df26Smrg
13737706df26Smrg    /*
13747706df26Smrg     * The next step is to setup the screen's visuals, and initialise the
13757706df26Smrg     * framebuffer code.  In cases where the framebuffer's default
13767706df26Smrg     * choices for things like visual layouts and bits per RGB are OK,
13777706df26Smrg     * this may be as simple as calling the framebuffer's ScreenInit()
13787706df26Smrg     * function.  If not, the visuals will need to be setup before calling
13797706df26Smrg     * a fb ScreenInit() function and fixed up after.
13807706df26Smrg     *
13817706df26Smrg     * For most PC hardware at depths >= 8, the defaults that fb uses
13827706df26Smrg     * are not appropriate.  In this driver, we fixup the visuals after.
13837706df26Smrg     */
13847706df26Smrg
13857706df26Smrg    /*
13867706df26Smrg     * Reset visual list.
13877706df26Smrg     */
13887706df26Smrg    miClearVisualTypes();
13897706df26Smrg
13907706df26Smrg    /* Setup the visuals we support. */
13917706df26Smrg
13927706df26Smrg    /*
13937706df26Smrg     * For bpp > 8, the default visuals are not acceptable because we only
13947706df26Smrg     * support TrueColor and not DirectColor.  To deal with this, call
13957706df26Smrg     * miSetVisualTypes for each visual supported.
13967706df26Smrg     */
13977706df26Smrg
13987706df26Smrg    if (pScrn->bitsPerPixel > 8) {
13997706df26Smrg	if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
14007706df26Smrg				pScrn->defaultVisual))
14017706df26Smrg	    return FALSE;
14027706df26Smrg    } else {
14037706df26Smrg	if (!miSetVisualTypes(pScrn->depth,
14047706df26Smrg			      miGetDefaultVisualMask(pScrn->depth),
14057706df26Smrg			      pScrn->rgbBits, pScrn->defaultVisual))
14067706df26Smrg	    return FALSE;
14077706df26Smrg    }
14087706df26Smrg
14097706df26Smrg    miSetPixmapDepths ();
14107706df26Smrg
14117706df26Smrg    /*
14127706df26Smrg     * Call the framebuffer layer's ScreenInit function, and fill in other
14137706df26Smrg     * pScreen fields.
14147706df26Smrg     */
14157706df26Smrg
14167706df26Smrg    switch (pScrn->bitsPerPixel) {
14177706df26Smrg    case 8:
14187706df26Smrg    case 32:
14197706df26Smrg	ret = fbScreenInit(pScreen, pTga->FbBase, pScrn->virtualX,
14207706df26Smrg			pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
14217706df26Smrg			pScrn->displayWidth, pScrn->bitsPerPixel);
14227706df26Smrg	break;
14237706df26Smrg    default:
1424b92e825aSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
14257706df26Smrg		   "Internal error: invalid bpp (%d) in TGAScrnInit\n",
14267706df26Smrg		   pScrn->bitsPerPixel);
14277706df26Smrg	    ret = FALSE;
14287706df26Smrg	break;
14297706df26Smrg    }
14307706df26Smrg    if (!ret)
14317706df26Smrg	return FALSE;
14327706df26Smrg
14337706df26Smrg    xf86SetBlackWhitePixels(pScreen);
14347706df26Smrg
14357706df26Smrg    if (pScrn->bitsPerPixel > 8) {
14367706df26Smrg        /* Fixup RGB ordering */
14377706df26Smrg        visual = pScreen->visuals + pScreen->numVisuals;
14387706df26Smrg        while (--visual >= pScreen->visuals) {
14397706df26Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
14407706df26Smrg		visual->offsetRed = pScrn->offset.red;
14417706df26Smrg		visual->offsetGreen = pScrn->offset.green;
14427706df26Smrg		visual->offsetBlue = pScrn->offset.blue;
14437706df26Smrg		visual->redMask = pScrn->mask.red;
14447706df26Smrg		visual->greenMask = pScrn->mask.green;
14457706df26Smrg		visual->blueMask = pScrn->mask.blue;
14467706df26Smrg	    }
14477706df26Smrg	}
14487706df26Smrg    }
14497706df26Smrg
14507706df26Smrg    /* must be after RGB ordering fixed */
14517706df26Smrg
14527706df26Smrg    fbPictureInit (pScreen, 0, 0);
14537706df26Smrg
14547706df26Smrg    miInitializeBackingStore(pScreen);
14557706df26Smrg    xf86SetBackingStore(pScreen);
14567706df26Smrg    xf86SetSilkenMouse(pScreen);
14577706df26Smrg
14587706df26Smrg    /* we should ALWAYS do this */
14597706df26Smrg    if (pScrn->bitsPerPixel == 8) {
14607706df26Smrg      TGA_WRITE_REG(SIMPLE | X11 | BPP8PACKED, TGA_MODE_REG);
14617706df26Smrg      TGA_WRITE_REG(0x3 | BPP8PACKED, TGA_RASTEROP_REG);
14627706df26Smrg      if (pTga->Chipset == PCI_CHIP_TGA2)
14637706df26Smrg	TGA_WRITE_REG(2 << 28, TGA_DEEP_REG);
14647706df26Smrg    } else {
14657706df26Smrg      TGA_WRITE_REG(SIMPLE | X11 | BPP24, TGA_MODE_REG);
14667706df26Smrg      TGA_WRITE_REG(0x3 | BPP24, TGA_RASTEROP_REG);
14677706df26Smrg      if (pTga->Chipset == PCI_CHIP_TGA2)
14687706df26Smrg	TGA_WRITE_REG((7 << 2) | 1 | (2 << 28), TGA_DEEP_REG);
14697706df26Smrg    }
14707706df26Smrg    TGA_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
14717706df26Smrg    TGA_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
14727706df26Smrg
14737706df26Smrg    if (!pTga->NoAccel) {
14747706df26Smrg        switch (pTga->Chipset)
14757706df26Smrg        {
14767706df26Smrg	case PCI_CHIP_TGA2:
14777706df26Smrg	case PCI_CHIP_DEC21030:
14787706df26Smrg	  if(DEC21030AccelInit(pScreen) == FALSE) {
14797706df26Smrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
14807706df26Smrg			 "XAA Initialization failed\n");
14817706df26Smrg	      return(FALSE);
14827706df26Smrg	  }
14837706df26Smrg	  break;
14847706df26Smrg        }
14857706df26Smrg    }
14867706df26Smrg
14877706df26Smrg    /* Initialise cursor functions */
14887706df26Smrg    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
14897706df26Smrg
14907706df26Smrg    /* Initialize HW cursor layer.
14917706df26Smrg       Must follow software cursor initialization*/
14927706df26Smrg    if (pTga->HWCursor) {
14937706df26Smrg      if(!TGAHWCursorInit(pScreen)) {
14947706df26Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
14957706df26Smrg		   "Hardware cursor initialization failed\n");
14967706df26Smrg	return(FALSE);
14977706df26Smrg      }
14987706df26Smrg    }
14997706df26Smrg
15007706df26Smrg
15017706df26Smrg    /* Initialise default colourmap */
15027706df26Smrg    if (!miCreateDefColormap(pScreen))
15037706df26Smrg	return FALSE;
15047706df26Smrg
15057706df26Smrg    if ((pScrn->bitsPerPixel==8) &&
15067706df26Smrg        (!RamDacHandleColormaps(pScreen, 256, pScrn->rgbBits,
15077706df26Smrg	 CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)))
15087706df26Smrg	return FALSE;
15097706df26Smrg
15107706df26Smrg    pTga->CloseScreen = pScreen->CloseScreen;
15117706df26Smrg    pScreen->CloseScreen = TGACloseScreen;
15127706df26Smrg    pScreen->SaveScreen = TGASaveScreen;
15137706df26Smrg
15147706df26Smrg    if(xf86DPMSInit(pScreen, TGADisplayPowerManagementSet, 0) == FALSE)
15157706df26Smrg      ErrorF("DPMS initialization failed!\n");
15167706df26Smrg
15177706df26Smrg    {
15187706df26Smrg      XF86VideoAdaptorPtr *ptr;
15197706df26Smrg      int n;
15207706df26Smrg
15217706df26Smrg      pScrn->memPhysBase = pTga->FbAddress;
15227706df26Smrg      pScrn->fbOffset = 0;
15237706df26Smrg
15247706df26Smrg      n = xf86XVListGenericAdaptors(pScrn,&ptr);
15257706df26Smrg
15267706df26Smrg      if(n) {
15277706df26Smrg	xf86XVScreenInit(pScreen, ptr, n);
15287706df26Smrg      }
15297706df26Smrg
15307706df26Smrg    }
15317706df26Smrg
15327706df26Smrg    /* Report any unused options (only for the first generation) */
15337706df26Smrg    if (serverGeneration == 1) {
15347706df26Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
15357706df26Smrg    }
15367706df26Smrg
15377706df26Smrg    /* unblank the screen */
15387706df26Smrg    TGASaveScreen(pScreen, SCREEN_SAVER_OFF);
15397706df26Smrg
15407706df26Smrg    /* Done */
15417706df26Smrg    return TRUE;
15427706df26Smrg}
15437706df26Smrg
15447706df26Smrg
15457706df26Smrg/* Usually mandatory */
15467706df26Smrgstatic Bool
1547b92e825aSmrgTGASwitchMode(SWITCH_MODE_ARGS_DECL)
15487706df26Smrg{
1549b92e825aSmrg    SCRN_INFO_PTR(arg);
1550b92e825aSmrg    return TGAModeInit(pScrn, mode);
15517706df26Smrg}
15527706df26Smrg
15537706df26Smrg
15547706df26Smrg/*
15557706df26Smrg * This function is used to initialize the Start Address - the first
15567706df26Smrg * displayed location in the video memory.
15577706df26Smrg */
15587706df26Smrg/* Usually mandatory */
15597706df26Smrgstatic void
1560b92e825aSmrgTGAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
15617706df26Smrg{
15627706df26Smrg    /* we don't support virtual desktops, because TGA doesn't have the
15637706df26Smrg       ability to set the start of the visible framebuffer at an arbitrary
15647706df26Smrg       pixel */
15657706df26Smrg    return;
15667706df26Smrg}
15677706df26Smrg
15687706df26Smrg/*
15697706df26Smrg * This is called when VT switching back to the X server.  Its job is
15707706df26Smrg * to reinitialise the video mode.
15717706df26Smrg *
15727706df26Smrg * We may wish to unmap video/MMIO memory too.
15737706df26Smrg */
15747706df26Smrg
15757706df26Smrg/* Mandatory */
15767706df26Smrgstatic Bool
1577b92e825aSmrgTGAEnterVT(VT_FUNC_ARGS_DECL)
15787706df26Smrg{
1579b92e825aSmrg    SCRN_INFO_PTR(arg);
15807706df26Smrg
15817706df26Smrg    /* Should we re-save the text mode on each VT enter? */
15827706df26Smrg    if (!TGAModeInit(pScrn, pScrn->currentMode))
15837706df26Smrg	return FALSE;
15847706df26Smrg
15857706df26Smrg    return TRUE;
15867706df26Smrg}
15877706df26Smrg
15887706df26Smrg
15897706df26Smrg/*
15907706df26Smrg * This is called when VT switching away from the X server.  Its job is
15917706df26Smrg * to restore the previous (text) mode.
15927706df26Smrg *
15937706df26Smrg * We may wish to remap video/MMIO memory too.
15947706df26Smrg */
15957706df26Smrg
15967706df26Smrg/* Mandatory */
15977706df26Smrgstatic void
1598b92e825aSmrgTGALeaveVT(VT_FUNC_ARGS_DECL)
15997706df26Smrg{
1600b92e825aSmrg    SCRN_INFO_PTR(arg);
16017706df26Smrg/*     TGAPtr pTga = TGAPTR(pScrn); */
16027706df26Smrg
16037706df26Smrg    TGARestore(pScrn);
16047706df26Smrg
16057706df26Smrg    /* no longer necessary with new VT switching code */
16067706df26Smrg/*      memset(pTga->FbBase, 0, pTga->FbMapSize); */
16077706df26Smrg    return;
16087706df26Smrg}
16097706df26Smrg
16107706df26Smrg
16117706df26Smrg/*
16127706df26Smrg * This is called at the end of each server generation.  It restores the
16137706df26Smrg * original (text) mode.
16147706df26Smrg */
16157706df26Smrg
16167706df26Smrg/* Mandatory */
16177706df26Smrgstatic Bool
1618b92e825aSmrgTGACloseScreen(CLOSE_SCREEN_ARGS_DECL)
16197706df26Smrg{
1620b92e825aSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
16217706df26Smrg    TGAPtr pTga = TGAPTR(pScrn);
16227706df26Smrg
16237706df26Smrg    TGARestore(pScrn);
16247706df26Smrg    /*    memset(pTga->FbBase, 0, pScrn->videoRam * 1024); */
16257706df26Smrg    TGASync(pScrn);
16267706df26Smrg    TGAUnmapMem(pScrn);
16277706df26Smrg
1628b92e825aSmrg#ifdef HAVE_XAA_H
16297706df26Smrg    if(pTga->AccelInfoRec)
16307706df26Smrg	XAADestroyInfoRec(pTga->AccelInfoRec);
1631b92e825aSmrg#endif
16327706df26Smrg    pScrn->vtSema = FALSE;
16337706df26Smrg
16347706df26Smrg    pScreen->CloseScreen = pTga->CloseScreen;
1635b92e825aSmrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
16367706df26Smrg}
16377706df26Smrg
16387706df26Smrg
16397706df26Smrg/* Free up any per-generation data structures */
16407706df26Smrg
16417706df26Smrg/* Optional */
16427706df26Smrgstatic void
1643b92e825aSmrgTGAFreeScreen(FREE_SCREEN_ARGS_DECL)
16447706df26Smrg{
1645b92e825aSmrg    SCRN_INFO_PTR(arg);
1646b92e825aSmrg    RamDacFreeRec(pScrn);
1647b92e825aSmrg    TGAFreeRec(pScrn);
16487706df26Smrg}
16497706df26Smrg
16507706df26Smrg
16517706df26Smrg/* Checks if a mode is suitable for the selected chipset. */
16527706df26Smrg
16537706df26Smrg/* Optional */
16547706df26Smrgstatic ModeStatus
1655b92e825aSmrgTGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
16567706df26Smrg{
16577706df26Smrg    if (mode->Flags & V_INTERLACE)
16587706df26Smrg	return(MODE_BAD);
16597706df26Smrg
16607706df26Smrg    return(MODE_OK);
16617706df26Smrg}
16627706df26Smrg
16637706df26Smrg/* Do screen blanking */
16647706df26Smrg
16657706df26Smrg/* Mandatory */
16667706df26Smrgstatic Bool
16677706df26SmrgTGASaveScreen(ScreenPtr pScreen, int mode)
16687706df26Smrg    /* this function should blank the screen when unblank is FALSE and
16697706df26Smrg       unblank it when unblank is TRUE -- it doesn't actually seem to be
16707706df26Smrg       used for much though */
16717706df26Smrg{
16727706df26Smrg    TGAPtr pTga;
16737706df26Smrg    ScrnInfoPtr pScrn;
16747706df26Smrg    int valid_reg = 0;
16757706df26Smrg    Bool unblank;
16767706df26Smrg
1677b92e825aSmrg    pScrn = xf86ScreenToScrn(pScreen);
16787706df26Smrg    pTga = TGAPTR(pScrn);
16797706df26Smrg    valid_reg = TGA_READ_REG(TGA_VALID_REG);
16807706df26Smrg    valid_reg &= 0xFFFFFFFC;
16817706df26Smrg
16827706df26Smrg    unblank = xf86IsUnblank(mode);
16837706df26Smrg
16847706df26Smrg    if(unblank == FALSE)
16857706df26Smrg	valid_reg |= 0x3;
16867706df26Smrg    else /* this function is sometimes called w/1 || 2 as TRUE */
16877706df26Smrg	valid_reg |= 0x1;
16887706df26Smrg
16897706df26Smrg    TGA_WRITE_REG(valid_reg, TGA_VALID_REG);
16907706df26Smrg
16917706df26Smrg/*      ErrorF("TGASaveScreen called\n"); */
16927706df26Smrg
16937706df26Smrg    return TRUE;
16947706df26Smrg}
16957706df26Smrg
16967706df26Smrg
16977706df26Smrg/*
16987706df26Smrg * TGADisplayPowerManagementSet --
16997706df26Smrg *
17007706df26Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode.
17017706df26Smrg */
17027706df26Smrgstatic void
17037706df26SmrgTGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
17047706df26Smrg			     int flags)
17057706df26Smrg{
17067706df26Smrg  TGAPtr pTga;
17077706df26Smrg  int valid_reg = 0;
17087706df26Smrg
17097706df26Smrg  pTga = TGAPTR(pScrn);
17107706df26Smrg  valid_reg = TGA_READ_REG(TGA_VALID_REG);
17117706df26Smrg  valid_reg &= 0xFFFFFFFC;
17127706df26Smrg
17137706df26Smrg  switch(PowerManagementMode) {
17147706df26Smrg  case DPMSModeOn:
17157706df26Smrg    /* HSync: On, VSync: On */
17167706df26Smrg    valid_reg |= 0x1;
17177706df26Smrg    break;
17187706df26Smrg  case DPMSModeStandby:
17197706df26Smrg  case DPMSModeSuspend:
17207706df26Smrg    /* TGA gives us a function to blank the screen while maintaining sync...
17217706df26Smrg       I guess we can just use that here... */
17227706df26Smrg    valid_reg |= 0x3;
17237706df26Smrg    break;
17247706df26Smrg  case DPMSModeOff:
17257706df26Smrg    valid_reg |= 0x2;
17267706df26Smrg    break;
17277706df26Smrg  default:
17287706df26Smrg    ErrorF("Invalid PowerManagementMode %d passed to TGADisplayPowerManagementSet\n", PowerManagementMode);
17297706df26Smrg    break;
17307706df26Smrg  }
17317706df26Smrg
17327706df26Smrg  TGA_WRITE_REG(valid_reg, TGA_VALID_REG);
17337706df26Smrg  return;
17347706df26Smrg}
17357706df26Smrg
17367706df26Smrgstatic void
17377706df26SmrgTGARestoreHWCursor(ScrnInfoPtr pScrn)
17387706df26Smrg     /*
17397706df26Smrg       from tga.c in the linux kernel...may not work for BSD...
17407706df26Smrg       when the cursor is restored, it is one line down from where it should
17417706df26Smrg       be...this is disconcerting, but purely cosmetic.  Unfortunately reading
17427706df26Smrg       in the cursor framebuffer doesn't seem to work, I get a bunch of junk
17437706df26Smrg       at the beginning...other than that, see tga_cursor.c
17447706df26Smrg       I believe this to be a problem with the linux kernel code.
17457706df26Smrg       Hmm...this seems to be a 2.0.* problem, 2.2 works ok
17467706df26Smrg     */
17477706df26Smrg{
17487706df26Smrg  unsigned char *p = NULL;
17497706df26Smrg  int i = 0;
17507706df26Smrg  TGAPtr pTga;
17517706df26Smrg
17527706df26Smrg  /* Making this static prevents EGCS from compiling memset code
17537706df26Smrg     to initialize it, which was causing a problem. */
17547706df26Smrg  static const CARD32 tga_cursor_source[128] = {
17557706df26Smrg    0x000000ff, 0x00000000, 0x000000ff, 0x00000000, 0x000000ff,
17567706df26Smrg    0x00000000, 0x000000ff, 0x00000000, 0x000000ff, 0x00000000,
17577706df26Smrg    0x000000ff, 0x00000000, 0x000000ff, 0x00000000, 0x000000ff,
17587706df26Smrg    0x00000000, 0x000000ff, 0x00000000, 0x000000ff, 0x00000000,
17597706df26Smrg    0x000000ff, 0x00000000, 0x000000ff, 0x00000000, 0x000000ff,
17607706df26Smrg    0x00000000, 0x000000ff, 0x00000000, 0x000000ff, 0x00000000,
17617706df26Smrg    0x000000ff, 0x00000000,
17627706df26Smrg    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
17637706df26Smrg    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
17647706df26Smrg    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
17657706df26Smrg    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
17667706df26Smrg    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
17677706df26Smrg    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
17687706df26Smrg  };
17697706df26Smrg
17707706df26Smrg  /* this is the linux console hw cursor...what about the bsd console? */
17717706df26Smrg  /* what about tgafb? */
17727706df26Smrg  pTga = TGAPTR(pScrn);
17737706df26Smrg
17747706df26Smrg  /* we want to move the cursor off the screen before we do anything with it
17757706df26Smrg     otherwise, there is a "ghost cursor" that shows up */
17767706df26Smrg
17777706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_LOW, 0x00, 0);
17787706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_X_HIGH, 0xF0, 0);
17797706df26Smrg
17807706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_LOW, 0x00, 0);
17817706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_Y_HIGH, 0xF0, 0);
17827706df26Smrg
17837706df26Smrg
17847706df26Smrg  /* set a windows cursor -- oddly, this doesn't seem necessary */
17857706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_2, 0xFC, 0x02);
17867706df26Smrg
17877706df26Smrg  /* set a 64 bit cursor */
17887706df26Smrg/*    pTga->RamDacRec->WriteDAC(pScrn, BT_COMMAND_REG_0, 0x7F, 0x80); */
17897706df26Smrg/*    pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0x00, 0x01); */
17907706df26Smrg/*    pTga->RamDacRec->WriteDAC(pScrn, BT_STATUS_REG, 0xF8, 0x04); */
17917706df26Smrg
17927706df26Smrg  /* set the colors */
17937706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_WR_ADDR, 0xFC, 0x01);
17947706df26Smrg
17957706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0xaa);
17967706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0xaa);
17977706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0xaa);
17987706df26Smrg
17997706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18007706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18017706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18027706df26Smrg
18037706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18047706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18057706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18067706df26Smrg
18077706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18087706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18097706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_DATA, 0x00, 0x00);
18107706df26Smrg
18117706df26Smrg
18127706df26Smrg  /* load the console cursor */
18137706df26Smrg  pTga->RamDacRec->WriteDAC(pScrn, BT_WRITE_ADDR, 0xFC, 0x00);
18147706df26Smrg  p = (unsigned char *)tga_cursor_source;
18157706df26Smrg  for(i = 0; i < 512; i++)
18167706df26Smrg    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, *p++);
18177706df26Smrg  for(i = 0; i < 512; i++)
18187706df26Smrg    pTga->RamDacRec->WriteDAC(pScrn, BT_CURS_RAM_DATA, 0x00, 0xff);
18197706df26Smrg
18207706df26Smrg  return;
18217706df26Smrg}
18227706df26Smrg
18237706df26Smrg
18247706df26Smrg/*
18257706df26Smrg * This is the implementation of the Sync() function.
18267706df26Smrg */
18277706df26Smrgvoid
18287706df26SmrgTGASync(ScrnInfoPtr pScrn)
18297706df26Smrg{
18307706df26Smrg    TGAPtr pTga = TGAPTR(pScrn);
18317706df26Smrg    unsigned int stat;
18327706df26Smrg
18337706df26Smrg    switch (pTga->Chipset)
18347706df26Smrg    {
18357706df26Smrg    case PCI_CHIP_TGA2:
18367706df26Smrg      /* This code is weird, but then so is TGA2... ;-} */
18377706df26Smrg	mem_barrier();
18387706df26Smrg	while((stat = TGA_READ_REG(TGA_CMD_STAT_REG))) {
18397706df26Smrg	    if (((stat >> 8) & 0xff) == ((stat >> 16) & 0xff)) {
18407706df26Smrg	        TGA_WRITE_REG(0, TGA_CMD_STAT_REG);
18417706df26Smrg		mem_barrier();
18427706df26Smrg#if 0
18437706df26SmrgErrorF("TGASync: writing CMD_STATUS\n");
18447706df26Smrg#endif
18457706df26Smrg	    }
18467706df26Smrg	    usleep(1000);
18477706df26Smrg	}
18487706df26Smrg	break;
18497706df26Smrg
18507706df26Smrg    case PCI_CHIP_DEC21030:
18517706df26Smrg#if 0
18527706df26Smrg        /* I'm experiencing lockups which could be due to this function.
18537706df26Smrg	   We don't seem to need it anyway...
18547706df26Smrg	*/
18557706df26Smrg        while (TGA_READ_REG(TGA_CMD_STAT_REG) & 0x01);
18567706df26Smrg#endif
18577706df26Smrg	break;
18587706df26Smrg    }
18597706df26Smrg
18607706df26Smrg    return;
18617706df26Smrg}
18627706df26Smrg
1863