aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaroslav Hensl <emulator@emulace.cz>2024-07-24 12:19:00 +0200
committerJaroslav Hensl <emulator@emulace.cz>2024-07-24 12:19:00 +0200
commit8848d29ef67f41ed995ae173eed4fe1140e8bfeb (patch)
tree878ebf2264a33bd7a17e79b2dca1ca99d75058ca
parent84061f384d2ddf0ee0242932df9a9e9a0829d81a (diff)
downloadvmdisp9x-8848d29ef67f41ed995ae173eed4fe1140e8bfeb.tar.gz
vxd_svga.c split
-rw-r--r--makefile10
-rw-r--r--vxd_svga.c1432
-rw-r--r--vxd_svga.h46
-rw-r--r--vxd_svga_cb.c606
-rw-r--r--vxd_svga_mem.c932
5 files changed, 1597 insertions, 1429 deletions
diff --git a/makefile b/makefile
index 20cf9b3..028cf83 100644
--- a/makefile
+++ b/makefile
@@ -8,7 +8,7 @@ OBJS += &
dbgprint32.obj svga.obj pci.obj vxd_fbhda.obj vxd_lib.obj vxd_main.obj &
vxd_main_qemu.obj vxd_main_svga.obj vxd_svga.obj vxd_vdd.obj vxd_vdd_qemu.obj &
vxd_vdd_svga.obj vxd_vbe.obj vxd_vbe_qemu.obj vxd_mouse.obj vxd_svga_st.obj &
- vxd_mouse_svga.obj vxd_svga_mouse.obj
+ vxd_mouse_svga.obj vxd_svga_mouse.obj vxd_svga_mem.obj vxd_svga_cb.obj
INCS = -I$(%WATCOM)\h\win -Iddk -Ivmware
@@ -170,6 +170,12 @@ vxd_svga_st.obj : vxd_svga_st.c .autodepend
vxd_svga_mouse.obj : vxd_svga_mouse.c .autodepend
$(CC32) $(CFLAGS32) $(INCS) $(FLAGS) $<
+vxd_svga_mem.obj : vxd_svga_mem.c .autodepend
+ $(CC32) $(CFLAGS32) $(INCS) $(FLAGS) $<
+
+vxd_svga_cb.obj : vxd_svga_cb.c .autodepend
+ $(CC32) $(CFLAGS32) $(INCS) $(FLAGS) $<
+
vxd_vbe.obj : vxd_vbe.c .autodepend
$(CC32) $(CFLAGS32) $(INCS) $(FLAGS) $<
@@ -434,6 +440,8 @@ file vxd_lib.obj
file vxd_svga.obj
file vxd_svga_st.obj
file vxd_svga_mouse.obj
+file vxd_svga_mem.obj
+file vxd_svga_cb.obj
file vxd_vdd_svga.obj
file vxd_mouse_svga.obj
segment '_LTEXT' PRELOAD NONDISCARDABLE
diff --git a/vxd_svga.c b/vxd_svga.c
index 1a9cb34..73b8bda 100644
--- a/vxd_svga.c
+++ b/vxd_svga.c
@@ -48,24 +48,7 @@ THE SOFTWARE.
/*
* consts
*/
-//#define SVGA3D_MAX_MOBS 33280UL /* SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_SURFACE_IDS */
#define SVGA3D_MAX_MOBS (SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_SURFACE_IDS)
-#define VBOX_VIDEO_MAX_SCREENS 64
-
-#define PTONPAGE (P_SIZE/sizeof(DWORD))
-
-#define SPARE_REGIONS_LARGE 2
-#define SPARE_REGION_LARGE_SIZE (32*1024*1024)
-
-#define SPARE_REGIONS_MEDIUM 16
-#define SPARE_REGION_MEDIUM_SIZE (1024*1024)
-
-#define SPARE_REGIONS_SMALL 128
-//#define SPARE_REGION_SMALL_SIZE 4096
-
-#define SPARE_REGIONS_CNT (SPARE_REGIONS_LARGE+SPARE_REGIONS_MEDIUM+SPARE_REGIONS_SMALL)
-
-#define CACHE_THRESHOLD 128
#define SVGA_MIN_VRAM 8
@@ -73,66 +56,6 @@ THE SOFTWARE.
BOOL CB_queue_check(SVGACBHeader *tracked);
-#define WAIT_FOR_CB(_cb, _forcesync) \
- do{ \
- /*dbg_printf(dbg_wait_cb, __LINE__);*/ \
- while(!CB_queue_check(_cb)){ \
- WAIT_FOR_CB_SYNC_ ## _forcesync \
- } \
- }while(0)
-
-/* expansions of WAIT_FOR_CB */
-#define WAIT_FOR_CB_SYNC_0
-#define WAIT_FOR_CB_SYNC_1 SVGA_Sync();
-
-static void SVGA_CB_start();
-static void SVGA_CB_restart();
-
-/*
- * types
- */
-
-#pragma pack(push)
-#pragma pack(1)
-typedef struct _cb_enable_t
-{
- uint32 cmd;
- SVGADCCmdStartStop cbstart;
-} cb_enable_t;
-
-typedef struct _cb_queue_t
-{
- struct _cb_queue_t *next;
- DWORD flags;
- DWORD data_size;
- DWORD pad[13];
-} cb_queue_t;
-
-#pragma pack(pop)
-
-typedef struct _cb_queue_info_t
-{
- cb_queue_t *first;
- cb_queue_t *last;
-} cb_queue_info_t;
-
-typedef struct spare_region
-{
- BOOL used;
- uint32 missed;
- SVGA_region_info_t region;
-} spare_region_t;
-
-typedef struct svga_cache_state
-{
- int free_index_min;
- int free_index_max;
- int cnt_large;
- int cnt_medium;
- int cnt_small;
- spare_region_t spare_region[SPARE_REGIONS_CNT];
-} svga_cache_state_t;
-
/*
* globals
*/
@@ -142,44 +65,23 @@ static SVGA_DB_t *svga_db = NULL;
extern LONG fb_lock_cnt;
-static BOOL gb_support = FALSE;
-static BOOL cb_support = FALSE;
-static BOOL cb_context0 = FALSE;
+ BOOL gb_support = FALSE;
+ BOOL cb_support = FALSE;
+ BOOL cb_context0 = FALSE;
/* for GPU9 is FIFO more stable (VMWARE) or faster (VBOX) */
static DWORD prefer_fifo = 1;
static BOOL SVGA_is_valid = FALSE;
-static uint64 cb_next_id = {0, 0};
static DWORD fence_next_id = 1;
void *cmdbuf = NULL;
void *ctlbuf = NULL;
-static DWORD cb_sem;
-
-static cb_queue_info_t cb_queue_info = {NULL, NULL};
-
-static svga_cache_state_t cache_state = {0, 0};
-
-static BOOL cache_enabled = FALSE;
/* guest frame buffer is dirty */
-static BOOL ST_FB_invalid = FALSE;
-
-static DWORD present_fence = 0;
-
-/* object table for GPU10 */
-static SVGA_OT_info_entry_t otable_setup[SVGA_OTABLE_DX_MAX] = {
- {0, NULL, RoundTo4k(VMWGFX_NUM_MOB*sizeof(SVGAOTableMobEntry)), 0, 0}, /* SVGA_OTABLE_MOB */
- {0, NULL, RoundTo4k(VMWGFX_NUM_GB_SURFACE*sizeof(SVGAOTableSurfaceEntry)), 0, 0}, /* SVGA_OTABLE_SURFACE */
- {0, NULL, RoundTo4k(VMWGFX_NUM_GB_CONTEXT*sizeof(SVGAOTableContextEntry)), 0, 0}, /* SVGA_OTABLE_CONTEXT */
- {0, NULL, RoundTo4k(VMWGFX_NUM_GB_SHADER *sizeof(SVGAOTableShaderEntry)), 0, 0}, /* SVGA_OTABLE_SHADER - not used */
- {0, NULL, RoundTo4k(VMWGFX_NUM_GB_SCREEN_TARGET*sizeof(SVGAOTableScreenTargetEntry)), 0, 0}, /* SVGA_OTABLE_SCREENTARGET (VBOX_VIDEO_MAX_SCREENS) */
- {0, NULL, RoundTo4k(VMWGFX_NUM_DXCONTEXT*sizeof(SVGAOTableDXContextEntry)), 0, 0}, /* SVGA_OTABLE_DXCONTEXT */
-};
-
-static SVGA_OT_info_entry_t *otable = NULL;
+BOOL ST_FB_invalid = FALSE;
+DWORD present_fence = 0;
/*
* strings
*/
@@ -197,249 +99,14 @@ static char SVGA_conf_st_size[] = "STSize";
static char SVGA_conf_st_flags[] = "STOptions";
static char SVGA_vxd_name[] = "vmwsmini.vxd";
-/* VM handle */
-extern DWORD ThisVM;
-
-/* prototypes */
-DWORD SVGA_GetDevCap(DWORD search_id);
-
-/**
- * Return PPN (physical page number) from virtual address
- *
- **/
-static DWORD getPPN(DWORD virtualaddr)
-{
- DWORD phy = 0;
- _CopyPageTable(virtualaddr/P_SIZE, 1, &phy, 0);
- return phy/P_SIZE;
-}
-
-static DWORD getPtrPPN(void *ptr)
-{
- return getPPN((DWORD)ptr);
-}
-
-/**
- * Delete item from cache
- **/
-static void cache_delete(int index)
-{
- if(cache_state.spare_region[index].used != FALSE)
- {
- SVGA_region_info_t *rinfo = &cache_state.spare_region[index].region;
- BYTE *free_ptr = (BYTE*)rinfo->address;
- uint32 region_size = rinfo->size;;
-
- if(rinfo->region_address != NULL)
- {
- dbg_printf(dbg_pagefree, rinfo->region_address);
- _PageFree((PVOID)rinfo->region_address, 0);
- }
- else
- {
- free_ptr -= P_SIZE;
- }
-
- if(rinfo->mob_address != NULL)
- {
- dbg_printf(dbg_pagefree, rinfo->mob_address);
- _PageFree((PVOID)rinfo->mob_address, 0);
- }
-
- dbg_printf(dbg_pagefree, free_ptr);
- _PageFree((PVOID)free_ptr, 0);
-
- cache_state.spare_region[index].used = FALSE;
-
- if((index+1) == cache_state.free_index_max)
- {
- cache_state.free_index_max--;
- }
-
- if(index < cache_state.free_index_min)
- {
- cache_state.free_index_min = index;
- }
-
- if(region_size >= SPARE_REGION_LARGE_SIZE)
- cache_state.cnt_large--;
- else if(region_size >= SPARE_REGION_MEDIUM_SIZE)
- cache_state.cnt_medium--;
- else
- cache_state.cnt_small--;
- }
-}
-
-/**
- * Insert region to cache
- **/
-static BOOL cache_insert(SVGA_region_info_t *region)
-{
- int i;
- BOOL rc = FALSE;
-
- if(!cache_enabled)
- {
- return FALSE;
- }
-
- if(region->size >= SPARE_REGION_LARGE_SIZE)
- {
- if(cache_state.cnt_large > SPARE_REGIONS_LARGE) return FALSE;
- }
- else if(region->size >= SPARE_REGION_MEDIUM_SIZE)
- {
- if(cache_state.cnt_medium > SPARE_REGIONS_MEDIUM) return FALSE;
- }
- else
- {
- if(cache_state.cnt_small > SPARE_REGIONS_SMALL) return FALSE;
- }
-
- for(i = cache_state.free_index_min; i < SPARE_REGIONS_CNT; i++)
- {
- if(!cache_state.spare_region[i].used)
- {
- memcpy(&cache_state.spare_region[i].region, region, sizeof(SVGA_region_info_t));
- cache_state.spare_region[i].used = TRUE;
- cache_state.spare_region[i].missed = 0;
- rc = TRUE;
- break;
- }
- }
-
- for(; i < SPARE_REGIONS_CNT; i++)
- {
- if(!cache_state.spare_region[i].used)
- {
- cache_state.free_index_min = i;
- break;
- }
- }
-
- if(i == SPARE_REGIONS_CNT)
- {
- cache_state.free_index_min = i;
- cache_state.free_index_max = SPARE_REGIONS_CNT;
- }
- else if(i >= cache_state.free_index_max)
- {
- cache_state.free_index_max = i+1;
- }
-
- if(rc)
- {
- if(region->size >= SPARE_REGION_LARGE_SIZE)
- cache_state.cnt_large++;
- else if(region->size >= SPARE_REGION_MEDIUM_SIZE)
- cache_state.cnt_medium++;
- else
- cache_state.cnt_small++;
-
- dbg_printf(dbg_cache_insert, region->region_id, region->size);
- }
-
- return rc;
-}
-
-/**
- * Use region from cache
- **/
-static BOOL cache_use(SVGA_region_info_t *region)
-{
- int i;
- BOOL rc = FALSE;
-
- if(!cache_enabled)
- {
- return FALSE;
- }
-
- dbg_printf(dbg_cache_search, region->size);
-
- for(i = cache_state.free_index_max-1; i >= 0; i--)
- {
- if(cache_state.spare_region[i].used != FALSE)
- {
- if(cache_state.spare_region[i].region.size == region->size)
- {
- SVGA_region_info_t *ptr = &cache_state.spare_region[i].region;
-
- region->address = ptr->address;
- region->region_address = ptr->region_address;
- region->region_ppn = ptr->region_ppn;
- region->mob_address = ptr->mob_address;
- region->mob_ppn = ptr->mob_ppn;
-
- cache_state.spare_region[i].used = FALSE;
- rc = TRUE;
- break;
- }
- else
- {
- if(++cache_state.spare_region[i].missed >= CACHE_THRESHOLD)
- {
- dbg_printf(dbg_cache_delete, cache_state.spare_region[i].region.size);
- cache_delete(i);
- }
- }
- }
- }
-
- if(rc)
- {
- if((i+1) == cache_state.free_index_max)
- {
- cache_state.free_index_max--;
- }
-
- if(i < cache_state.free_index_min)
- {
- cache_state.free_index_min = i;
- }
-
- if(region->size >= SPARE_REGION_LARGE_SIZE)
- cache_state.cnt_large--;
- else if(region->size >= SPARE_REGION_MEDIUM_SIZE)
- cache_state.cnt_medium--;
- else
- cache_state.cnt_small--;
-
- dbg_printf(dbg_cache_used, region->region_id, region->size);
- }
-
- return rc;
-}
-
/**
* Notify virtual HW that is some work to do
**/
-static void SVGA_Sync()
+void SVGA_Sync()
{
SVGA_WriteReg(SVGA_REG_SYNC, 1);
}
-static void SVGA_Flush_CB_critical()
-{
- /* wait for actual CB */
- while(!CB_queue_check(NULL))
- {
- SVGA_Sync();
- }
-
- /* drain FIFO */
- SVGA_Flush();
-}
-
-#if 0
-static void SVGA_Flush_CB()
-{
- Begin_Critical_Section(0);
- SVGA_Flush_CB_critical();
- End_Critical_Section();
-}
-#endif
-
/* map physical addresses to system linear space */
void SVGA_MapIO()
{
@@ -450,132 +117,6 @@ void SVGA_MapIO()
}
}
-static DWORD PT_count(DWORD size)
-{
- DWORD pt1_entries = 0;
- DWORD pt2_entries = 0;
-
- pt1_entries = RoundToPages(size);
- pt2_entries = ((pt1_entries + PTONPAGE - 1)/PTONPAGE);
-
- dbg_printf(dbg_pt_build_2, size, pt1_entries, pt2_entries);
-
- if(pt2_entries > 1)
- {
- return pt2_entries + 1;
- }
-
- return 1;
-}
-
-static void PT_build(DWORD size, void *buf, DWORD *outBase, DWORD *outType, void **outUserPtr)
-{
- DWORD pt1_entries = 0;
- DWORD pt2_entries = 0;
- DWORD i;
-
- pt1_entries = RoundToPages(size);
- pt2_entries = ((pt1_entries + PTONPAGE - 1)/PTONPAGE);
-
- if(pt2_entries > 1)
- {
- DWORD *ptbuf = buf;
- BYTE *ptr = ((BYTE*)buf)+((pt2_entries+1)*P_SIZE);
-
- memset(buf, 0, (pt2_entries+1)*P_SIZE);
-
- /* build PT2 */
- for(i = 0; i < pt2_entries; i++)
- {
- ptbuf[i] = getPtrPPN(ptbuf + ((i+1)*PTONPAGE));
- }
-
- ptbuf += PTONPAGE;
-
- /* build PT2 */
- for(i = 0; i < pt1_entries; i++)
- {
- ptbuf[i] = getPtrPPN(ptr + i*P_SIZE);
- }
-
- *outBase = getPtrPPN(buf);
- *outType = SVGA3D_MOBFMT_PTDEPTH_2;
- *outUserPtr = (void*)ptr;
- }
- else
- {
- DWORD *ptbuf = buf;
- BYTE *ptr = ((BYTE*)buf)+P_SIZE;
-
- memset(buf, 0, P_SIZE);
-
- for(i = 0; i < pt1_entries; i++)
- {
- ptbuf[i] = getPtrPPN(ptr + i*P_SIZE);
- }
-
- *outBase = getPtrPPN(buf);
- *outType = SVGA3D_MOBFMT_PTDEPTH_1;
- *outUserPtr = (void*)ptr;
- }
-
- dbg_printf(dbg_pt_build, size, *outBase, *outType, *outUserPtr);
-}
-
-/**
- * Allocate OTable for GB objects
- **/
-static void SVGA_OTable_alloc(BOOL screentargets)
-{
- int i;
-
- if(otable == NULL)
- {
- otable = (SVGA_OT_info_entry_t *)_PageAllocate(RoundToPages(sizeof(otable_setup)), PG_VM, ThisVM, 0, 0x0, 0x100000, NULL, PAGEFIXED);
- if(otable)
- {
- memcpy(otable, &(otable_setup[0]), sizeof(otable_setup));
- }
- }
-
- /* not allocate DX when there is no DX support */
- if(!SVGA_GetDevCap(SVGA3D_DEVCAP_DXCONTEXT))
- {
- otable[SVGA_OTABLE_DXCONTEXT].size = 0;
- }
-
-/* if(!screentargets)
- {
- otable[SVGA_OTABLE_SCREENTARGET].size = 0;
- }*/
-
- if(otable)
- {
- for(i = 0; i < SVGA_OTABLE_DX_MAX; i++)
- {
- SVGA_OT_info_entry_t *entry = &otable[i];
- if(entry->size != 0 && (entry->flags & SVGA_OT_FLAG_ALLOCATED) == 0)
- {
- void *ptr = (void*)_PageAllocate(RoundToPages(entry->size)+PT_count(entry->size), PG_VM, ThisVM, 0, 0x0, 0x100000, NULL, PAGEFIXED);
-
- if(ptr)
- {
- dbg_printf(dbg_mob_allocate, i);
- PT_build(entry->size, ptr, &entry->ppn, &entry->pt_depth, &entry->lin);
-
- entry->flags |= SVGA_OT_FLAG_ALLOCATED;
- entry->flags |= SVGA_OT_FLAG_DIRTY;
- }
- }
- }
- }
-}
-
-SVGA_OT_info_entry_t *SVGA_OT_setup()
-{
- return otable;
-}
-
static char db_mutexname[] = "svga_db_mux";
static void SVGA_DB_alloc()
@@ -651,7 +192,7 @@ SVGA_DB_t *SVGA_DB_setup()
return svga_db;
}
-static DWORD SVGA_fence_passed()
+DWORD SVGA_fence_passed()
{
if(SVGA_IsSVGA3())
{
@@ -693,7 +234,7 @@ void SVGA_fence_query(DWORD FBPTR ptr_fence_passed, DWORD FBPTR ptr_fence_last)
}
}
-static BOOL SVGA_fence_is_passed(DWORD fence_id)
+BOOL SVGA_fence_is_passed(DWORD fence_id)
{
DWORD last_pased;
DWORD last_fence;
@@ -735,58 +276,6 @@ void SVGA_fence_wait(DWORD fence_id)
}*/
}
-/**
- * Allocate memory for command buffer
- **/
-static DWORD *SVGA_CMB_alloc_size(DWORD datasize)
-{
- DWORD phy;
- SVGACBHeader *cb;
- cb_queue_t *q;
-
- Begin_Critical_Section(0);
-
- q = (cb_queue_t*)_PageAllocate(RoundToPages(datasize+sizeof(SVGACBHeader)+sizeof(cb_queue_t)), PG_SYS, 0, 0, 0x0, 0x100000, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
-
- if(q)
- {
- q->next = NULL;
- q->flags = 0;
- q->data_size = 0;
-
- cb = (SVGACBHeader*)(q+1);
-
- memset(cb, 0, sizeof(SVGACBHeader));
- cb->status = SVGA_CB_STATUS_COMPLETED; /* important to sync between commands */
- cb->ptr.pa.hi = 0;
- cb->ptr.pa.low = phy + sizeof(cb_queue_t) + sizeof(SVGACBHeader);
-
- End_Critical_Section();
- return (DWORD*)(cb+1);
- }
- End_Critical_Section();
-
- return NULL;
-}
-
-void SVGA_CMB_free(DWORD *cmb)
-{
- SVGACBHeader *cb = ((SVGACBHeader *)cmb)-1;
-
- Begin_Critical_Section(0);
-
- WAIT_FOR_CB(cb, 1);
-
- _PageFree(cb-1, 0);
-
- End_Critical_Section();
-}
-
-DWORD *SVGA_CMB_alloc()
-{
- return SVGA_CMB_alloc_size(SVGA_CB_MAX_SIZE);
-}
-
void *SVGA_cmd_ptr(DWORD *buf, DWORD *pOffset, DWORD cmd, DWORD cmdsize)
{
DWORD pp = (*pOffset)/sizeof(DWORD);
@@ -806,331 +295,6 @@ void *SVGA_cmd3d_ptr(DWORD *buf, DWORD *pOffset, DWORD cmd, DWORD cmdsize)
return (void*)(buf + pp + 2);
}
-// FIXME: inline?
-static void SVGA_cb_id_inc()
-{
- _asm
- {
- inc dword ptr [cb_next_id]
- adc dword ptr [cb_next_id+4], 0
- }
-}
-
-#ifdef DBGPRINT
-#include "vxd_svga_debug.h"
-#endif
-
-/*
- * @param tracked: check specific CB, or NULL to check full queue
- *
- * @return: TRUE if tracked is complete or TRUE id queue is empty
-
- */
-
-BOOL CB_queue_check(SVGACBHeader *tracked)
-{
- cb_queue_t *last = NULL;
- cb_queue_t *item = cb_queue_info.first;
- BOOL in_queue = FALSE;
-
- while(item != NULL)
- {
- SVGACBHeader *cb = (SVGACBHeader*)(item+1);
- if(cb->status >= SVGA_CB_STATUS_COMPLETED)
- {
- if(last == NULL)
- {
- cb_queue_info.first = item->next;
- }
- else
- {
- last->next = item->next;
- }
-
- if(cb->status > SVGA_CB_STATUS_COMPLETED)
- {
- SVGA_CB_restart();
- }
-
- item = item->next;
- }
- else
- {
- if(tracked == cb)
- {
- in_queue = TRUE;
- }
- last = item;
- item = item->next;
- }
- }
-
- cb_queue_info.last = last;
-
- if(cb_queue_info.first == NULL)
- {
- return TRUE;
- }
-
- if(tracked != NULL && in_queue == FALSE)
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-void CB_queue_insert(SVGACBHeader *cb)
-{
- cb_queue_t *item = (cb_queue_t*)(cb-1);
- item->next = NULL;
-
- if(cb_queue_info.last != NULL)
- {
- cb_queue_info.last->next = item;
- cb_queue_info.last = item;
- }
- else
- {
- cb_queue_info.first = item;
- cb_queue_info.last = item;
- }
-}
-
-
-void SVGA_CMB_submit_critical(DWORD FBPTR cmb, DWORD cmb_size, SVGA_CMB_status_t FBPTR status, DWORD flags, DWORD DXCtxId)
-{
- DWORD fence = 0;
- SVGACBHeader *cb = ((SVGACBHeader *)cmb)-1;
-
- CB_queue_check(NULL);
-
- if(status)
- {
- cb->status = SVGA_CB_STATUS_NONE;
- status->sStatus = SVGA_PROC_NONE;
- status->qStatus = (volatile DWORD*)&cb->status;
- }
-
-#ifdef DBGPRINT
- debug_cmdbuf(cmb, cmb_size);
-// debug_cmdbuf_trace(cmb, cmb_size, SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
-// debug_draw(cmb, cmb_size);
-#endif
-
- if(flags & SVGA_CB_PRESENT_ASYNC)
- {
- if(present_fence != 0)
- {
- SVGA_fence_wait(present_fence);
- }
-
- flags |= SVGA_CB_FORCE_FENCE;
- }
- else if(present_fence)
- {
- if(SVGA_fence_is_passed(present_fence))
- {
- present_fence = 0;
- }
- }
-
- if(flags & SVGA_CB_PRESENT_GPU)
- {
- ST_FB_invalid = TRUE;
- }
-
- if( /* CB are supported and enabled */
- cb_support &&
- (cb_context0 || (flags & SVGA_CB_USE_CONTEXT_DEVICE)) &&
- (flags & SVGA_CB_FORCE_FIFO) == 0
- )
- {
- DWORD cbhwctxid = SVGA_CB_CONTEXT_0;
-
- if(flags & SVGA_CB_USE_CONTEXT_DEVICE)
- {
- cbhwctxid = SVGA_CB_CONTEXT_DEVICE;
- }
-
- if(flags & SVGA_CB_FORCE_FENCE)
- {
- DWORD dwords = cmb_size/sizeof(DWORD);
- fence = SVGA_fence_get();
- cmb[dwords] = SVGA_CMD_FENCE;
- cmb[dwords+1] = fence;
- cmb_size += sizeof(DWORD)*2;
- }
-
- if(cmb_size == 0)
- {
- cb->status = SVGA_PROC_COMPLETED;
- if(status)
- {
- status->sStatus = SVGA_PROC_COMPLETED;
- status->qStatus = NULL;
- status->fifo_fence_used = 0;
- }
- }
- else
- {
- cb->status = SVGA_CB_STATUS_NONE;
- cb->errorOffset = 0;
- cb->offset = 0; /* VMware modified this, needs to be clear */
- cb->flags = SVGA_CB_FLAG_NO_IRQ;
-
- if(flags & SVGA_CB_FLAG_DX_CONTEXT)
- {
- cb->flags |= SVGA_CB_FLAG_DX_CONTEXT;
- cb->dxContext = DXCtxId;
- }
- else
- {
- cb->dxContext = 0;
- }
-
- cb->id.low = cb_next_id.low;
- cb->id.hi = cb_next_id.hi;
- cb->length = cmb_size;
-
- CB_queue_insert(cb);
-
- SVGA_WriteReg(SVGA_REG_COMMAND_HIGH, 0); // high part of 64-bit memory address...
- SVGA_WriteReg(SVGA_REG_COMMAND_LOW, (cb->ptr.pa.low - sizeof(SVGACBHeader)) | cbhwctxid);
- SVGA_Sync(); /* notify HV to read registers (VMware needs it) */
-
- SVGA_cb_id_inc();
-
- if(flags & SVGA_CB_SYNC)
- {
- WAIT_FOR_CB(cb, 0);
-
- if(cb->status != SVGA_CB_STATUS_COMPLETED)
- {
- dbg_printf(dbg_cmd_error, cb->status, cmb[0], cb->errorOffset);
- if(flags & SVGA_CB_FORCE_FENCE)
- {
- /* this may cause freeze, when fence is in buffer and isn't complete. So return some passed fence */
- fence = SVGA_fence_passed();
- }
- }
- else
- {
- dbg_printf(dbg_cb_suc);
- }
-
- if(status)
- {
- status->sStatus = SVGA_PROC_COMPLETED;
- status->qStatus = NULL;
- status->fifo_fence_used = fence;
- }
- }
- else
- {
- if(status)
- {
- status->sStatus = SVGA_PROC_NONE;
- status->qStatus = (volatile DWORD*)&cb->status;
- status->fifo_fence_used = fence;
- }
- }
- }
- }
- else /* copy to FIFO */
- {
- DWORD *ptr = cmb;
- DWORD dwords = cmb_size/sizeof(DWORD);
- DWORD nextCmd, max, min;
-
- /* insert fence CMD */
- fence = SVGA_fence_get();
- ptr[dwords] = SVGA_CMD_FENCE;
- ptr[dwords+1] = fence;
-
- dwords += 2;
-
- //SVGA_Flush();
-
- nextCmd = gSVGA.fifoMem[SVGA_FIFO_NEXT_CMD];
- max = gSVGA.fifoMem[SVGA_FIFO_MAX];
- min = gSVGA.fifoMem[SVGA_FIFO_MIN];
-
- /* copy to fifo */
- while(dwords > 0)
- {
- gSVGA.fifoMem[nextCmd/sizeof(DWORD)] = *ptr;
- ptr++;
-
- nextCmd += sizeof(uint32);
- if (nextCmd >= max)
- {
- nextCmd = min;
- }
- gSVGA.fifoMem[SVGA_FIFO_NEXT_CMD] = nextCmd;
- dwords--;
- }
-
- //SVGA_Sync();
-
- if(flags & SVGA_CB_SYNC)
- {
- SVGA_fence_wait(fence);
- if(status)
- {
- status->sStatus = SVGA_PROC_COMPLETED;
- status->qStatus = NULL;
- status->fifo_fence_used = 0;
- }
- }
- else
- {
- if(status)
- {
- status->sStatus = SVGA_PROC_FENCE;
- status->qStatus = NULL;
- status->fifo_fence_used = fence;
- }
- }
-
- cb->status = SVGA_PROC_COMPLETED;
- } /* FIFO */
-
- if(status)
- {
- status->fifo_fence_last = SVGA_fence_passed();
- }
-
- if(flags & SVGA_CB_PRESENT_ASYNC)
- {
- present_fence = fence;
- }
-
- //dbg_printf(dbg_cmd_off, cmb[0]);
-}
-
-void wait_for_cmdbuf()
-{
- SVGACBHeader *cb;
-
- Begin_Critical_Section(0);
- cb = ((SVGACBHeader *)cmdbuf)-1;
- WAIT_FOR_CB(cb, 0);
-}
-
-void submit_cmdbuf(DWORD cmdsize, DWORD flags, DWORD dx)
-{
- SVGA_CMB_submit_critical(cmdbuf, cmdsize, NULL, flags, dx);
- End_Critical_Section();
-}
-
-void SVGA_CMB_submit(DWORD FBPTR cmb, DWORD cmb_size, SVGA_CMB_status_t FBPTR status, DWORD flags, DWORD DXCtxId)
-{
- Begin_Critical_Section(0);
- SVGA_CMB_submit_critical(cmb, cmb_size, status, flags, DXCtxId);
- End_Critical_Section();
-}
-
void SVGA_IRQ_proc()
{
dbg_printf(dbg_irq);
@@ -1341,7 +505,7 @@ BOOL SVGA_init_hw()
}
}
- cb_sem = Create_Semaphore(1);
+ //cb_sem = Create_Semaphore(1);
SVGA_DB_alloc();
@@ -1397,16 +561,16 @@ BOOL SVGA_init_hw()
{
hda->flags |= FB_ACCEL_VMSVGA10;
}
-
- memset(&cache_state, 0, sizeof(svga_cache_state_t));
-
+
+ cache_init();
+
SVGA_is_valid = TRUE;
if(_GetFreePageCount(NULL) >= 0x38000UL) /* 896MB / 4096 */
{
if(!gb_support) /* mob cache is done by RING-3 DLL */
{
- cache_enabled = TRUE;
+ cache_enable(TRUE);
}
}
@@ -1421,493 +585,13 @@ BOOL SVGA_init_hw()
SVGA_region_create(&testregion);
}*/
-
- dbg_printf(dbg_cache, cache_enabled);
-
+
return TRUE;
}
return FALSE;
}
-
-//#define GMR_CONTIG
-//#define GMR_SYSTEM
-
-//static DWORD pa_flags = PAGEFIXED | PAGEUSEALIGN;
-//static DWORD pa_align = 0x0000000F; // 64k
-
-static DWORD pa_flags = PAGEFIXED;
-static DWORD pa_align = 0x00000000;
-
-/**
- * Allocate guest memory region (GMR) - HW needs know memory physical
- * addressed of pages in (virtual) memory block.
- * Technically this allocate 2 memory block, 1st for data and 2nd as its
- * physical description.
- *
- * @return: TRUE on success
- *
- **/
-BOOL SVGA_region_create(SVGA_region_info_t *rinfo)
-{
-#ifdef GMR_CONTIG
- ULONG phy = 0;
-#endif
- ULONG laddr;
- ULONG pgblk;
- ULONG new_size = RoundTo4k(rinfo->size);
- ULONG nPages = RoundToPages(new_size);
- //ULONG nPages = RoundToPages64k(rinfo->size);
- ULONG pa_vm = ThisVM;
- ULONG pa_type = PG_VM;
- SVGAGuestMemDescriptor *desc;
- ULONG size_total = 0;
-
-#ifdef GMR_SYSTEM
- pa_vm = 0;
- pa_type = PG_SYS;
-#endif
-
- rinfo->size = new_size;
-
- Begin_Critical_Section(0);
-
- if(cache_use(rinfo))
- {
- goto spare_region_used;
- }
-
- //dbg_printf(dbg_pages, rinfo->size, nPages, P_SIZE);
-#ifdef GMR_CONTIG
- /* JH: OK, using PAGECONTIG leads to very fast memory exhaustion, so using only slower way! */
- /* first try to allocate continuous physical memory space, 1st page is used for GMR descriptor */
- laddr = _PageAllocate(nPages+1, pa_type, pa_vm, 0, 0x0, 0x100000, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
-
- if(laddr)
- {
- desc = (SVGAGuestMemDescriptor*)laddr;
- desc->ppn = (phy/P_SIZE)+1;
- desc->numPages = nPages;
- desc++;
- desc->ppn = 0;
- desc->numPages = 0;
-
- rinfo->address = (void*)(laddr+P_SIZE);
- rinfo->region_address = 0;
- rinfo->region_ppn = (phy/P_SIZE);
- rinfo->mob_address = 0;
- rinfo->mob_ppn = (phy/P_SIZE)+1;
-
- //dbg_printf(dbg_region_simple, laddr, rinfo->address);
-
- size_total = (nPages+1)*P_SIZE;
- }
- else
-#endif
- {
- /* memory is too fragmented to create this large continous region */
- ULONG taddr;
- ULONG tppn;
- ULONG pgi;
- ULONG base_ppn;
- ULONG base_cnt;
- ULONG blocks = 1;
- ULONG blk_pages = 0;
- ULONG mob_pages = 0;
-
- DWORD *mob = NULL;
- //DWORD mobphy = 0;
-
- /* allocate user block */
- laddr = _PageAllocate(nPages, pa_type, pa_vm, pa_align, 0x0, 0x100000, NULL, pa_flags);
-
- if(!laddr)
- {
- End_Critical_Section();
- return FALSE;
- }
-
- /* determine how many physical continuous blocks we have */
- base_ppn = getPPN(laddr);
- base_cnt = 1;
- for(pgi = 1; pgi < nPages; pgi++)
- {
- taddr = laddr + pgi*P_SIZE;
- tppn = getPPN(taddr);
-
- if(tppn != base_ppn + base_cnt)
- {
- base_ppn = tppn;
- base_cnt = 1;
- blocks++;
- }
- else
- {
- base_cnt++;
- }
- }
-
- // number of pages to store regions information
- blk_pages = ((blocks+1)/(P_SIZE/sizeof(SVGAGuestMemDescriptor))) + 1;
-
- // add extra descriptors for pages edge
- blk_pages = ((blocks+blk_pages+1)/(P_SIZE/sizeof(SVGAGuestMemDescriptor))) + 1;
-
- /* allocate memory for GMR descriptor */
- pgblk = _PageAllocate(blk_pages, pa_type, pa_vm, pa_align, 0x0, 0x100000, NULL, pa_flags);
- if(!pgblk)
- {
- _PageFree((PVOID)laddr, 0);
- End_Critical_Section();
- return FALSE;
- }
-
- desc = (SVGAGuestMemDescriptor*)pgblk;
- desc->ppn = getPPN(laddr);
- desc->numPages = 1;
- blocks = 1;
-
- /* fill GMR physical structure */
- for(pgi = 1; pgi < nPages; pgi++)
- {
- taddr = laddr + pgi*P_SIZE;
- tppn = getPPN(taddr);
-
- if(tppn == desc->ppn + desc->numPages)
- {
- desc->numPages++;
- }
- else
- {
- /* next descriptor is on page edge */
- if((blocks+1) % (P_SIZE/sizeof(SVGAGuestMemDescriptor)) == 0)
- {
- desc++;
- desc->numPages = 0;
- desc->ppn = getPPN((DWORD)(desc+1));
- blocks++;
- }
-
- desc++;
- desc->ppn = tppn;
- desc->numPages = 1;
- blocks++;
- }
- }
-
- desc++;
- desc->ppn = 0;
- desc->numPages = 0;
-
- if(gb_support) /* don't create MOBs for Gen9 */
- {
- int i;
- /* for simplicity we're always creating table of depth 2, first page is page of PPN pages */
- //mob = (DWORD *)_PageAllocate(1 + (nPages + PTONPAGE - 1)/PTONPAGE, pa_type, pa_vm, 0, 0x0, 0x100000, &mobphy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
- mob_pages = 1 + (nPages + PTONPAGE - 1)/PTONPAGE;
- mob = (DWORD *)_PageAllocate(mob_pages, pa_type, pa_vm, pa_align, 0x0, 0x100000, 0, pa_flags);
-
- if(!mob)
- {
- _PageFree((PVOID)laddr, 0);
- _PageFree((PVOID)pgblk, 0);
- End_Critical_Section();
- return FALSE;
- }
-
- memset(mob, 0, mob_pages*P_SIZE);
-
- /* dim 1 */
- for(i = 0; i < mob_pages-1; i++)
- {
- //mob[i] = (mobphy/P_SIZE) + i + 1;
- mob[i] = getPPN(((ULONG)mob) + ((i + 1)*P_SIZE));
- }
- /* dim 2 */
- for(i = 0; i < nPages; i++)
- {
- mob[PTONPAGE + i] = getPPN(laddr + i*P_SIZE);
- }
- }
-
- rinfo->address = (void*)laddr;
- rinfo->region_address = (void*)pgblk;
- rinfo->region_ppn = getPPN(pgblk);
- rinfo->mob_address = (void*)mob;
- rinfo->mob_ppn = 0;
- if(mob)
- {
- //rinfo->mob_ppn = mobphy/P_SIZE;
- rinfo->mob_ppn = getPPN((ULONG)mob);
- }
-
- size_total = (nPages + blk_pages + mob_pages)*P_SIZE;
-
- //dbg_printf(dbg_region_fragmented);
- }
-
- //dbg_printf(dbg_gmr, rinfo->region_id, rinfo->region_ppn);
-
- spare_region_used:
- //dbg_printf(dbg_mobonly, rinfo->mobonly);
-
- // JH: no need here
- //SVGA_Flush_CB();
-
- if(!rinfo->mobonly)
- {
- if(rinfo->region_id < SVGA_ReadReg(SVGA_REG_GMR_MAX_IDS))
- {
- /* register GMR */
- SVGA_WriteReg(SVGA_REG_GMR_ID, rinfo->region_id);
- SVGA_WriteReg(SVGA_REG_GMR_DESCRIPTOR, rinfo->region_ppn);
- SVGA_Sync(); // notify register change
-
- SVGA_Flush_CB_critical();
- }
- else
- {
- /* GMR is too high, use it as only as MOB (DX) */
- rinfo->region_ppn = 0;
- }
- }
-
- if(gb_support)
- {
- SVGA3dCmdDefineGBMob *mob;
- DWORD cmdoff = 0;
-
- wait_for_cmdbuf();
- mob = SVGA_cmd3d_ptr(cmdbuf, &cmdoff, SVGA_3D_CMD_DEFINE_GB_MOB, sizeof(SVGA3dCmdDefineGBMob));
- mob->mobid = rinfo->region_id;
- mob->base = rinfo->mob_ppn;
- mob->sizeInBytes = rinfo->size;
- if(rinfo->mob_address == NULL) /* continual memory space */
- {
- mob->ptDepth = SVGA3D_MOBFMT_RANGE;
- }
- else
- {
- mob->ptDepth = SVGA3D_MOBFMT_PTDEPTH_2;
- }
-
- submit_cmdbuf(cmdoff, SVGA_CB_SYNC, 0);
-
- rinfo->is_mob = 1;
- }
- else
- {
- rinfo->is_mob = 0;
- }
-
- svga_db->stat_regions_usage += rinfo->size;
-
- End_Critical_Section();
-
- //dbg_printf(dbg_gmr_succ, rinfo->region_id, rinfo->size);
-
- return TRUE;
-}
-
-/**
- * Free data allocated by SVGA_region_create
- *
- **/
-void SVGA_region_free(SVGA_region_info_t *rinfo)
-{
- BOOL saved_in_cache;
- BYTE *free_ptr = (BYTE*)rinfo->address;
-
- Begin_Critical_Section(0);
- svga_db->stat_regions_usage -= rinfo->size;
-
- saved_in_cache = cache_insert(rinfo);
-
- if(gb_support)
- {
- SVGA3dCmdDestroyGBMob *mob;
- DWORD cmdoff = 0;
-
- wait_for_cmdbuf();
- mob = SVGA_cmd3d_ptr(cmdbuf, &cmdoff, SVGA_3D_CMD_DESTROY_GB_MOB, sizeof(SVGA3dCmdDestroyGBMob));
- mob->mobid = rinfo->region_id;
-
- if(saved_in_cache)
- submit_cmdbuf(cmdoff, 0, 0);
- else
- submit_cmdbuf(cmdoff, SVGA_CB_SYNC, 0);
- }
-
- if(!rinfo->mobonly)
- {
- SVGA_Sync();
- SVGA_Flush_CB_critical();
-
- SVGA_WriteReg(SVGA_REG_GMR_ID, rinfo->region_id);
- SVGA_WriteReg(SVGA_REG_GMR_DESCRIPTOR, 0);
- SVGA_Sync(); // notify register change
- }
-
- if(!saved_in_cache)
- {
- if(rinfo->region_address != NULL)
- {
- //dbg_printf(dbg_pagefree, rinfo->region_address);
- _PageFree((PVOID)rinfo->region_address, 0);
- }
- else
- {
- free_ptr -= P_SIZE;
- }
-
- if(rinfo->mob_address != NULL)
- {
- //dbg_printf(dbg_pagefree, rinfo->mob_address);
- _PageFree((PVOID)rinfo->mob_address, 0);
- }
-
- //dbg_printf(dbg_pagefree, free_ptr);
- _PageFree((PVOID)free_ptr, 0);
- }
- End_Critical_Section();
-
- //dbg_printf(dbg_pagefree_end, rinfo->region_id, rinfo->size, saved_in_cache);
-
- rinfo->address = NULL;
- rinfo->region_address = NULL;
- rinfo->mob_address = NULL;
- rinfo->region_ppn = 0;
- rinfo->mob_ppn = 0;
-}
-
-/**
- * Destroy saved regions and free memory
- *
- **/
-void SVGA_flushcache()
-{
- int i;
-
- Begin_Critical_Section(0);
-
- for(i = 0; i < cache_state.free_index_max ; i++)
- {
- cache_delete(i);
- }
-
- cache_state.free_index_max = 0;
- cache_state.free_index_min = 0;
- cache_state.cnt_large = 0;
- cache_state.cnt_medium = 0;
- cache_state.cnt_small = 0;
-
- End_Critical_Section();
-}
-
-static DWORD SVGA_CB_ctr(DWORD data_size)
-{
- SVGACBHeader *cb = ((SVGACBHeader *)ctlbuf)-1;
-
- dbg_printf(dbg_ctr_start);
-
- //Begin_Critical_Section(0);
-
- cb->status = SVGA_CB_STATUS_NONE;
- cb->errorOffset = 0;
- cb->offset = 0; /* VMware modified this, needs to be clear */
- cb->flags = SVGA_CB_FLAG_NO_IRQ;
- cb->mustBeZero[0] = 0;
- cb->mustBeZero[1] = 0;
- cb->mustBeZero[2] = 0;
- cb->mustBeZero[3] = 0;
- cb->mustBeZero[4] = 0;
- cb->mustBeZero[5] = 0;
- cb->dxContext = 0;
- cb->id.low = cb_next_id.low;
- cb->id.hi = cb_next_id.hi;
- cb->length = data_size;
-
- SVGA_WriteReg(SVGA_REG_COMMAND_HIGH, 0);
- SVGA_WriteReg(SVGA_REG_COMMAND_LOW, (cb->ptr.pa.low - sizeof(SVGACBHeader)) | SVGA_CB_CONTEXT_DEVICE);
- SVGA_Sync();
-
- SVGA_cb_id_inc();
-
- while(cb->status == SVGA_CB_STATUS_NONE)
- {
- SVGA_Sync();
- }
-
- //End_Critical_Section();
-
- dbg_printf(dbg_ctr_end);
-
- return cb->status;
-}
-
-/**
- * GPU10: start context0
- *
- **/
-static void SVGA_CB_start()
-{
- if(cb_support && cb_context0 == FALSE)
- {
- cb_enable_t *cbe = ctlbuf;
- DWORD status;
-
- memset(cbe, 0, sizeof(cb_enable_t));
- cbe->cmd = SVGA_DC_CMD_START_STOP_CONTEXT;
- cbe->cbstart.enable = 1;
- cbe->cbstart.context = SVGA_CB_CONTEXT_0;
-
- status = SVGA_CB_ctr(sizeof(cb_enable_t));
-
- if(status == SVGA_CB_STATUS_COMPLETED)
- {
- dbg_printf(dbg_cb_start);
- cb_context0 = TRUE;
- }
- else
- {
- cb_support = FALSE;
- dbg_printf(dbg_cb_start_err, status);
- }
- }
-}
-
-/**
- * GPU10: stop context0
- *
- **/
-static void SVGA_CB_stop()
-{
- cb_context0 = FALSE;
-
- if(cb_support)
- {
- DWORD status;
- cb_enable_t *cbe = ctlbuf;
-
- memset(cbe, 0, sizeof(cb_enable_t));
- cbe->cmd = SVGA_DC_CMD_START_STOP_CONTEXT;
- cbe->cbstart.enable = 0;
- cbe->cbstart.context = SVGA_CB_CONTEXT_0;
-
- status = SVGA_CB_ctr(sizeof(cb_enable_t));
- dbg_printf(dbg_cb_stop_status, status);
-
- dbg_printf(dbg_cb_stop);
- }
-}
-
-static void SVGA_CB_restart()
-{
- cb_context0 = FALSE;
- SVGA_CB_start();
-}
-
/* Check if screen acceleration is available */
static BOOL SVGA_hasAccelScreen()
{
@@ -2026,94 +710,6 @@ static void SVGA_defineScreen(DWORD w, DWORD h, DWORD bpp)
submit_cmdbuf(cmdoff, SVGA_CB_SYNC/*|SVGA_CB_FORCE_FIFO*/, 0);
}
-/**
- * Apply tables to VGPU
- **/
-void SVGA_OTable_load()
-{
- DWORD i;
- DWORD cmd_offset = 0;
- SVGA3dCmdSetOTableBase *cmd;
-
- SVGA_OT_info_entry_t *ot = SVGA_OT_setup();
- if(ot == NULL)
- {
- return;
- }
-
- wait_for_cmdbuf();
-
- for(i = SVGA_OTABLE_MOB; i < SVGA_OTABLE_DX_MAX; i++)
- {
- SVGA_OT_info_entry_t *entry = &(ot[i]);
-
- if((entry->flags & SVGA_OT_FLAG_ACTIVE) == 0)
- {
- if(entry->size > 0)
- {
- cmd = SVGA_cmd3d_ptr(cmdbuf, &cmd_offset, SVGA_3D_CMD_SET_OTABLE_BASE, sizeof(SVGA3dCmdSetOTableBase));
- cmd->type = i;
- cmd->baseAddress = entry->ppn;
- cmd->sizeInBytes = entry->size;
- if((entry->flags & SVGA_OT_FLAG_DIRTY) == 0)
- {
- cmd->validSizeInBytes = entry->size;
- }
- else
- {
- cmd->validSizeInBytes = 0;
- }
- cmd->ptDepth = entry->pt_depth;
-
- entry->flags |= SVGA_OT_FLAG_ACTIVE;
- }
- }
- }
-
- submit_cmdbuf(cmd_offset, SVGA_CB_SYNC, 0);
-}
-
-void SVGA_OTable_unload()
-{
- DWORD i;
- DWORD cmd_offset = 0;
- SVGA3dCmdSetOTableBase *cmd;
- SVGA3dCmdReadbackOTable *cmd_readback;
-
- SVGA_OT_info_entry_t *ot = SVGA_OT_setup();
- if(ot == NULL)
- {
- return;
- }
-
- wait_for_cmdbuf();
-
- for(i = SVGA_OTABLE_MOB; i < SVGA_OTABLE_DX_MAX; i++)
- {
- SVGA_OT_info_entry_t *entry = &(ot[i]);
-
- if(entry->flags & SVGA_OT_FLAG_ACTIVE)
- {
- if(entry->size > 0)
- {
- cmd_readback = SVGA_cmd3d_ptr(cmdbuf, &cmd_offset, SVGA_3D_CMD_READBACK_OTABLE, sizeof(SVGA3dCmdReadbackOTable));
- cmd_readback->type = i;
- entry->flags &= ~SVGA_OT_FLAG_DIRTY;
-
- cmd = SVGA_cmd3d_ptr(cmdbuf, &cmd_offset, SVGA_3D_CMD_SET_OTABLE_BASE, sizeof(SVGA3dCmdSetOTableBase));
- cmd->type = i;
- cmd->baseAddress = 0;
- cmd->sizeInBytes = 0;
- cmd->validSizeInBytes = 0;
- cmd->ptDepth = SVGA3D_MOBFMT_INVALID;
-
- entry->flags &= ~SVGA_OT_FLAG_ACTIVE;
- }
- }
- }
-
- submit_cmdbuf(cmd_offset, SVGA_CB_SYNC, 0);
-}
/**
* Test if display mode is supported
diff --git a/vxd_svga.h b/vxd_svga.h
index fe7ea05..04c1897 100644
--- a/vxd_svga.h
+++ b/vxd_svga.h
@@ -1,35 +1,47 @@
#ifndef __VXD_SVGA_H__INCLUDED__
#define __VXD_SVGA_H__INCLUDED__
+/* consts */
+#define ST_REGION_ID 1
+#define ST_SURFACE_ID 1
+
+#define ST_16BPP 1
+#define ST_CURSOR 2
+#define ST_CURSOR_HIDEABLE 4
+
+
+/* VM handle */
+extern DWORD ThisVM;
+
extern void *cmdbuf;
+extern void *ctlbuf;
void wait_for_cmdbuf();
void submit_cmdbuf(DWORD cmdsize, DWORD flags, DWORD dx);
void *SVGA_cmd_ptr(DWORD *buf, DWORD *pOffset, DWORD cmd, DWORD cmdsize);
void *SVGA_cmd3d_ptr(DWORD *buf, DWORD *pOffset, DWORD cmd, DWORD cmdsize);
DWORD SVGA_pitch(DWORD width, DWORD bpp);
void SVGA_region_usage_reset();
+BOOL SVGA_fence_is_passed(DWORD fence_id);
+DWORD SVGA_fence_passed();
+DWORD SVGA_GetDevCap(DWORD search_id);
+/* screen target */
extern BOOL st_used;
extern DWORD st_flags;
BOOL st_memory_allocate(DWORD size, DWORD *out);
void st_defineScreen(DWORD w, DWORD h, DWORD bpp);
void st_destroyScreen();
-void SVGA_OTable_load();
-void SVGA_OTable_unload();
SVGA_DB_surface_t *SVGA_GetSurfaceInfo(DWORD sid);
-
-#define ST_REGION_ID 1
-#define ST_SURFACE_ID 1
-
-#define ST_16BPP 1
-#define ST_CURSOR 2
-#define ST_CURSOR_HIDEABLE 4
-
BOOL st_useable(DWORD bpp);
+/* VDD */
DWORD map_pm16(DWORD vm, DWORD linear, DWORD size);
+void SVGA_Sync();
+void SVGA_Flush_CB();
+void SVGA_Flush_CB_critical();
+
/* mouse */
BOOL SVGA_mouse_hw();
BOOL SVGA_mouse_load();
@@ -37,4 +49,18 @@ void SVGA_mouse_move(int x, int y);
void SVGA_mouse_show();
void SVGA_mouse_hide(BOOL invalidate);
+/* memory */
+void SVGA_OTable_load();
+void SVGA_OTable_alloc(BOOL screentargets);
+void SVGA_OTable_unload();
+void cache_init();
+void cache_enable(BOOL enabled);
+
+/* CB */
+DWORD *SVGA_CMB_alloc_size(DWORD datasize);
+void SVGA_CMB_free(DWORD *cmb);
+void SVGA_CB_start();
+void SVGA_CB_stop();
+void SVGA_CB_restart();
+
#endif /* __VXD_SVGA_H__INCLUDED__ */
diff --git a/vxd_svga_cb.c b/vxd_svga_cb.c
new file mode 100644
index 0000000..2fcbc81
--- /dev/null
+++ b/vxd_svga_cb.c
@@ -0,0 +1,606 @@
+/*****************************************************************************
+
+Copyright (c) 2024 Jaroslav Hensl <emulator@emulace.cz>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*****************************************************************************/
+
+/* 32 bit RING-0 code for SVGA-II 3D acceleration */
+#define SVGA
+
+#include <limits.h>
+
+#include "winhack.h"
+#include "vmm.h"
+#include "vxd.h"
+#include "vxd_lib.h"
+
+#include "svga_all.h"
+#include "3d_accel.h"
+#include "code32.h"
+#include "vxd_svga.h"
+#include "vxd_strings.h"
+
+#include "svga_ver.h"
+
+/*
+ * types
+ */
+
+#pragma pack(push)
+#pragma pack(1)
+typedef struct _cb_enable_t
+{
+ uint32 cmd;
+ SVGADCCmdStartStop cbstart;
+} cb_enable_t;
+
+typedef struct _cb_queue_t
+{
+ struct _cb_queue_t *next;
+ DWORD flags;
+ DWORD data_size;
+ DWORD pad[13];
+} cb_queue_t;
+
+#pragma pack(pop)
+
+typedef struct _cb_queue_info_t
+{
+ cb_queue_t *first;
+ cb_queue_t *last;
+} cb_queue_info_t;
+
+/*
+ * Globals
+ */
+extern BOOL gb_support;
+extern BOOL cb_support;
+extern BOOL cb_context0;
+
+extern DWORD present_fence;
+extern BOOL ST_FB_invalid;
+
+BOOL CB_queue_check(SVGACBHeader *tracked);
+
+/*
+ * Locals
+ **/
+static cb_queue_info_t cb_queue_info = {NULL, NULL};
+static uint64 cb_next_id = {0, 0};
+
+/*
+ * Macros
+ */
+
+#define WAIT_FOR_CB(_cb, _forcesync) \
+ do{ \
+ /*dbg_printf(dbg_wait_cb, __LINE__);*/ \
+ while(!CB_queue_check(_cb)){ \
+ WAIT_FOR_CB_SYNC_ ## _forcesync \
+ } \
+ }while(0)
+
+/* expansions of WAIT_FOR_CB */
+#define WAIT_FOR_CB_SYNC_0
+#define WAIT_FOR_CB_SYNC_1 SVGA_Sync();
+
+/* wait for all commands */
+void SVGA_Flush_CB_critical()
+{
+ /* wait for actual CB */
+ while(!CB_queue_check(NULL))
+ {
+ SVGA_Sync();
+ }
+
+ /* drain FIFO */
+ SVGA_Flush();
+}
+
+void SVGA_Flush_CB()
+{
+ Begin_Critical_Section(0);
+ SVGA_Flush_CB_critical();
+ End_Critical_Section();
+}
+
+/**
+ * Allocate memory for command buffer
+ **/
+DWORD *SVGA_CMB_alloc_size(DWORD datasize)
+{
+ DWORD phy;
+ SVGACBHeader *cb;
+ cb_queue_t *q;
+
+ Begin_Critical_Section(0);
+
+ q = (cb_queue_t*)_PageAllocate(RoundToPages(datasize+sizeof(SVGACBHeader)+sizeof(cb_queue_t)), PG_SYS, 0, 0, 0x0, 0x100000, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+
+ if(q)
+ {
+ q->next = NULL;
+ q->flags = 0;
+ q->data_size = 0;
+
+ cb = (SVGACBHeader*)(q+1);
+
+ memset(cb, 0, sizeof(SVGACBHeader));
+ cb->status = SVGA_CB_STATUS_COMPLETED; /* important to sync between commands */
+ cb->ptr.pa.hi = 0;
+ cb->ptr.pa.low = phy + sizeof(cb_queue_t) + sizeof(SVGACBHeader);
+
+ End_Critical_Section();
+ return (DWORD*)(cb+1);
+ }
+ End_Critical_Section();
+
+ return NULL;
+}
+
+void SVGA_CMB_free(DWORD *cmb)
+{
+ SVGACBHeader *cb = ((SVGACBHeader *)cmb)-1;
+
+ Begin_Critical_Section(0);
+
+ WAIT_FOR_CB(cb, 1);
+
+ _PageFree(cb-1, 0);
+
+ End_Critical_Section();
+}
+
+DWORD *SVGA_CMB_alloc()
+{
+ return SVGA_CMB_alloc_size(SVGA_CB_MAX_SIZE);
+}
+
+// FIXME: inline?
+static void SVGA_cb_id_inc()
+{
+ _asm
+ {
+ inc dword ptr [cb_next_id]
+ adc dword ptr [cb_next_id+4], 0
+ }
+}
+
+#ifdef DBGPRINT
+#include "vxd_svga_debug.h"
+#endif
+
+/*
+ * @param tracked: check specific CB, or NULL to check full queue
+ *
+ * @return: TRUE if tracked is complete or TRUE id queue is empty
+
+ */
+BOOL CB_queue_check(SVGACBHeader *tracked)
+{
+ cb_queue_t *last = NULL;
+ cb_queue_t *item = cb_queue_info.first;
+ BOOL in_queue = FALSE;
+
+ while(item != NULL)
+ {
+ SVGACBHeader *cb = (SVGACBHeader*)(item+1);
+ if(cb->status >= SVGA_CB_STATUS_COMPLETED)
+ {
+ if(last == NULL)
+ {
+ cb_queue_info.first = item->next;
+ }
+ else
+ {
+ last->next = item->next;
+ }
+
+ if(cb->status > SVGA_CB_STATUS_COMPLETED)
+ {
+ SVGA_CB_restart();
+ }
+
+ item = item->next;
+ }
+ else
+ {
+ if(tracked == cb)
+ {
+ in_queue = TRUE;
+ }
+ last = item;
+ item = item->next;
+ }
+ }
+
+ cb_queue_info.last = last;
+
+ if(cb_queue_info.first == NULL)
+ {
+ return TRUE;
+ }
+
+ if(tracked != NULL && in_queue == FALSE)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CB_queue_insert(SVGACBHeader *cb)
+{
+ cb_queue_t *item = (cb_queue_t*)(cb-1);
+ item->next = NULL;
+
+ if(cb_queue_info.last != NULL)
+ {
+ cb_queue_info.last->next = item;
+ cb_queue_info.last = item;
+ }
+ else
+ {
+ cb_queue_info.first = item;
+ cb_queue_info.last = item;
+ }
+}
+
+
+void SVGA_CMB_submit_critical(DWORD FBPTR cmb, DWORD cmb_size, SVGA_CMB_status_t FBPTR status, DWORD flags, DWORD DXCtxId)
+{
+ DWORD fence = 0;
+ SVGACBHeader *cb = ((SVGACBHeader *)cmb)-1;
+
+ CB_queue_check(NULL);
+
+ if(status)
+ {
+ cb->status = SVGA_CB_STATUS_NONE;
+ status->sStatus = SVGA_PROC_NONE;
+ status->qStatus = (volatile DWORD*)&cb->status;
+ }
+
+#ifdef DBGPRINT
+ debug_cmdbuf(cmb, cmb_size);
+// debug_cmdbuf_trace(cmb, cmb_size, SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
+// debug_draw(cmb, cmb_size);
+#endif
+
+ if(flags & SVGA_CB_PRESENT_ASYNC)
+ {
+ if(present_fence != 0)
+ {
+ SVGA_fence_wait(present_fence);
+ }
+
+ flags |= SVGA_CB_FORCE_FENCE;
+ }
+ else if(present_fence)
+ {
+ if(SVGA_fence_is_passed(present_fence))
+ {
+ present_fence = 0;
+ }
+ }
+
+ if(flags & SVGA_CB_PRESENT_GPU)
+ {
+ ST_FB_invalid = TRUE;
+ }
+
+ if( /* CB are supported and enabled */
+ cb_support &&
+ (cb_context0 || (flags & SVGA_CB_USE_CONTEXT_DEVICE)) &&
+ (flags & SVGA_CB_FORCE_FIFO) == 0
+ )
+ {
+ DWORD cbhwctxid = SVGA_CB_CONTEXT_0;
+
+ if(flags & SVGA_CB_USE_CONTEXT_DEVICE)
+ {
+ cbhwctxid = SVGA_CB_CONTEXT_DEVICE;
+ }
+
+ if(flags & SVGA_CB_FORCE_FENCE)
+ {
+ DWORD dwords = cmb_size/sizeof(DWORD);
+ fence = SVGA_fence_get();
+ cmb[dwords] = SVGA_CMD_FENCE;
+ cmb[dwords+1] = fence;
+ cmb_size += sizeof(DWORD)*2;
+ }
+
+ if(cmb_size == 0)
+ {
+ cb->status = SVGA_PROC_COMPLETED;
+ if(status)
+ {
+ status->sStatus = SVGA_PROC_COMPLETED;
+ status->qStatus = NULL;
+ status->fifo_fence_used = 0;
+ }
+ }
+ else
+ {
+ cb->status = SVGA_CB_STATUS_NONE;
+ cb->errorOffset = 0;
+ cb->offset = 0; /* VMware modified this, needs to be clear */
+ cb->flags = SVGA_CB_FLAG_NO_IRQ;
+
+ if(flags & SVGA_CB_FLAG_DX_CONTEXT)
+ {
+ cb->flags |= SVGA_CB_FLAG_DX_CONTEXT;
+ cb->dxContext = DXCtxId;
+ }
+ else
+ {
+ cb->dxContext = 0;
+ }
+
+ cb->id.low = cb_next_id.low;
+ cb->id.hi = cb_next_id.hi;
+ cb->length = cmb_size;
+
+ CB_queue_insert(cb);
+
+ SVGA_WriteReg(SVGA_REG_COMMAND_HIGH, 0); // high part of 64-bit memory address...
+ SVGA_WriteReg(SVGA_REG_COMMAND_LOW, (cb->ptr.pa.low - sizeof(SVGACBHeader)) | cbhwctxid);
+ SVGA_Sync(); /* notify HV to read registers (VMware needs it) */
+
+ SVGA_cb_id_inc();
+
+ if(flags & SVGA_CB_SYNC)
+ {
+ WAIT_FOR_CB(cb, 0);
+
+ if(cb->status != SVGA_CB_STATUS_COMPLETED)
+ {
+ dbg_printf(dbg_cmd_error, cb->status, cmb[0], cb->errorOffset);
+ if(flags & SVGA_CB_FORCE_FENCE)
+ {
+ /* this may cause freeze, when fence is in buffer and isn't complete. So return some passed fence */
+ fence = SVGA_fence_passed();
+ }
+ }
+ else
+ {
+ dbg_printf(dbg_cb_suc);
+ }
+
+ if(status)
+ {
+ status->sStatus = SVGA_PROC_COMPLETED;
+ status->qStatus = NULL;
+ status->fifo_fence_used = fence;
+ }
+ }
+ else
+ {
+ if(status)
+ {
+ status->sStatus = SVGA_PROC_NONE;
+ status->qStatus = (volatile DWORD*)&cb->status;
+ status->fifo_fence_used = fence;
+ }
+ }
+ }
+ }
+ else /* copy to FIFO */
+ {
+ DWORD *ptr = cmb;
+ DWORD dwords = cmb_size/sizeof(DWORD);
+ DWORD nextCmd, max, min;
+
+ /* insert fence CMD */
+ fence = SVGA_fence_get();
+ ptr[dwords] = SVGA_CMD_FENCE;
+ ptr[dwords+1] = fence;
+
+ dwords += 2;
+
+ //SVGA_Flush();
+
+ nextCmd = gSVGA.fifoMem[SVGA_FIFO_NEXT_CMD];
+ max = gSVGA.fifoMem[SVGA_FIFO_MAX];
+ min = gSVGA.fifoMem[SVGA_FIFO_MIN];
+
+ /* copy to fifo */
+ while(dwords > 0)
+ {
+ gSVGA.fifoMem[nextCmd/sizeof(DWORD)] = *ptr;
+ ptr++;
+
+ nextCmd += sizeof(uint32);
+ if (nextCmd >= max)
+ {
+ nextCmd = min;
+ }
+ gSVGA.fifoMem[SVGA_FIFO_NEXT_CMD] = nextCmd;
+ dwords--;
+ }
+
+ //SVGA_Sync();
+
+ if(flags & SVGA_CB_SYNC)
+ {
+ SVGA_fence_wait(fence);
+ if(status)
+ {
+ status->sStatus = SVGA_PROC_COMPLETED;
+ status->qStatus = NULL;
+ status->fifo_fence_used = 0;
+ }
+ }
+ else
+ {
+ if(status)
+ {
+ status->sStatus = SVGA_PROC_FENCE;
+ status->qStatus = NULL;
+ status->fifo_fence_used = fence;
+ }
+ }
+
+ cb->status = SVGA_PROC_COMPLETED;
+ } /* FIFO */
+
+ if(status)
+ {
+ status->fifo_fence_last = SVGA_fence_passed();
+ }
+
+ if(flags & SVGA_CB_PRESENT_ASYNC)
+ {
+ present_fence = fence;
+ }
+
+ //dbg_printf(dbg_cmd_off, cmb[0]);
+}
+
+void wait_for_cmdbuf()
+{
+ SVGACBHeader *cb;
+
+ Begin_Critical_Section(0);
+ cb = ((SVGACBHeader *)cmdbuf)-1;
+ WAIT_FOR_CB(cb, 0);
+}
+
+void submit_cmdbuf(DWORD cmdsize, DWORD flags, DWORD dx)
+{
+ SVGA_CMB_submit_critical(cmdbuf, cmdsize, NULL, flags, dx);
+ End_Critical_Section();
+}
+
+void SVGA_CMB_submit(DWORD FBPTR cmb, DWORD cmb_size, SVGA_CMB_status_t FBPTR status, DWORD flags, DWORD DXCtxId)
+{
+ Begin_Critical_Section(0);
+ SVGA_CMB_submit_critical(cmb, cmb_size, status, flags, DXCtxId);
+ End_Critical_Section();
+}
+
+static DWORD SVGA_CB_ctr(DWORD data_size)
+{
+ SVGACBHeader *cb = ((SVGACBHeader *)ctlbuf)-1;
+
+ dbg_printf(dbg_ctr_start);
+
+ //Begin_Critical_Section(0);
+
+ cb->status = SVGA_CB_STATUS_NONE;
+ cb->errorOffset = 0;
+ cb->offset = 0; /* VMware modified this, needs to be clear */
+ cb->flags = SVGA_CB_FLAG_NO_IRQ;
+ cb->mustBeZero[0] = 0;
+ cb->mustBeZero[1] = 0;
+ cb->mustBeZero[2] = 0;
+ cb->mustBeZero[3] = 0;
+ cb->mustBeZero[4] = 0;
+ cb->mustBeZero[5] = 0;
+ cb->dxContext = 0;
+ cb->id.low = cb_next_id.low;
+ cb->id.hi = cb_next_id.hi;
+ cb->length = data_size;
+
+ SVGA_WriteReg(SVGA_REG_COMMAND_HIGH, 0);
+ SVGA_WriteReg(SVGA_REG_COMMAND_LOW, (cb->ptr.pa.low - sizeof(SVGACBHeader)) | SVGA_CB_CONTEXT_DEVICE);
+ SVGA_Sync();
+
+ SVGA_cb_id_inc();
+
+ while(cb->status == SVGA_CB_STATUS_NONE)
+ {
+ SVGA_Sync();
+ }
+
+ //End_Critical_Section();
+
+ dbg_printf(dbg_ctr_end);
+
+ return cb->status;
+}
+
+/**
+ * GPU10: start context0
+ *
+ **/
+void SVGA_CB_start()
+{
+ if(cb_support && cb_context0 == FALSE)
+ {
+ cb_enable_t *cbe = ctlbuf;
+ DWORD status;
+
+ memset(cbe, 0, sizeof(cb_enable_t));
+ cbe->cmd = SVGA_DC_CMD_START_STOP_CONTEXT;
+ cbe->cbstart.enable = 1;
+ cbe->cbstart.context = SVGA_CB_CONTEXT_0;
+
+ status = SVGA_CB_ctr(sizeof(cb_enable_t));
+
+ if(status == SVGA_CB_STATUS_COMPLETED)
+ {
+ dbg_printf(dbg_cb_start);
+ cb_context0 = TRUE;
+ }
+ else
+ {
+ cb_support = FALSE;
+ dbg_printf(dbg_cb_start_err, status);
+ }
+ }
+}
+
+/**
+ * GPU10: stop context0
+ *
+ **/
+void SVGA_CB_stop()
+{
+ cb_context0 = FALSE;
+
+ if(cb_support)
+ {
+ DWORD status;
+ cb_enable_t *cbe = ctlbuf;
+
+ memset(cbe, 0, sizeof(cb_enable_t));
+ cbe->cmd = SVGA_DC_CMD_START_STOP_CONTEXT;
+ cbe->cbstart.enable = 0;
+ cbe->cbstart.context = SVGA_CB_CONTEXT_0;
+
+ status = SVGA_CB_ctr(sizeof(cb_enable_t));
+ dbg_printf(dbg_cb_stop_status, status);
+
+ dbg_printf(dbg_cb_stop);
+ }
+}
+
+/**
+ * GPU10: restart context0 after error
+ *
+ **/
+void SVGA_CB_restart()
+{
+ cb_context0 = FALSE;
+ SVGA_CB_start();
+}
diff --git a/vxd_svga_mem.c b/vxd_svga_mem.c
new file mode 100644
index 0000000..319fb53
--- /dev/null
+++ b/vxd_svga_mem.c
@@ -0,0 +1,932 @@
+/*****************************************************************************
+
+Copyright (c) 2024 Jaroslav Hensl <emulator@emulace.cz>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*****************************************************************************/
+
+/* 32 bit RING-0 code for SVGA-II 3D acceleration */
+#define SVGA
+
+#include <limits.h>
+
+#include "winhack.h"
+#include "vmm.h"
+#include "vxd.h"
+#include "vxd_lib.h"
+
+#include "svga_all.h"
+#include "3d_accel.h"
+#include "code32.h"
+#include "vxd_svga.h"
+#include "vxd_strings.h"
+
+#include "svga_ver.h"
+
+/*
+ * consts
+ */
+#define PTONPAGE (P_SIZE/sizeof(DWORD))
+
+#define SPARE_REGIONS_LARGE 2
+#define SPARE_REGION_LARGE_SIZE (32*1024*1024)
+
+#define SPARE_REGIONS_MEDIUM 16
+#define SPARE_REGION_MEDIUM_SIZE (1024*1024)
+
+#define SPARE_REGIONS_SMALL 128
+//#define SPARE_REGION_SMALL_SIZE 4096
+
+#define SPARE_REGIONS_CNT (SPARE_REGIONS_LARGE+SPARE_REGIONS_MEDIUM+SPARE_REGIONS_SMALL)
+
+#define CACHE_THRESHOLD 128
+
+/**
+ * types
+ */
+
+typedef struct spare_region
+{
+ BOOL used;
+ uint32 missed;
+ SVGA_region_info_t region;
+} spare_region_t;
+
+typedef struct svga_cache_state
+{
+ int free_index_min;
+ int free_index_max;
+ int cnt_large;
+ int cnt_medium;
+ int cnt_small;
+ spare_region_t spare_region[SPARE_REGIONS_CNT];
+} svga_cache_state_t;
+
+
+/* object table for GPU10 */
+static SVGA_OT_info_entry_t otable_setup[SVGA_OTABLE_DX_MAX] = {
+ {0, NULL, RoundTo4k(VMWGFX_NUM_MOB*sizeof(SVGAOTableMobEntry)), 0, 0}, /* SVGA_OTABLE_MOB */
+ {0, NULL, RoundTo4k(VMWGFX_NUM_GB_SURFACE*sizeof(SVGAOTableSurfaceEntry)), 0, 0}, /* SVGA_OTABLE_SURFACE */
+ {0, NULL, RoundTo4k(VMWGFX_NUM_GB_CONTEXT*sizeof(SVGAOTableContextEntry)), 0, 0}, /* SVGA_OTABLE_CONTEXT */
+ {0, NULL, RoundTo4k(VMWGFX_NUM_GB_SHADER *sizeof(SVGAOTableShaderEntry)), 0, 0}, /* SVGA_OTABLE_SHADER - not used */
+ {0, NULL, RoundTo4k(VMWGFX_NUM_GB_SCREEN_TARGET*sizeof(SVGAOTableScreenTargetEntry)), 0, 0}, /* SVGA_OTABLE_SCREENTARGET (VBOX_VIDEO_MAX_SCREENS) */
+ {0, NULL, RoundTo4k(VMWGFX_NUM_DXCONTEXT*sizeof(SVGAOTableDXContextEntry)), 0, 0}, /* SVGA_OTABLE_DXCONTEXT */
+};
+
+static SVGA_OT_info_entry_t *otable = NULL;
+
+static svga_cache_state_t cache_state = {0, 0};
+
+static BOOL cache_enabled = FALSE;
+
+
+/*
+ * globals
+ */
+extern FBHDA_t *hda;
+extern ULONG hda_sem;
+static SVGA_DB_t *svga_db = NULL;
+
+extern LONG fb_lock_cnt;
+
+extern BOOL gb_support;
+
+
+/**
+ * Return PPN (physical page number) to virtual address
+ *
+ **/
+static DWORD getPPN(DWORD virtualaddr)
+{
+ DWORD phy = 0;
+ _CopyPageTable(virtualaddr/P_SIZE, 1, &phy, 0);
+ return phy/P_SIZE;
+}
+
+/**
+ * Return PPN for pointer
+ *
+ **/
+static DWORD getPtrPPN(void *ptr)
+{
+ return getPPN((DWORD)ptr);
+}
+
+/**
+ * Return page table pages need for buffer of specific size
+ *
+ **/
+static DWORD PT_count(DWORD size)
+{
+ DWORD pt1_entries = 0;
+ DWORD pt2_entries = 0;
+
+ pt1_entries = RoundToPages(size);
+ pt2_entries = ((pt1_entries + PTONPAGE - 1)/PTONPAGE);
+
+ dbg_printf(dbg_pt_build_2, size, pt1_entries, pt2_entries);
+
+ if(pt2_entries > 1)
+ {
+ return pt2_entries + 1;
+ }
+
+ return 1;
+}
+
+/**
+ * Build paget table for specific buffer
+ *
+ **/
+static void PT_build(DWORD size, void *buf, DWORD *outBase, DWORD *outType, void **outUserPtr)
+{
+ DWORD pt1_entries = 0;
+ DWORD pt2_entries = 0;
+ DWORD i;
+
+ pt1_entries = RoundToPages(size);
+ pt2_entries = ((pt1_entries + PTONPAGE - 1)/PTONPAGE);
+
+ if(pt2_entries > 1)
+ {
+ DWORD *ptbuf = buf;
+ BYTE *ptr = ((BYTE*)buf)+((pt2_entries+1)*P_SIZE);
+
+ memset(buf, 0, (pt2_entries+1)*P_SIZE);
+
+ /* build PT2 */
+ for(i = 0; i < pt2_entries; i++)
+ {
+ ptbuf[i] = getPtrPPN(ptbuf + ((i+1)*PTONPAGE));
+ }
+
+ ptbuf += PTONPAGE;
+
+ /* build PT2 */
+ for(i = 0; i < pt1_entries; i++)
+ {
+ ptbuf[i] = getPtrPPN(ptr + i*P_SIZE);
+ }
+
+ *outBase = getPtrPPN(buf);
+ *outType = SVGA3D_MOBFMT_PTDEPTH_2;
+ *outUserPtr = (void*)ptr;
+ }
+ else
+ {
+ DWORD *ptbuf = buf;
+ BYTE *ptr = ((BYTE*)buf)+P_SIZE;
+
+ memset(buf, 0, P_SIZE);
+
+ for(i = 0; i < pt1_entries; i++)
+ {
+ ptbuf[i] = getPtrPPN(ptr + i*P_SIZE);
+ }
+
+ *outBase = getPtrPPN(buf);
+ *outType = SVGA3D_MOBFMT_PTDEPTH_1;
+ *outUserPtr = (void*)ptr;
+ }
+
+ dbg_printf(dbg_pt_build, size, *outBase, *outType, *outUserPtr);
+}
+
+/**
+ * Allocate OTable for GB objects
+ **/
+void SVGA_OTable_alloc(BOOL screentargets)
+{
+ int i;
+
+ if(otable == NULL)
+ {
+ otable = (SVGA_OT_info_entry_t *)_PageAllocate(RoundToPages(sizeof(otable_setup)), PG_VM, ThisVM, 0, 0x0, 0x100000, NULL, PAGEFIXED);
+ if(otable)
+ {
+ memcpy(otable, &(otable_setup[0]), sizeof(otable_setup));
+ }
+ }
+
+ /* not allocate DX when there is no DX support */
+ if(!SVGA_GetDevCap(SVGA3D_DEVCAP_DXCONTEXT))
+ {
+ otable[SVGA_OTABLE_DXCONTEXT].size = 0;
+ }
+
+ if(!screentargets)
+ {
+ otable[SVGA_OTABLE_SCREENTARGET].size = 0;
+ }
+
+ if(otable)
+ {
+ for(i = 0; i < SVGA_OTABLE_DX_MAX; i++)
+ {
+ SVGA_OT_info_entry_t *entry = &otable[i];
+ if(entry->size != 0 && (entry->flags & SVGA_OT_FLAG_ALLOCATED) == 0)
+ {
+ void *ptr = (void*)_PageAllocate(RoundToPages(entry->size)+PT_count(entry->size), PG_VM, ThisVM, 0, 0x0, 0x100000, NULL, PAGEFIXED);
+
+ if(ptr)
+ {
+ dbg_printf(dbg_mob_allocate, i);
+ PT_build(entry->size, ptr, &entry->ppn, &entry->pt_depth, &entry->lin);
+
+ entry->flags |= SVGA_OT_FLAG_ALLOCATED;
+ entry->flags |= SVGA_OT_FLAG_DIRTY;
+ }
+ }
+ }
+ }
+}
+
+SVGA_OT_info_entry_t *SVGA_OT_setup()
+{
+ return otable;
+}
+
+/**
+ * Apply tables to VGPU
+ **/
+void SVGA_OTable_load()
+{
+ DWORD i;
+ DWORD cmd_offset = 0;
+ SVGA3dCmdSetOTableBase *cmd;
+
+ SVGA_OT_info_entry_t *ot = SVGA_OT_setup();
+ if(ot == NULL)
+ {
+ return;
+ }
+
+ wait_for_cmdbuf();
+
+ for(i = SVGA_OTABLE_MOB; i < SVGA_OTABLE_DX_MAX; i++)
+ {
+ SVGA_OT_info_entry_t *entry = &(ot[i]);
+
+ if((entry->flags & SVGA_OT_FLAG_ACTIVE) == 0)
+ {
+ if(entry->size > 0)
+ {
+ cmd = SVGA_cmd3d_ptr(cmdbuf, &cmd_offset, SVGA_3D_CMD_SET_OTABLE_BASE, sizeof(SVGA3dCmdSetOTableBase));
+ cmd->type = i;
+ cmd->baseAddress = entry->ppn;
+ cmd->sizeInBytes = entry->size;
+ if((entry->flags & SVGA_OT_FLAG_DIRTY) == 0)
+ {
+ cmd->validSizeInBytes = entry->size;
+ }
+ else
+ {
+ cmd->validSizeInBytes = 0;
+ }
+ cmd->ptDepth = entry->pt_depth;
+
+ entry->flags |= SVGA_OT_FLAG_ACTIVE;
+ }
+ }
+ }
+
+ submit_cmdbuf(cmd_offset, SVGA_CB_SYNC, 0);
+}
+
+void SVGA_OTable_unload()
+{
+ DWORD i;
+ DWORD cmd_offset = 0;
+ SVGA3dCmdSetOTableBase *cmd;
+ SVGA3dCmdReadbackOTable *cmd_readback;
+
+ SVGA_OT_info_entry_t *ot = SVGA_OT_setup();
+ if(ot == NULL)
+ {
+ return;
+ }
+
+ wait_for_cmdbuf();
+
+ for(i = SVGA_OTABLE_MOB; i < SVGA_OTABLE_DX_MAX; i++)
+ {
+ SVGA_OT_info_entry_t *entry = &(ot[i]);
+
+ if(entry->flags & SVGA_OT_FLAG_ACTIVE)
+ {
+ if(entry->size > 0)
+ {
+ cmd_readback = SVGA_cmd3d_ptr(cmdbuf, &cmd_offset, SVGA_3D_CMD_READBACK_OTABLE, sizeof(SVGA3dCmdReadbackOTable));
+ cmd_readback->type = i;
+ entry->flags &= ~SVGA_OT_FLAG_DIRTY;
+
+ cmd = SVGA_cmd3d_ptr(cmdbuf, &cmd_offset, SVGA_3D_CMD_SET_OTABLE_BASE, sizeof(SVGA3dCmdSetOTableBase));
+ cmd->type = i;
+ cmd->baseAddress = 0;
+ cmd->sizeInBytes = 0;
+ cmd->validSizeInBytes = 0;
+ cmd->ptDepth = SVGA3D_MOBFMT_INVALID;
+
+ entry->flags &= ~SVGA_OT_FLAG_ACTIVE;
+ }
+ }
+ }
+
+ submit_cmdbuf(cmd_offset, SVGA_CB_SYNC, 0);
+}
+
+
+/**/
+/**
+ * Delete item from cache
+ **/
+static void cache_delete(int index)
+{
+ if(cache_state.spare_region[index].used != FALSE)
+ {
+ SVGA_region_info_t *rinfo = &cache_state.spare_region[index].region;
+ BYTE *free_ptr = (BYTE*)rinfo->address;
+ uint32 region_size = rinfo->size;;
+
+ if(rinfo->region_address != NULL)
+ {
+ dbg_printf(dbg_pagefree, rinfo->region_address);
+ _PageFree((PVOID)rinfo->region_address, 0);
+ }
+ else
+ {
+ free_ptr -= P_SIZE;
+ }
+
+ if(rinfo->mob_address != NULL)
+ {
+ dbg_printf(dbg_pagefree, rinfo->mob_address);
+ _PageFree((PVOID)rinfo->mob_address, 0);
+ }
+
+ dbg_printf(dbg_pagefree, free_ptr);
+ _PageFree((PVOID)free_ptr, 0);
+
+ cache_state.spare_region[index].used = FALSE;
+
+ if((index+1) == cache_state.free_index_max)
+ {
+ cache_state.free_index_max--;
+ }
+
+ if(index < cache_state.free_index_min)
+ {
+ cache_state.free_index_min = index;
+ }
+
+ if(region_size >= SPARE_REGION_LARGE_SIZE)
+ cache_state.cnt_large--;
+ else if(region_size >= SPARE_REGION_MEDIUM_SIZE)
+ cache_state.cnt_medium--;
+ else
+ cache_state.cnt_small--;
+ }
+}
+
+/**
+ * Insert region to cache
+ **/
+static BOOL cache_insert(SVGA_region_info_t *region)
+{
+ int i;
+ BOOL rc = FALSE;
+
+ if(!cache_enabled)
+ {
+ return FALSE;
+ }
+
+ if(region->size >= SPARE_REGION_LARGE_SIZE)
+ {
+ if(cache_state.cnt_large > SPARE_REGIONS_LARGE) return FALSE;
+ }
+ else if(region->size >= SPARE_REGION_MEDIUM_SIZE)
+ {
+ if(cache_state.cnt_medium > SPARE_REGIONS_MEDIUM) return FALSE;
+ }
+ else
+ {
+ if(cache_state.cnt_small > SPARE_REGIONS_SMALL) return FALSE;
+ }
+
+ for(i = cache_state.free_index_min; i < SPARE_REGIONS_CNT; i++)
+ {
+ if(!cache_state.spare_region[i].used)
+ {
+ memcpy(&cache_state.spare_region[i].region, region, sizeof(SVGA_region_info_t));
+ cache_state.spare_region[i].used = TRUE;
+ cache_state.spare_region[i].missed = 0;
+ rc = TRUE;
+ break;
+ }
+ }
+
+ for(; i < SPARE_REGIONS_CNT; i++)
+ {
+ if(!cache_state.spare_region[i].used)
+ {
+ cache_state.free_index_min = i;
+ break;
+ }
+ }
+
+ if(i == SPARE_REGIONS_CNT)
+ {
+ cache_state.free_index_min = i;
+ cache_state.free_index_max = SPARE_REGIONS_CNT;
+ }
+ else if(i >= cache_state.free_index_max)
+ {
+ cache_state.free_index_max = i+1;
+ }
+
+ if(rc)
+ {
+ if(region->size >= SPARE_REGION_LARGE_SIZE)
+ cache_state.cnt_large++;
+ else if(region->size >= SPARE_REGION_MEDIUM_SIZE)
+ cache_state.cnt_medium++;
+ else
+ cache_state.cnt_small++;
+
+ dbg_printf(dbg_cache_insert, region->region_id, region->size);
+ }
+
+ return rc;
+}
+
+/**
+ * Use region from cache
+ **/
+static BOOL cache_use(SVGA_region_info_t *region)
+{
+ int i;
+ BOOL rc = FALSE;
+
+ if(!cache_enabled)
+ {
+ return FALSE;
+ }
+
+ dbg_printf(dbg_cache_search, region->size);
+
+ for(i = cache_state.free_index_max-1; i >= 0; i--)
+ {
+ if(cache_state.spare_region[i].used != FALSE)
+ {
+ if(cache_state.spare_region[i].region.size == region->size)
+ {
+ SVGA_region_info_t *ptr = &cache_state.spare_region[i].region;
+
+ region->address = ptr->address;
+ region->region_address = ptr->region_address;
+ region->region_ppn = ptr->region_ppn;
+ region->mob_address = ptr->mob_address;
+ region->mob_ppn = ptr->mob_ppn;
+
+ cache_state.spare_region[i].used = FALSE;
+ rc = TRUE;
+ break;
+ }
+ else
+ {
+ if(++cache_state.spare_region[i].missed >= CACHE_THRESHOLD)
+ {
+ dbg_printf(dbg_cache_delete, cache_state.spare_region[i].region.size);
+ cache_delete(i);
+ }
+ }
+ }
+ }
+
+ if(rc)
+ {
+ if((i+1) == cache_state.free_index_max)
+ {
+ cache_state.free_index_max--;
+ }
+
+ if(i < cache_state.free_index_min)
+ {
+ cache_state.free_index_min = i;
+ }
+
+ if(region->size >= SPARE_REGION_LARGE_SIZE)
+ cache_state.cnt_large--;
+ else if(region->size >= SPARE_REGION_MEDIUM_SIZE)
+ cache_state.cnt_medium--;
+ else
+ cache_state.cnt_small--;
+
+ dbg_printf(dbg_cache_used, region->region_id, region->size);
+ }
+
+ return rc;
+}
+
+void cache_init()
+{
+ memset(&cache_state, 0, sizeof(svga_cache_state_t));
+}
+
+void cache_enable(BOOL enabled)
+{
+ cache_enabled = enabled;
+}
+
+//#define GMR_CONTIG
+//#define GMR_SYSTEM
+
+//static DWORD pa_flags = PAGEFIXED | PAGEUSEALIGN;
+//static DWORD pa_align = 0x0000000F; // 64k
+
+static DWORD pa_flags = PAGEFIXED;
+static DWORD pa_align = 0x00000000;
+
+/**
+ * Allocate guest memory region (GMR) - HW needs know memory physical
+ * addressed of pages in (virtual) memory block.
+ * Technically this allocate 2 memory block, 1st for data and 2nd as its
+ * physical description.
+ *
+ * @return: TRUE on success
+ *
+ **/
+BOOL SVGA_region_create(SVGA_region_info_t *rinfo)
+{
+#ifdef GMR_CONTIG
+ ULONG phy = 0;
+#endif
+ ULONG laddr;
+ ULONG pgblk;
+ ULONG new_size = RoundTo4k(rinfo->size);
+ ULONG nPages = RoundToPages(new_size);
+ //ULONG nPages = RoundToPages64k(rinfo->size);
+ ULONG pa_vm = ThisVM;
+ ULONG pa_type = PG_VM;
+ SVGAGuestMemDescriptor *desc;
+ ULONG size_total = 0;
+
+#ifdef GMR_SYSTEM
+ pa_vm = 0;
+ pa_type = PG_SYS;
+#endif
+
+ rinfo->size = new_size;
+
+ Begin_Critical_Section(0);
+
+ if(cache_use(rinfo))
+ {
+ goto spare_region_used;
+ }
+
+ //dbg_printf(dbg_pages, rinfo->size, nPages, P_SIZE);
+#ifdef GMR_CONTIG
+ /* JH: OK, using PAGECONTIG leads to very fast memory exhaustion, so using only slower way! */
+ /* first try to allocate continuous physical memory space, 1st page is used for GMR descriptor */
+ laddr = _PageAllocate(nPages+1, pa_type, pa_vm, 0, 0x0, 0x100000, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+
+ if(laddr)
+ {
+ desc = (SVGAGuestMemDescriptor*)laddr;
+ desc->ppn = (phy/P_SIZE)+1;
+ desc->numPages = nPages;
+ desc++;
+ desc->ppn = 0;
+ desc->numPages = 0;
+
+ rinfo->address = (void*)(laddr+P_SIZE);
+ rinfo->region_address = 0;
+ rinfo->region_ppn = (phy/P_SIZE);
+ rinfo->mob_address = 0;
+ rinfo->mob_ppn = (phy/P_SIZE)+1;
+
+ //dbg_printf(dbg_region_simple, laddr, rinfo->address);
+
+ size_total = (nPages+1)*P_SIZE;
+ }
+ else
+#endif
+ {
+ /* memory is too fragmented to create this large continous region */
+ ULONG taddr;
+ ULONG tppn;
+ ULONG pgi;
+ ULONG base_ppn;
+ ULONG base_cnt;
+ ULONG blocks = 1;
+ ULONG blk_pages = 0;
+ ULONG mob_pages = 0;
+
+ DWORD *mob = NULL;
+ //DWORD mobphy = 0;
+
+ /* allocate user block */
+ laddr = _PageAllocate(nPages, pa_type, pa_vm, pa_align, 0x0, 0x100000, NULL, pa_flags);
+
+ if(!laddr)
+ {
+ End_Critical_Section();
+ return FALSE;
+ }
+
+ /* determine how many physical continuous blocks we have */
+ base_ppn = getPPN(laddr);
+ base_cnt = 1;
+ for(pgi = 1; pgi < nPages; pgi++)
+ {
+ taddr = laddr + pgi*P_SIZE;
+ tppn = getPPN(taddr);
+
+ if(tppn != base_ppn + base_cnt)
+ {
+ base_ppn = tppn;
+ base_cnt = 1;
+ blocks++;
+ }
+ else
+ {
+ base_cnt++;
+ }
+ }
+
+ // number of pages to store regions information
+ blk_pages = ((blocks+1)/(P_SIZE/sizeof(SVGAGuestMemDescriptor))) + 1;
+
+ // add extra descriptors for pages edge
+ blk_pages = ((blocks+blk_pages+1)/(P_SIZE/sizeof(SVGAGuestMemDescriptor))) + 1;
+
+ /* allocate memory for GMR descriptor */
+ pgblk = _PageAllocate(blk_pages, pa_type, pa_vm, pa_align, 0x0, 0x100000, NULL, pa_flags);
+ if(!pgblk)
+ {
+ _PageFree((PVOID)laddr, 0);
+ End_Critical_Section();
+ return FALSE;
+ }
+
+ desc = (SVGAGuestMemDescriptor*)pgblk;
+ desc->ppn = getPPN(laddr);
+ desc->numPages = 1;
+ blocks = 1;
+
+ /* fill GMR physical structure */
+ for(pgi = 1; pgi < nPages; pgi++)
+ {
+ taddr = laddr + pgi*P_SIZE;
+ tppn = getPPN(taddr);
+
+ if(tppn == desc->ppn + desc->numPages)
+ {
+ desc->numPages++;
+ }
+ else
+ {
+ /* next descriptor is on page edge */
+ if((blocks+1) % (P_SIZE/sizeof(SVGAGuestMemDescriptor)) == 0)
+ {
+ desc++;
+ desc->numPages = 0;
+ desc->ppn = getPPN((DWORD)(desc+1));
+ blocks++;
+ }
+
+ desc++;
+ desc->ppn = tppn;
+ desc->numPages = 1;
+ blocks++;
+ }
+ }
+
+ desc++;
+ desc->ppn = 0;
+ desc->numPages = 0;
+
+ if(gb_support) /* don't create MOBs for Gen9 */
+ {
+ int i;
+ /* for simplicity we're always creating table of depth 2, first page is page of PPN pages */
+ //mob = (DWORD *)_PageAllocate(1 + (nPages + PTONPAGE - 1)/PTONPAGE, pa_type, pa_vm, 0, 0x0, 0x100000, &mobphy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+ mob_pages = 1 + (nPages + PTONPAGE - 1)/PTONPAGE;
+ mob = (DWORD *)_PageAllocate(mob_pages, pa_type, pa_vm, pa_align, 0x0, 0x100000, 0, pa_flags);
+
+ if(!mob)
+ {
+ _PageFree((PVOID)laddr, 0);
+ _PageFree((PVOID)pgblk, 0);
+ End_Critical_Section();
+ return FALSE;
+ }
+
+ memset(mob, 0, mob_pages*P_SIZE);
+
+ /* dim 1 */
+ for(i = 0; i < mob_pages-1; i++)
+ {
+ //mob[i] = (mobphy/P_SIZE) + i + 1;
+ mob[i] = getPPN(((ULONG)mob) + ((i + 1)*P_SIZE));
+ }
+ /* dim 2 */
+ for(i = 0; i < nPages; i++)
+ {
+ mob[PTONPAGE + i] = getPPN(laddr + i*P_SIZE);
+ }
+ }
+
+ rinfo->address = (void*)laddr;
+ rinfo->region_address = (void*)pgblk;
+ rinfo->region_ppn = getPPN(pgblk);
+ rinfo->mob_address = (void*)mob;
+ rinfo->mob_ppn = 0;
+ if(mob)
+ {
+ //rinfo->mob_ppn = mobphy/P_SIZE;
+ rinfo->mob_ppn = getPPN((ULONG)mob);
+ }
+
+ size_total = (nPages + blk_pages + mob_pages)*P_SIZE;
+
+ //dbg_printf(dbg_region_fragmented);
+ }
+
+ //dbg_printf(dbg_gmr, rinfo->region_id, rinfo->region_ppn);
+
+ spare_region_used:
+ //dbg_printf(dbg_mobonly, rinfo->mobonly);
+
+ // JH: no need here
+ //SVGA_Flush_CB();
+
+ if(!rinfo->mobonly)
+ {
+ if(rinfo->region_id < SVGA_ReadReg(SVGA_REG_GMR_MAX_IDS))
+ {
+ /* register GMR */
+ SVGA_WriteReg(SVGA_REG_GMR_ID, rinfo->region_id);
+ SVGA_WriteReg(SVGA_REG_GMR_DESCRIPTOR, rinfo->region_ppn);
+ SVGA_Sync(); // notify register change
+
+ SVGA_Flush_CB_critical();
+ }
+ else
+ {
+ /* GMR is too high, use it as only as MOB (DX) */
+ rinfo->region_ppn = 0;
+ }
+ }
+
+ if(gb_support)
+ {
+ SVGA3dCmdDefineGBMob *mob;
+ DWORD cmdoff = 0;
+
+ wait_for_cmdbuf();
+ mob = SVGA_cmd3d_ptr(cmdbuf, &cmdoff, SVGA_3D_CMD_DEFINE_GB_MOB, sizeof(SVGA3dCmdDefineGBMob));
+ mob->mobid = rinfo->region_id;
+ mob->base = rinfo->mob_ppn;
+ mob->sizeInBytes = rinfo->size;
+ if(rinfo->mob_address == NULL) /* continual memory space */
+ {
+ mob->ptDepth = SVGA3D_MOBFMT_RANGE;
+ }
+ else
+ {
+ mob->ptDepth = SVGA3D_MOBFMT_PTDEPTH_2;
+ }
+
+ submit_cmdbuf(cmdoff, SVGA_CB_SYNC, 0);
+
+ rinfo->is_mob = 1;
+ }
+ else
+ {
+ rinfo->is_mob = 0;
+ }
+
+ svga_db->stat_regions_usage += rinfo->size;
+
+ End_Critical_Section();
+
+ //dbg_printf(dbg_gmr_succ, rinfo->region_id, rinfo->size);
+
+ return TRUE;
+}
+
+/**
+ * Free data allocated by SVGA_region_create
+ *
+ **/
+void SVGA_region_free(SVGA_region_info_t *rinfo)
+{
+ BOOL saved_in_cache;
+ BYTE *free_ptr = (BYTE*)rinfo->address;
+
+ Begin_Critical_Section(0);
+ svga_db->stat_regions_usage -= rinfo->size;
+
+ saved_in_cache = cache_insert(rinfo);
+
+ if(gb_support)
+ {
+ SVGA3dCmdDestroyGBMob *mob;
+ DWORD cmdoff = 0;
+
+ wait_for_cmdbuf();
+ mob = SVGA_cmd3d_ptr(cmdbuf, &cmdoff, SVGA_3D_CMD_DESTROY_GB_MOB, sizeof(SVGA3dCmdDestroyGBMob));
+ mob->mobid = rinfo->region_id;
+
+ if(saved_in_cache)
+ submit_cmdbuf(cmdoff, 0, 0);
+ else
+ submit_cmdbuf(cmdoff, SVGA_CB_SYNC, 0);
+ }
+
+ if(!rinfo->mobonly)
+ {
+ SVGA_Sync();
+ SVGA_Flush_CB_critical();
+
+ SVGA_WriteReg(SVGA_REG_GMR_ID, rinfo->region_id);
+ SVGA_WriteReg(SVGA_REG_GMR_DESCRIPTOR, 0);
+ SVGA_Sync(); // notify register change
+ }
+
+ if(!saved_in_cache)
+ {
+ if(rinfo->region_address != NULL)
+ {
+ //dbg_printf(dbg_pagefree, rinfo->region_address);
+ _PageFree((PVOID)rinfo->region_address, 0);
+ }
+ else
+ {
+ free_ptr -= P_SIZE;
+ }
+
+ if(rinfo->mob_address != NULL)
+ {
+ //dbg_printf(dbg_pagefree, rinfo->mob_address);
+ _PageFree((PVOID)rinfo->mob_address, 0);
+ }
+
+ //dbg_printf(dbg_pagefree, free_ptr);
+ _PageFree((PVOID)free_ptr, 0);
+ }
+ End_Critical_Section();
+
+ //dbg_printf(dbg_pagefree_end, rinfo->region_id, rinfo->size, saved_in_cache);
+
+ rinfo->address = NULL;
+ rinfo->region_address = NULL;
+ rinfo->mob_address = NULL;
+ rinfo->region_ppn = 0;
+ rinfo->mob_ppn = 0;
+}
+
+/**
+ * Destroy saved regions and free memory
+ *
+ **/
+void SVGA_flushcache()
+{
+ int i;
+
+ Begin_Critical_Section(0);
+
+ for(i = 0; i < cache_state.free_index_max ; i++)
+ {
+ cache_delete(i);
+ }
+
+ cache_state.free_index_max = 0;
+ cache_state.free_index_min = 0;
+ cache_state.cnt_large = 0;
+ cache_state.cnt_medium = 0;
+ cache_state.cnt_small = 0;
+
+ End_Critical_Section();
+}
+