16df26cacSmrg/*
26df26cacSmrg * Copyright 2006 by VMware, Inc.
36df26cacSmrg *
46df26cacSmrg * Permission is hereby granted, free of charge, to any person obtaining a
56df26cacSmrg * copy of this software and associated documentation files (the "Software"),
66df26cacSmrg * to deal in the Software without restriction, including without limitation
76df26cacSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86df26cacSmrg * and/or sell copies of the Software, and to permit persons to whom the
96df26cacSmrg * Software is furnished to do so, subject to the following conditions:
106df26cacSmrg *
116df26cacSmrg * The above copyright notice and this permission notice shall be included in
126df26cacSmrg * all copies or substantial portions of the Software.
136df26cacSmrg *
146df26cacSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156df26cacSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166df26cacSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
176df26cacSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
186df26cacSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
196df26cacSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
206df26cacSmrg * OTHER DEALINGS IN THE SOFTWARE.
216df26cacSmrg *
226df26cacSmrg * Except as contained in this notice, the name of the copyright holder(s)
236df26cacSmrg * and author(s) shall not be used in advertising or otherwise to promote
246df26cacSmrg * the sale, use or other dealings in this Software without prior written
256df26cacSmrg * authorization from the copyright holder(s) and author(s).
266df26cacSmrg */
276df26cacSmrg
286df26cacSmrg/*
296df26cacSmrg * vmwarectrl.c --
306df26cacSmrg *
316df26cacSmrg *      The implementation of the VMWARE_CTRL protocol extension that
326df26cacSmrg *      allows X clients to communicate with the driver.
336df26cacSmrg */
346df26cacSmrg
356df26cacSmrg
366df26cacSmrg#ifdef HAVE_CONFIG_H
376df26cacSmrg#include "config.h"
386df26cacSmrg#endif
396df26cacSmrg
406df26cacSmrg#include "dixstruct.h"
416df26cacSmrg#include "extnsionst.h"
423bfa90b6Smrg#include "randrstr.h"
436df26cacSmrg#include <X11/X.h>
446df26cacSmrg#include <X11/extensions/panoramiXproto.h>
456df26cacSmrg
466df26cacSmrg#include "vmware.h"
476df26cacSmrg#include "vmwarectrlproto.h"
486df26cacSmrg
49a241306cSmrg#ifndef HAVE_XORG_SERVER_1_5_0
50a241306cSmrg#include <xf86_ansic.h>
51a241306cSmrg#include <xf86_libc.h>
52a241306cSmrg#endif
536df26cacSmrg
546df26cacSmrg/*
556df26cacSmrg *----------------------------------------------------------------------------
566df26cacSmrg *
576df26cacSmrg * VMwareCtrlQueryVersion --
586df26cacSmrg *
596df26cacSmrg *      Implementation of QueryVersion command handler. Initialises and
606df26cacSmrg *      sends a reply.
616df26cacSmrg *
626df26cacSmrg * Results:
636df26cacSmrg *      Standard response codes.
646df26cacSmrg *
656df26cacSmrg * Side effects:
666df26cacSmrg *      Writes reply to client
676df26cacSmrg *
686df26cacSmrg *----------------------------------------------------------------------------
696df26cacSmrg */
706df26cacSmrg
716df26cacSmrgstatic int
726df26cacSmrgVMwareCtrlQueryVersion(ClientPtr client)
736df26cacSmrg{
746df26cacSmrg   xVMwareCtrlQueryVersionReply rep = { 0, };
756df26cacSmrg   register int n;
766df26cacSmrg
776df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
786df26cacSmrg
796df26cacSmrg   rep.type = X_Reply;
806df26cacSmrg   rep.length = 0;
816df26cacSmrg   rep.sequenceNumber = client->sequence;
826df26cacSmrg   rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
836df26cacSmrg   rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
846df26cacSmrg   if (client->swapped) {
853bfa90b6Smrg      _swaps(&rep.sequenceNumber, n);
863bfa90b6Smrg      _swapl(&rep.length, n);
873bfa90b6Smrg      _swapl(&rep.majorVersion, n);
883bfa90b6Smrg      _swapl(&rep.minorVersion, n);
896df26cacSmrg   }
906df26cacSmrg   WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
916df26cacSmrg
926df26cacSmrg   return client->noClientException;
936df26cacSmrg}
946df26cacSmrg
956df26cacSmrg
966df26cacSmrg/*
976df26cacSmrg *----------------------------------------------------------------------------
986df26cacSmrg *
996df26cacSmrg * VMwareCtrlDoSetRes --
1006df26cacSmrg *
1016df26cacSmrg *      Set the custom resolution into the mode list.
1026df26cacSmrg *
1036df26cacSmrg *      This is done by alternately updating one of two dynamic modes. It is
1046df26cacSmrg *      done this way because the server gets upset if you try to switch
1056df26cacSmrg *      to a new resolution that has the same index as the current one.
1066df26cacSmrg *
1076df26cacSmrg * Results:
1086df26cacSmrg *      TRUE on success, FALSE otherwise.
1096df26cacSmrg *
1106df26cacSmrg * Side effects:
1116df26cacSmrg *      One dynamic mode will be updated if successful.
1126df26cacSmrg *
1136df26cacSmrg *----------------------------------------------------------------------------
1146df26cacSmrg */
1156df26cacSmrg
1166df26cacSmrgstatic Bool
1176df26cacSmrgVMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
1186df26cacSmrg                   CARD32 x,
1196df26cacSmrg                   CARD32 y,
1206df26cacSmrg                   Bool resetXinerama)
1216df26cacSmrg{
12216fd1166Smrg   int modeIndex;
1236df26cacSmrg   DisplayModePtr mode;
1246df26cacSmrg   VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1256df26cacSmrg
1266df26cacSmrg   if (pScrn && pScrn->modes) {
1276df26cacSmrg      VmwareLog(("DoSetRes: %d %d\n", x, y));
12816fd1166Smrg
1296df26cacSmrg      if (resetXinerama) {
130a241306cSmrg         free(pVMWARE->xineramaNextState);
1316df26cacSmrg         pVMWARE->xineramaNextState = NULL;
1326df26cacSmrg         pVMWARE->xineramaNextNumOutputs = 0;
1336df26cacSmrg      }
1346df26cacSmrg
13516fd1166Smrg      /*
1366df26cacSmrg       * Don't resize larger than possible but don't
1376df26cacSmrg       * return an X Error either.
1386df26cacSmrg       */
1396df26cacSmrg      if (x > pVMWARE->maxWidth ||
1406df26cacSmrg          y > pVMWARE->maxHeight) {
1416df26cacSmrg         return TRUE;
1426df26cacSmrg      }
1436df26cacSmrg
1446df26cacSmrg      /*
14516fd1166Smrg       * Find an dynamic mode which isn't current, and replace it with
14616fd1166Smrg       * the requested mode. Normally this will cause us to alternate
14716fd1166Smrg       * between two dynamic mode slots, but there are some important
14816fd1166Smrg       * corner cases to consider. For example, adding the same mode
14916fd1166Smrg       * multiple times, adding a mode that we never switch to, or
15016fd1166Smrg       * adding a mode which is a duplicate of a built-in mode. The
15116fd1166Smrg       * best way to handle all of these cases is to directly test the
15216fd1166Smrg       * dynamic mode against the current mode pointer for this
15316fd1166Smrg       * screen.
1546df26cacSmrg       */
1556df26cacSmrg
15616fd1166Smrg      for (modeIndex = 0; modeIndex < NUM_DYN_MODES; modeIndex++) {
15716fd1166Smrg         /*
15816fd1166Smrg          * Initialise the dynamic mode if it hasn't been used before.
15916fd1166Smrg          */
16016fd1166Smrg         if (!pVMWARE->dynModes[modeIndex]) {
16116fd1166Smrg            pVMWARE->dynModes[modeIndex] = VMWAREAddDisplayMode(pScrn, "DynMode", 1, 1);
16216fd1166Smrg         }
16316fd1166Smrg
16416fd1166Smrg         mode = pVMWARE->dynModes[modeIndex];
16516fd1166Smrg         if (mode != pScrn->currentMode) {
16616fd1166Smrg            break;
16716fd1166Smrg         }
1686df26cacSmrg      }
1696df26cacSmrg
1706df26cacSmrg      mode->HDisplay = x;
1716df26cacSmrg      mode->VDisplay = y;
1726df26cacSmrg
1736df26cacSmrg      return TRUE;
1746df26cacSmrg   } else {
1756df26cacSmrg      return FALSE;
1766df26cacSmrg   }
1776df26cacSmrg}
1786df26cacSmrg
1796df26cacSmrg
1806df26cacSmrg/*
1816df26cacSmrg *----------------------------------------------------------------------------
1826df26cacSmrg *
1836df26cacSmrg * VMwareCtrlSetRes --
1846df26cacSmrg *
1856df26cacSmrg *      Implementation of SetRes command handler. Initialises and sends a
1866df26cacSmrg *      reply.
1876df26cacSmrg *
1886df26cacSmrg * Results:
1896df26cacSmrg *      Standard response codes.
1906df26cacSmrg *
1916df26cacSmrg * Side effects:
1926df26cacSmrg *      Writes reply to client
1936df26cacSmrg *
1946df26cacSmrg *----------------------------------------------------------------------------
1956df26cacSmrg */
1966df26cacSmrg
1976df26cacSmrgstatic int
1986df26cacSmrgVMwareCtrlSetRes(ClientPtr client)
1996df26cacSmrg{
2006df26cacSmrg   REQUEST(xVMwareCtrlSetResReq);
2016df26cacSmrg   xVMwareCtrlSetResReply rep = { 0, };
2026df26cacSmrg   ScrnInfoPtr pScrn;
2036df26cacSmrg   ExtensionEntry *ext;
2046df26cacSmrg   register int n;
2056df26cacSmrg
2066df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
2076df26cacSmrg
2086df26cacSmrg   if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
2096df26cacSmrg      return BadMatch;
2106df26cacSmrg   }
2116df26cacSmrg
2126df26cacSmrg   pScrn = ext->extPrivate;
2136df26cacSmrg   if (pScrn->scrnIndex != stuff->screen) {
2146df26cacSmrg      return BadMatch;
2156df26cacSmrg   }
2166df26cacSmrg
2176df26cacSmrg   if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y, TRUE)) {
2186df26cacSmrg      return BadValue;
2196df26cacSmrg   }
2206df26cacSmrg
2216df26cacSmrg   rep.type = X_Reply;
2226df26cacSmrg   rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2;
2236df26cacSmrg   rep.sequenceNumber = client->sequence;
2246df26cacSmrg   rep.screen = stuff->screen;
2256df26cacSmrg   rep.x = stuff->x;
2266df26cacSmrg   rep.y = stuff->y;
2276df26cacSmrg   if (client->swapped) {
2283bfa90b6Smrg      _swaps(&rep.sequenceNumber, n);
2293bfa90b6Smrg      _swapl(&rep.length, n);
2303bfa90b6Smrg      _swapl(&rep.screen, n);
2313bfa90b6Smrg      _swapl(&rep.x, n);
2323bfa90b6Smrg      _swapl(&rep.y, n);
2336df26cacSmrg   }
2346df26cacSmrg   WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep);
2356df26cacSmrg
2366df26cacSmrg   return client->noClientException;
2376df26cacSmrg}
2386df26cacSmrg
2396df26cacSmrg
2406df26cacSmrg/*
2416df26cacSmrg *----------------------------------------------------------------------------
2426df26cacSmrg *
2436df26cacSmrg * VMwareCtrlDoSetTopology --
2446df26cacSmrg *
2456df26cacSmrg *      Set the custom topology and set a dynamic mode to the bounding box
2466df26cacSmrg *      of the passed topology. If a topology is already pending, then do
2476df26cacSmrg *      nothing but do not return failure.
2486df26cacSmrg *
2496df26cacSmrg * Results:
2506df26cacSmrg *      TRUE on success, FALSE otherwise.
2516df26cacSmrg *
2526df26cacSmrg * Side effects:
2536df26cacSmrg *      One dynamic mode and the pending xinerama state will be updated if
2546df26cacSmrg *      successful.
2556df26cacSmrg *
2566df26cacSmrg *----------------------------------------------------------------------------
2576df26cacSmrg */
2586df26cacSmrg
2596df26cacSmrgstatic Bool
2606df26cacSmrgVMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
2616df26cacSmrg                        xXineramaScreenInfo *extents,
2626df26cacSmrg                        unsigned long number)
2636df26cacSmrg{
2646df26cacSmrg   VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
2656df26cacSmrg
2666df26cacSmrg   if (pVMWARE && pVMWARE->xinerama) {
2676df26cacSmrg      VMWAREXineramaPtr xineramaState;
2686df26cacSmrg      short maxX = 0;
2696df26cacSmrg      short maxY = 0;
2706df26cacSmrg      size_t i;
2716df26cacSmrg
2726df26cacSmrg      if (pVMWARE->xineramaNextState) {
2736df26cacSmrg         VmwareLog(("DoSetTopology: Aborting due to existing pending state\n"));
2746df26cacSmrg         return TRUE;
2756df26cacSmrg      }
2766df26cacSmrg
2776df26cacSmrg      for (i = 0; i < number; i++) {
2786df26cacSmrg         maxX = MAX(maxX, extents[i].x_org + extents[i].width);
2796df26cacSmrg         maxY = MAX(maxY, extents[i].y_org + extents[i].height);
2806df26cacSmrg      }
2816df26cacSmrg
2826df26cacSmrg      VmwareLog(("DoSetTopology: %d %d\n", maxX, maxY));
2836df26cacSmrg
284a241306cSmrg      xineramaState = (VMWAREXineramaPtr)calloc(number, sizeof(VMWAREXineramaRec));
2856df26cacSmrg      if (xineramaState) {
2866df26cacSmrg         memcpy(xineramaState, extents, number * sizeof (VMWAREXineramaRec));
2876df26cacSmrg
2882e8abef9Smrg         /*
2892e8abef9Smrg          * Make this the new pending Xinerama state. Normally we'll
2902e8abef9Smrg          * wait until the next mode switch in order to synchronously
2912e8abef9Smrg          * push this state out to X clients and the virtual hardware.
2922e8abef9Smrg          *
2932e8abef9Smrg          * However, if we're already in the right video mode, there
2942e8abef9Smrg          * will be no mode change. In this case, push it out
2952e8abef9Smrg          * immediately.
2962e8abef9Smrg          */
297a241306cSmrg         free(pVMWARE->xineramaNextState);
2986df26cacSmrg         pVMWARE->xineramaNextState = xineramaState;
2996df26cacSmrg         pVMWARE->xineramaNextNumOutputs = number;
3006df26cacSmrg
3012e8abef9Smrg         if (maxX == pVMWARE->ModeReg.svga_reg_width &&
3022e8abef9Smrg             maxY == pVMWARE->ModeReg.svga_reg_height) {
3032e8abef9Smrg
3043bfa90b6Smrg	    /*
3053bfa90b6Smrg	     * The annoyance here is that when we reprogram the
3063bfa90b6Smrg	     * SVGA device's monitor topology registers, it may
3073bfa90b6Smrg	     * rearrange those monitors on the host's screen, but they
3083bfa90b6Smrg	     * will still have the old contents. This might be
3093bfa90b6Smrg	     * correct, but it isn't guaranteed to match what's on X's
3103bfa90b6Smrg	     * framebuffer at the moment. So we'll send a
3113bfa90b6Smrg	     * full-framebuffer update rect afterwards.
3123bfa90b6Smrg	     */
3132e8abef9Smrg
3142e8abef9Smrg            vmwareNextXineramaState(pVMWARE);
3153bfa90b6Smrg#ifdef HAVE_XORG_SERVER_1_2_0
3163bfa90b6Smrg            RRSendConfigNotify(pScrn->pScreen);
3173bfa90b6Smrg#endif
3182e8abef9Smrg            vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
3192e8abef9Smrg
3202e8abef9Smrg            return TRUE;
3212e8abef9Smrg         } else {
3222e8abef9Smrg            return VMwareCtrlDoSetRes(pScrn, maxX, maxY, FALSE);
3232e8abef9Smrg         }
3242e8abef9Smrg
3256df26cacSmrg      } else {
3266df26cacSmrg         return FALSE;
3276df26cacSmrg      }
3286df26cacSmrg   } else {
3296df26cacSmrg      return FALSE;
3306df26cacSmrg   }
3316df26cacSmrg}
3326df26cacSmrg
3336df26cacSmrg
3346df26cacSmrg/*
3356df26cacSmrg *----------------------------------------------------------------------------
3366df26cacSmrg *
3376df26cacSmrg * VMwareCtrlSetTopology --
3386df26cacSmrg *
3396df26cacSmrg *      Implementation of SetTopology command handler. Initialises and sends a
3406df26cacSmrg *      reply.
3416df26cacSmrg *
3426df26cacSmrg * Results:
3436df26cacSmrg *      Standard response codes.
3446df26cacSmrg *
3456df26cacSmrg * Side effects:
3466df26cacSmrg *      Writes reply to client
3476df26cacSmrg *
3486df26cacSmrg *----------------------------------------------------------------------------
3496df26cacSmrg */
3506df26cacSmrg
3516df26cacSmrgstatic int
3526df26cacSmrgVMwareCtrlSetTopology(ClientPtr client)
3536df26cacSmrg{
3546df26cacSmrg   REQUEST(xVMwareCtrlSetTopologyReq);
3556df26cacSmrg   xVMwareCtrlSetTopologyReply rep = { 0, };
3566df26cacSmrg   ScrnInfoPtr pScrn;
3576df26cacSmrg   ExtensionEntry *ext;
3586df26cacSmrg   register int n;
3596df26cacSmrg   xXineramaScreenInfo *extents;
3606df26cacSmrg
3616df26cacSmrg   REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq);
3626df26cacSmrg
3636df26cacSmrg   if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
3646df26cacSmrg      return BadMatch;
3656df26cacSmrg   }
3666df26cacSmrg
3676df26cacSmrg   pScrn = ext->extPrivate;
3686df26cacSmrg   if (pScrn->scrnIndex != stuff->screen) {
3696df26cacSmrg      return BadMatch;
3706df26cacSmrg   }
3716df26cacSmrg
3726df26cacSmrg   extents = (xXineramaScreenInfo *)(stuff + 1);
3736df26cacSmrg   if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) {
3746df26cacSmrg      return BadValue;
3756df26cacSmrg   }
3766df26cacSmrg
3776df26cacSmrg   rep.type = X_Reply;
3786df26cacSmrg   rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2;
3796df26cacSmrg   rep.sequenceNumber = client->sequence;
3806df26cacSmrg   rep.screen = stuff->screen;
3816df26cacSmrg   if (client->swapped) {
3823bfa90b6Smrg      _swaps(&rep.sequenceNumber, n);
3833bfa90b6Smrg      _swapl(&rep.length, n);
3843bfa90b6Smrg      _swapl(&rep.screen, n);
3856df26cacSmrg   }
3866df26cacSmrg   WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep);
3876df26cacSmrg
3886df26cacSmrg   return client->noClientException;
3896df26cacSmrg}
3906df26cacSmrg
3916df26cacSmrg
3926df26cacSmrg/*
3936df26cacSmrg *----------------------------------------------------------------------------
3946df26cacSmrg *
3956df26cacSmrg * VMwareCtrlDispatch --
3966df26cacSmrg *
3976df26cacSmrg *      Dispatcher for VMWARE_CTRL commands. Calls the correct handler for
3986df26cacSmrg *      each command type.
3996df26cacSmrg *
4006df26cacSmrg * Results:
4016df26cacSmrg *      Standard response codes.
4026df26cacSmrg *
4036df26cacSmrg * Side effects:
4046df26cacSmrg *      Side effects of individual command handlers.
4056df26cacSmrg *
4066df26cacSmrg *----------------------------------------------------------------------------
4076df26cacSmrg */
4086df26cacSmrg
4096df26cacSmrgstatic int
4106df26cacSmrgVMwareCtrlDispatch(ClientPtr client)
4116df26cacSmrg{
4126df26cacSmrg   REQUEST(xReq);
4136df26cacSmrg
4146df26cacSmrg   switch(stuff->data) {
4156df26cacSmrg   case X_VMwareCtrlQueryVersion:
4166df26cacSmrg      return VMwareCtrlQueryVersion(client);
4176df26cacSmrg   case X_VMwareCtrlSetRes:
4186df26cacSmrg      return VMwareCtrlSetRes(client);
4196df26cacSmrg   case X_VMwareCtrlSetTopology:
4206df26cacSmrg      return VMwareCtrlSetTopology(client);
4216df26cacSmrg   }
4226df26cacSmrg   return BadRequest;
4236df26cacSmrg}
4246df26cacSmrg
4256df26cacSmrg
4266df26cacSmrg/*
4276df26cacSmrg *----------------------------------------------------------------------------
4286df26cacSmrg *
4296df26cacSmrg * SVMwareCtrlQueryVersion --
4306df26cacSmrg *
4316df26cacSmrg *      Wrapper for QueryVersion handler that handles input from other-endian
4326df26cacSmrg *      clients.
4336df26cacSmrg *
4346df26cacSmrg * Results:
4356df26cacSmrg *      Standard response codes.
4366df26cacSmrg *
4376df26cacSmrg * Side effects:
4386df26cacSmrg *      Side effects of unswapped implementation.
4396df26cacSmrg *
4406df26cacSmrg *----------------------------------------------------------------------------
4416df26cacSmrg */
4426df26cacSmrg
4436df26cacSmrgstatic int
4446df26cacSmrgSVMwareCtrlQueryVersion(ClientPtr client)
4456df26cacSmrg{
4466df26cacSmrg   register int n;
4476df26cacSmrg
4486df26cacSmrg   REQUEST(xVMwareCtrlQueryVersionReq);
4496df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
4506df26cacSmrg
4513bfa90b6Smrg   _swaps(&stuff->length, n);
4526df26cacSmrg
4536df26cacSmrg   return VMwareCtrlQueryVersion(client);
4546df26cacSmrg}
4556df26cacSmrg
4566df26cacSmrg
4576df26cacSmrg/*
4586df26cacSmrg *----------------------------------------------------------------------------
4596df26cacSmrg *
4606df26cacSmrg * SVMwareCtrlSetRes --
4616df26cacSmrg *
4626df26cacSmrg *      Wrapper for SetRes handler that handles input from other-endian
4636df26cacSmrg *      clients.
4646df26cacSmrg *
4656df26cacSmrg * Results:
4666df26cacSmrg *      Standard response codes.
4676df26cacSmrg *
4686df26cacSmrg * Side effects:
4696df26cacSmrg *      Side effects of unswapped implementation.
4706df26cacSmrg *
4716df26cacSmrg *----------------------------------------------------------------------------
4726df26cacSmrg */
4736df26cacSmrg
4746df26cacSmrgstatic int
4756df26cacSmrgSVMwareCtrlSetRes(ClientPtr client)
4766df26cacSmrg{
4776df26cacSmrg   register int n;
4786df26cacSmrg
4796df26cacSmrg   REQUEST(xVMwareCtrlSetResReq);
4806df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
4816df26cacSmrg
4823bfa90b6Smrg   _swaps(&stuff->length, n);
4833bfa90b6Smrg   _swapl(&stuff->screen, n);
4843bfa90b6Smrg   _swapl(&stuff->x, n);
4853bfa90b6Smrg   _swapl(&stuff->y, n);
4866df26cacSmrg
4876df26cacSmrg   return VMwareCtrlSetRes(client);
4886df26cacSmrg}
4896df26cacSmrg
4906df26cacSmrg
4916df26cacSmrg/*
4926df26cacSmrg *----------------------------------------------------------------------------
4936df26cacSmrg *
4946df26cacSmrg * SVMwareCtrlSetTopology --
4956df26cacSmrg *
4966df26cacSmrg *      Wrapper for SetTopology handler that handles input from other-endian
4976df26cacSmrg *      clients.
4986df26cacSmrg *
4996df26cacSmrg * Results:
5006df26cacSmrg *      Standard response codes.
5016df26cacSmrg *
5026df26cacSmrg * Side effects:
5036df26cacSmrg *      Side effects of unswapped implementation.
5046df26cacSmrg *
5056df26cacSmrg *----------------------------------------------------------------------------
5066df26cacSmrg */
5076df26cacSmrg
5086df26cacSmrgstatic int
5096df26cacSmrgSVMwareCtrlSetTopology(ClientPtr client)
5106df26cacSmrg{
5116df26cacSmrg   register int n;
5126df26cacSmrg
5136df26cacSmrg   REQUEST(xVMwareCtrlSetTopologyReq);
5146df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq);
5156df26cacSmrg
5163bfa90b6Smrg   _swaps(&stuff->length, n);
5173bfa90b6Smrg   _swapl(&stuff->screen, n);
5183bfa90b6Smrg   _swapl(&stuff->number, n);
5196df26cacSmrg   /* Each extent is a struct of shorts. */
5206df26cacSmrg   SwapRestS(stuff);
5216df26cacSmrg
5226df26cacSmrg   return VMwareCtrlSetTopology(client);
5236df26cacSmrg}
5246df26cacSmrg
5256df26cacSmrg
5266df26cacSmrg/*
5276df26cacSmrg *----------------------------------------------------------------------------
5286df26cacSmrg *
5296df26cacSmrg * SVMwareCtrlDispatch --
5306df26cacSmrg *
5316df26cacSmrg *      Wrapper for dispatcher that handles input from other-endian clients.
5326df26cacSmrg *
5336df26cacSmrg * Results:
5346df26cacSmrg *      Standard response codes.
5356df26cacSmrg *
5366df26cacSmrg * Side effects:
5376df26cacSmrg *      Side effects of individual command handlers.
5386df26cacSmrg *
5396df26cacSmrg *----------------------------------------------------------------------------
5406df26cacSmrg */
5416df26cacSmrg
5426df26cacSmrgstatic int
5436df26cacSmrgSVMwareCtrlDispatch(ClientPtr client)
5446df26cacSmrg{
5456df26cacSmrg   REQUEST(xReq);
5466df26cacSmrg
5476df26cacSmrg   switch(stuff->data) {
5486df26cacSmrg   case X_VMwareCtrlQueryVersion:
5496df26cacSmrg      return SVMwareCtrlQueryVersion(client);
5506df26cacSmrg   case X_VMwareCtrlSetRes:
5516df26cacSmrg      return SVMwareCtrlSetRes(client);
5526df26cacSmrg   case X_VMwareCtrlSetTopology:
5536df26cacSmrg      return SVMwareCtrlSetTopology(client);
5546df26cacSmrg   }
5556df26cacSmrg   return BadRequest;
5566df26cacSmrg}
5576df26cacSmrg
5586df26cacSmrg
5596df26cacSmrg/*
5606df26cacSmrg *----------------------------------------------------------------------------
5616df26cacSmrg *
5626df26cacSmrg * VMwareCtrlResetProc --
5636df26cacSmrg *
5646df26cacSmrg *      Cleanup handler called when the extension is removed.
5656df26cacSmrg *
5666df26cacSmrg * Results:
5676df26cacSmrg *      None
5686df26cacSmrg *
5696df26cacSmrg * Side effects:
5706df26cacSmrg *      None
5716df26cacSmrg *
5726df26cacSmrg *----------------------------------------------------------------------------
5736df26cacSmrg */
5746df26cacSmrg
5756df26cacSmrgstatic void
5766df26cacSmrgVMwareCtrlResetProc(ExtensionEntry* extEntry)
5776df26cacSmrg{
5786df26cacSmrg   /* Currently, no cleanup is necessary. */
5796df26cacSmrg}
5806df26cacSmrg
5816df26cacSmrg
5826df26cacSmrg/*
5836df26cacSmrg *----------------------------------------------------------------------------
5846df26cacSmrg *
5856df26cacSmrg * VMwareCtrl_ExitInit --
5866df26cacSmrg *
5876df26cacSmrg *      Initialiser for the VMWARE_CTRL protocol extension.
5886df26cacSmrg *
5896df26cacSmrg * Results:
5906df26cacSmrg *      None.
5916df26cacSmrg *
5926df26cacSmrg * Side effects:
5936df26cacSmrg *      Protocol extension will be registered if successful.
5946df26cacSmrg *
5956df26cacSmrg *----------------------------------------------------------------------------
5966df26cacSmrg */
5976df26cacSmrg
5986df26cacSmrgvoid
5996df26cacSmrgVMwareCtrl_ExtInit(ScrnInfoPtr pScrn)
6006df26cacSmrg{
6016df26cacSmrg   ExtensionEntry *myext;
6026df26cacSmrg
6036df26cacSmrg   if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
6046df26cacSmrg      if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0,
6056df26cacSmrg                                 VMwareCtrlDispatch,
6066df26cacSmrg                                 SVMwareCtrlDispatch,
6076df26cacSmrg                                 VMwareCtrlResetProc,
6086df26cacSmrg                                 StandardMinorOpcode))) {
6096df26cacSmrg         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
6106df26cacSmrg                    "Failed to add VMWARE_CTRL extension\n");
6116df26cacSmrg	 return;
6126df26cacSmrg      }
6136df26cacSmrg
6146df26cacSmrg      /*
6156df26cacSmrg       * For now, only support one screen as that's all the virtual
6166df26cacSmrg       * hardware supports.
6176df26cacSmrg       */
6186df26cacSmrg      myext->extPrivate = pScrn;
6196df26cacSmrg
6206df26cacSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
6216df26cacSmrg                 "Initialized VMWARE_CTRL extension version %d.%d\n",
6226df26cacSmrg                 VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION);
6236df26cacSmrg   }
6246df26cacSmrg}
625