[Spice-commits] 6 commits - display/driver.c display/qxldd.h display/res.c display/res.h display/surface.c display/surface.h miniport/qxl.c

Yonit Halperin yhalperi at kemper.freedesktop.org
Sun Aug 28 04:14:44 PDT 2011


 display/driver.c  |  137 ++++++++----
 display/qxldd.h   |  128 ++++++-----
 display/res.c     |  581 ++++++++++++++++++++----------------------------------
 display/res.h     |    2 
 display/surface.c |   62 ++++-
 display/surface.h |   28 --
 miniport/qxl.c    |   75 ++----
 7 files changed, 462 insertions(+), 551 deletions(-)

New commits:
commit 3ca826cce277ca6c52aad4175aa96b283825ad25
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Sun Aug 28 10:18:42 2011 +0300

    display: add missing 'continue' in MoveAllSurfacesToVideoRam

diff --git a/display/surface.c b/display/surface.c
index 16723d3..2cc5895 100644
--- a/display/surface.c
+++ b/display/surface.c
@@ -307,6 +307,7 @@ int MoveAllSurfacesToVideoRam(PDev *pdev)
         if (surface_info->copy == NULL) {
             DEBUG_PRINT((pdev, 3, "%s: %p: %d: no copy buffer, ignored\n", __FUNCTION__,
                          pdev, surface_id));
+            continue;
         }
         if (!MoveSurfaceToVideoRam(pdev, surface_id)) {
             /* Some of the surfaces have not been moved to video ram.
commit bb3791172cafb84e10ba26df5c78bbe35a069000
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Sun Aug 28 10:15:30 2011 +0300

    display: fix how MoveAllSurfacesToRam handles failure
    
    1) send create surface commands for all the surfaces that have not been
       moved to vram
    2) fix the parameters sent to SendSurfaceCreateCommand
    3) send create primary surface IO

diff --git a/display/driver.c b/display/driver.c
index 30f0373..de1f714 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -1028,6 +1028,7 @@ static BOOL AssertModeDisable(PDev *pdev)
     async_io(pdev, ASYNCABLE_DESTROY_ALL_SURFACES, 0);
     /* move all surfaces from device to system memory */
     if (!MoveAllSurfacesToRam(pdev)) {
+        EnableQXLPrimarySurface(pdev);
         return FALSE;
     }
     if (!FlushRelease(pdev)) {
diff --git a/display/qxldd.h b/display/qxldd.h
index b03c3de..6482e8a 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -200,6 +200,7 @@ struct SurfaceInfo {
     SIZEL       size;
     UINT8      *copy;
     ULONG       bitmap_format;
+    INT32       stride;
     union {
         PDev *pdev;
         SurfaceInfo *next_free;
diff --git a/display/surface.c b/display/surface.c
index 60bbd99..16723d3 100644
--- a/display/surface.c
+++ b/display/surface.c
@@ -187,7 +187,7 @@ HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, QXLPHYSICAL *ph
                     __FUNCTION__, pdev, surface_id));
         goto out_error2;
     }
-
+    surface_info->stride = stride;
     if (allocation_type != DEVICE_BITMAP_ALLOCATION_TYPE_SURF0) {
         SendSurfaceCreateCommand(pdev, surface_id, size, surface_format, -stride, *phys_mem, 0);
     }
@@ -318,6 +318,42 @@ int MoveAllSurfacesToVideoRam(PDev *pdev)
     return TRUE;
 }
 
+/* to_surface_id is exclusive */
+static void SendSurfaceRangeCreateCommand(PDev *pdev, UINT32 from_surface_id, UINT32 to_surface_id)
+{
+    UINT32 surface_id;
+
+    ASSERT(pdev, from_surface_id < to_surface_id);
+    ASSERT(pdev, to_surface_id <= pdev->n_surfaces);
+
+    for (surface_id = from_surface_id; surface_id < to_surface_id; surface_id++) {
+        SurfaceInfo *surface_info;
+        SURFOBJ *surf_obj;
+        QXLPHYSICAL phys_mem;
+        UINT32 surface_format;
+        UINT32 depth;
+
+        surface_info = GetSurfaceInfo(pdev, surface_id);
+        if (!surface_info->draw_area.base_mem) {
+            continue;
+        }
+
+        surf_obj = surface_info->draw_area.surf_obj;
+
+        if (!surf_obj) {
+            continue;
+        }
+
+        phys_mem = SurfaceToPhysical(pdev, surface_info->draw_area.base_mem);
+        BitmapFormatToDepthAndSurfaceFormat(surface_info->bitmap_format, &depth, &surface_format);
+
+        SendSurfaceCreateCommand(pdev, surface_id, surf_obj->sizlBitmap,
+                                 surface_format, -surface_info->stride, phys_mem,
+                                 /* the surface is still there, tell server not to erase */
+                                 1);
+    }
+}
+
 BOOL MoveAllSurfacesToRam(PDev *pdev)
 {
     UINT32 surface_id;
@@ -357,19 +393,9 @@ BOOL MoveAllSurfacesToRam(PDev *pdev)
             /* Send a create messsage for this surface - we previously did a destroy all. */
             EngFreeMem(surface_info->copy);
             surface_info->copy = NULL;
-            DEBUG_PRINT((pdev, 0, "%s: %d: EngModifySurface failed, sending create\n",
-                         __FUNCTION__, surface_id));
-            phys_mem = SurfaceToPhysical(pdev, surface_info->draw_area.base_mem);
-            /*
-             * TODO: bug. create_command should be send for all surfaces >= surface_id
-             *       since they stay in the pci-bar. Alternatively,
-             *       don't call destroy_all_surfaces, instead send destroy commands
-             *       for all surfaces with id < surface_id.
-             */
-            SendSurfaceCreateCommand(pdev, surface_id, surf_obj->sizlBitmap,
-                                     surface_info->bitmap_format, -surf_obj->lDelta, phys_mem,
-                                     /* the surface is still there, tell server not to erase */
-                                     1);
+            DEBUG_PRINT((pdev, 0, "%s: %d: EngModifySurface failed, sending create for %d-%d\n",
+                         __FUNCTION__, surface_id, surface_id, pdev->n_surfaces - 1));
+            SendSurfaceRangeCreateCommand(pdev, surface_id, pdev->n_surfaces);
             return FALSE;
         }
         QXLDelSurface(pdev, surface_info->draw_area.base_mem, DEVICE_BITMAP_ALLOCATION_TYPE_VRAM);
commit 6dca8c709936f743958a322f75dde41b24535db4
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Wed Aug 24 11:23:06 2011 +0300

    display: not using globals, RHBZ #731644
    
    due to the previous patch ("support clearing the pci-bar when the pdev is disabled for revision<3 as well"),
    surfaces_info and other resources like caches, are no longer shared between pdevs. Moreover,
    it is an error to use globals, since different display driver sessions have different memory space.
    
    In addition I removed all the semaphores that are not related to the pci ram. These semaphores
    were protecting the surfaces_info array and the caches, however these sturctures belong only to one pdev,
    and according to http://msdn.microsoft.com/en-us/library/ff568281%28v=vs.85%29.aspx, can be accessed
    only from a single thread.
    
    For the rest of the semaphores, I returned them to the same state that was in revision 1 => they
    are part of the PDev. However, this should be fixed:
    1) In order to protect the device log buffer,
       the print_sem must be shared by different pdevs and
       different display sessions. Alternatively, we can use IOCTL for logging.
    2) malloc_sem: not sure what it protects. Maybe globals in mspace?
       since only the enabled pdev is allocating memory, I don't
       think it is required (unless it is possible to have
       AssertMode(x, enable) before AssertMode(y, disable).
    3) cmd_sem, cursor_sem: again, since only the enabled pdev touches the cmd rings
       I don't think it is required.
    4) io_sem - same as print sem. Note that we should prevent starvation between
                print_sem and io_sem in DebugPrintV.

