diff options
author | Jaroslav Hensl <jara@hensl.cz> | 2023-06-28 22:04:13 +0200 |
---|---|---|
committer | Jaroslav Hensl <jara@hensl.cz> | 2023-06-28 22:04:13 +0200 |
commit | 7f80983c1b9431380a9dce18586e0eea57be5707 (patch) | |
tree | 48c295786a1f749f883989cef3063fd123134370 | |
parent | 14395d1ce8759ce490beb87c80ddb1f7ed35904f (diff) | |
download | vmdisp9x-7f80983c1b9431380a9dce18586e0eea57be5707.tar.gz |
SVGA3D: better GMR allocator, some 32bit calls support, API version update
-rw-r--r-- | control.c | 25 | ||||
-rw-r--r-- | control_vxd.c | 16 | ||||
-rw-r--r-- | control_vxd.h | 4 | ||||
-rw-r--r-- | dbgprint.c | 6 | ||||
-rw-r--r-- | makefile | 2 | ||||
-rw-r--r-- | version.h | 2 | ||||
-rw-r--r-- | vmdisp9x.inf | 2 | ||||
-rw-r--r-- | vmm.h | 25 | ||||
-rw-r--r-- | vmwsvxd.c | 275 |
9 files changed, 319 insertions, 38 deletions
@@ -306,7 +306,7 @@ void SVGAHDA_init() SVGAHDA.ul_fence_index = SVGAHDA.ul_flags_index + 5;
SVGAHDA.ul_gmr_start = SVGAHDA.ul_fence_index + 1;
SVGAHDA.ul_gmr_count = SVGA_ReadReg(SVGA_REG_GMR_MAX_IDS);
- SVGAHDA.ul_ctx_start = SVGAHDA.ul_gmr_start + SVGAHDA.ul_gmr_count*3;
+ SVGAHDA.ul_ctx_start = SVGAHDA.ul_gmr_start + SVGAHDA.ul_gmr_count*4;
SVGAHDA.ul_ctx_count = GetDevCap(SVGA3D_DEVCAP_MAX_CONTEXT_IDS);
SVGAHDA.ul_surf_start = SVGAHDA.ul_ctx_start + SVGAHDA.ul_ctx_count;
SVGAHDA.ul_surf_count = GetDevCap(SVGA3D_DEVCAP_MAX_SURFACE_IDS);
@@ -372,12 +372,17 @@ void SVGAHDA_update(DWORD width, DWORD height, DWORD bpp, DWORD pitch) FBHDA_REQ
* 2) access VMWare SVGA II registers and memory to real GPU acceleration
*
+ * 2023-II:
+ * Added DCICOMMAND to query DirectDraw/DirectX interface
+ *
**/
LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function,
LPVOID lpInput, LPVOID lpOutput)
{
LONG rc = -1;
+ dbg_printf("Control (16bit): %d (0x%x)\n", function, function);
+
if(function == QUERYESCSUPPORT)
{
WORD function_code = 0;
@@ -442,7 +447,7 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function, }
else if(function == DCICOMMAND) /* input ptr DCICMD */
{
- DCICMD_t __far *lpDCICMD = lpInput;
+ DCICMD_t __far *lpDCICMD = lpInput;
if(lpDCICMD != NULL)
{
if(lpDCICMD->dwVersion == DD_VERSION)
@@ -563,18 +568,19 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function, uint32_t __far *lpOut = lpOutput;
uint32_t rid = lpIn[0];
- dbg_printf("Region id = %ld\n", rid);
+ dbg_printf("Region id = %ld, max desc = %ld\n", rid, SVGA_ReadReg(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH));
if(rid)
{
uint32_t lAddr;
uint32_t ppn;
+ uint32_t pgblk;
VXD_load();
- if(VXD_CreateRegion(lpIn[1], &lAddr, &ppn)) /* allocate physical memory */
+ if(VXD_CreateRegion(lpIn[1], &lAddr, &ppn, &pgblk)) /* allocate physical memory */
{
- dbg_printf("Region address = %lX, PPN = %lX\n", lAddr, ppn);
+ dbg_printf("Region address = %lX, PPN = %lX, GMRBLK = %lX\n", lAddr, ppn, pgblk);
SVGA_WriteReg(SVGA_REG_GMR_ID, rid);
SVGA_WriteReg(SVGA_REG_GMR_DESCRIPTOR, ppn);
@@ -583,12 +589,14 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function, SVGA_Flush();
lpOut[0] = rid;
- lpOut[1] = lAddr + 4096;
+ lpOut[1] = lAddr;
+ lpOut[2] = pgblk;
}
else
{
lpOut[0] = 0;
lpOut[1] = 0;
+ lpOut[2] = 0;
}
}
@@ -598,7 +606,8 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function, {
uint32_t __far *lpin = lpInput;
uint32_t id = lpin[0];
- uint32_t linear = lpin[1] - 4096;
+ uint32_t linear = lpin[1];
+ uint32_t pgblk = lpin[2];
/* flush all register inc. fifo so make sure, that all commands are processed */
SVGA_Flush();
@@ -611,7 +620,7 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function, /* region physical delete */
VXD_load();
- VXD_FreeRegion(linear);
+ VXD_FreeRegion(linear, pgblk);
rc = 1;
}
diff --git a/control_vxd.c b/control_vxd.c index 23630af..aaefb18 100644 --- a/control_vxd.c +++ b/control_vxd.c @@ -73,11 +73,12 @@ BOOL VXD_load() return VXD_srv != 0;
}
-BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far *lpPPN)
+BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far *lpPPN, uint32_t __far *lpPGBLKAddr)
{
static uint32_t snPages;
static uint32_t sLAddr;
static uint32_t sPPN;
+ static uint32_t sPGBLKAddr;
static uint16_t state = 0;
snPages = nPages;
@@ -90,6 +91,7 @@ BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far * push eax
push edx
push ecx
+ push ebx
mov edx, VMWSVXD_PM16_CREATE_REGION
mov ecx, [snPages]
@@ -97,7 +99,9 @@ BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far * mov [state], ax
mov [sLAddr], edx
mov [sPPN], ecx
+ mov [sPGBLKAddr], ebx
+ pop ebx
pop ecx
pop edx
pop eax
@@ -107,6 +111,7 @@ BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far * {
*lpLAddr = sLAddr;
*lpPPN = sPPN;
+ *lpPGBLKAddr = sPGBLKAddr;
return TRUE;
}
@@ -119,12 +124,14 @@ BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far * return FALSE;
}
-BOOL VXD_FreeRegion(uint32_t LAddr)
+BOOL VXD_FreeRegion(uint32_t LAddr, uint32_t PGBLKAddr)
{
static uint32_t sLAddr;
static uint16_t state;
+ static uint32_t sPGBLKAddr;
sLAddr = LAddr;
+ sPGBLKAddr = PGBLKAddr;
if(VXD_srv != 0)
{
@@ -134,12 +141,15 @@ BOOL VXD_FreeRegion(uint32_t LAddr) push eax
push edx
push ecx
+ push ebx
mov edx, VMWSVXD_PM16_DESTROY_REGION
- mov ecx, [LAddr]
+ mov ecx, [sLAddr]
+ mov ebx, [sPGBLKAddr]
call dword ptr [VXD_srv]
mov [state], ax
+ pop ebx
pop ecx
pop edx
pop eax
diff --git a/control_vxd.h b/control_vxd.h index a515731..e2b624f 100644 --- a/control_vxd.h +++ b/control_vxd.h @@ -2,8 +2,8 @@ #define __CONTROL_VXD_H__INCLUDED__
BOOL VXD_load();
-BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far *lpPPN);
-BOOL VXD_FreeRegion(uint32_t LAddr);
+BOOL VXD_CreateRegion(uint32_t nPages, uint32_t __far *lpLAddr, uint32_t __far *lpPPN, uint32_t __far *lpPGBLKAddr);
+BOOL VXD_FreeRegion(uint32_t LAddr, uint32_t PGBLKAddr);
void VXD_zeromem(uint32_t LAddr, uint32_t size);
uint32_t VXD_apiver();
@@ -231,6 +231,11 @@ void dbg_printf( const char *s, ... ) if( conv ) {
/* Time to start grabbing stuff off the stack. */
+#ifdef VXD32
+ /* in 32-bit are all args 32bit... */
+ dword = va_arg( args, uint32_t );
+ word = (dword & 0xFFFF);
+#else
word = va_arg( args, uint16_t );
/* If argument is double wide, build a doubleword. */
if( type_len == 'l' || type_len == 'W' ) {
@@ -238,6 +243,7 @@ void dbg_printf( const char *s, ... ) dword <<= 16;
dword |= word;
}
+#endif
if( conv == 'c' ) {
prt_ch( word );
} else if( conv == 'd' ) {
@@ -14,7 +14,7 @@ FLAGS = -DDRV_VER_BUILD=$(VER_BUILD) -DCAP_R5G6B5_ALWAYS_WRONG #FLAGS += -DHWBLT
# Set DBGPRINT to add debug printf logging.
-DBGPRINT = 1
+#DBGPRINT = 1
!ifdef DBGPRINT
FLAGS += -DDBGPRINT
@@ -5,7 +5,7 @@ #define DRV_STR(x) DRV_STR_(x)
/* DRV, VXD and DLL have to have the same */
-#define DRV_API_LEVEL 20230326UL
+#define DRV_API_LEVEL 20230628UL
/* on binaries equals 1 and for INF is 1 = separate driver, 2 = softgpu pack */
#define DRV_VER_MAJOR 1
diff --git a/vmdisp9x.inf b/vmdisp9x.inf index 39c9fce..6ea79ef 100644 --- a/vmdisp9x.inf +++ b/vmdisp9x.inf @@ -31,7 +31,7 @@ vmwsmini.vxd=1 ;mesa:vmwsgl32.dll=1
;openglide:glide2x.dll=1
;openglide:glide3x.dll=1
-;openglide:wined3d.dll=1
+;wined3d:wined3d.dll=1
;wined3d:dwine.dll=1
;wined3d:ddraw.dll=1
;wined3d:ddrawme.dll=1
@@ -701,4 +701,29 @@ typedef struct tagCRS_32 #define D_ACCESSED 1 /* segment accessed bit */
+/* contains information that an aplication passed to VXD by calling DeviceIoControl function */
+struct DIOCParams
+{
+ DWORD Intrenal1;
+ DWORD VMHandle;
+ DWORD Internal2;
+ DWORD dwIoControlCode;
+ DWORD lpInBuffer;
+ DWORD cbInBuffer;
+ DWORD lpOutBuffer;
+ DWORD cbOutBuffer;
+ DWORD lpcbBytesReturned;
+ DWORD lpOverlapped;
+ DWORD hDevice;
+ DWORD tagProcess;
+};
+
+/* vWin32 communicates with Vxds on behalf of Win32 apps thru this mechanism. */
+#define W32_DEVICEIOCONTROL 0x0023
+
+/* sub-functions */
+#define DIOC_GETVERSION 0x0
+#define DIOC_OPEN DIOC_GETVERSION
+#define DIOC_CLOSEHANDLE -1
+
#endif /* __VMM_H__INCLUDED__ */
@@ -84,12 +84,20 @@ DDB VMWS_DDB = { };
/* string tables */
+#ifdef DBGPRINT
char dbg_hello[] = "Hello world!\n";
char dbg_version[] = "VMM version: ";
char dbg_region_err[] = "region create error\n";
char dbg_Device_Init_proc[] = "Device_Init_proc\n";
char dbg_Device_Init_proc_succ[] = "Device_Init_proc success\n";
+char dbg_dic_ring[] = "DeviceIOControl: Ring\n";
+char dbg_dic_sync[] = "DeviceIOControl: Sync\n";
+char dbg_dic_unknown[] = "DeviceIOControl: Unknown: %d\n";
+char dbg_dic_system[] = "DeviceIOControl: System code: %d\n";
+char dbg_get_ppa[] = "%lx -> %lx\n";
+char dbg_get_ppa_beg[] = "Virtual: %lx\n";
+#endif
DWORD *DispatchTable = 0;
DWORD DispatchTableLength = 0;
@@ -124,6 +132,21 @@ ULONG __declspec(naked) __cdecl _PageFree(PVOID hMem, DWORD flags) VMMJmp(_PageFree);
}
+ULONG __declspec(naked) __cdecl _CopyPageTable(ULONG LinPgNum, ULONG nPages, DWORD *PageBuf, ULONG flags)
+{
+ VMMJmp(_CopyPageTable);
+}
+
+ULONG __declspec(naked) __cdecl _LinPageLock(ULONG page, ULONG npages, ULONG flags)
+{
+ VMMJmp(_LinPageLock);
+}
+
+ULONG __declspec(naked) __cdecl _LinPageUnLock(ULONG page, ULONG npages, ULONG flags)
+{
+ VMMJmp(_LinPageUnLock);
+}
+
/**
* VDD calls wrapers
**/
@@ -142,6 +165,46 @@ void Sys_Critical_Init_proc() // nop
}
+/*
+ * 32-bit DeviceIoControl ends here
+ *
+ */
+
+#define SVGA_SYNC 0x1116
+#define SVGA_RING 0x1117
+
+DWORD __stdcall Device_IO_Control_entry(struct DIOCParams *params)
+{
+ switch(params->dwIoControlCode)
+ {
+ case DIOC_OPEN:
+ case DIOC_CLOSEHANDLE:
+ dbg_printf(dbg_dic_system, params->dwIoControlCode);
+ return 0;
+ case SVGA_SYNC:
+ //dbg_printf(dbg_dic_sync);
+ SVGA_Flush();
+ return 0;
+ case SVGA_RING:
+ //dbg_printf(dbg_dic_ring);
+ SVGA_WriteReg(SVGA_REG_SYNC, 1);
+ return 0;
+ }
+
+ dbg_printf(dbg_dic_unknown, params->dwIoControlCode);
+
+ return 1;
+}
+
+void __declspec(naked) Device_IO_Control_proc()
+{
+ _asm {
+ push esi /* struct DIOCParams */
+ call Device_IO_Control_entry
+ retn
+ }
+}
+
void Device_Init_proc();
/*
@@ -157,61 +220,226 @@ void __declspec(naked) VMWS_Control() // eax = 0x23 - device IO control
_asm {
- pushad
cmp eax,Sys_Critical_Init
jnz control_1
- call Sys_Critical_Init_proc
+ pushad
+ call Sys_Critical_Init_proc
+ popad
+ clc
+ ret
control_1:
cmp eax,Device_Init
jnz control_2
+ pushad
call Device_Init_proc
+ popad
+ clc
+ ret
control_2:
cmp eax,0x1B
jnz control_3
+ pushad
call Device_Init_proc
+ popad
+ clc
+ ret
control_3:
- popad
+ cmp eax,W32_DEVICEIOCONTROL
+ jnz control_4
+ jmp Device_IO_Control_proc
+ control_4:
clc
ret
};
}
/**
- * PM16 driver RING0 calls
+ * Return PPN (physical page number) from virtual address
+ *
**/
-BOOL CreateRegion(unsigned int nPages, ULONG *lpLAddr, ULONG *lpPPN)
+static DWORD getPPN(DWORD virtualaddr)
+{
+ DWORD phy = 0;
+ _CopyPageTable(virtualaddr/P_SIZE, 1, &phy, 0);
+ return phy/P_SIZE;
+}
+
+/**
+ * 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.
+ *
+ * @param nPages: number of pages to allocate
+ * @param outDataAddr: linear address (system space) of data block
+ * @param outGMRAddr: linear address of GMR block
+ * @param outPPN: physical page number of outGMRAddr (first page)
+ *
+ * @return: TRUE on success
+ *
+ **/
+static BOOL GMRAlloc(ULONG nPages, ULONG *outDataAddr, ULONG *outGMRAddr, ULONG *outPPN)
{
ULONG phy;
+ ULONG pgblk_phy;
ULONG laddr;
+ ULONG pgblk;
SVGAGuestMemDescriptor *desc;
- laddr = _PageAllocate(nPages + 1, PG_SYS, 0, 0x00000000, 0, 0x100000, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+ laddr = _PageAllocate(nPages, PG_SYS, 0, 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;
+ pgblk = _PageAllocate(1, PG_SYS, 0, 0, 0x0, 0x100000, &pgblk_phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+ if(pgblk)
+ {
+ desc = (SVGAGuestMemDescriptor*)pgblk;
+ desc->ppn = (phy/P_SIZE);
+ desc->numPages = nPages;
+ desc++;
+ desc->ppn = 0;
+ desc->numPages = 0;
- *lpLAddr = laddr;
- *lpPPN = (phy/P_SIZE);
+ *outDataAddr = laddr;
+ *outGMRAddr = pgblk;
+ *outPPN = (pgblk_phy/P_SIZE);
- return TRUE;
+ return TRUE;
+ }
+ else
+ {
+ _PageFree((PVOID)laddr, 0);
+ return FALSE;
+ }
+ }
+ else
+ {
+ ULONG taddr;
+ ULONG tppn;
+ ULONG pgi;
+ ULONG base_ppn;
+ ULONG base_cnt;
+ ULONG blocks = 1;
+ ULONG blk_pages = 0;
+
+ laddr = _PageAllocate(nPages, PG_SYS, 0, 0, 0x0, 0x100000, NULL, PAGEFIXED);
+
+ if(laddr)
+ {
+ /* 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;
+
+ pgblk = _PageAllocate(blk_pages, PG_SYS, 0, 0, 0x0, 0x100000, &pgblk_phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+ if(pgblk)
+ {
+ desc = (SVGAGuestMemDescriptor*)pgblk;
+ desc->ppn = getPPN(laddr);
+ desc->numPages = 1;
+ blocks = 1;
+
+ 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));
+ //dbg_printf(old_new_ppn, blocks, getPPN((DWORD)(desc)), getPPN((DWORD)(desc+1)), getPPN((DWORD)(desc+2)));
+ blocks++;
+ }
+
+ desc++;
+ desc->ppn = tppn;
+ desc->numPages = 1;
+ blocks++;
+ }
+ }
+
+ desc++;
+ desc->ppn = 0;
+ desc->numPages = 0;
+
+ *outDataAddr = laddr;
+ *outGMRAddr = pgblk;
+ *outPPN = (pgblk_phy/P_SIZE);
+
+ return TRUE;
+ }
+ else
+ {
+ _PageFree((PVOID)laddr, 0);
+ return FALSE;
+ }
+ }
}
return FALSE;
}
-BOOL FreeRegion(ULONG LAddr)
+/**
+ * Free data allocated by GMRAlloc
+ *
+ **/
+static BOOL GMRFree(ULONG DataAddr, ULONG GMRAddr)
{
- if(_PageFree((PVOID)LAddr, 0) != 0)
+ BOOL ret = FALSE;
+
+ if(_PageFree((PVOID)DataAddr, 0) != 0)
{
- return TRUE;
+ ret = TRUE;
}
- return FALSE;
+ if(_PageFree((PVOID)GMRAddr, 0) != 0)
+ {
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+/**
+ * PM16 driver RING0 calls
+ **/
+BOOL CreateRegion(unsigned int nPages, ULONG *lpLAddr, ULONG *lpPPN, ULONG *lpPGBLK)
+{
+ return GMRAlloc(nPages, lpLAddr, lpPGBLK, lpPPN);
+}
+
+BOOL FreeRegion(ULONG LAddr, ULONG PGBLK)
+{
+ return GMRFree(LAddr, PGBLK);
}
#define MOB_PER_PAGE_CNT (P_SIZE/sizeof(ULONG))
@@ -222,7 +450,7 @@ BOOL CreateMOB(unsigned int nPages, ULONG *lpLAddr, ULONG *lpPPN) ULONG phy;
ULONG laddr;
- laddr = _PageAllocate(nPages + mobBasePages, PG_SYS, 0, 0x00000000, 0, 0x100000, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
+ laddr = _PageAllocate(nPages + mobBasePages, PG_SYS, 0, 0x0, 0, 0x0fffff, &phy, PAGECONTIG | PAGEUSEALIGN | PAGEFIXED);
if(laddr)
{
unsigned int i;
@@ -270,17 +498,20 @@ WORD __stdcall VMWS_API_Proc(PCRS_32 state) {
ULONG lAddr;
ULONG PPN;
+ ULONG PGBLK;
- if(CreateRegion(state->Client_ECX, &lAddr, &PPN))
+ if(CreateRegion(state->Client_ECX, &lAddr, &PPN, &PGBLK))
{
state->Client_ECX = PPN;
state->Client_EDX = lAddr;
+ state->Client_EBX = PGBLK;
rc = 1;
}
else
{
state->Client_ECX = 0;
state->Client_EDX = 0;
+ state->Client_EBX = 0;
dbg_printf(dbg_region_err);
@@ -291,7 +522,7 @@ WORD __stdcall VMWS_API_Proc(PCRS_32 state) /* free region = input: ECX: lin. address */
case VMWSVXD_PM16_DESTROY_REGION:
{
- if(FreeRegion(state->Client_ECX))
+ if(FreeRegion(state->Client_ECX, state->Client_EBX))
{
rc = 1;
}
|