vesa.c 49.5 KB
Newer Older
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1 2 3
#define DEBUG_VERB 2
/*
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
Adam Jackson's avatar
Adam Jackson committed
4
 * Copyright 2008 Red Hat, Inc.
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Except as contained in this notice, the name of Conectiva Linux shall
 * not be used in advertising or otherwise to promote the sale, use or other
 * dealings in this Software without prior written authorization from
 * Conectiva Linux.
 *
29
 * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
30
 *          David Dawes <dawes@xfree86.org>
Adam Jackson's avatar
Adam Jackson committed
31
 *          Adam Jackson <ajax@redhat.com>
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
32 33
 */

Adam Jackson's avatar
Adam Jackson committed
34 35 36 37 38 39 40
/*
 * TODO:
 * - Port to RANDR 1.2 setup to make mode selection slightly better
 * - Port to RANDR 1.2 to drop the old-school DGA junk
 * - VBE/SCI for secondary DDC method?
 */

41 42 43 44
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

45 46
#include <string.h>

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
47 48 49 50 51 52 53 54
#include "vesa.h"

/* All drivers initialising the SW cursor need this */
#include "mipointer.h"

/* Colormap handling */
#include "micmap.h"
#include "xf86cmap.h"
55
#include "xf86Modes.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
56 57

/* DPMS */
58 59 60
#ifdef HAVE_XEXTPROTO_71
#include <X11/extensions/dpmsconst.h>
#else
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
61
#define DPMS_SERVER
62
#include <X11/extensions/dpms.h>
63
#endif
Dave Airlie's avatar
Dave Airlie committed
64
#include "compat-api.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
65 66 67 68

/* Mandatory functions */
static const OptionInfoRec * VESAAvailableOptions(int chipid, int busid);
static void VESAIdentify(int flags);
69 70 71
#if defined(XSERVER_LIBPCIACCESS) && !defined(HAVE_ISA)
#define VESAProbe NULL
#else
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
72
static Bool VESAProbe(DriverPtr drv, int flags);
73
#endif
74
#ifdef XSERVER_LIBPCIACCESS
75 76 77
static Bool VESAPciProbe(DriverPtr drv, int entity_num,
     struct pci_device *dev, intptr_t match_data);
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
78
static Bool VESAPreInit(ScrnInfoPtr pScrn, int flags);
Dave Airlie's avatar
Dave Airlie committed
79 80 81 82
static Bool VESAScreenInit(SCREEN_INIT_ARGS_DECL);
static Bool VESAEnterVT(VT_FUNC_ARGS_DECL);
static void VESALeaveVT(VT_FUNC_ARGS_DECL);
static Bool VESACloseScreen(CLOSE_SCREEN_ARGS_DECL);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
83 84
static Bool VESASaveScreen(ScreenPtr pScreen, int mode);

Dave Airlie's avatar
Dave Airlie committed
85
static Bool VESASwitchMode(SWITCH_MODE_ARGS_DECL);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
86
static Bool VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
Dave Airlie's avatar
Dave Airlie committed
87 88
static void VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL);
static void VESAFreeScreen(FREE_SCREEN_ARGS_DECL);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
89
static void VESAFreeRec(ScrnInfoPtr pScrn);
90
static VESAPtr VESAGetRec(ScrnInfoPtr pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
91 92 93 94 95 96

static void
VESADisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
                int flags);

/* locally used functions */
Adam Jackson's avatar
Adam Jackson committed
97
#ifdef HAVE_ISA
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
98
static int VESAFindIsaDevice(GDevPtr dev);
Adam Jackson's avatar
Adam Jackson committed
99
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
100 101 102 103 104 105 106 107 108 109
static Bool VESAMapVidMem(ScrnInfoPtr pScrn);
static void VESAUnmapVidMem(ScrnInfoPtr pScrn);
static int VESABankSwitch(ScreenPtr pScreen, unsigned int iBank);
static void VESALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
			    LOCO *colors, VisualPtr pVisual);
static void SaveFonts(ScrnInfoPtr pScrn);
static void RestoreFonts(ScrnInfoPtr pScrn);
static Bool 
VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function);

Adam Jackson's avatar
Adam Jackson committed
110 111 112 113
static void *
VESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
		 CARD32 *size, void *closure)
{
114
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Adam Jackson's avatar
Adam Jackson committed
115 116 117 118 119 120 121 122 123 124
    VESAPtr pVesa = VESAGetRec(pScrn);

    *size = pVesa->maxBytesPerScanline;
    return ((CARD8 *)pVesa->base + row * pVesa->maxBytesPerScanline + offset);
}

static void *
VESAWindowWindowed(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
		   CARD32 *size, void *closure)
{
125
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Adam Jackson's avatar
Adam Jackson committed
126 127 128 129 130 131 132 133 134 135 136 137 138
    VESAPtr pVesa = VESAGetRec(pScrn);
    VbeModeInfoBlock *data = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
    int window;

    offset += pVesa->maxBytesPerScanline * row;
    window = offset / (data->WinGranularity * 1024);
    pVesa->windowAoffset = window * data->WinGranularity * 1024;
    VESABankSwitch(pScreen, window);
    *size = data->WinSize * 1024 - (offset - pVesa->windowAoffset);

    return (void *)((unsigned long)pVesa->base +
		    (offset - pVesa->windowAoffset));
}
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
139

140 141 142 143 144 145
static void
vesaUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
{
    shadowUpdatePacked(pScreen, pBuf);
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
146 147 148 149 150 151 152
static Bool VESADGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);

enum GenericTypes
{
    CHIP_VESA_GENERIC
};

153
#ifdef XSERVER_LIBPCIACCESS
154 155 156 157 158 159 160 161 162 163
static const struct pci_id_match vesa_device_match[] = {
    {
	PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
	0x00030000, 0x00ffffff, CHIP_VESA_GENERIC 
    },

    { 0, 0, 0 },
};
#endif
    
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
164 165 166 167 168 169 170
/* Supported chipsets */
static SymTabRec VESAChipsets[] =
{
    {CHIP_VESA_GENERIC, "vesa"},
    {-1,		 NULL}
};