diff --git a/display/driver.c b/display/driver.c
index 935567d..30f0373 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -106,13 +106,13 @@ static CallCounterInfo counters_info[NUM_CALL_COUNTERS] = {
 
 void DebugPrintV(PDev *pdev, const char *message, va_list ap)
 {
-    if (pdev && pdev->log_buf && pdev->Res) {
-        EngAcquireSemaphore(pdev->Res->print_sem);
+    if (pdev && pdev->log_buf) {
+        EngAcquireSemaphore(pdev->print_sem);
         _snprintf(pdev->log_buf, QXL_LOG_BUF_SIZE, QXLDD_DEBUG_PREFIX);
         _vsnprintf(pdev->log_buf + strlen(QXLDD_DEBUG_PREFIX),
                    QXL_LOG_BUF_SIZE - strlen(QXLDD_DEBUG_PREFIX), message, ap);
         sync_io(pdev, pdev->log_port, 0);
-        EngReleaseSemaphore(pdev->Res->print_sem);
+        EngReleaseSemaphore(pdev->print_sem);
     } else {
         EngDebugPrint(QXLDD_DEBUG_PREFIX, (PCHAR)message, ap);
     }
@@ -248,7 +248,6 @@ BOOL DrvEnableDriver(ULONG engine_version, ULONG enable_data_size, PDRVENABLEDAT
 #ifndef _WIN64
     CheckAndSetSSE2();
 #endif
-    InitGlobalRes();
     DEBUG_PRINT((NULL, 1, "%s: end\n", __FUNCTION__));
     return TRUE;
 }
@@ -257,7 +256,6 @@ VOID DrvDisableDriver(VOID)
 {
     DEBUG_PRINT((NULL, 1, "%s\n", __FUNCTION__));
     ResDestroyGlobals();
-    CleanGlobalRes();
 }
 
 DWORD GetAvailableModes(HANDLE driver, PVIDEO_MODE_INFORMATION *mode_info,
@@ -541,6 +539,7 @@ static void DebugCountAliveSurfaces(PDev *pdev)
         surface_info = GetSurfaceInfo(pdev, i);
         if (surface_info->draw_area.base_mem != NULL) {
             total++;
+            // all should belong to the same pdev
             if (surface_info->u.pdev == pdev) {
                 of_pdev++;
                 if (surface_info->draw_area.surf_obj == NULL) {
@@ -563,7 +562,6 @@ VOID DrvDisablePDEV(DHPDEV in_pdev)
     PDev* pdev = (PDev*)in_pdev;
 
     DEBUG_PRINT((pdev, 1, "%s: 0x%lx\n", __FUNCTION__, pdev));
-    DebugCountAliveSurfaces(pdev);
     ResDestroy(pdev);
     DestroyPalette(pdev);
     EngFreeMem(pdev);
@@ -954,6 +952,8 @@ VOID DrvDisableSurface(DHPDEV in_pdev)
         pdev->mem_slots = NULL;
     }
 
+    DebugCountAliveSurfaces(pdev);
+    ClearResources(pdev);
     DEBUG_PRINT((pdev, 1, "%s: 0x%lx exit\n", __FUNCTION__, pdev));
 }
 
@@ -965,7 +965,7 @@ static void FlushSurfaces(PDev *pdev)
     RECTL area = {0, 0, 0, 0};
 
     if (pdev->pci_revision < QXL_REVISION_STABLE_V10) {
-        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_SURFACES", __FUNCTION__));
+        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_SURFACES\n", __FUNCTION__));
         for (surface_id = pdev->n_surfaces - 1; surface_id >  0 ; --surface_id) {
             surface_info = GetSurfaceInfo(pdev, surface_id);
 
@@ -990,7 +990,7 @@ static BOOL FlushRelease(PDev *pdev)
     if (pdev->pci_revision<  QXL_REVISION_STABLE_V10) {
         DWORD length;
 
-        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_RELEASE", __FUNCTION__));
+        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_RELEASE\n", __FUNCTION__));
         if (EngDeviceIoControl(pdev->driver, IOCTL_VIDEO_RESET_DEVICE,
                                NULL, 0, NULL, 0, &length)) {
             DEBUG_PRINT((NULL, 0, "%s: reset failed 0x%lx\n", __FUNCTION__, pdev));
@@ -1039,20 +1039,19 @@ static BOOL AssertModeDisable(PDev *pdev)
         pdev->cmd_ring->prod, pdev->cmd_ring->cons,
         pdev->cursor_ring->prod, pdev->cursor_ring->cons,
         pdev->release_ring->prod, pdev->release_ring->cons,
-        pdev->Res->free_outputs));
-    DEBUG_PRINT((pdev, 4, "%s exit\n", __FUNCTION__));
+        pdev->free_outputs));
+    DEBUG_PRINT((pdev, 3, "%s exit\n", __FUNCTION__));
     return TRUE;
 }
 
 static void AssertModeEnable(PDev *pdev)
 {
-    InitResources(pdev);
     InitDeviceMemoryResources(pdev);
     DEBUG_PRINT((pdev, 3, "%s: [%d,%d] [%d,%d] [%d,%d] %lx\n", __FUNCTION__,
         pdev->cmd_ring->prod, pdev->cmd_ring->cons,
         pdev->cursor_ring->prod, pdev->cursor_ring->cons,
         pdev->release_ring->prod, pdev->release_ring->cons,
-        pdev->Res->free_outputs));
+        pdev->free_outputs));
     EnableQXLPrimarySurface(pdev);
     CreateVRamSlot(pdev);
     DebugCountAliveSurfaces(pdev);
@@ -1377,6 +1376,9 @@ HBITMAP APIENTRY DrvCreateDeviceBitmap(DHPDEV dhpdev, SIZEL size, ULONG format)
     pdev = (PDev *)dhpdev;
 
     if (!pdev->vram_slot_initialized || pdev->bitmap_format != format || pdev->fb == 0) {
+        DEBUG_PRINT((pdev, 3, "%s failed: %p: slot_initialized %d, format(%d,%d), fb %p\n",
+                    __FUNCTION__, pdev, pdev->vram_slot_initialized,
+                    pdev->bitmap_format, format, pdev->fb));
         return 0;
     }
 
@@ -1384,6 +1386,7 @@ HBITMAP APIENTRY DrvCreateDeviceBitmap(DHPDEV dhpdev, SIZEL size, ULONG format)
 
     surface_id = GetFreeSurface(pdev);
     if (!surface_id) {
+        DEBUG_PRINT((pdev, 3, "%s:%p GetFreeSurface failed\n", __FUNCTION__, pdev));
         goto out_error;
     }
     DEBUG_PRINT((pdev, 3, "%s: %p: %d\n", __FUNCTION__, pdev, surface_id));
@@ -1391,6 +1394,7 @@ HBITMAP APIENTRY DrvCreateDeviceBitmap(DHPDEV dhpdev, SIZEL size, ULONG format)
     hbitmap = CreateDeviceBitmap(pdev, size, pdev->bitmap_format, &phys_mem, &base_mem, surface_id,
                                  DEVICE_BITMAP_ALLOCATION_TYPE_VRAM);
     if (!hbitmap) {
+         DEBUG_PRINT((pdev, 3, "%s:%p CreateDeviceBitmap failed\n", __FUNCTION__, pdev));
         goto out_error2;
     }
 
@@ -1426,20 +1430,20 @@ VOID APIENTRY DrvDeleteDeviceBitmap(DHSURF dhsurf)
 
 void CountCall(PDev *pdev, int counter)
 {
-    if (pdev->Res->count_calls) {
+    if (pdev->count_calls) {
         int i;
 
-        pdev->Res->call_counters[counter]++;
-        if((++pdev->Res->total_calls % 500) == 0) {
-            DEBUG_PRINT((pdev, 0, "total eng calls is %u\n", pdev->Res->total_calls));
+        pdev->call_counters[counter]++;
+        if((++pdev->total_calls % 500) == 0) {
+            DEBUG_PRINT((pdev, 0, "total eng calls is %u\n", pdev->total_calls));
             for (i = 0; i < NUM_CALL_COUNTERS; i++) {
                 DEBUG_PRINT((pdev, 0, "%s count is %u\n",
-                             counters_info[i].name, pdev->Res->call_counters[i]));
+                             counters_info[i].name, pdev->call_counters[i]));
             }
         }
-        pdev->Res->count_calls = FALSE;
+        pdev->count_calls = FALSE;
     } else if (counters_info[counter].effective) {
-        pdev->Res->count_calls = TRUE;
+        pdev->count_calls = TRUE;
     }
 }
 
diff --git a/display/qxldd.h b/display/qxldd.h
index 9b613c1..b03c3de 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -206,57 +206,6 @@ struct SurfaceInfo {
     } u;
 };
 
-typedef struct DevRes {   
-    MspaceInfo mspaces[NUM_MSPACES];
-    HSEMAPHORE malloc_sem; /* Also protects release ring */
-
-    BOOL need_init;
-    UINT64 free_outputs;
-    UINT32 update_id;
-
-    HSEMAPHORE print_sem;
-    HSEMAPHORE cmd_sem;
-    HSEMAPHORE cursor_sem; /* Protects cursor_ring */
-    HSEMAPHORE surface_sem; /* Protects surfaces allocation */
-    HSEMAPHORE image_cache_sem; /* Protects image cache */
-    HSEMAPHORE cursor_cache_sem; /* Protects cursor cache */
-    HSEMAPHORE palette_cache_sem; /* Protects palette cache */
-
-    CacheImage cache_image_pool[IMAGE_POOL_SIZE];
-    Ring cache_image_lru;
-    Ring cursors_lru;
-    Ring palette_lru;
-
-    ImageKey image_key_lookup[IMAGE_KEY_HASH_SIZE];
-    struct CacheImage *image_cache[IMAGE_HASH_SIZE];
-    struct InternalCursor *cursor_cache[CURSOR_HASH_SIZE];
-    UINT32 num_cursors;
-    UINT32 last_cursor_id;
-    struct InternalPalette *palette_cache[PALETTE_HASH_SIZE];
-    UINT32 num_palettes;
-
-    SurfaceInfo *surfaces_info;
-    SurfaceInfo *free_surfaces;
-
-    HANDLE driver;
-#ifdef DBG
-    int num_free_pages;
-    int num_outputs;
-    int num_path_pages;
-    int num_rects_pages;
-    int num_bits_pages;
-    int num_buf_pages;
-    int num_glyphs_pages;
-    int num_cursor_pages;
-#endif
-
-#ifdef CALL_TEST
-    BOOL count_calls;
-    UINT32 total_calls;
-    UINT32 call_counters[NUM_CALL_COUNTERS];
-#endif
-} DevRes;
-
 #define SSE_MASK 15
 #define SSE_ALIGN 16
 
@@ -345,26 +294,82 @@ typedef struct PDev {
 
     UINT32 dev_id;
 
-    DevRes *Res;
-
     Ring update_trace;
     UpdateTrace update_trace_items[NUM_UPDATE_TRACE_ITEMS];
 
+    UINT64 free_outputs;
+
+    MspaceInfo mspaces[NUM_MSPACES];
+
+    /*
+     * TODO: reconsider semaphores according to
+     * http://msdn.microsoft.com/en-us/library/ff568281%28v=vs.85%29.aspx
+     * 1) In order to protect the device log buffer,
+     *     the print_sem must be shared between different pdevs and
+     *     different display sessions.
+     * 2) malloc_sem: not sure what it protects. Maybe globals in mspace?
+     *    since only the enabled pdev is allocating memory, I don't
+     *    think it is required (unless it is possible to have
+     *    AssertMode(x, enable) before AssertMode(y, disable).
+     * 3) cmd_sem, cursor_sem: again, since only the enabled pdev touches the cmd rings
+     *    I don't think it is required.
+     * 4) io_sem - same as print sem. Note that we should prevent starvation between
+     *    print_sem and io_sem in DebugPrintV.
+     *
+     */
+    HSEMAPHORE malloc_sem; /* Also protects release ring */
+    HSEMAPHORE print_sem;
+    HSEMAPHORE cmd_sem;
+    HSEMAPHORE cursor_sem; /* Protects cursor_ring */
+
+    CacheImage cache_image_pool[IMAGE_POOL_SIZE];
+    Ring cache_image_lru;
+    Ring cursors_lru;
+    Ring palette_lru;
+    ImageKey image_key_lookup[IMAGE_KEY_HASH_SIZE];
+    struct CacheImage *image_cache[IMAGE_HASH_SIZE];
+    struct InternalCursor *cursor_cache[CURSOR_HASH_SIZE];
+    UINT32 num_cursors;
+    UINT32 last_cursor_id;
+    struct InternalPalette *palette_cache[PALETTE_HASH_SIZE];
+    UINT32 num_palettes;
+
     UINT32 n_surfaces;
     SurfaceInfo surface0_info;
+    SurfaceInfo *surfaces_info;
+    SurfaceInfo *free_surfaces;
+
+    UINT32 update_id;
 
     UINT32 enabled; /* 1 between DrvAssertMode(TRUE) and DrvAssertMode(FALSE) */
 
+
     UCHAR  pci_revision;
+
+#ifdef DBG
+    int num_free_pages;
+    int num_outputs;
+    int num_path_pages;
+    int num_rects_pages;
+    int num_bits_pages;
+    int num_buf_pages;
+    int num_glyphs_pages;
+    int num_cursor_pages;
+#endif
+
+#ifdef CALL_TEST
+    BOOL count_calls;
+    UINT32 total_calls;
+    UINT32 call_counters[NUM_CALL_COUNTERS];
+#endif
 } PDev;
 
 
 void DebugPrintV(PDev *pdev, const char *message, va_list ap);
 void DebugPrint(PDev *pdev, int level, const char *message, ...);
 
-void InitGlobalRes();
-void CleanGlobalRes();
 void InitResources(PDev *pdev);
+void ClearResources(PDev *pdev);
 
 #ifdef CALL_TEST
 void CountCall(PDev *pdev, int counter);
@@ -478,9 +483,9 @@ static _inline void sync_io(PDev *pdev, PUCHAR port, UCHAR val)
 #ifdef DBG
 #define DUMP_VRAM_MSPACE(pdev) \
     do { \
-        DEBUG_PRINT((pdev, 0, "%s: dumping mspace vram (%p, %p)\n", __FUNCTION__, pdev, global_res ? global_res[pdev->dev_id] : NULL)); \
-        if (pdev && global_res && global_res[pdev->dev_id]) {  \
-            mspace_malloc_stats(global_res[pdev->dev_id]->mspaces[MSPACE_TYPE_VRAM]._mspace); \
+        DEBUG_PRINT((pdev, 0, "%s: dumping mspace vram (%p)\n", __FUNCTION__, pdev)); \
+        if (pdev) {  \
+            mspace_malloc_stats(pdev->mspaces[MSPACE_TYPE_VRAM]._mspace); \
         } else { \
             DEBUG_PRINT((pdev, 0, "nothing\n")); \
         }\
@@ -488,9 +493,9 @@ static _inline void sync_io(PDev *pdev, PUCHAR port, UCHAR val)
 
 #define DUMP_DEVRAM_MSPACE(pdev) \
     do { \
-        DEBUG_PRINT((pdev, 0, "%s: dumping mspace devram (%p, %p)\n", __FUNCTION__, pdev, global_res ? global_res[pdev->dev_id] : NULL)); \
-        if (pdev && global_res && global_res[pdev->dev_id]) {  \
-            mspace_malloc_stats(global_res[pdev->dev_id]->mspaces[MSPACE_TYPE_DEVRAM]._mspace); \
+        DEBUG_PRINT((pdev, 0, "%s: dumping mspace devram (%p)\n", __FUNCTION__, pdev)); \
+        if (pdev) {  \
+            mspace_malloc_stats(pdev->mspaces[MSPACE_TYPE_DEVRAM]._mspace); \
         } else { \
             DEBUG_PRINT((pdev, 0, "nothing\n")); \
         }\
diff --git a/display/res.c b/display/res.c
index 1274f43..f7c0a58 100644
--- a/display/res.c
+++ b/display/res.c
@@ -186,7 +186,7 @@ UINT64 ReleaseOutput(PDev *pdev, UINT64 output_id)
     next = *(UINT64*)output->data;
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, output);
     DEBUG_PRINT((pdev, 10, "%s done\n", __FUNCTION__));
-    ONDBG(pdev->Res->num_outputs--); //todo: atomic
+    ONDBG(pdev->num_outputs--); //todo: atomic
     return next;
 }
 
@@ -326,14 +326,14 @@ static void WaitForReleaseRing(PDev* pdev)
             DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
             DEBUG_PRINT((pdev, 0,
                 "\tfree %d out %d path %d rect %d bits %d buf %d glyph %d cursor %d\n",
-                         pdev->Res->num_free_pages,
-                         pdev->Res->num_outputs,
-                         pdev->Res->num_path_pages,
-                         pdev->Res->num_rects_pages,
-                         pdev->Res->num_bits_pages,
-                         pdev->Res->num_buf_pages,
-                         pdev->Res->num_glyphs_pages,
-                         pdev->Res->num_cursor_pages));
+                         pdev->num_free_pages,
+                         pdev->num_outputs,
+                         pdev->num_path_pages,
+                         pdev->num_rects_pages,
+                         pdev->num_bits_pages,
+                         pdev->num_buf_pages,
+                         pdev->num_glyphs_pages,
+                         pdev->num_cursor_pages));
 #endif
             //oom
             sync_io(pdev, pdev->notify_oom_port, 0);
@@ -349,7 +349,7 @@ static void FlushReleaseRing(PDev *pdev)
     int notify;
     int num_to_release = 50;
 
-    output = pdev->Res->free_outputs;
+    output = pdev->free_outputs;
 
     while (1) {
         while (output != 0) {
@@ -368,19 +368,19 @@ static void FlushReleaseRing(PDev *pdev)
         SPICE_RING_POP(pdev->release_ring, notify);
     }
 
-    pdev->Res->free_outputs = output;
+    pdev->free_outputs = output;
 }
 
 void EmptyReleaseRing(PDev *pdev)
 {
     int count = 0;
 
-    EngAcquireSemaphore(pdev->Res->malloc_sem);
-    while (pdev->Res->free_outputs || !SPICE_RING_IS_EMPTY(pdev->release_ring)) {
+    EngAcquireSemaphore(pdev->malloc_sem);
+    while (pdev->free_outputs || !SPICE_RING_IS_EMPTY(pdev->release_ring)) {
         FlushReleaseRing(pdev);
         count++;
     }
-    EngReleaseSemaphore(pdev->Res->malloc_sem);
+    EngReleaseSemaphore(pdev->malloc_sem);
     DEBUG_PRINT((pdev, 3, "%s: complete after %d rounds\n", __FUNCTION__, count));
 }
 
@@ -390,29 +390,29 @@ static void *__AllocMem(PDev* pdev, UINT32 mspace_type, size_t size, BOOL force)
 {
     UINT8 *ptr;
 
-    ASSERT(pdev, pdev && pdev->Res->mspaces[mspace_type]._mspace);
+    ASSERT(pdev, pdev && pdev->mspaces[mspace_type]._mspace);
     DEBUG_PRINT((pdev, 12, "%s: 0x%lx %p(%d) size %u\n", __FUNCTION__, pdev,
-        pdev->Res->mspaces[mspace_type]._mspace,
-        mspace_footprint(pdev->Res->mspaces[mspace_type]._mspace),
+        pdev->mspaces[mspace_type]._mspace,
+        mspace_footprint(pdev->mspaces[mspace_type]._mspace),
         size));
 #ifdef DBG
     if (pdev && pdev->log_level && *pdev->log_level > 11) {
-        mspace_malloc_stats(pdev->Res->mspaces[mspace_type]._mspace);
+        mspace_malloc_stats(pdev->mspaces[mspace_type]._mspace);
     }
 #endif
-    EngAcquireSemaphore(pdev->Res->malloc_sem);
+    EngAcquireSemaphore(pdev->malloc_sem);
 
     while (1) {
         /* Release lots of queued resources, before allocating, as we
            want to release early to minimize fragmentation risks. */
         FlushReleaseRing(pdev);
 
-        ptr = mspace_malloc(pdev->Res->mspaces[mspace_type]._mspace, size);
+        ptr = mspace_malloc(pdev->mspaces[mspace_type]._mspace, size);
         if (ptr) {
             break;
         }
 
-        if (pdev->Res->free_outputs != 0 ||
+        if (pdev->free_outputs != 0 ||
             !SPICE_RING_IS_EMPTY(pdev->release_ring)) {
             /* We have more things to free, try that */
             continue;
@@ -427,133 +427,60 @@ static void *__AllocMem(PDev* pdev, UINT32 mspace_type, size_t size, BOOL force)
         }
     }
 
-    EngReleaseSemaphore(pdev->Res->malloc_sem);
-    ASSERT(pdev, (!ptr && !force) || (ptr >= pdev->Res->mspaces[mspace_type].mspace_start &&
-                                      ptr < pdev->Res->mspaces[mspace_type].mspace_end));
+    EngReleaseSemaphore(pdev->malloc_sem);
+    ASSERT(pdev, (!ptr && !force) || (ptr >= pdev->mspaces[mspace_type].mspace_start &&
+                                      ptr < pdev->mspaces[mspace_type].mspace_end));
     DEBUG_PRINT((pdev, 13, "%s: 0x%lx done 0x%x\n", __FUNCTION__, pdev, ptr));
     return ptr;
 }
 
 static void FreeMem(PDev* pdev, UINT32 mspace_type, void *ptr)
 {
-    ASSERT(pdev, pdev && pdev->Res->mspaces[mspace_type]._mspace);
+    ASSERT(pdev, pdev && pdev->mspaces[mspace_type]._mspace);
 #ifdef DBG
-    if (!((UINT8 *)ptr >= pdev->Res->mspaces[mspace_type].mspace_start &&
-                 (UINT8 *)ptr < pdev->Res->mspaces[mspace_type].mspace_end)) {
+    if (!((UINT8 *)ptr >= pdev->mspaces[mspace_type].mspace_start &&
+                 (UINT8 *)ptr < pdev->mspaces[mspace_type].mspace_end)) {
         DebugPrint(pdev, 0, "ASSERT failed @ %s, %p not in [%p, %p) (%d)\n", __FUNCTION__,
-            ptr, pdev->Res->mspaces[mspace_type].mspace_start,
-            pdev->Res->mspaces[mspace_type].mspace_end, mspace_type);
+            ptr, pdev->mspaces[mspace_type].mspace_start,
+            pdev->mspaces[mspace_type].mspace_end, mspace_type);
         EngDebugBreak();
     }
 #endif
-    EngAcquireSemaphore(pdev->Res->malloc_sem);
-    mspace_free(pdev->Res->mspaces[mspace_type]._mspace, ptr);
-    EngReleaseSemaphore(pdev->Res->malloc_sem);
-}
-
-DevRes **global_res = NULL;
-UINT8 num_global_res = 0;
-HSEMAPHORE res_sem = NULL;
-
-void CleanGlobalRes()
-{
-    UINT32 i;
-    DevRes *res;
-
-    if (global_res) {
-        for (i = 0; i < num_global_res; ++i) {
-            res = global_res[i];
-            if (res != NULL) {
-                if (res->surfaces_info) {
-                    EngFreeMem(res->surfaces_info);
-                    res->surfaces_info = NULL;
-                }
-                if (res->malloc_sem) {
-                    EngDeleteSemaphore(res->malloc_sem);
-                    res->malloc_sem = NULL;
-                }
-                if (res->cmd_sem) {
-                    EngDeleteSemaphore(res->cmd_sem);
-                    res->cmd_sem = NULL;
-                }
-                if (res->cursor_sem) {
-                    EngDeleteSemaphore(res->cursor_sem);
-                    res->cursor_sem = NULL;
-                }
-                if (res->print_sem) {
-                    EngDeleteSemaphore(res->print_sem);
-                    res->print_sem = NULL;
-                }
-                if (res->surface_sem) {
-                    EngDeleteSemaphore(res->surface_sem);
-                    res->surface_sem = NULL;
-                }
-                if (res->image_cache_sem) {
-                    EngDeleteSemaphore(res->image_cache_sem);
-                    res->image_cache_sem = NULL;
-                }
-                if (res->cursor_cache_sem) {
-                    EngDeleteSemaphore(res->cursor_cache_sem);
-                    res->cursor_cache_sem = NULL;
-                }
-                if (res->palette_cache_sem) {
-                    EngDeleteSemaphore(res->palette_cache_sem);
-                    res->palette_cache_sem = NULL;
-                }
-                EngFreeMem(res);
-            }
-        }
-        EngFreeMem(global_res);
-        global_res = NULL;
-    }
-    num_global_res = 0;
-    if (res_sem) {
-        EngDeleteSemaphore(res_sem);
-        res_sem = NULL;
-    }
-}
-
-void InitGlobalRes()
-{
-    CleanGlobalRes();
-    res_sem = EngCreateSemaphore();
-    if (!res_sem) {
-        EngDebugBreak();
-    }
+    EngAcquireSemaphore(pdev->malloc_sem);
+    mspace_free(pdev->mspaces[mspace_type]._mspace, ptr);
+    EngReleaseSemaphore(pdev->malloc_sem);
 }
 
 static void InitMspace(PDev *pdev, UINT32 mspace_type, UINT8 *start, size_t capacity)
 {
-    DevRes *res = pdev->Res;
-
-    res->mspaces[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, pdev);
-    res->mspaces[mspace_type].mspace_start = start;
-    res->mspaces[mspace_type].mspace_end = start + capacity;
+    pdev->mspaces[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, pdev);
+    pdev->mspaces[mspace_type].mspace_start = start;
+    pdev->mspaces[mspace_type].mspace_end = start + capacity;
 }
 
 static void ResetCache(PDev *pdev)
 {
     int i;
 
-    RtlZeroMemory(pdev->Res->image_key_lookup,
-                  sizeof(pdev->Res->image_key_lookup));
-    RtlZeroMemory(pdev->Res->cache_image_pool,
-                  sizeof(pdev->Res->cache_image_pool));
-    RingInit(&pdev->Res->cache_image_lru);
+    RtlZeroMemory(pdev->image_key_lookup,
+                  sizeof(pdev->image_key_lookup));
+    RtlZeroMemory(pdev->cache_image_pool,
+                  sizeof(pdev->cache_image_pool));
+    RingInit(&pdev->cache_image_lru);
     for (i = 0; i < IMAGE_POOL_SIZE; i++) {
-        RingAdd(pdev, &pdev->Res->cache_image_lru,
-                &pdev->Res->cache_image_pool[i].lru_link);
+        RingAdd(pdev, &pdev->cache_image_lru,
+                &pdev->cache_image_pool[i].lru_link);
     }
 
-    RtlZeroMemory(pdev->Res->image_cache, sizeof(pdev->Res->image_cache));
-    RtlZeroMemory(pdev->Res->cursor_cache, sizeof(pdev->Res->cursor_cache));
-    RingInit(&pdev->Res->cursors_lru);
-    pdev->Res->num_cursors = 0;
-    pdev->Res->last_cursor_id = 0;
+    RtlZeroMemory(pdev->image_cache, sizeof(pdev->image_cache));
+    RtlZeroMemory(pdev->cursor_cache, sizeof(pdev->cursor_cache));
+    RingInit(&pdev->cursors_lru);
+    pdev->num_cursors = 0;
+    pdev->last_cursor_id = 0;
 
-    RtlZeroMemory(pdev->Res->palette_cache, sizeof(pdev->Res->palette_cache));
-    RingInit(&pdev->Res->palette_lru);
-    pdev->Res->num_palettes = 0;
+    RtlZeroMemory(pdev->palette_cache, sizeof(pdev->palette_cache));
+    RingInit(&pdev->palette_lru);
+    pdev->num_palettes = 0;
 }
 
 /* Init anything that resides on the device memory (pci vram and devram bars).
@@ -562,126 +489,107 @@ static void ResetCache(PDev *pdev)
  */
 void InitDeviceMemoryResources(PDev *pdev)
 {
+    UINT32 i;
+
     DEBUG_PRINT((pdev, 0, "%s: %d, %d\n", __FUNCTION__, pdev->num_io_pages * PAGE_SIZE,
-        pdev->fb_size));
+                pdev->fb_size));
+    RtlZeroMemory(pdev->update_trace_items, sizeof(pdev->update_trace_items));
+    RingInit(&pdev->update_trace);
+    for (i = 0; i < NUM_UPDATE_TRACE_ITEMS; i++) {
+         RingAdd(pdev, &pdev->update_trace, &pdev->update_trace_items[i].link);
+    }
     InitMspace(pdev, MSPACE_TYPE_DEVRAM, pdev->io_pages_virt, pdev->num_io_pages * PAGE_SIZE);
     InitMspace(pdev, MSPACE_TYPE_VRAM, pdev->fb, pdev->fb_size);
     ResetCache(pdev);
+    pdev->free_outputs = 0;
 }
 
-static void InitRes(PDev *pdev)
+void InitSurfaces(PDev *pdev)
 {
     UINT32 i;
-
-    pdev->Res->surface_sem = EngCreateSemaphore();
-    if (!pdev->Res->surface_sem) {
-        PANIC(pdev, "Res surface sem creation failed\n");
-    }
-    pdev->Res->surfaces_info = (SurfaceInfo *)EngAllocMem(FL_ZERO_MEMORY,
-							  sizeof(SurfaceInfo) * pdev->n_surfaces, 
-							  ALLOC_TAG);
-    if (!pdev->Res->surfaces_info) {
-        PANIC(pdev, "Res surfaces_info allocation failed\n");
+    pdev->surfaces_info = (SurfaceInfo *)EngAllocMem(FL_ZERO_MEMORY,
+                                                     sizeof(SurfaceInfo) * pdev->n_surfaces,
+                                                     ALLOC_TAG);
+    if (!pdev->surfaces_info) {
+        PANIC(pdev, "surfaces_info allocation failed\n");
     }
-    pdev->Res->free_surfaces = &pdev->Res->surfaces_info[0];
+
+    pdev->free_surfaces = &pdev->surfaces_info[1];
     for (i = 0; i < pdev->n_surfaces - 1; i++) {
-        pdev->Res->surfaces_info[i].u.next_free = &pdev->Res->surfaces_info[i+1];
+        pdev->surfaces_info[i].u.next_free = &pdev->surfaces_info[i+1];
     }
+}
 
-    pdev->Res->free_outputs = 0;
-    pdev->Res->malloc_sem = EngCreateSemaphore();
-    if (!pdev->Res->malloc_sem) {
-        PANIC(pdev, "Res malloc sem creation failed\n");
-    }
-    pdev->Res->cmd_sem = EngCreateSemaphore();
-    if (!pdev->Res->cmd_sem) {
-        PANIC(pdev, "Res cmd sem creation failed\n");
-    }
-    pdev->Res->cursor_sem = EngCreateSemaphore();
-    if (!pdev->Res->cursor_sem) {
-        PANIC(pdev, "Res cursor sem creation failed\n");
-    }
-    pdev->Res->print_sem = EngCreateSemaphore();
-    if (!pdev->Res->print_sem) {
-        PANIC(pdev, "Res print sem creation failed\n");
-    }
-    pdev->Res->image_cache_sem = EngCreateSemaphore();
-    if (!pdev->Res->image_cache_sem) {
-        PANIC(pdev, "Res cache sem creation failed\n");
-    }
-    pdev->Res->cursor_cache_sem = EngCreateSemaphore();
-    if (!pdev->Res->cursor_cache_sem) {
-        PANIC(pdev, "Res cache sem creation failed\n");
-    }
-    pdev->Res->palette_cache_sem = EngCreateSemaphore();
-    if (!pdev->Res->palette_cache_sem) {
-        PANIC(pdev, "Res cache sem creation failed\n");
+void ClearResources(PDev *pdev)
+{
+    if (pdev->surfaces_info) {
+        EngFreeMem(pdev->surfaces_info);
+        pdev->surfaces_info = NULL;
     }
 
-    pdev->Res->update_id = *pdev->dev_update_id;
-    InitDeviceMemoryResources(pdev);
+    if (pdev->malloc_sem) {
+        EngDeleteSemaphore(pdev->malloc_sem);
+        pdev->malloc_sem = NULL;
+    }
 
-    pdev->Res->driver = pdev->driver;
+    if (pdev->cmd_sem) {
+        EngDeleteSemaphore(pdev->cmd_sem);
+        pdev->cmd_sem = NULL;
+    }
 
-    ONDBG(pdev->Res->num_outputs = 0);
-    ONDBG(pdev->Res->num_path_pages = 0);
-    ONDBG(pdev->Res->num_rects_pages = 0);
-    ONDBG(pdev->Res->num_bits_pages = 0);
-    ONDBG(pdev->Res->num_buf_pages = 0);
-    ONDBG(pdev->Res->num_glyphs_pages = 0);
-    ONDBG(pdev->Res->num_cursor_pages = 0);
+    if (pdev->cursor_sem) {
+        EngDeleteSemaphore(pdev->cursor_sem);
+        pdev->cursor_sem = NULL;
+    }
 
-#ifdef CALL_TEST
-    pdev->Res->count_calls = TRUE;
-    pdev->Res->total_calls = 0;
-    for (i = 0; i < NUM_CALL_COUNTERS; i++) {
-        pdev->Res->call_counters[i] = 0;
+    if (pdev->print_sem) {
+        EngDeleteSemaphore(pdev->print_sem);
+        pdev->print_sem = NULL;
     }
-#endif
 }
 
 void InitResources(PDev *pdev)
 {
-    UINT32 i;
-    UINT32 id;
-    DevRes **new_global_res;
-
     DEBUG_PRINT((pdev, 3, "%s: entry\n", __FUNCTION__));
-    RtlZeroMemory(pdev->update_trace_items, sizeof(pdev->update_trace_items));
-    RingInit(&pdev->update_trace);
-    for (i = 0; i < NUM_UPDATE_TRACE_ITEMS; i++) {
-         RingAdd(pdev, &pdev->update_trace, &pdev->update_trace_items[i].link);
-    }
 
-    EngAcquireSemaphore(res_sem);
+    InitSurfaces(pdev);
+    InitDeviceMemoryResources(pdev);
 
-    id = pdev->dev_id;
-    if (id >= num_global_res) {
-        new_global_res = EngAllocMem(FL_ZERO_MEMORY, (id + 1) * sizeof(DevRes *), ALLOC_TAG);
-        if (!new_global_res) {
-            PANIC(pdev, "new_global_res malloc failed\n");
-        }
-        for (i = 0; i < num_global_res; ++i) {
-            new_global_res[i] = global_res[i];
-        }
-        if (global_res) {
-            EngFreeMem(global_res);
-        }
-        num_global_res = id + 1;
-        global_res = new_global_res;
+    pdev->update_id = *pdev->dev_update_id;
+
+    pdev->malloc_sem = EngCreateSemaphore();
+    if (!pdev->malloc_sem) {
+        PANIC(pdev, "malloc sem creation failed\n");
+    }
+    pdev->cmd_sem = EngCreateSemaphore();
+    if (!pdev->cmd_sem) {
+        PANIC(pdev, "cmd sem creation failed\n");
+    }
+    pdev->cursor_sem = EngCreateSemaphore();
+    if (!pdev->cursor_sem) {
+        PANIC(pdev, "cursor sem creation failed\n");
+    }
+    pdev->print_sem = EngCreateSemaphore();
+    if (!pdev->print_sem) {
+        PANIC(pdev, "print sem creation failed\n");
     }
 
-    if (global_res[id] == NULL) {
-        global_res[id] = EngAllocMem(FL_ZERO_MEMORY, sizeof(DevRes), ALLOC_TAG);
-        pdev->Res = global_res[id];
-        DEBUG_PRINT((pdev, 3, "%s: calling InitRes (id == %d)\n", __FUNCTION__, id));
-        InitRes(pdev);
-         DEBUG_PRINT((pdev, 1, "%s: called InitRes (id == %d)\n", __FUNCTION__, id));
-    } else {
-        pdev->Res = global_res[id];
+    ONDBG(pdev->num_outputs = 0);
+    ONDBG(pdev->num_path_pages = 0);
+    ONDBG(pdev->num_rects_pages = 0);
+    ONDBG(pdev->num_bits_pages = 0);
+    ONDBG(pdev->num_buf_pages = 0);
+    ONDBG(pdev->num_glyphs_pages = 0);
+    ONDBG(pdev->num_cursor_pages = 0);
+
+#ifdef CALL_TEST
+    pdev->count_calls = TRUE;
+    pdev->total_calls = 0;
+    for (i = 0; i < NUM_CALL_COUNTERS; i++) {
+        pdev->call_counters[i] = 0;
     }
+#endif
     DEBUG_PRINT((pdev, 1, "%s: exit\n", __FUNCTION__));
-    EngReleaseSemaphore(res_sem);
 }
 
 static QXLDrawable *GetDrawable(PDev *pdev)
@@ -693,7 +601,7 @@ static QXLDrawable *GetDrawable(PDev *pdev)
     RESOURCE_TYPE(output, RESOURCE_TYPE_DRAWABLE);
     ((QXLDrawable *)output->data)->release_info.id = (UINT64)output;
     DEBUG_PRINT((pdev, 9, "%s 0x%x\n", __FUNCTION__, output));
-    ONDBG(pdev->Res->num_outputs++); //todo: atomic
+    ONDBG(pdev->num_outputs++); //todo: atomic
     return(QXLDrawable *)output->data;
 }
 
@@ -726,13 +634,13 @@ void PushDrawable(PDev *pdev, QXLDrawable *drawable)
 {
     QXLCommand *cmd;
 
-    EngAcquireSemaphore(pdev->Res->cmd_sem);
+    EngAcquireSemaphore(pdev->cmd_sem);
     WaitForCmdRing(pdev);
     cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
     cmd->type = QXL_CMD_DRAW;
     cmd->data = PA(pdev, drawable, pdev->main_mem_slot);
     PUSH_CMD(pdev);
-    EngReleaseSemaphore(pdev->Res->cmd_sem);
+    EngReleaseSemaphore(pdev->cmd_sem);
 }
 
 static QXLSurfaceCmd *GetSurfaceCmd(PDev *pdev)
@@ -744,7 +652,7 @@ static QXLSurfaceCmd *GetSurfaceCmd(PDev *pdev)
     RESOURCE_TYPE(output, RESOURCE_TYPE_SURFACE);
     ((QXLSurfaceCmd *)output->data)->release_info.id = (UINT64)output;
     DEBUG_PRINT((pdev, 9, "%s 0x%x\n", __FUNCTION__, output));
-    ONDBG(pdev->Res->num_outputs++); //todo: atomic
+    ONDBG(pdev->num_outputs++); //todo: atomic
     return(QXLSurfaceCmd *)output->data;
 }
 
@@ -766,13 +674,13 @@ void PushSurfaceCmd(PDev *pdev, QXLSurfaceCmd *surface_cmd)
 {
     QXLCommand *cmd;
 
-    EngAcquireSemaphore(pdev->Res->cmd_sem);
+    EngAcquireSemaphore(pdev->cmd_sem);
     WaitForCmdRing(pdev);
     cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
     cmd->type = QXL_CMD_SURFACE;
     cmd->data = PA(pdev, surface_cmd, pdev->main_mem_slot);
     PUSH_CMD(pdev);
-    EngReleaseSemaphore(pdev->Res->cmd_sem);
+    EngReleaseSemaphore(pdev->cmd_sem);
 }
 
 QXLPHYSICAL SurfaceToPhysical(PDev *pdev, UINT8 *base_mem)
@@ -897,10 +805,10 @@ static void FreePath(PDev *pdev, Resource *res)
         QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
         chunk_phys = chunk->next_chunk;
         FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
-        ONDBG(pdev->Res->num_path_pages--);
+        ONDBG(pdev->num_path_pages--);
     }
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
-    ONDBG(pdev->Res->num_path_pages--);
+    ONDBG(pdev->num_path_pages--);
 
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
@@ -1004,7 +912,7 @@ static Resource *__GetPath(PDev *pdev, PATHOBJ *path)
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, PATH_ALLOC_SIZE);
-    ONDBG(pdev->Res->num_path_pages++);
+    ONDBG(pdev->num_path_pages++);
     res->refs = 1;
     res->free = FreePath;
     RESOURCE_TYPE(res, RESOURCE_TYPE_PATH);
@@ -1019,7 +927,7 @@ static Resource *__GetPath(PDev *pdev, PATHOBJ *path)
     now = chunk->data;
     end = (UINT8 *)res + PATH_ALLOC_SIZE;
     GetPathCommon(pdev, path, &chunk, &now, &end, &qxl_path->data_size,
-                  &pdev->Res->num_path_pages);
+                  &pdev->num_path_pages);
 
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
     return res;
@@ -1051,10 +959,10 @@ static void FreeClipRects(PDev *pdev, Resource *res)
         QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
         chunk_phys = chunk->next_chunk;
         FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
-        ONDBG(pdev->Res->num_rects_pages--);
+        ONDBG(pdev->num_rects_pages--);
     }
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
-    ONDBG(pdev->Res->num_rects_pages--);
+    ONDBG(pdev->num_rects_pages--);
 
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
@@ -1077,7 +985,7 @@ static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
 
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
     res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, RECTS_ALLOC_SIZE);
