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 /src/vmware.c | |
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>
Diffstat (limited to 'src/vmware.c')
-rw-r--r-- | src/vmware.c | 77 |
1 files changed, 28 insertions, 49 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); } } |