Adam Jackson's avatar
Adam Jackson committed
171
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
172 173 174 175
static PciChipsets VESAPCIchipsets[] = {
  { CHIP_VESA_GENERIC, PCI_CHIP_VGA, RES_SHARED_VGA },
  { -1,		-1,	   RES_UNDEFINED },
};
Adam Jackson's avatar
Adam Jackson committed
176
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
177

Adam Jackson's avatar
Adam Jackson committed
178
#ifdef HAVE_ISA
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
179 180 181 182
static IsaChipsets VESAISAchipsets[] = {
  {CHIP_VESA_GENERIC, RES_EXCLUSIVE_VGA},
  {-1,		0 }
};
Adam Jackson's avatar
Adam Jackson committed
183
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

/* 
 * This contains the functions needed by the server after loading the
 * driver module.  It must be supplied, and gets added the driver list by
 * the Module Setup funtion 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.
 */
_X_EXPORT DriverRec VESA = {
    VESA_VERSION,
    VESA_DRIVER_NAME,
    VESAIdentify,
    VESAProbe,
    VESAAvailableOptions,
    NULL,
    0,
    NULL,

203
#ifdef XSERVER_LIBPCIACCESS
204 205 206 207 208 209
    vesa_device_match,
    VESAPciProbe
#endif
};


Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
210 211
typedef enum {
    OPTION_SHADOW_FB,
212 213
    OPTION_DFLT_REFRESH,
    OPTION_MODESET_CLEAR_SCREEN
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
214 215 216 217 218
} VESAOpts;

static const OptionInfoRec VESAOptions[] = {
    { OPTION_SHADOW_FB,    "ShadowFB",		OPTV_BOOLEAN,	{0},	FALSE },
    { OPTION_DFLT_REFRESH, "DefaultRefresh",	OPTV_BOOLEAN,	{0},	FALSE },
219 220
    { OPTION_MODESET_CLEAR_SCREEN, "ModeSetClearScreen",
						OPTV_BOOLEAN,	{0},	FALSE },
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
221 222 223
    { -1,		   NULL,		OPTV_NONE,	{0},	FALSE }
};

224
#ifdef XFree86LOADER
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
225 226 227 228 229 230 231 232 233 234

/* Module loader interface */
static MODULESETUPPROTO(vesaSetup);

static XF86ModuleVersionInfo vesaVersionRec =
{
    VESA_DRIVER_NAME,
    MODULEVENDORSTRING,
    MODINFOSTRING1,
    MODINFOSTRING2,
235
    XORG_VERSION_CURRENT,
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
236 237 238 239 240 241 242 243 244 245 246
    VESA_MAJOR_VERSION, VESA_MINOR_VERSION, VESA_PATCHLEVEL,
    ABI_CLASS_VIDEODRV,			/* This is a video driver */
    ABI_VIDEODRV_VERSION,
    MOD_CLASS_VIDEODRV,
    {0, 0, 0, 0}
};

/*
 * This data is accessed by the loader.  The name must be the module name
 * followed by "ModuleData".
 */
247
_X_EXPORT XF86ModuleData vesaModuleData = { &vesaVersionRec, vesaSetup, NULL };
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
248 249 250 251 252 253 254 255 256

static pointer
vesaSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
{
    static Bool Initialised = FALSE;

    if (!Initialised)
    {
	Initialised = TRUE;
257
	xf86AddDriver(&VESA, Module, 1);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
	return (pointer)TRUE;
    }

    if (ErrorMajor)
	*ErrorMajor = LDR_ONCEONLY;
    return (NULL);
}

#endif

static const OptionInfoRec *
VESAAvailableOptions(int chipid, int busid)
{
    return (VESAOptions);
}

static void
VESAIdentify(int flags)
{
    xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets);
}

280 281 282 283
static VESAPtr
VESAGetRec(ScrnInfoPtr pScrn)
{
    if (!pScrn->driverPrivate)
284
	pScrn->driverPrivate = calloc(sizeof(VESARec), 1);
285 286 287 288 289 290 291 292 293 294 295 296 297 298

    return ((VESAPtr)pScrn->driverPrivate);
}