-    ONDBG(pdev->Res->num_rects_pages++);
+    ONDBG(pdev->num_rects_pages++);
     res->refs = 1;
     res->free = FreeClipRects;
     RESOURCE_TYPE(res, RESOURCE_TYPE_CLIP_RECTS);
@@ -1106,7 +1014,7 @@ static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
         for (now = buf.rects, end = now + buf.count; now < end; now++, dest++) {
             if (dest == dest_end) {
                 void *page = AllocMem(pdev, MSPACE_TYPE_DEVRAM, RECTS_CHUNK_ALLOC_SIZE);
-                ONDBG(pdev->Res->num_rects_pages++);
+                ONDBG(pdev->num_rects_pages++);
                 chunk->next_chunk = PA(pdev, page, pdev->main_mem_slot);
                 ((QXLDataChunk *)page)->prev_chunk = PA(pdev, chunk, pdev->main_mem_slot);
                 chunk = (QXLDataChunk *)page;
@@ -1460,12 +1368,10 @@ static void ImageKeyPut(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 key)
     if (!unique) {
         return;
     }
-    EngAcquireSemaphore(pdev->Res->image_cache_sem);
-    image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
+    image_key = &pdev->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
     image_key->hsurf = hsurf;
     image_key->unique = unique;
     image_key->key = key;
-    EngReleaseSemaphore(pdev->Res->image_cache_sem);
 }
 
 static BOOL ImageKeyGet(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 *key)
@@ -1476,13 +1382,11 @@ static BOOL ImageKeyGet(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 *key)
     if (!unique) {
         return FALSE;
     }
-    EngAcquireSemaphore(pdev->Res->image_cache_sem);
-    image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
+    image_key = &pdev->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
     if (image_key->hsurf == hsurf && image_key->unique == unique) {
         *key = image_key->key;
         res = TRUE;
     }
-    EngReleaseSemaphore(pdev->Res->image_cache_sem);
     return res;
 }
 
