diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-03-25 19:17:00 +0100 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-03-29 09:04:18 +0200 |
commit | cdb04224db69a6b3beb66c99879e20917b8b0fb2 (patch) | |
tree | 22364a65c785ace7fdc7236ad86250c0117e0d17 | |
parent | 9a8f0af8782fd5e9de2d71dfa86fad1d48d52b64 (diff) |
vmwlegacy: Fix segfault and setup of initial mode.
The fact that modes were added without names caused segfaults on older
X servers. At least up to and including Xserver 1.4.
Also, for some reason, at least Xserver 1.4 insists on setting the first mode
in the modelist, even if we set another mode as the current one.
Work around this by inserting a new mode with the current screen dimensions,
and add that modename last to the array of display requested mode names.
This means that if none of the previous mode names are found, we will at least
find the newly inserted mode.
Also, if there are no requested mode names at all, the driver previously
chose the largest mode that fit the timings. Now we will, in that case,
always select the newly inserted mode and thus not change resolution unless
specified.
Also add an option to not add this default mode. The option
"AddDefaultMode" is true by default.
Finally when we restore registers at exit and VT switch, make sure we
reprogram the initial width, height and bpp for the next time we start a
server.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r-- | src/vmware.c | 77 | ||||
-rw-r--r-- | src/vmware.h | 2 | ||||
-rw-r--r-- | src/vmwaremodes.c | 76 |
3 files changed, 82 insertions, 73 deletions
diff --git a/src/vmware.c b/src/vmware.c index 795ad08..e04835f 100644 --- a/src/vmware.c +++ b/src/vmware.c @@ -217,13 +217,15 @@ static XF86ModuleVersionInfo vmwlegacyVersRec = { typedef enum { OPTION_HW_CURSOR, OPTION_XINERAMA, - OPTION_STATIC_XINERAMA + OPTION_STATIC_XINERAMA, + OPTION_DEFAULT_MODE, } VMWAREOpts; static const OptionInfoRec VMWAREOptions[] = { { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, + { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -608,6 +610,7 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) ClockRange* clockRanges; IOADDRESS domainIOBase = 0; uint32 width = 0, height = 0; + Bool defaultMode; #ifndef BUILD_FOR_420 domainIOBase = pScrn->domainIOBase; @@ -923,6 +926,17 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam = pVMWARE->videoRam / 1024; pScrn->memPhysBase = pVMWARE->memPhysBase; + from = X_DEFAULT; + defaultMode = TRUE; + if (xf86GetOptValBool(options, OPTION_DEFAULT_MODE, &defaultMode)) { + from = X_CONFIG; + } + width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); + height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); + xf86DrvMsg(pScrn->scrnIndex, from, + "Will %sset up a driver mode with dimensions %dx%d.\n", + defaultMode ? "" : "not ", width, height); + free(options); { @@ -950,24 +964,10 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) clockRanges->doubleScanAllowed = FALSE; clockRanges->ClockMulFactor = 1; clockRanges->ClockDivFactor = 1; - - /* Read the configured registers for an initial mode. - * This gives the benefit that at initial bootup, we're most likely - * to have an 800x600 mode and thus we have a reasonable default at - * power on. Subsequent logouts will use the pre-configured mode from - * last session which is a more natural thing. - * - * But, only if we haven't any modes specified in the config file. - */ - if (pScrn->display && pScrn->display->modes) { - width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); - height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); - } - /* - * Get the default supported modelines - */ - vmwareGetSupportedModelines(pScrn, width, height); + if (defaultMode) { + vmwareAddDefaultMode(pScrn, width, height); + } i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, NULL, 256, pVMWARE->maxWidth, 32 * 32, @@ -986,38 +986,12 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) VMWAREFreeRec(pScrn); return FALSE; } - xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); - /* Walk the mode list and choose one that matches our registers */ - { - DisplayModePtr modes = pScrn->modes; - while (modes) { - if (modes->type != M_T_USERDEF) { - /* The first mode isn't our specified one, so fallback - * to a sane default so we don't get a large virtual - * screen that may be scaled to a very small initial - * login screen. - * We read the current SVGA registers, so we'll either - * end up with a default 800x600 at bootup, or the last - * virtual autofitted resolution from the previous session. - */ - width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); - height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); - } + pScrn->currentMode = pScrn->modes; + pScrn->virtualX = pScrn->modes->HDisplay; + pScrn->virtualY = pScrn->modes->VDisplay; - if (modes->HDisplay == width && modes->VDisplay == height) - break; - - modes = modes->next; - - if (modes == pScrn->modes) - break; - } - - pScrn->currentMode = modes; - pScrn->virtualX = modes->HDisplay; - pScrn->virtualY = modes->VDisplay; - } + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); xf86PrintModes(pScrn); xf86SetDpi(pScrn, 0, 0); @@ -1153,7 +1127,12 @@ VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg) vmwareReg->svga_reg_cursor_on); } } else { - vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); + vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); + vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); + vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, + vmwareReg->svga_reg_bits_per_pixel); + vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); } } diff --git a/src/vmware.h b/src/vmware.h index 3253a64..cf32462 100644 --- a/src/vmware.h +++ b/src/vmware.h @@ -313,7 +313,7 @@ void vmwareCheckVideoSanity( ); /* vmwaremode.c */ -void vmwareGetSupportedModelines( +void vmwareAddDefaultMode( ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight diff --git a/src/vmwaremodes.c b/src/vmwaremodes.c index ceeedf6..d82eba6 100644 --- a/src/vmwaremodes.c +++ b/src/vmwaremodes.c @@ -28,11 +28,7 @@ /* * vmwaremodes.c -- * - * Provide the supported modelines for the driver. - * - * VMware does not have virtual monitor and there is no EDID to - * automatically report the supported mode. The list of - * supported modelines are manually added in the driver. + * Provide additional modes for the driver. */ #ifdef HAVE_CONFIG_H @@ -51,9 +47,13 @@ #define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER #define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 +#define VMW_DEFLT_MODE_NAME "vmwlegacy-default-%dx%d" + /* * Most of the modelines copied from DMTModes table of xf86EdidModes.c. * For those modes not in DMTModes table are generated by gtf + * These modes are not used currently, and not really necessary. + * Consider removing them in a future release. */ static DisplayModeRec VMwareModes[] = { /* 4:3 modes */ @@ -96,12 +96,12 @@ static DisplayModeRec VMwareModes[] = { /* *----------------------------------------------------------------------------- * - * vmwareGetSupportedModelines -- + * vmwareAddDefaultMode -- * - * Get the supported modelines. + * Add a default mode with the current screen dimensions. * * Results: - * The supported modelines. + * The default mode. * * Side effects: * None. @@ -110,30 +110,57 @@ static DisplayModeRec VMwareModes[] = { */ void -vmwareGetSupportedModelines(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight) +vmwareAddDefaultMode(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight) { MonPtr monitor = pScrn->monitor; DisplayModePtr *monitorModes = &pScrn->monitor->Modes; - DisplayModePtr modes = NULL, mode = NULL; - DisplayModeRec dynamic = - { MODEPREFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX }; - int i = 0; + DisplayModePtr modes = NULL; if (monitorModes == NULL || *monitorModes == NULL) { - return; + goto out_err; } #ifdef HAVE_XORG_SERVER_1_2_0 - for (i = 0; i < sizeof(VMwareModes)/sizeof(DisplayModeRec); i++) { - mode = xf86DuplicateMode(&(VMwareModes[i])); - modes = xf86ModesAdd(modes, mode); - } - - /* - * Let's add a mode of current SVGA register values and so we can - * match against this for subsequent login. - */ if (dwidth && dheight) { + DisplayModePtr mode = NULL; + DisplayModeRec dynamic = + { MODEPREFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX }; + int i = 0; + unsigned dispModeCount = 0; + char **dispModeList; + char *dynModeName; + char name[80]; + + /* First, add the default mode name to the display mode + * requests. + */ + + snprintf(name, sizeof(name), VMW_DEFLT_MODE_NAME, dwidth, dheight); + + dynModeName = xnfstrdup(name); + if (!dynModeName || !pScrn->display) + goto out_err; + + if (pScrn->display->modes) { + dispModeList = pScrn->display->modes; + while(*dispModeList) + dispModeList++; + } + + dispModeCount = dispModeList - pScrn->display->modes; + dispModeList = xnfcalloc(dispModeCount + 2, sizeof(*dispModeList)); + if (!dispModeList) + goto out_err; + + memcpy(dispModeList, pScrn->display->modes, + dispModeCount * sizeof(*dispModeList)); + dispModeList[dispModeCount] = dynModeName; + pScrn->display->modes = dispModeList; + + /* Then, add the default mode itself. + */ + + dynamic.name = name; dynamic.HDisplay = dwidth; dynamic.HSyncStart = dynamic.HDisplay + 1; dynamic.HSyncEnd = dynamic.HSyncStart + 1; @@ -157,4 +184,7 @@ vmwareGetSupportedModelines(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight) *monitorModes = xf86ModesAdd(*monitorModes, modes); #endif + return; + out_err: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to add default mode."); } |