/* Only a little like VBESetModeParameters */
static void
VESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode,
		      DisplayModePtr ddcmode)
{
    VbeModeInfoData *data;
    int clock;

    data = (VbeModeInfoData *)vbemode->Private;

299
    data->block = calloc(sizeof(VbeCRTCInfoBlock), 1);
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
    data->block->HorizontalTotal = ddcmode->HTotal;
    data->block->HorizontalSyncStart = ddcmode->HSyncStart;
    data->block->HorizontalSyncEnd = ddcmode->HSyncEnd;
    data->block->VerticalTotal = ddcmode->VTotal;
    data->block->VerticalSyncStart = ddcmode->VSyncStart;
    data->block->VerticalSyncEnd = ddcmode->VSyncEnd;
    data->block->Flags = ((ddcmode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) |
	                 ((ddcmode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0);
    data->block->PixelClock = ddcmode->Clock * 1000;

    /* ask the BIOS to figure out the real clock */
    clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock);
    if (clock)
	data->block->PixelClock = clock;

    data->mode |= (1 << 11);
    data->block->RefreshRate = 100 * ((double)(data->block->PixelClock) /
				(double)(ddcmode->HTotal * ddcmode->VTotal));
}

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
/*
 * Despite that VBE gives you pixel granularity for mode sizes, some BIOSes
 * think they can only give sizes in multiples of character cells; and
 * indeed, the reference CVT and GTF formulae only give results where
 * (h % 8) == 0.  Whatever, let's just try to cope.  What we're looking for
 * here is cases where the display says 1366x768 and the BIOS says 1360x768.
 */
static Bool
vesaModesCloseEnough(DisplayModePtr edid, DisplayModePtr vbe)
{
    if (!(edid->type & M_T_DRIVER))
	return FALSE;

    /* never seen a height granularity... */
    if (edid->VDisplay != vbe->VDisplay)
	return FALSE;

    if (edid->HDisplay >= vbe->HDisplay &&
	(edid->HDisplay & ~7) == (vbe->HDisplay & ~7))
	return TRUE;

    return FALSE;
}

344
static ModeStatus
Dave Airlie's avatar
Dave Airlie committed
345
VESAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr p, Bool flag, int pass)
346
{
Dave Airlie's avatar
Dave Airlie committed
347
    SCRN_INFO_PTR(arg);
348 349 350 351
    static int warned = 0;
    int found = 0;
    VESAPtr pVesa = VESAGetRec(pScrn);
    MonPtr mon = pScrn->monitor;
352
    ModeStatus ret = MODE_BAD;
353 354 355 356 357 358 359
    DisplayModePtr mode;
    float v;

    pVesa = VESAGetRec(pScrn);

    if (pass != MODECHECK_FINAL) {
	if (!warned) {
Dave Airlie's avatar
Dave Airlie committed
360
	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VESAValidMode called unexpectedly\n");
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	    warned = 1;
	}
	return MODE_OK;
    }

    /*
     * This is suboptimal.  We pass in just the barest description of a mode
     * we can get away with to VBEValidateModes, so it can't really throw
     * out anything we give it.  But we need to filter the list so that we
     * don't populate the mode list with things the monitor can't do.
     *
     * So first off, if this isn't a mode we handed to the server (ie,
     * M_T_BUILTIN), then we know we can't do it.
     */
    if (!(p->type & M_T_BUILTIN))
	return MODE_NOMODE;

    if (pVesa->strict_validation) {
	/*
	 * If it's our first pass at mode validation, we'll try for a strict
	 * intersection between the VBE and DDC mode lists.
	 */
	if (pScrn->monitor->DDC) {
	    for (mode = pScrn->monitor->Modes; mode; mode = mode->next) {
385
		if (vesaModesCloseEnough(mode, p)) {
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
		    if (xf86CheckModeForMonitor(mode, mon) == MODE_OK) {
			found = 1;
			break;
		    }
		}
		if (mode == pScrn->monitor->Last)
		    break;
	    }
	    if (!found)
		return MODE_NOMODE;

	    /* having found a matching mode, stash the CRTC values aside */
	    VESASetModeParameters(pVesa->pVbe, p, mode);
	    return MODE_OK;
	}

	/* No DDC and no modes make Homer something something... */
	return MODE_NOMODE;
    }

    /*
     * Finally, walk through the vsync rates 1Hz at a time looking for a mode
     * that will fit.  This is assuredly a terrible way to do this, but
     * there's no obvious method for computing a mode of a given size that
     * will pass xf86CheckModeForMonitor.  XXX this path is terrible, but
     * then, by this point, you're well into despair territory.
     */
    for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
	mode = xf86GTFMode(p->HDisplay, p->VDisplay, v, 0, 0);
	ret = xf86CheckModeForMonitor(mode, mon);
416
	free(mode->name);
417
	free(mode);
418 419 420 421 422 423 424
	if (ret == MODE_OK)
	    break;
    }

    return ret;
}

Adam Jackson's avatar
Adam Jackson committed
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
static void
VESAInitScrn(ScrnInfoPtr pScrn)
{
    pScrn->driverVersion = VESA_VERSION;
    pScrn->driverName    = VESA_DRIVER_NAME;
    pScrn->name		 = VESA_NAME;
    pScrn->Probe	 = VESAProbe;
    pScrn->PreInit       = VESAPreInit;
    pScrn->ScreenInit    = VESAScreenInit;
    pScrn->SwitchMode    = VESASwitchMode;
    pScrn->ValidMode     = VESAValidMode;
    pScrn->AdjustFrame   = VESAAdjustFrame;
    pScrn->EnterVT       = VESAEnterVT;
    pScrn->LeaveVT       = VESALeaveVT;
    pScrn->FreeScreen    = VESAFreeScreen;
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
442 443 444 445 446
/*
 * This function is called once, at the start of the first server generation to
 * do a minimal probe for supported hardware.
 */

447
#ifdef XSERVER_LIBPCIACCESS
448 449 450 451 452 453 454 455 456
static Bool
VESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
	     intptr_t match_data)
{
    ScrnInfoPtr pScrn;
    
    pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, 
				NULL, NULL, NULL, NULL, NULL);
    if (pScrn != NULL) {
457
	VESAPtr pVesa;
458

459 460 461 462 463 464
	if (pci_device_has_kernel_driver(dev)) {
	    ErrorF("vesa: Ignoring device with a bound kernel driver\n");
	    return FALSE;
	}

	pVesa = VESAGetRec(pScrn);
Adam Jackson's avatar
Adam Jackson committed
465
	VESAInitScrn(pScrn);
466 467
	pVesa->pciInfo = dev;
    }
Adam Jackson's avatar
Adam Jackson committed
468

469 470 471 472
    return (pScrn != NULL);
}
#endif

473
#ifndef VESAProbe
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
static Bool
VESAProbe(DriverPtr drv, int flags)
{
    Bool foundScreen = FALSE;
    int numDevSections, numUsed;
    GDevPtr *devSections;
    int *usedChips;
    int i;

    /*
     * Find the config file Device sections that match this
     * driver, and return if there are none.
     */
    if ((numDevSections = xf86MatchDevice(VESA_NAME,
					  &devSections)) <= 0)
	return (FALSE);

491
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
    /* PCI BUS */
    if (xf86GetPciVideoInfo()) {
	numUsed = xf86MatchPciInstances(VESA_NAME, PCI_VENDOR_GENERIC,
					VESAChipsets, VESAPCIchipsets, 
					devSections, numDevSections,
					drv, &usedChips);
	if (numUsed > 0) {
	    if (flags & PROBE_DETECT)
		foundScreen = TRUE;
	    else {
		for (i = 0; i < numUsed; i++) {
		    ScrnInfoPtr pScrn = NULL;
		    /* Allocate a ScrnInfoRec  */
		    if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
						     VESAPCIchipsets,NULL,
						     NULL,NULL,NULL,NULL))) {
Adam Jackson's avatar
Adam Jackson committed
508
			VESAInitScrn(pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
509 510 511 512
			foundScreen = TRUE;
		    }
		}
	    }
513
	    free(usedChips);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
514 515
	}
    }
516
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
517