@@ -1493,8 +1397,7 @@ static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
 {
     CacheImage *cache_image;
 
-    EngAcquireSemaphore(pdev->Res->image_cache_sem);
-    cache_image = pdev->Res->image_cache[IMAGE_HASH_VAL(key)];
+    cache_image = pdev->image_cache[IMAGE_HASH_VAL(key)];
     while (cache_image) {
         if (cache_image->key == key && (!check_rest || (cache_image->format == format &&
             cache_image->width == width && cache_image->height == height))) {
@@ -1502,24 +1405,19 @@ static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
         }
         cache_image = cache_image->next;
     }
-    EngReleaseSemaphore(pdev->Res->image_cache_sem);
     return cache_image;
 }
 
-/* Called with image_cache_sem held */
 static void ImageCacheAdd(PDev *pdev, CacheImage *cache_image)
 {
     int key;
 
-    EngAcquireSemaphore(pdev->Res->image_cache_sem);
     key = IMAGE_HASH_VAL(cache_image->key);
-    cache_image->next = pdev->Res->image_cache[key];
+    cache_image->next = pdev->image_cache[key];
     cache_image->hits = 1;
-    pdev->Res->image_cache[key] = cache_image;
-    EngReleaseSemaphore(pdev->Res->image_cache_sem);
+    pdev->image_cache[key] = cache_image;
 }
 
-/* Called with image_cache_sem held */
 static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
 {
     CacheImage **cache_img;
@@ -1527,7 +1425,7 @@ static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
     if (!cache_image->hits) {
         return;
     }
-    cache_img = &pdev->Res->image_cache[IMAGE_HASH_VAL(cache_image->key)];
+    cache_img = &pdev->image_cache[IMAGE_HASH_VAL(cache_image->key)];
     while (*cache_img) {
         if ((*cache_img)->key == cache_image->key) {
             *cache_img = cache_image->next;
@@ -1537,19 +1435,18 @@ static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
     }
 }
 
-/* Called with image_cache_sem held */
 static CacheImage *AllocCacheImage(PDev* pdev)
 {
     RingItem *item;
-    while (!(item = RingGetTail(pdev, &pdev->Res->cache_image_lru))) {
+    while (!(item = RingGetTail(pdev, &pdev->cache_image_lru))) {
         /* malloc_sem protects release_ring too */
-        EngAcquireSemaphore(pdev->Res->malloc_sem);
-        if (pdev->Res->free_outputs == 0 &&
+        EngAcquireSemaphore(pdev->malloc_sem);
+        if (pdev->free_outputs == 0 &&
             SPICE_RING_IS_EMPTY(pdev->release_ring)) {
             WaitForReleaseRing(pdev);
         }
         FlushReleaseRing(pdev);
-        EngReleaseSemaphore(pdev->Res->malloc_sem);
+        EngReleaseSemaphore(pdev->malloc_sem);
     }
     RingRemove(pdev, item);
     return CONTAINEROF(item, CacheImage, lru_link);
@@ -1593,7 +1490,6 @@ static _inline void ReleasePalette(PDev *pdev, InternalPalette *palette)
     }
 }
 
-/* Called with palette_cache_sem held */
 static _inline void PaletteCacheRemove(PDev *pdev, InternalPalette *palette)
 {
     InternalPalette **internal;
@@ -1602,7 +1498,7 @@ static _inline void PaletteCacheRemove(PDev *pdev, InternalPalette *palette)
     DEBUG_PRINT((pdev, 15, "%s\n", __FUNCTION__));
 
     ASSERT(pdev, palette->palette.unique);
-    internal = &pdev->Res->palette_cache[PALETTE_HASH_VAL(palette->palette.unique)];
+    internal = &pdev->palette_cache[PALETTE_HASH_VAL(palette->palette.unique)];
 
     while (*internal) {
         if ((*internal)->palette.unique == palette->palette.unique) {
@@ -1615,7 +1511,7 @@ static _inline void PaletteCacheRemove(PDev *pdev, InternalPalette *palette)
 
     RingRemove(pdev, &palette->lru_link);
     ReleasePalette(pdev, palette);
-    pdev->Res->num_palettes--;
+    pdev->num_palettes--;
 
     if (!found) {
         DEBUG_PRINT((pdev, 0, "%s: Error: palette 0x%x isn't in cache \n", __FUNCTION__, palette));
@@ -1633,35 +1529,30 @@ static _inline InternalPalette *PaletteCacheGet(PDev *pdev, UINT32 unique)
     if (!unique) {
         return NULL;
     }
-    EngAcquireSemaphore(pdev->Res->palette_cache_sem);
 
-    now = pdev->Res->palette_cache[PALETTE_HASH_VAL(unique)];
+    now = pdev->palette_cache[PALETTE_HASH_VAL(unique)];
     while (now) {
         if (now->palette.unique == unique) {
             RingRemove(pdev, &now->lru_link);
-            RingAdd(pdev, &pdev->Res->palette_lru, &now->lru_link);
+            RingAdd(pdev, &pdev->palette_lru, &now->lru_link);
             now->refs++;
-            EngReleaseSemaphore(pdev->Res->palette_cache_sem);
             DEBUG_PRINT((pdev, 13, "%s: found\n", __FUNCTION__));
             return now;
         }
         now = now->next;
     }
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
-    EngReleaseSemaphore(pdev->Res->palette_cache_sem);
     return NULL;
 }
 
 static void PaletteCacheClear(PDev *pdev)
 {
     DEBUG_PRINT((pdev, 1, "%s\n", __FUNCTION__));
-    EngAcquireSemaphore(pdev->Res->palette_cache_sem);
-    while(pdev->Res->num_palettes) {
-        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->palette_lru));
-        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->palette_lru),
+    while(pdev->num_palettes) {
+        ASSERT(pdev, RingGetTail(pdev, &pdev->palette_lru));
+        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->palette_lru),
                                              InternalPalette, lru_link));
     }
-    EngReleaseSemaphore(pdev->Res->palette_cache_sem);
 }
 
 static _inline void PaletteCacheAdd(PDev *pdev, InternalPalette *palette)
@@ -1675,21 +1566,19 @@ static _inline void PaletteCacheAdd(PDev *pdev, InternalPalette *palette)
         return;
     }
 
-    EngAcquireSemaphore(pdev->Res->palette_cache_sem);
-    if (pdev->Res->num_palettes == PALETTE_CACHE_SIZE) {
-        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->palette_lru));
-        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->palette_lru),
+    if (pdev->num_palettes == PALETTE_CACHE_SIZE) {
+        ASSERT(pdev, RingGetTail(pdev, &pdev->palette_lru));
+        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->palette_lru),
                                              InternalPalette, lru_link));
     }
 
     key = PALETTE_HASH_VAL(palette->palette.unique);
-    palette->next = pdev->Res->palette_cache[key];
-    pdev->Res->palette_cache[key] = palette;
+    palette->next = pdev->palette_cache[key];
+    pdev->palette_cache[key] = palette;
 
-    RingAdd(pdev, &pdev->Res->palette_lru, &palette->lru_link);
+    RingAdd(pdev, &pdev->palette_lru, &palette->lru_link);
     palette->refs++;
-    pdev->Res->num_palettes++;
-    EngReleaseSemaphore(pdev->Res->palette_cache_sem);
+    pdev->num_palettes++;
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
 
@@ -1732,10 +1621,8 @@ static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
 
     internal = (InternalImage *)res->res;
     if (internal->cache) {
-        EngAcquireSemaphore(pdev->Res->image_cache_sem);
-        RingAdd(pdev, &pdev->Res->cache_image_lru, &internal->cache->lru_link);
+        RingAdd(pdev, &pdev->cache_image_lru, &internal->cache->lru_link);
         internal->cache->image = NULL;
-        EngReleaseSemaphore(pdev->Res->image_cache_sem);
     }
 
     chunk_phys = ((QXLDataChunk *)internal->image.quic.data)->next_chunk;
@@ -1743,11 +1630,11 @@ static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
         QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
         chunk_phys = chunk->next_chunk;
         FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
-        ONDBG(pdev->Res->num_bits_pages--);
+        ONDBG(pdev->num_bits_pages--);
 
     }
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
-    ONDBG(pdev->Res->num_bits_pages--);
+    ONDBG(pdev->num_bits_pages--);
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
 
@@ -1806,7 +1693,7 @@ static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_
 
     usr_data->chunk_io_words = alloc_size >> 2;
 
-    ONDBG(pdev->Res->num_bits_pages++);
+    ONDBG(pdev->num_bits_pages++);
 
     *io_ptr = (UINT32 *)new_chank->data;
     return usr_data->chunk_io_words;
@@ -1848,7 +1735,7 @@ static _inline Resource *GetQuicImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color
     alloc_size = MAX(alloc_size, QUIC_ALLOC_BASE + QUIC_BUF_MIN);
 
     image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
-    ONDBG(pdev->Res->num_bits_pages++);
+    ONDBG(pdev->num_bits_pages++);
     image_res->refs = 1;
     image_res->free = FreeQuicImage;
     RESOURCE_TYPE(image_res, RESOURCE_TYPE_QUIC_IMAGE);
@@ -1898,10 +1785,8 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
 
     internal = (InternalImage *)res->res;
     if (internal->cache) {
-        EngAcquireSemaphore(pdev->Res->image_cache_sem);
-        RingAdd(pdev, &pdev->Res->cache_image_lru, &internal->cache->lru_link);
+        RingAdd(pdev, &pdev->cache_image_lru, &internal->cache->lru_link);
         internal->cache->image = NULL;
-        EngReleaseSemaphore(pdev->Res->image_cache_sem);
     }
 
     if (internal->image.bitmap.palette) {
@@ -1915,12 +1800,12 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
         QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
         chunk_phys = chunk->next_chunk;
         FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
-        ONDBG(pdev->Res->num_bits_pages--);
+        ONDBG(pdev->num_bits_pages--);
 
     }
 
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
-    ONDBG(pdev->Res->num_bits_pages--);
+    ONDBG(pdev->num_bits_pages--);
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
 
@@ -1990,7 +1875,7 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
     alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size;
     alloc_size = MIN(BITMAP_ALLOC_BASE + height * line_size, alloc_size);
     image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
-    ONDBG(pdev->Res->num_bits_pages++);
+    ONDBG(pdev->num_bits_pages++);
 
     image_res->refs = 1;
     image_res->free = FreeBitmapImage;
@@ -2023,7 +1908,7 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
 #endif
     for (; src != src_end; src -= surf->lDelta, alloc_size -= line_size) {
         PutBytesAlign(pdev, &chunk, &dest, &dest_end, src, line_size,
-                      &pdev->Res->num_bits_pages, alloc_size, line_size, use_sse);
+                      &pdev->num_bits_pages, alloc_size, line_size, use_sse);
     }
 #ifndef _WIN64
     if (use_sse) {
@@ -2220,7 +2105,6 @@ static CacheImage *GetCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
 
     if (CacheSizeTest(pdev, surf)) {
         CacheImage *cache_image;
-        EngAcquireSemaphore(pdev->Res->image_cache_sem);
         cache_image = AllocCacheImage(pdev);
         ImageCacheRemove(pdev, cache_image);
         cache_image->key = key;
@@ -2229,13 +2113,13 @@ static CacheImage *GetCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
         cache_image->width = surf->sizlBitmap.cx;
         cache_image->height = surf->sizlBitmap.cy;
         ImageCacheAdd(pdev, cache_image);
-        RingAdd(pdev, &pdev->Res->cache_image_lru, &cache_image->lru_link);
-        EngReleaseSemaphore(pdev->Res->image_cache_sem);
+        RingAdd(pdev, &pdev->cache_image_lru, &cache_image->lru_link);
         DEBUG_PRINT((pdev, 11, "%s: ImageCacheAdd %u\n", __FUNCTION__, key));
     }
     return NULL;
 }
 
+// TODO: reconsider
 static HSEMAPHORE image_id_sem = NULL;
 
 static _inline UINT32 get_image_serial()
@@ -2302,7 +2186,7 @@ BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SU
         alloc_size = sizeof(Resource) + sizeof(InternalImage);
         image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
 
-        ONDBG(pdev->Res->num_bits_pages++);
+        ONDBG(pdev->num_bits_pages++);
         image_res->refs = 1;
         image_res->free = FreeSurfaceImage;
         RESOURCE_TYPE(image_res, RESOURCE_TYPE_SURFACE_IMAGE);
@@ -2469,7 +2353,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
         alloc_size = sizeof(Resource) + sizeof(InternalImage);
         image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
 
-        ONDBG(pdev->Res->num_bits_pages++);
+        ONDBG(pdev->num_bits_pages++);
         image_res->refs = 1;
         image_res->free = FreeSurfaceImage;
         RESOURCE_TYPE(image_res, RESOURCE_TYPE_SURFACE_IMAGE);