Adam Jackson's avatar
Adam Jackson committed
518
#ifdef HAVE_ISA
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
519 520 521 522 523 524 525 526 527 528 529 530 531
    /* Isa Bus */
    numUsed = xf86MatchIsaInstances(VESA_NAME,VESAChipsets,
				    VESAISAchipsets, drv,
				    VESAFindIsaDevice, devSections,
				    numDevSections, &usedChips);
    if(numUsed > 0) {
	if (flags & PROBE_DETECT)
	    foundScreen = TRUE;
	else for (i = 0; i < numUsed; i++) {
	    ScrnInfoPtr pScrn = NULL;
	    if ((pScrn = xf86ConfigIsaEntity(pScrn, 0,usedChips[i],
					     VESAISAchipsets, NULL,
					     NULL, NULL, NULL, NULL))) {
Adam Jackson's avatar
Adam Jackson committed
532
		VESAInitScrn(pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
533 534 535
		foundScreen = TRUE;
	    }
	}
536
	free(usedChips);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
537
    }
Adam Jackson's avatar
Adam Jackson committed
538
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
539

540
    free(devSections);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
541 542 543

    return (foundScreen);
}
544
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
545

Adam Jackson's avatar
Adam Jackson committed
546
#ifdef HAVE_ISA
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
static int
VESAFindIsaDevice(GDevPtr dev)
{
#ifndef PC98_EGC
    CARD16 GenericIOBase = VGAHW_GET_IOBASE();
    CARD8 CurrentValue, TestValue;

    /* There's no need to unlock VGA CRTC registers here */

    /* VGA has one more read/write attribute register than EGA */
    (void) inb(GenericIOBase + VGA_IN_STAT_1_OFFSET);  /* Reset flip-flop */
    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
    CurrentValue = inb(VGA_ATTR_DATA_R);
    outb(VGA_ATTR_DATA_W, CurrentValue ^ 0x0F);
    outb(VGA_ATTR_INDEX, 0x14 | 0x20);
    TestValue = inb(VGA_ATTR_DATA_R);
    outb(VGA_ATTR_DATA_R, CurrentValue);

    /* Quit now if no VGA is present */
    if ((CurrentValue ^ 0x0F) != TestValue)
      return -1;
#endif
    return (int)CHIP_VESA_GENERIC;
}
Adam Jackson's avatar
Adam Jackson committed
571
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587

static void
VESAFreeRec(ScrnInfoPtr pScrn)
{
    VESAPtr pVesa = VESAGetRec(pScrn);
#if 0
    DisplayModePtr mode = pScrn->modes;
    /* I am not sure if the modes will ever get freed.
     * Anyway, the data unknown to other modules is being freed here.
     */
    if (mode) {
	do {
	    if (mode->Private) {
		VbeModeInfoData *data = (VbeModeInfoData*)mode->Private;

		if (data->block)
588
		    free(data->block);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
589

590
		free(data);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
591 592 593 594 595 596 597

		mode->Private = NULL;
	    }
	    mode = mode->next;
	} while (mode && mode != pScrn->modes);
    }
#endif
598
    free(pVesa->monitor);
Adam Jackson's avatar
Adam Jackson committed
599 600
    if (pVesa->vbeInfo)
	VBEFreeVBEInfo(pVesa->vbeInfo);
601 602 603 604
    free(pVesa->pal);
    free(pVesa->savedPal);
    free(pVesa->fonts);
    free(pScrn->driverPrivate);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
605 606 607
    pScrn->driverPrivate = NULL;
}

608 609 610 611 612 613 614 615 616 617
static int
VESAValidateModes(ScrnInfoPtr pScrn)
{
    VESAPtr pVesa = VESAGetRec(pScrn);
    DisplayModePtr mode;

    for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
	mode->status = MODE_OK;

    return VBEValidateModes(pScrn, NULL, pScrn->display->modes, 
618
			    NULL, NULL, 0, 32767, 1, 0, 32767,
619 620 621 622 623
			    pScrn->display->virtualX,
			    pScrn->display->virtualY,
			    pVesa->mapSize, LOOKUP_BEST_REFRESH);
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
624 625 626 627 628 629 630 631 632 633 634 635 636
/*
 * This function is called once for each screen at the start of the first
 * server generation to initialise the screen for all server generations.
 */
static Bool
VESAPreInit(ScrnInfoPtr pScrn, int flags)
{
    VESAPtr pVesa;
    VbeInfoBlock *vbe;
    DisplayModePtr pMode;
    VbeModeInfoBlock *mode;
    Gamma gzeros = {0.0, 0.0, 0.0};
    rgb rzeros = {0, 0, 0};
637
    pointer pDDCModule;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
638 639 640
    int i;
    int flags24 = 0;
    int defaultDepth = 0;
641
    int defaultBpp = 0;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
642 643 644 645 646 647 648 649 650
    int depths = 0;

    if (flags & PROBE_DETECT)
	return (FALSE);

    pVesa = VESAGetRec(pScrn);
    pVesa->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);

    /* Load vbe module */
651
    if (!xf86LoadSubModule(pScrn, "vbe"))
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
652 653 654 655 656 657 658
        return (FALSE);

    if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
				       SET_BIOS_SCRATCH
				       | RESTORE_BIOS_SCRATCH)) == NULL)
        return (FALSE);

659
#ifndef XSERVER_LIBPCIACCESS
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
660 661 662 663 664
    if (pVesa->pEnt->location.type == BUS_PCI) {
	pVesa->pciInfo = xf86GetPciInfoForEntity(pVesa->pEnt->index);
	pVesa->pciTag = pciTag(pVesa->pciInfo->bus, pVesa->pciInfo->device,
			       pVesa->pciInfo->func);
    }
665
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685

    pScrn->chipset = "vesa";
    pScrn->monitor = pScrn->confScreen->monitor;
    pScrn->progClock = TRUE;
    pScrn->rgbBits = 8;

    if ((vbe = VBEGetVBEInfo(pVesa->pVbe)) == NULL)
	return (FALSE);
    pVesa->major = (unsigned)(vbe->VESAVersion >> 8);
    pVesa->minor = vbe->VESAVersion & 0xff;
    pVesa->vbeInfo = vbe;
    pScrn->videoRam = vbe->TotalMemory * 64;

    /*
     * Find what depths are available.
     */
    depths = VBEFindSupportedDepths(pVesa->pVbe, pVesa->vbeInfo, &flags24,
				    V_MODETYPE_VBE);

    /* Preferred order for default depth selection. */