@@ -2523,7 +2407,6 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
         }
     } else if (CacheSizeTest(pdev, surf)) {
         CacheImage *cache_image;
-        EngAcquireSemaphore(pdev->Res->image_cache_sem);
         cache_image = AllocCacheImage(pdev);
         ImageCacheRemove(pdev, cache_image);
         cache_image->key = key;
@@ -2532,8 +2415,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
         cache_image->width = surf->sizlBitmap.cx;
         cache_image->height = surf->sizlBitmap.cy;
         ImageCacheAdd(pdev, cache_image);
-        RingAdd(pdev, &pdev->Res->cache_image_lru, &cache_image->lru_link);
-        EngReleaseSemaphore(pdev->Res->image_cache_sem);
+        RingAdd(pdev, &pdev->cache_image_lru, &cache_image->lru_link);
         DEBUG_PRINT((pdev, 11, "%s: ImageCacheAdd %u\n", __FUNCTION__, key));
     }
 
@@ -2619,7 +2501,7 @@ BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, QXLQMask *qxl_mask, SURFOBJ *
 
 static void FreeBuf(PDev *pdev, Resource *res)
 {
-    ONDBG(pdev->Res->num_buf_pages--);
+    ONDBG(pdev->num_buf_pages--);
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
 }
 
@@ -2634,7 +2516,7 @@ UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *buf_phys, UINT3
     }
 
     buf_res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, sizeof(Resource) + size);
-    ONDBG(pdev->Res->num_buf_pages++);
+    ONDBG(pdev->num_buf_pages++);
     buf_res->refs = 1;
     buf_res->free = FreeBuf;
     RESOURCE_TYPE(buf_res, RESOURCE_TYPE_BUF);
@@ -2659,26 +2541,26 @@ void UpdateArea(PDev *pdev, RECTL *area, UINT32 surface_id)
     output->num_res = 0;
     updat_cmd = (QXLUpdateCmd *)output->data;
     updat_cmd->release_info.id = (UINT64)output;
-    ONDBG(pdev->Res->num_outputs++); //todo: atomic
+    ONDBG(pdev->num_outputs++); //todo: atomic
 
     CopyRect(&updat_cmd->area, area);
-    updat_cmd->update_id = ++pdev->Res->update_id;
+    updat_cmd->update_id = ++pdev->update_id;
     updat_cmd->surface_id = surface_id;
 
-    EngAcquireSemaphore(pdev->Res->cmd_sem);
+    EngAcquireSemaphore(pdev->cmd_sem);
     WaitForCmdRing(pdev);
     cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
     cmd->type = QXL_CMD_UPDATE;
     cmd->data = PA(pdev, updat_cmd, pdev->main_mem_slot);
     PUSH_CMD(pdev);
-    EngReleaseSemaphore(pdev->Res->cmd_sem);
+    EngReleaseSemaphore(pdev->cmd_sem);
     do {
 #ifdef DBG
         {
             LARGE_INTEGER timeout; // 1 => 100 nanoseconds
             timeout.QuadPart = -1 * (1000 * 1000 * 10); //negative  => relative // 1s
             WAIT_FOR_EVENT(pdev, pdev->display_event, &timeout);
-            if (*pdev->dev_update_id != pdev->Res->update_id) {
+            if (*pdev->dev_update_id != pdev->update_id) {
                 DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
             }
         }
@@ -2686,7 +2568,7 @@ void UpdateArea(PDev *pdev, RECTL *area, UINT32 surface_id)
         WAIT_FOR_EVENT(pdev, pdev->display_event, NULL);
 #endif // DEBUG
         mb();
-    } while (*pdev->dev_update_id != pdev->Res->update_id);
+    } while (*pdev->dev_update_id != pdev->update_id);
 }
 
 #else
@@ -2718,7 +2600,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
         UINT32 stride;
 
         if (end - now < sizeof(*glyph)) {
-            NEW_DATA_CHUNK(&pdev->Res->num_glyphs_pages, PAGE_SIZE);
+            NEW_DATA_CHUNK(&pdev->num_glyphs_pages, PAGE_SIZE);
         }
 
         glyph = (QXLRasterGlyph *)now;
@@ -2758,7 +2640,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
                 UINT8 val;
                 int i;
                 if (end - now < sizeof(*bits_pos)) {
-                    NEW_DATA_CHUNK(&pdev->Res->num_glyphs_pages, PAGE_SIZE);
+                    NEW_DATA_CHUNK(&pdev->num_glyphs_pages, PAGE_SIZE);
                 }
                 *(UINT8 *)now = *bits_pos;
                 now += sizeof(*bits_pos);
@@ -2794,11 +2676,11 @@ static void FreeSring(PDev *pdev, Resource *res)
         QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
         chunk_phys = chunk->next_chunk;
         FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
-        ONDBG(pdev->Res->num_glyphs_pages--);
+        ONDBG(pdev->num_glyphs_pages--);
     }
 
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
-    ONDBG(pdev->Res->num_glyphs_pages--);
+    ONDBG(pdev->num_glyphs_pages--);
 
     DEBUG_PRINT((pdev, 14, "%s: done\n", __FUNCTION__));
 }
@@ -2822,7 +2704,7 @@ BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *str_phys, FONTOBJ
     DEBUG_PRINT((pdev, 9, "%s\n", __FUNCTION__));
 
     str_res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, TEXT_ALLOC_SIZE);
-    ONDBG(pdev->Res->num_glyphs_pages++);
+    ONDBG(pdev->num_glyphs_pages++);
     str_res->refs = 1;
     str_res->free = FreeSring;
     RESOURCE_TYPE(str_res, RESOURCE_TYPE_SRING);
@@ -2907,7 +2789,7 @@ QXLCursorCmd *CursorCmd(PDev *pdev)
     RESOURCE_TYPE(output, RESOURCE_TYPE_CURSOR);
     cursor_cmd = (QXLCursorCmd *)output->data;
     cursor_cmd->release_info.id = (UINT64)output;
-    ONDBG(pdev->Res->num_outputs++); //todo: atomic
+    ONDBG(pdev->num_outputs++); //todo: atomic
     DEBUG_PRINT((pdev, 8, "%s: done\n", __FUNCTION__));
     return cursor_cmd;
 }
@@ -2917,13 +2799,13 @@ void PushCursorCmd(PDev *pdev, QXLCursorCmd *cursor_cmd)
     QXLCommand *cmd;
 
     DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
-    EngAcquireSemaphore(pdev->Res->cursor_sem);
+    EngAcquireSemaphore(pdev->cursor_sem);
     WaitForCursorRing(pdev);
     cmd = SPICE_RING_PROD_ITEM(pdev->cursor_ring);
     cmd->type = QXL_CMD_CURSOR;
     cmd->data = PA(pdev, cursor_cmd, pdev->main_mem_slot);
     PUSH_CURSOR_CMD(pdev);
-    EngReleaseSemaphore(pdev->Res->cursor_sem);
+    EngReleaseSemaphore(pdev->cursor_sem);
     DEBUG_PRINT((pdev, 8, "%s: done\n", __FUNCTION__));
 }
 
@@ -2938,7 +2820,6 @@ typedef struct InternalCursor {
 
 #define CURSOR_HASH_VAL(hsurf) (HSURF_HASH_VAL(hsurf) & CURSOR_HASH_NASKE)
 
-/* Called with cursor_cache_sem held */
 static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
 {
     InternalCursor **internal;
@@ -2947,7 +2828,7 @@ static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
     DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
 
     ASSERT(pdev, cursor->unique);
-    internal = &pdev->Res->cursor_cache[CURSOR_HASH_VAL(cursor->hsurf)];
+    internal = &pdev->cursor_cache[CURSOR_HASH_VAL(cursor->hsurf)];
 
     while (*internal) {
         if ((*internal)->hsurf == cursor->hsurf) {
@@ -2963,7 +2844,7 @@ static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
 
     RingRemove(pdev, &cursor->lru_link);
     RELEASE_RES(pdev, (Resource *)((UINT8 *)cursor - sizeof(Resource)));
-    pdev->Res->num_cursors--;
+    pdev->num_cursors--;
 
     if (!found) {
         DEBUG_PRINT((pdev, 0, "%s: Error: cursor 0x%x isn't in cache \n", __FUNCTION__, cursor));
@@ -2977,13 +2858,11 @@ static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
 static void CursorCacheClear(PDev *pdev)
 {
     DEBUG_PRINT((pdev, 1, "%s\n", __FUNCTION__));
-    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
-    while (pdev->Res->num_cursors) {
-        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->cursors_lru));
-        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->cursors_lru),
+    while (pdev->num_cursors) {
+        ASSERT(pdev, RingGetTail(pdev, &pdev->cursors_lru));
+        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->cursors_lru),
                                             InternalCursor, lru_link));
     }
-    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
 }
 
 static void CursorCacheAdd(PDev *pdev, InternalCursor *cursor)
@@ -2996,21 +2875,19 @@ static void CursorCacheAdd(PDev *pdev, InternalCursor *cursor)
         return;
     }
 
-    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
-    if (pdev->Res->num_cursors == CURSOR_CACHE_SIZE) {
-        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->cursors_lru));
-        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->cursors_lru),
+    if (pdev->num_cursors == CURSOR_CACHE_SIZE) {
+        ASSERT(pdev, RingGetTail(pdev, &pdev->cursors_lru));
+        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->cursors_lru),
                                             InternalCursor, lru_link));
     }
 
     key = CURSOR_HASH_VAL(cursor->hsurf);
-    cursor->next = pdev->Res->cursor_cache[key];
-    pdev->Res->cursor_cache[key] = cursor;
+    cursor->next = pdev->cursor_cache[key];
+    pdev->cursor_cache[key] = cursor;
 
-    RingAdd(pdev, &pdev->Res->cursors_lru, &cursor->lru_link);
+    RingAdd(pdev, &pdev->cursors_lru, &cursor->lru_link);
     GET_RES((Resource *)((UINT8 *)cursor - sizeof(Resource)));
-    pdev->Res->num_cursors++;
-    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
+    pdev->num_cursors++;
 }
 
 static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
@@ -3022,15 +2899,13 @@ static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
         return NULL;
     }
 
-    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
-    internal = &pdev->Res->cursor_cache[CURSOR_HASH_VAL(hsurf)];
+    internal = &pdev->cursor_cache[CURSOR_HASH_VAL(hsurf)];
     while (*internal) {
         InternalCursor *now = *internal;
         if (now->hsurf == hsurf) {
             if (now->unique == unique) {
                 RingRemove(pdev, &now->lru_link);
-                RingAdd(pdev, &pdev->Res->cursors_lru, &now->lru_link);
-                EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
+                RingAdd(pdev, &pdev->cursors_lru, &now->lru_link);
                 return now;
             }
             CursorCacheRemove(pdev, now);
@@ -3038,7 +2913,6 @@ static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
         }
         internal = &now->next;
     }
-    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
     return NULL;
 }
 
@@ -3052,11 +2926,11 @@ static void FreeCursor(PDev *pdev, Resource *res)
         QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
         chunk_phys = chunk->next_chunk;
         FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
-        ONDBG(pdev->Res->num_cursor_pages--);
+        ONDBG(pdev->num_cursor_pages--);
     }
 
     FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
-    ONDBG(pdev->Res->num_cursor_pages--);
+    ONDBG(pdev->num_cursor_pages--);
 
     DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
 }
@@ -3136,7 +3010,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
 
     ASSERT(pdev, sizeof(Resource) + sizeof(InternalCursor) < CURSOR_ALLOC_SIZE);
     res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, CURSOR_ALLOC_SIZE);
-    ONDBG(pdev->Res->num_cursor_pages++);
+    ONDBG(pdev->num_cursor_pages++);
     res->refs = 1;
     res->free = FreeCursor;
     RESOURCE_TYPE(res, RESOURCE_TYPE_CURSOR);
@@ -3148,9 +3022,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
 
     cursor = info->cursor = &internal->cursor;
     cursor->header.type = type;
-    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
-    cursor->header.unique = unique ? ++pdev->Res->last_cursor_id : 0;
-    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
+    cursor->header.unique = unique ? ++pdev->last_cursor_id : 0;
     cursor->header.width = (UINT16)local_surf->sizlBitmap.cx;
     cursor->header.height = (type == SPICE_CURSOR_TYPE_MONO) ? (UINT16)local_surf->sizlBitmap.cy >> 1 :
                             (UINT16)local_surf->sizlBitmap.cy;
@@ -3194,7 +3066,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
     src_end = src + (local_surf->lDelta * local_surf->sizlBitmap.cy);
     for (; src != src_end; src += local_surf->lDelta) {
         PutBytes(pdev, &info->chunk, &info->now, &info->end, src, line_size,
-                 &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
+                 &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
     }
 
     CursorCacheAdd(pdev, internal);
@@ -3313,14 +3185,14 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
             if (pdev->bitmap_format == BMF_32BPP) {
                 PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)color_trans->pulXlate,
-                         256 << 2, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
+                         256 << 2, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
             } else {
                 int i;
 
                 for (i = 0; i < 256; i++) {
                     UINT32 ent = _16bppTo32bpp(color_trans->pulXlate[i]);
                     PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)&ent,
-                             4, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
+                             4, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
                 }
             }
             info.cursor->data_size += 256 << 2;
@@ -3333,14 +3205,14 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
             if (pdev->bitmap_format == BMF_32BPP) {
                 PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)color_trans->pulXlate,
-                         16 << 2, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
+                         16 << 2, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
             } else {
                 int i;
 
                 for (i = 0; i < 16; i++) {
                     UINT32 ent = _16bppTo32bpp(color_trans->pulXlate[i]);
                     PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)&ent,
-                             4, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
+                             4, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
                 }
             }
             info.cursor->data_size += 16 << 2;
@@ -3356,7 +3228,7 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
 
         for (; src != src_end; src += mask->lDelta) {
             PutBytes(pdev, &info.chunk, &info.now, &info.end, src, line_size,
-                     &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
+                     &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
         }
     }
 
@@ -3374,7 +3246,7 @@ BOOL GetTransparentCursor(PDev *pdev, QXLCursorCmd *cmd)
     ASSERT(pdev, sizeof(Resource) + sizeof(InternalCursor) < PAGE_SIZE);
 
     res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, sizeof(Resource) + sizeof(InternalCursor));
-    ONDBG(pdev->Res->num_cursor_pages++);
+    ONDBG(pdev->num_cursor_pages++);
     res->refs = 1;
     res->free = FreeCursor;
     RESOURCE_TYPE(res, RESOURCE_TYPE_CURSOR);
diff --git a/display/res.h b/display/res.h
index d447cee..d69986e 100644
--- a/display/res.h
+++ b/display/res.h
@@ -73,6 +73,5 @@ void CheckAndSetSSE2();
 void EmptyReleaseRing(PDev *pdev);
 void InitDeviceMemoryResources(PDev *pdev);
 void ReleaseCacheDeviceMemoryResources(PDev *pdev);
-extern DevRes **global_res;
 
 #endif
diff --git a/display/surface.c b/display/surface.c
index 8422cd3..60bbd99 100644
--- a/display/surface.c
+++ b/display/surface.c
@@ -208,14 +208,15 @@ VOID DeleteDeviceBitmap(PDev *pdev, UINT32 surface_id, UINT8 allocation_type)
     FreeDrawArea(drawarea);
 
     if (allocation_type != DEVICE_BITMAP_ALLOCATION_TYPE_SURF0 &&
-        pdev->Res->surfaces_info[surface_id].draw_area.base_mem != NULL) {
+        pdev->surfaces_info[surface_id].draw_area.base_mem != NULL) {
 
         if (allocation_type == DEVICE_BITMAP_ALLOCATION_TYPE_RAM) {
             /* server side this surface is already destroyed, just free it here */
-            ASSERT(pdev, pdev->Res->surfaces_info[surface_id].draw_area.base_mem ==
-                pdev->Res->surfaces_info[surface_id].copy);
-            QXLDelSurface(pdev, pdev->Res->surfaces_info[surface_id].draw_area.base_mem,
-                allocation_type);
+            ASSERT(pdev, pdev->surfaces_info[surface_id].draw_area.base_mem ==
+                         pdev->surfaces_info[surface_id].copy);
+            QXLDelSurface(pdev,
+                          pdev->surfaces_info[surface_id].draw_area.base_mem,
+                          allocation_type);
             FreeSurfaceInfo(pdev, surface_id);
         } else {
             QXLSurfaceCmd *surface_cmd;
@@ -286,7 +287,7 @@ int MoveAllSurfacesToVideoRam(PDev *pdev)
     SurfaceInfo *surface_info;
 
     /* brute force implementation - alternative is to keep an updated used_surfaces list */
-    DEBUG_PRINT((pdev, 3, "%s\n", __FUNCTION__));
+    DEBUG_PRINT((pdev, 3, "%s %p\n", __FUNCTION__, pdev));
 
     for (surface_id = 1 ; surface_id < pdev->n_surfaces ; ++surface_id) {
         surface_info = GetSurfaceInfo(pdev, surface_id);
diff --git a/display/surface.h b/display/surface.h
index d770884..c3e5a47 100644
--- a/display/surface.h
+++ b/display/surface.h
@@ -26,7 +26,7 @@ static _inline UINT32 GetSurfaceIdFromInfo(SurfaceInfo *info)
   if (info == &pdev->surface0_info) {
     return 0;
   }
-  return (UINT32)(info - pdev->Res->surfaces_info);
+  return (UINT32)(info - pdev->surfaces_info);
 }
 
 static _inline SurfaceInfo *GetSurfaceInfo(PDev *pdev, UINT32 id)
@@ -34,7 +34,7 @@ static _inline SurfaceInfo *GetSurfaceInfo(PDev *pdev, UINT32 id)
   if (id == 0) {
     return &pdev->surface0_info;
   }
-  return &pdev->Res->surfaces_info[id];
+  return &pdev->surfaces_info[id];
 }
 
 static _inline UINT32 GetSurfaceId(SURFOBJ *surf)
@@ -55,42 +55,34 @@ static _inline void FreeSurfaceInfo(PDev *pdev, UINT32 surface_id)
     if (surface_id == 0) {
         return;
     }
-    EngAcquireSemaphore(pdev->Res->surface_sem);
 
     DEBUG_PRINT((pdev, 9, "%s: %p: %d\n", __FUNCTION__, pdev, surface_id));
-    surface = &pdev->Res->surfaces_info[surface_id];
+    surface = &pdev->surfaces_info[surface_id];
     if (surface->draw_area.base_mem == NULL) {
         DEBUG_PRINT((pdev, 9, "%s: %p: %d: double free. safely ignored\n", __FUNCTION__,
-            pdev, surface_id));
-        EngReleaseSemaphore(pdev->Res->surface_sem);
+                     pdev, surface_id));
         return;
     }
     surface->draw_area.base_mem = NULL; /* Mark as not used */
-    surface->u.next_free = pdev->Res->free_surfaces;
-    pdev->Res->free_surfaces = surface;
-
-    EngReleaseSemaphore(pdev->Res->surface_sem);
+    surface->u.next_free = pdev->free_surfaces;
+    pdev->free_surfaces = surface;
 }
 
-
 static UINT32 GetFreeSurface(PDev *pdev)
 {
     UINT32 x, id;
     SurfaceInfo *surface;
 
-    EngAcquireSemaphore(pdev->Res->surface_sem);
-
-    surface = pdev->Res->free_surfaces;
+    ASSERT(pdev, pdev->enabled);
+    surface = pdev->free_surfaces;
     if (surface == NULL) {
         id = 0;
     } else {
-      pdev->Res->free_surfaces = surface->u.next_free;
+      pdev->free_surfaces = surface->u.next_free;
 
-      id = (UINT32)(surface - pdev->Res->surfaces_info);
+      id = (UINT32)(surface - pdev->surfaces_info);
     }
 
-    EngReleaseSemaphore(pdev->Res->surface_sem);
-
     return id;
 }
 
commit dcdfa5779dd2884384aa7780b66c399aaf0eb937
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Sun Aug 21 11:30:28 2011 +0300

    display: support clearing the pci-bar when the pdev is disabled for revision<3 as well, RHBZ #731644
    
    see also commit "display/driver: reimplement DrvAssertMode for Suspend+Hibernate (S3+S4) support".
    
    In revision < 3, objects (surfaces and other devram objects) stayed alive in the pci ram
    after DrvAssertMode(Disable) was called. Then, when another display driver session started (upon switch user),
    the driver had newly initiated mspace, but an old release ring (with objects from the older session's mspace).
    This state led to a crash.

diff --git a/display/driver.c b/display/driver.c
index 252d429..935567d 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -957,24 +957,82 @@ VOID DrvDisableSurface(DHPDEV in_pdev)
     DEBUG_PRINT((pdev, 1, "%s: 0x%lx exit\n", __FUNCTION__, pdev));
 }
 