686 687 688
    if (depths & V_DEPTH_24)
	defaultDepth = 24;
    else if (depths & V_DEPTH_16)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
689 690 691 692 693 694 695 696 697 698
	defaultDepth = 16;
    else if (depths & V_DEPTH_15)
	defaultDepth = 15;
    else if (depths & V_DEPTH_8)
	defaultDepth = 8;
    else if (depths & V_DEPTH_4)
	defaultDepth = 4;
    else if (depths & V_DEPTH_1)
	defaultDepth = 1;

699 700
    if (defaultDepth == 24 && !(flags24 & Support32bppFb))
	defaultBpp = 24;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
701

702 703 704
    /* Prefer 32bpp because 1999 called and wants its packed pixels back */
    if (flags24 & Support32bppFb)
	flags24 |= SupportConvert24to32 | PreferConvert24to32;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
705
    if (flags24 & Support24bppFb)
706
	flags24 |= SupportConvert32to24;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
707

708
    if (!xf86SetDepthBpp(pScrn, defaultDepth, 0, defaultBpp, flags24)) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }
    xf86PrintDepthBpp(pScrn);

    /* color weight */
    if (pScrn->depth > 8 && !xf86SetWeight(pScrn, rzeros, rzeros)) {
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }
    /* visual init */
    if (!xf86SetDefaultVisual(pScrn, -1)) {
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }

    xf86SetGamma(pScrn, gzeros);

Ian Lepore's avatar
Ian Lepore committed
727 728 729
    /* set up options before loading any modules that may look at them */
    xf86CollectOptions(pScrn, NULL);

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
    if (pVesa->major >= 2) {
	/* Load ddc module */
	if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
	    vbeFree(pVesa->pVbe);
	    return (FALSE);
	}

	if ((pVesa->monitor = vbeDoEDID(pVesa->pVbe, pDDCModule)) != NULL) {
	    xf86PrintEDID(pVesa->monitor);
	}

	xf86UnloadSubModule(pDDCModule);
    }

    if ((pScrn->monitor->DDC = pVesa->monitor) != NULL)
	xf86SetDDCproperties(pScrn, pVesa->monitor);
746 747
    else {
	void *panelid = VBEReadPanelID(pVesa->pVbe);
Dave Airlie's avatar
Dave Airlie committed
748
	VBEInterpretPanelID(SCRN_OR_INDEX_ARG(pScrn), panelid);
749
	free(panelid);
750
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776

    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
			"Searching for matching VESA mode(s):\n");

    /*
     * Check the available BIOS modes, and extract those that match the
     * requirements into the modePool.  Note: modePool is a NULL-terminated
     * list.
     */
    pScrn->modePool = VBEGetModePool (pScrn, pVesa->pVbe, pVesa->vbeInfo,
				      V_MODETYPE_VBE);

    xf86ErrorFVerb(DEBUG_VERB, "\n");
    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
		   "Total Memory: %d 64KB banks (%dkB)\n", vbe->TotalMemory,
		   (vbe->TotalMemory * 65536) / 1024);

    pVesa->mapSize = vbe->TotalMemory * 65536;
    if (pScrn->modePool == NULL) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No matching modes\n");
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }

    VBESetModeNames(pScrn->modePool);

777
    pVesa->strict_validation = TRUE;
778
    i = VESAValidateModes(pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
779

780 781
    if (i <= 0) {
	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
782
		"No valid modes left. Trying less strict filter...\n");
783
	pVesa->strict_validation = FALSE;
784
	i = VESAValidateModes(pScrn);
785 786
    }

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
    if (i <= 0) do {
	Bool changed = FALSE;
	/* maybe there's more modes at the bottom... */
	if (pScrn->monitor->vrefresh[0].lo > 50) {
	    changed = TRUE;
	    pScrn->monitor->vrefresh[0].lo = 50;
	}
	if (pScrn->monitor->hsync[0].lo > 31.5) {
	    changed = TRUE;
	    pScrn->monitor->hsync[0].lo = 31.5;
	}

	if (!changed)
	    break;

	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		   "No valid modes left. Trying aggressive sync range...\n");
	i = VESAValidateModes(pScrn);
    } while (0);	

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
807
    if (i <= 0) {
808
	/* alright, i'm out of ideas */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n");
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }

    xf86PruneDriverModes(pScrn);

    pMode = pScrn->modes;
    do {
	mode = ((VbeModeInfoData*)pMode->Private)->data;
	if (mode->BytesPerScanline > pVesa->maxBytesPerScanline) {
	    pVesa->maxBytesPerScanline = mode->BytesPerScanline;
	}
	pMode = pMode->next;
    } while (pMode != pScrn->modes);

    pScrn->currentMode = pScrn->modes;
    pScrn->displayWidth = pScrn->virtualX;

    VBEPrintModes(pScrn);

    /* Set display resolution */
    xf86SetDpi(pScrn, 0, 0);

    if (pScrn->modes == NULL) {
	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n");
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }

    /* options */
840
    if (!(pVesa->Options = malloc(sizeof(VESAOptions)))) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
841 842 843 844 845 846 847
        vbeFree(pVesa->pVbe);
	return FALSE;
    }
    memcpy(pVesa->Options, VESAOptions, sizeof(VESAOptions));
    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVesa->Options);

    /* Use shadow by default */
848 849
    pVesa->shadowFB = xf86ReturnOptValBool(pVesa->Options, OPTION_SHADOW_FB,
                                           TRUE);
Stefan Dirsch's avatar
Stefan Dirsch committed
850 851 852 853 854
    /*  Use default refresh by default. Too many VBE 3.0
     *   BIOSes are incorrectly implemented.
     */
    pVesa->defaultRefresh = xf86ReturnOptValBool(pVesa->Options,
                                                 OPTION_DFLT_REFRESH, TRUE);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
855

856 857 858
    pVesa->ModeSetClearScreen =
        xf86ReturnOptValBool(pVesa->Options,
                             OPTION_MODESET_CLEAR_SCREEN, FALSE);
859

860
    if (!pVesa->defaultRefresh && !pVesa->strict_validation)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
861 862 863 864 865
	VBESetModeParameters(pScrn, pVesa->pVbe);

    mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
    switch (mode->MemoryModel) {
	case 0x4:	/* Packed pixel */
866
	case 0x6:	/* Direct Color */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
867 868 869 870 871 872 873 874 875 876
	    pScrn->bitmapBitOrder = BITMAP_BIT_ORDER; 

	    switch (pScrn->bitsPerPixel) {
		case 8:
		case 16:
		case 24:
		case 32:
		    break;
		default:
		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
877
			       "Unsupported bpp: %d\n", pScrn->bitsPerPixel);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
878 879 880 881
		    vbeFree(pVesa->pVbe);
		    return FALSE;
	    }
	    break;
882 883
	default:
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
884
		       "Unsupported Memory Model: %d\n", mode->MemoryModel);
885
	    return FALSE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
886 887 888 889 890 891 892 893 894 895
    }

    if (pVesa->shadowFB) {
	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n");
	if (!xf86LoadSubModule(pScrn, "shadow")) {
	    vbeFree(pVesa->pVbe);
	    return (FALSE);
	}
    }

896
    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
897 898 899 900 901 902 903 904 905 906
	VESAFreeRec(pScrn);
        vbeFree(pVesa->pVbe);
	return (FALSE);
    }

    vbeFree(pVesa->pVbe);

    return (TRUE);
}

Adam Jackson's avatar
Adam Jackson committed
907 908 909
static Bool
vesaCreateScreenResources(ScreenPtr pScreen)
{
910
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Adam Jackson's avatar
Adam Jackson committed
911 912 913 914 915 916 917 918 919 920 921 922 923
    VESAPtr pVesa = VESAGetRec(pScrn);
    Bool ret;

    pScreen->CreateScreenResources = pVesa->CreateScreenResources;
    ret = pScreen->CreateScreenResources(pScreen);
    pScreen->CreateScreenResources = vesaCreateScreenResources;

    shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen), pVesa->update,
	      pVesa->window, 0, 0);

    return ret;
}

924
static void
Dave Airlie's avatar
Dave Airlie committed
925
vesaEnableDisableFBAccess(SCRN_ARG_TYPE arg, Bool enable)
926
{
Dave Airlie's avatar
Dave Airlie committed
927
    SCRN_INFO_PTR(arg);
928 929 930
    VESAPtr pVesa = VESAGetRec(pScrn);

    pVesa->accessEnabled = enable;
Dave Airlie's avatar
Dave Airlie committed
931
    pVesa->EnableDisableFBAccess(arg, enable);
932 933
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
934
static Bool
Dave Airlie's avatar
Dave Airlie committed
935
VESAScreenInit(SCREEN_INIT_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
936
{
Dave Airlie's avatar
Dave Airlie committed
937
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
    VESAPtr pVesa = VESAGetRec(pScrn);
    VisualPtr visual;
    VbeModeInfoBlock *mode;
    int flags;

    if ((pVesa->pVbe = VBEExtendedInit(NULL, pVesa->pEnt->index,
				       SET_BIOS_SCRATCH
				       | RESTORE_BIOS_SCRATCH)) == NULL)
        return (FALSE);

    if (pVesa->mapPhys == 0) {
	mode = ((VbeModeInfoData*)(pScrn->currentMode->Private))->data;
	pScrn->videoRam = pVesa->mapSize;
	pVesa->mapPhys = mode->PhysBasePtr;
	pVesa->mapOff = 0;
    }

    if (pVesa->mapPhys == 0) {
	pVesa->mapPhys = 0xa0000;
	pVesa->mapSize = 0x10000;
    }

    if (!VESAMapVidMem(pScrn)) {
	if (pVesa->mapPhys != 0xa0000) {
	    pVesa->mapPhys = 0xa0000;
	    pVesa->mapSize = 0x10000;
	    if (!VESAMapVidMem(pScrn))
		return (FALSE);
	}
	else
	    return (FALSE);
    }

    /* Set bpp to 8 for depth 4 when using shadowfb. */
    if (pVesa->shadowFB && pScrn->bitsPerPixel == 4)
	pScrn->bitsPerPixel = 8;

Adam Jackson's avatar
Adam Jackson committed
975
    if (pVesa->shadowFB) {
976
	pVesa->shadow = calloc(1, pScrn->displayWidth * pScrn->virtualY *
Adam Jackson's avatar
Adam Jackson committed
977 978 979 980 981 982 983 984
				   ((pScrn->bitsPerPixel + 7) / 8));
	if (!pVesa->shadow) {
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Failed to allocate shadow buffer\n");
	    return FALSE;
	}
    }

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
985 986 987 988 989 990 991 992 993
    /* save current video state */
    VESASaveRestore(pScrn, MODE_SAVE);
    pVesa->savedPal = VBESetGetPaletteData(pVesa->pVbe, FALSE, 0, 256,
					    NULL, FALSE, FALSE);

    /* set first video mode */
    if (!VESASetMode(pScrn, pScrn->currentMode))
	return (FALSE);

994
    /* set the viewport */
Dave Airlie's avatar
Dave Airlie committed
995
    VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
996 997 998 999

    /* Blank the screen for aesthetic reasons. */
    VESASaveScreen(pScreen, SCREEN_SAVER_ON);

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
    /* mi layer */
    miClearVisualTypes();
    if (!xf86SetDefaultVisual(pScrn, -1))
	return (FALSE);
    if (pScrn->bitsPerPixel > 8) {
	if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
			      pScrn->rgbBits, TrueColor))
	    return (FALSE);
    }
    else {
	if (!miSetVisualTypes(pScrn->depth,
			      miGetDefaultVisualMask(pScrn->depth),
			      pScrn->rgbBits, pScrn->defaultVisual))
	    return (FALSE);
    }
    if (!miSetPixmapDepths())
	return (FALSE);

    mode = ((VbeModeInfoData*)pScrn->modes->Private)->data;
    switch (mode->MemoryModel) {
	case 0x4:	/* Packed pixel */
1021
	case 0x6:	/* Direct Color */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1022 1023 1024 1025 1026 1027
	    switch (pScrn->bitsPerPixel) {
		case 8:
		case 16:
		case 24:
		case 32:
		    if (!fbScreenInit(pScreen,
Adam Jackson's avatar
Adam Jackson committed
1028
				pVesa->shadowFB ? pVesa->shadow : pVesa->base,
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
				       pScrn->virtualX, pScrn->virtualY,
				       pScrn->xDpi, pScrn->yDpi,
				       pScrn->displayWidth, pScrn->bitsPerPixel))
			return (FALSE);
		    break;
		default:
		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
			       "Unsupported bpp: %d", pScrn->bitsPerPixel);
		    return (FALSE);
	    }
	    break;
1040 1041 1042 1043
	default:
	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
		       "Unsupported Memory Model: %d", mode->MemoryModel);
	    return (FALSE);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    }


    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 */