+static void FlushSurfaces(PDev *pdev)
+{
+    UINT32 surface_id;
+    SurfaceInfo *surface_info;
+    SURFOBJ *surf_obj;
+    RECTL area = {0, 0, 0, 0};
+
+    if (pdev->pci_revision < QXL_REVISION_STABLE_V10) {
+        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_SURFACES", __FUNCTION__));
+        for (surface_id = pdev->n_surfaces - 1; surface_id >  0 ; --surface_id) {
+            surface_info = GetSurfaceInfo(pdev, surface_id);
+
+            if (!surface_info->draw_area.base_mem) {
+                continue;
+            }
+            surf_obj = surface_info->draw_area.surf_obj;
+            if (!surf_obj) {
+                continue;
+            }
+            area.right = surf_obj->sizlBitmap.cx;
+            area.bottom = surf_obj->sizlBitmap.cy;
+            UpdateArea(pdev,&area, surface_id);
+        }
+    } else {
+        async_io(pdev, ASYNCABLE_FLUSH_SURFACES, 0);
+    }
+}
+
+static BOOL FlushRelease(PDev *pdev)
+{
+    if (pdev->pci_revision<  QXL_REVISION_STABLE_V10) {
+        DWORD length;
+
+        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_RELEASE", __FUNCTION__));
+        if (EngDeviceIoControl(pdev->driver, IOCTL_VIDEO_RESET_DEVICE,
+                               NULL, 0, NULL, 0, &length)) {
+            DEBUG_PRINT((NULL, 0, "%s: reset failed 0x%lx\n", __FUNCTION__, pdev));
+            return FALSE;
+        }
+    } else {
+        /* Free release ring contents */
+        ReleaseCacheDeviceMemoryResources(pdev);
+        EmptyReleaseRing(pdev);
+        /* Get the last free list onto the release ring */
+        sync_io(pdev, pdev->flush_release_port, 0);
+        DEBUG_PRINT((pdev, 4, "%s after FLUSH_RELEASE\n", __FUNCTION__));
+        /* And release that. mspace allocators should be clean after. */
+        EmptyReleaseRing(pdev);
+    }
+    return TRUE;
+}
+
 static BOOL AssertModeDisable(PDev *pdev)
 {
     DEBUG_PRINT((pdev, 3, "%s entry\n", __FUNCTION__));
     /* flush command ring and update all surfaces */
-    async_io(pdev, ASYNCABLE_FLUSH_SURFACES, 0);
+    FlushSurfaces(pdev);
+    DebugCountAliveSurfaces(pdev);
+    /*
+     * this call is redundant for
+     * pci_revision <  QXL_REVISION_STABLE_V10, due to the
+     * IOCTL_VIDEO_RESET_DEVICE in FlushRelease. However,
+     * MoveAllSurfacesToRam depends on destroy_all_surfaces
+     * in case of failure.
+     * TODO: make MoveAllSurfacesToRam send destroy_surface
+     * commands instead of create_surface commands in case
+     * of failure
+     */
     async_io(pdev, ASYNCABLE_DESTROY_ALL_SURFACES, 0);
     /* move all surfaces from device to system memory */
     if (!MoveAllSurfacesToRam(pdev)) {
         return FALSE;
     }
-    /* Free release ring contents */
-    ReleaseCacheDeviceMemoryResources(pdev);
-    EmptyReleaseRing(pdev);
-    /* Get the last free list onto the release ring */
-    sync_io(pdev, pdev->flush_release_port, 0);
-    DEBUG_PRINT((pdev, 4, "%s after FLUSH_RELEASE\n", __FUNCTION__));
-    /* And release that. mspace allocators should be clean after. */
-    EmptyReleaseRing(pdev);
+    if (!FlushRelease(pdev)) {
+        return FALSE;
+    }
     RemoveVRamSlot(pdev);
     DebugCountAliveSurfaces(pdev);
     DEBUG_PRINT((pdev, 4, "%s: [%d,%d] [%d,%d] [%d,%d] %lx\n", __FUNCTION__,
@@ -1002,31 +1060,12 @@ static void AssertModeEnable(PDev *pdev)
     DebugCountAliveSurfaces(pdev);
 }
 
-BOOL DrvAssertModeOld(PDev *pdev, BOOL enable)
-{
-    if (enable) {
-        InitResources(pdev);
-        EnableQXLPrimarySurface(pdev);
-        CreateVRamSlot(pdev);
-    } else {
-        DisableQXLPrimarySurface(pdev, 0);
-        RemoveVRamSlot(pdev);
-    }
-    DEBUG_PRINT((pdev, 1, "%s: 0x%lx exit %d\n", __FUNCTION__, pdev, enable));
-    return TRUE;
-}
-
 BOOL DrvAssertMode(DHPDEV in_pdev, BOOL enable)
 {
     PDev* pdev = (PDev*)in_pdev;
     BOOL ret = TRUE;
 
-    DEBUG_PRINT((pdev, 1, "%s: 0x%lx %d\n", __FUNCTION__, pdev, enable));
-    if (pdev->pci_revision < QXL_REVISION_STABLE_V10) {
-        return DrvAssertModeOld(pdev, enable);
-    }
-    /* new implementation that works correctly only with newer devices
-     * that implement QXL_IO_FLUSH_RELEASE */
+    DEBUG_PRINT((pdev, 1, "%s: 0x%lx revision %d enable %d\n", __FUNCTION__, pdev, pdev->pci_revision, enable));
     if (pdev->enabled == enable) {
         DEBUG_PRINT((pdev, 1, "%s: called twice with same argument (%d)\n", __FUNCTION__,
             enable));
diff --git a/display/res.c b/display/res.c
index 850d35a..1274f43 100644
--- a/display/res.c
+++ b/display/res.c
@@ -676,10 +676,11 @@ void InitResources(PDev *pdev)
         pdev->Res = global_res[id];
         DEBUG_PRINT((pdev, 3, "%s: calling InitRes (id == %d)\n", __FUNCTION__, id));
         InitRes(pdev);
+         DEBUG_PRINT((pdev, 1, "%s: called InitRes (id == %d)\n", __FUNCTION__, id));
     } else {
         pdev->Res = global_res[id];
     }
-    DEBUG_PRINT((pdev, 3, "%s: exit\n", __FUNCTION__));
+    DEBUG_PRINT((pdev, 1, "%s: exit\n", __FUNCTION__));
     EngReleaseSemaphore(res_sem);
 }
 
diff --git a/display/surface.c b/display/surface.c
index b40721d..8422cd3 100644
--- a/display/surface.c
+++ b/display/surface.c
@@ -359,6 +359,12 @@ BOOL MoveAllSurfacesToRam(PDev *pdev)
             DEBUG_PRINT((pdev, 0, "%s: %d: EngModifySurface failed, sending create\n",
                          __FUNCTION__, surface_id));
             phys_mem = SurfaceToPhysical(pdev, surface_info->draw_area.base_mem);
+            /*
+             * TODO: bug. create_command should be send for all surfaces >= surface_id
+             *       since they stay in the pci-bar. Alternatively,
+             *       don't call destroy_all_surfaces, instead send destroy commands
+             *       for all surfaces with id < surface_id.
+             */
             SendSurfaceCreateCommand(pdev, surface_id, surf_obj->sizlBitmap,
                                      surface_info->bitmap_format, -surf_obj->lDelta, phys_mem,
                                      /* the surface is still there, tell server not to erase */
commit 8dc61f6a1680ee01189d05bf3e86ef681f197a79
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Sun Aug 21 11:26:31 2011 +0300

    display: not reset devices on DrvDisableDriver, RHBZ #731644
    
    When several sessions of the display driver are alive,
    DrvDisableDriver can be called for the older session while the newer session has already started.
    It happens when you switch users on a dual monitor XP guest. Reseting the devices in DrvDisableDriver
    while they are used by another session leads to a BSOD.

diff --git a/display/driver.c b/display/driver.c
index 00dd7ec..252d429 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -256,7 +256,6 @@ BOOL DrvEnableDriver(ULONG engine_version, ULONG enable_data_size, PDRVENABLEDAT
 VOID DrvDisableDriver(VOID)
 {
     DEBUG_PRINT((NULL, 1, "%s\n", __FUNCTION__));
-    ResetAllDevices();
     ResDestroyGlobals();
     CleanGlobalRes();
 }
diff --git a/display/res.c b/display/res.c
index 5d28184..850d35a 100644
--- a/display/res.c
+++ b/display/res.c
@@ -3512,23 +3512,3 @@ void CheckAndSetSSE2()
 }
 
 #endif
-
-void ResetAllDevices()
-{
-    UINT32 i;
-    EngAcquireSemaphore(res_sem);
-
-    for (i = 0; i < num_global_res; i++) {
-        if (global_res[i] && global_res[i]->driver) {
-            DWORD length;
-            if (EngDeviceIoControl(global_res[i]->driver, IOCTL_VIDEO_RESET_DEVICE,
-                                   NULL, 0, NULL, 0, &length)) {
-                DEBUG_PRINT((NULL, 0, "%s: reset to device failed 0x%lx\n",
-                            __FUNCTION__, global_res[i]->driver));
-                
-            }
-        }
-    }
-
-    EngReleaseSemaphore(res_sem);
-}
diff --git a/display/res.h b/display/res.h
index 1feadb0..d447cee 100644
--- a/display/res.h
+++ b/display/res.h
@@ -70,7 +70,6 @@ void ResDestroyGlobals();
 #ifndef _WIN64
 void CheckAndSetSSE2();
 #endif
-void ResetAllDevices();
 void EmptyReleaseRing(PDev *pdev);
 void InitDeviceMemoryResources(PDev *pdev);
 void ReleaseCacheDeviceMemoryResources(PDev *pdev);
commit 6f5cf2dbcc876c82db5cd870ef21104b7b83c838
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Wed Aug 17 14:48:39 2011 +0300

    miniport: map vram to virtual address only once, #722954
    
    Drv<Enable/Disbale>Surface calls IOCTL_VIDEO_MAP/UNMAP_VIDEO_MEMORY respectively.
    These calls make the miniport map/unmap the vram to/from system space.
    The BSOD occurred since with qxl revision 2, the driver assumes that
    as long as it is loaded the vram stays (and all the other mem slots) valid
    and in the same place. However, the miniport's call to VideoPortMapMemory
    (in IOCTL_VIDEO_MAP_VIDEO_MEMORY) is not guaranteed to map the vram to the same
    virtual address. As a result, when the driver accessed to an mspace instance
    that was initialized with a no longer valid virtual address, we got BSOD.
    
    Since we don't change the size of the vram, I see no point in mapping and
    unmapping it more then once.
    
    For qxl revision 3 this problem is not relevant since between DrvAssertMode(disable)
    to DrvAssertMode(enable) we clear the pci ram and initialize all
    the data structure that are related to it (mspace, caches, etc.)
    
    I didn't remove the calls to IOCTL_VIDEO_MAP/UNMAP_VIDEO_MEMORY
    since I think they would be useful for supporting dynamically changing the
    size of the memslots according to the current resolution. Which I think is the
    real purpose of IOCTL_VIDEO_MAP/UNMAP_VIDEO_MEMORY. Today, the size
    of the frame buffer (surface0) is static -> the maximal resolution we support.

diff --git a/miniport/qxl.c b/miniport/qxl.c
index 40e8379..7006adf 100644
--- a/miniport/qxl.c
+++ b/miniport/qxl.c
@@ -324,6 +324,11 @@ VP_STATUS InitVRAM(QXLExtension *dev, PVIDEO_ACCESS_RANGE range);
 
 VP_STATUS InitVRAM(QXLExtension *dev, PVIDEO_ACCESS_RANGE range)
 {
+    UINT8 *vram_addr = NULL;
+    ULONG vram_mapped_size = range->RangeLength;
+    ULONG io_space = VIDEO_MEMORY_SPACE_MEMORY;
+    VP_STATUS error;
+
     PAGED_CODE();
     DEBUG_PRINT((dev, 0, "%s\n", __FUNCTION__));
 
@@ -332,10 +337,24 @@ VP_STATUS InitVRAM(QXLExtension *dev, PVIDEO_ACCESS_RANGE range)
         return ERROR_INVALID_DATA;
     }
 
+    if ((error = VideoPortMapMemory(dev, range->RangeStart,
+                                    &vram_mapped_size,
+                                    &io_space,
+                                    &vram_addr))) {
+        DEBUG_PRINT((dev, 0, "%s: map vram failed\n",  __FUNCTION__));
+        return error;
+    }
+
+    if (vram_mapped_size < range->RangeLength) {
+        DEBUG_PRINT((dev, 0, "%s: vram shrinked\n", __FUNCTION__));
+        VideoPortUnmapMemory(dev, vram_addr, NULL);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
     dev->vram_physical = range->RangeStart;
+    dev->vram_start = vram_addr;
     dev->vram_size = range->RangeLength;
-    DEBUG_PRINT((dev, 0, "%s: OK, vram 0x%lx size %lu\n",
-                 __FUNCTION__, (ULONG)range->RangeStart.QuadPart, range->RangeLength));
+    DEBUG_PRINT((dev, 0, "%s: OK, vram 0x%lx size %lu vaddr 0x%lx\n", __FUNCTION__,
+                (ULONG)range->RangeStart.QuadPart, range->RangeLength, dev->vram_start));
     return NO_ERROR;
 }
 
@@ -577,6 +596,10 @@ void DevExternsionCleanup(QXLExtension *dev)
         VideoPortUnmapMemory(dev, dev->ram_start, NULL);
     }
 
+    if (dev->vram_start) {
+        VideoPortUnmapMemory(dev, dev->vram_start, NULL);
+    }
+
     if (dev->modes) {
         VideoPortFreePool(dev, dev->modes);
     }
@@ -966,7 +989,6 @@ BOOLEAN StartIO(PVOID dev_extension, PVIDEO_REQUEST_PACKET packet)
         break;
     case IOCTL_VIDEO_MAP_VIDEO_MEMORY: {
             PVIDEO_MEMORY_INFORMATION mem_info;
-            ULONG fb_io_space;
 
             DEBUG_PRINT((dev_ext, 0, "%s: IOCTL_VIDEO_MAP_VIDEO_MEMORY\n", __FUNCTION__));
 
@@ -976,36 +998,11 @@ BOOLEAN StartIO(PVOID dev_extension, PVIDEO_REQUEST_PACKET packet)
                 error = ERROR_INSUFFICIENT_BUFFER;
                 goto err;
             }
-            mem_info = packet->OutputBuffer;
 
-            mem_info->VideoRamBase =
-                                    ((PVIDEO_MEMORY)(packet->InputBuffer))->RequestedVirtualAddress;
-            ASSERT(mem_info->VideoRamBase == NULL);
-            mem_info->VideoRamLength = dev_ext->vram_size;
-            fb_io_space = VIDEO_MEMORY_SPACE_MEMORY;
-
-            if ((error = VideoPortMapMemory(dev_ext, dev_ext->vram_physical,
-                                            &mem_info->VideoRamLength,
-                                            &fb_io_space, &mem_info->VideoRamBase)) != NO_ERROR) {
-                DEBUG_PRINT((dev_ext, 0, "%s: map filed\n", __FUNCTION__));
-                goto err;
-            }
-            dev_ext->vram_start = mem_info->VideoRamBase;
-            DEBUG_PRINT((dev_ext, 0, "%s: vram size %lu ret size %lu fb vaddr 0x%lx\n",
-                         __FUNCTION__,
-                         dev_ext->vram_size,
-                         mem_info->VideoRamLength,
-                         mem_info->VideoRamBase));
-            if (mem_info->VideoRamLength < dev_ext->vram_size) {
-                DEBUG_PRINT((dev_ext, 0, "%s: fb shrink\n", __FUNCTION__));
-                VideoPortUnmapMemory(dev_ext, mem_info->VideoRamBase, NULL);
-                mem_info->VideoRamBase = NULL;
-                mem_info->VideoRamLength = 0;
-                error = ERROR_NOT_ENOUGH_MEMORY;
-                goto err;
-            }
-            mem_info->FrameBufferBase = mem_info->VideoRamBase;
-            mem_info->FrameBufferLength = mem_info->VideoRamLength;
+            ASSERT(((PVIDEO_MEMORY)(packet->InputBuffer))->RequestedVirtualAddress == NULL);
+            mem_info = packet->OutputBuffer;
+            mem_info->VideoRamBase = mem_info->FrameBufferBase = dev_ext->vram_start;
+            mem_info->VideoRamLength = mem_info->FrameBufferLength = dev_ext->vram_size;
 #if 0
 #ifdef DBG
             DEBUG_PRINT((dev, 0, "%s: zap\n", __FUNCTION__));
@@ -1016,19 +1013,7 @@ BOOLEAN StartIO(PVOID dev_extension, PVIDEO_REQUEST_PACKET packet)
         }
         break;
     case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: {
-            PVOID addr;
-
-            DEBUG_PRINT((dev_ext, 0, "%s: IOCTL_VIDEO_UNMAP_VIDEO_MEMORY\n", __FUNCTION__));
-
-            if (packet->InputBufferLength < sizeof(VIDEO_MEMORY)) {
-                error = ERROR_INSUFFICIENT_BUFFER;
-                goto err;
-            }
-            addr = ((PVIDEO_MEMORY)(packet->InputBuffer))->RequestedVirtualAddress;
-            if ((error = VideoPortUnmapMemory(dev_ext, addr, NULL)) != NO_ERROR) {
-                DEBUG_PRINT((dev_ext, 0, "%s: unmap failed\n", __FUNCTION__));
-            }
-            dev_ext->vram_start = NULL;
+            DEBUG_PRINT((dev_ext, 0, "%s: IOCTL_VIDEO_UNMAP_VIDEO_MEMORY (do nothing) \n", __FUNCTION__));
         }
         break;
     case IOCTL_VIDEO_RESET_DEVICE:


More information about the Spice-commits mailing list