Adam Jackson's avatar
Adam Jackson committed
1063
    fbPictureInit(pScreen, 0, 0);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1064 1065

    if (pVesa->shadowFB) {
Julien Cristau's avatar
Julien Cristau committed
1066
	if (pVesa->mapPhys == 0xa0000) {	/* Windowed */
1067
	    pVesa->update = vesaUpdatePacked;
Adam Jackson's avatar
Adam Jackson committed
1068
	    pVesa->window = VESAWindowWindowed;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1069 1070
	}
	else {	/* Linear */
1071
	    pVesa->update = vesaUpdatePacked;
Adam Jackson's avatar
Adam Jackson committed
1072
	    pVesa->window = VESAWindowLinear;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1073 1074
	}

Adam Jackson's avatar
Adam Jackson committed
1075 1076 1077 1078
	if (!shadowSetup(pScreen))
	    return FALSE;
	pVesa->CreateScreenResources = pScreen->CreateScreenResources;
	pScreen->CreateScreenResources = vesaCreateScreenResources;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1079
    }
Julien Cristau's avatar
Julien Cristau committed
1080
    else if (pVesa->mapPhys == 0xa0000) {
1081 1082 1083
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Banked framebuffer requires ShadowFB\n");
        return FALSE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
    }

    VESADGAInit(pScrn, pScreen);

    xf86SetBlackWhitePixels(pScreen);
    xf86SetBackingStore(pScreen);

    /* software cursor */
    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());

    /* colormap */
    if (!miCreateDefColormap(pScreen))
	return (FALSE);

    flags = CMAP_RELOAD_ON_MODE_SWITCH;

    if(!xf86HandleColormaps(pScreen, 256,
	pVesa->vbeInfo->Capabilities[0] & 0x01 ? 8 : 6,
	VESALoadPalette, NULL, flags))
	return (FALSE);

1105 1106 1107 1108
    pVesa->accessEnabled = TRUE;
    pVesa->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
    pScrn->EnableDisableFBAccess = vesaEnableDisableFBAccess;

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
    pVesa->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = VESACloseScreen;
    pScreen->SaveScreen = VESASaveScreen;

    xf86DPMSInit(pScreen, VESADisplayPowerManagementSet, 0);

    /* Report any unused options (only for the first generation) */
    if (serverGeneration == 1)
        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);

    return (TRUE);
}

static Bool
Dave Airlie's avatar
Dave Airlie committed
1123
VESAEnterVT(VT_FUNC_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1124
{
Dave Airlie's avatar
Dave Airlie committed
1125
    SCRN_INFO_PTR(arg);
1126 1127 1128

    if (!VESASetMode(pScrn, pScrn->currentMode))
	return FALSE;
Dave Airlie's avatar
Dave Airlie committed
1129
    VESAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1130
    return TRUE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1131 1132 1133
}

static void
Dave Airlie's avatar
Dave Airlie committed
1134
VESALeaveVT(VT_FUNC_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1135
{
Dave Airlie's avatar
Dave Airlie committed
1136 1137
    SCRN_INFO_PTR(arg);
    VESASaveRestore(pScrn, MODE_RESTORE);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1138 1139 1140
}

static Bool
Dave Airlie's avatar
Dave Airlie committed
1141
VESACloseScreen(CLOSE_SCREEN_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1142
{
Dave Airlie's avatar
Dave Airlie committed
1143
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1144 1145 1146
    VESAPtr pVesa = VESAGetRec(pScrn);

    if (pScrn->vtSema) {
Dave Airlie's avatar
Dave Airlie committed
1147
	VESASaveRestore(pScrn, MODE_RESTORE);
1148 1149 1150
	if (pVesa->savedPal)
	    VBESetGetPaletteData(pVesa->pVbe, TRUE, 0, 256,
				 pVesa->savedPal, FALSE, TRUE);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1151 1152
	VESAUnmapVidMem(pScrn);
    }
1153 1154
    if (pVesa->shadowFB && pVesa->shadow) {
	shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
1155
	free(pVesa->shadow);
1156
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1157
    if (pVesa->pDGAMode) {
1158
	free(pVesa->pDGAMode);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1159 1160 1161 1162 1163
	pVesa->pDGAMode = NULL;
	pVesa->nDGAMode = 0;
    }
    pScrn->vtSema = FALSE;

1164
    pScrn->EnableDisableFBAccess = pVesa->EnableDisableFBAccess;
Adam Jackson's avatar
Adam Jackson committed
1165
    pScreen->CreateScreenResources = pVesa->CreateScreenResources;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1166
    pScreen->CloseScreen = pVesa->CloseScreen;
Dave Airlie's avatar
Dave Airlie committed
1167
    return pScreen->CloseScreen(CLOSE_SCREEN_ARGS);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1168 1169 1170
}

static Bool
Dave Airlie's avatar
Dave Airlie committed
1171
VESASwitchMode(SWITCH_MODE_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1172
{
Dave Airlie's avatar
Dave Airlie committed
1173
    SCRN_INFO_PTR(arg);
1174
    VESAPtr pVesa = VESAGetRec(pScrn);
1175
    Bool ret, disableAccess = pVesa->ModeSetClearScreen && pVesa->accessEnabled;
1176

1177
    if (disableAccess)
Dave Airlie's avatar
Dave Airlie committed
1178 1179
        pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),FALSE);
    ret = VESASetMode(pScrn, mode);
1180
    if (disableAccess)
Dave Airlie's avatar
Dave Airlie committed
1181
	pScrn->EnableDisableFBAccess(SCRN_OR_INDEX_ARG(pScrn),TRUE);
1182
    return ret;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
}

/* Set a graphics mode */
static Bool
VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
{
    VESAPtr pVesa;
    VbeModeInfoData *data;
    int mode;

    pVesa = VESAGetRec(pScrn);

    data = (VbeModeInfoData*)pMode->Private;
1196

1197 1198 1199 1200
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
	       "Setting up VESA Mode 0x%X (%dx%d)\n",
	       data->mode & 0x7FF, pMode->HDisplay, pMode->VDisplay);

1201 1202
    /* careful, setting the bit means don't clear the screen */
    mode = data->mode | (pVesa->ModeSetClearScreen ? 0 : (1U << 15));
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214

    /* enable linear addressing */
    if (pVesa->mapPhys != 0xa0000)
	mode |= 1 << 14;

    if (VBESetVBEMode(pVesa->pVbe, mode, data->block) == FALSE) {
	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBESetVBEMode failed");
	if ((data->block || (data->mode & (1 << 11))) &&
	    VBESetVBEMode(pVesa->pVbe, (mode & ~(1 << 11)), NULL) == TRUE) {
	    /* Some cards do not like setting the clock.
	     * Free it as it will not be any longer useful
	     */
1215
	    xf86ErrorF(", mode set without customized refresh.\n");
1216
	    free(data->block);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
	    data->block = NULL;
	    data->mode &= ~(1 << 11);
	}
	else {
	    ErrorF("\n");
	    return (FALSE);
	}
    }

    pVesa->bankSwitchWindowB =
	!((data->data->WinBSegment == 0) && (data->data->WinBAttributes == 0));

    if (data->data->XResolution != pScrn->displayWidth)
	VBESetLogicalScanline(pVesa->pVbe, pScrn->displayWidth);

1232
    if (pScrn->bitsPerPixel == 8 && pVesa->vbeInfo->Capabilities[0] & 0x01 &&
1233
        !(data->data->MemoryModel == 0x6 || data->data->MemoryModel == 0x7)) 
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1234 1235 1236 1237 1238 1239 1240 1241
	VBESetGetDACPaletteFormat(pVesa->pVbe, 8);

    pScrn->vtSema = TRUE;

    return (TRUE);
}

static void
Dave Airlie's avatar
Dave Airlie committed
1242
VESAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1243
{
Dave Airlie's avatar
Dave Airlie committed
1244 1245
    SCRN_INFO_PTR(arg);
    VESAPtr pVesa = VESAGetRec(pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1246 1247 1248 1249 1250

    VBESetDisplayStart(pVesa->pVbe, x, y, TRUE);
}

static void
Dave Airlie's avatar
Dave Airlie committed
1251
VESAFreeScreen(FREE_SCREEN_ARGS_DECL)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1252
{
Dave Airlie's avatar
Dave Airlie committed
1253 1254
    SCRN_INFO_PTR(arg);
    VESAFreeRec(pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
}

static Bool
VESAMapVidMem(ScrnInfoPtr pScrn)
{
    VESAPtr pVesa = VESAGetRec(pScrn);

    if (pVesa->base != NULL)
	return (TRUE);

    pScrn->memPhysBase = pVesa->mapPhys;
    pScrn->fbOffset = pVesa->mapOff;

1268
#ifdef XSERVER_LIBPCIACCESS
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
    if (pVesa->pciInfo != NULL) {
	if (pVesa->mapPhys != 0xa0000) {
	    (void) pci_device_map_range(pVesa->pciInfo, pScrn->memPhysBase,
	                                pVesa->mapSize,
				        (PCI_DEV_MAP_FLAG_WRITABLE
				         | PCI_DEV_MAP_FLAG_WRITE_COMBINE),
				        & pVesa->base);

	    if (pVesa->base)
		(void) pci_device_map_legacy(pVesa->pciInfo, 0xa0000, 0x10000,
		                             PCI_DEV_MAP_FLAG_WRITABLE,
		                             & pVesa->VGAbase);
	}
	else {
	    (void) pci_device_map_legacy(pVesa->pciInfo, pScrn->memPhysBase,
	                                 pVesa->mapSize,
1285
	                                 PCI_DEV_MAP_FLAG_WRITABLE,
1286
	                                 & pVesa->base);
1287

1288 1289 1290
	    if (pVesa->base)
		pVesa->VGAbase = pVesa->base;
	}
1291 1292
    }
#else
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
    if (pVesa->mapPhys != 0xa0000 && pVesa->pEnt->location.type == BUS_PCI)
	pVesa->base = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
				    pVesa->pciTag, pScrn->memPhysBase,
				    pVesa->mapSize);
    else
	pVesa->base = xf86MapDomainMemory(pScrn->scrnIndex, 0, pVesa->pciTag,
					  pScrn->memPhysBase, pVesa->mapSize);

    if (pVesa->base) {
	if (pVesa->mapPhys != 0xa0000)
	    pVesa->VGAbase = xf86MapDomainMemory(pScrn->scrnIndex, 0,
						 pVesa->pciTag,
						 0xa0000, 0x10000);
	else
	    pVesa->VGAbase = pVesa->base;
    }
1309
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1310

1311
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1312
    pVesa->ioBase = pScrn->domainIOBase;
1313 1314 1315
#else
    pVesa->ioBase = 0;
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1316 1317

    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, DEBUG_VERB,
1318
		   "virtual address = %p, VGAbase = %p\n"
1319
		   "\tphysical address = 0x%lx, size = %ld\n",
1320 1321
		   pVesa->base, pVesa->VGAbase,
		   pScrn->memPhysBase, pVesa->mapSize);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1322 1323 1324 1325 1326 1327