summaryrefslogtreecommitdiffstats
path: root/private/mvdm/dpmi32/i386
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/dpmi32/i386')
-rw-r--r--private/mvdm/dpmi32/i386/dpmi386.c386
-rw-r--r--private/mvdm/dpmi32/i386/dpmimem.c266
-rw-r--r--private/mvdm/dpmi32/i386/dpmimisc.c71
3 files changed, 723 insertions, 0 deletions
diff --git a/private/mvdm/dpmi32/i386/dpmi386.c b/private/mvdm/dpmi32/i386/dpmi386.c
new file mode 100644
index 000000000..19c9d678c
--- /dev/null
+++ b/private/mvdm/dpmi32/i386/dpmi386.c
@@ -0,0 +1,386 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ dpmi386.c
+
+Abstract:
+
+ This file contains support for 386/486 only dpmi bops
+
+Author:
+
+ Dave Hastings (daveh) 27-Jun-1991
+
+Revision History:
+
+ Matt Felton (mattfe) Dec 6 1992 removed unwanted verification
+ Dave Hastings (daveh) 24-Nov-1992 Moved to mvdm\dpmi32
+ Matt Felton (mattfe) 8 Feb 1992 optimize getvdmpointer for regular protect mode path.
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+#include <softpc.h>
+#include <memory.h>
+#include <malloc.h>
+
+
+BOOL
+DpmiSetX86Descriptor(
+ LDT_ENTRY *Descriptors,
+ USHORT registerAX,
+ USHORT registerCX
+ )
+/*++
+
+Routine Description:
+
+ This function puts descriptors into the Ldt. It verifies the contents
+ and calls nt to actually set up the selector(s).
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPROCESS_LDT_INFORMATION LdtInformation = NULL;
+ NTSTATUS Status;
+ ULONG ulLdtEntrySize;
+ ULONG Selector0,Selector1;
+
+ ulLdtEntrySize = registerCX * sizeof(LDT_ENTRY);
+
+ //
+ // If there are only 2 descriptors, set them the fast way
+ //
+ Selector0 = (ULONG)registerAX;
+ if ((registerCX <= 2) && (Selector0 != 0)) {
+ if (registerCX == 2) {
+ Selector1 = registerAX + sizeof(LDT_ENTRY);
+ } else {
+ Selector1 = 0;
+ }
+ Status = NtSetLdtEntries(
+ Selector0,
+ *((PULONG)(&Descriptors[0])),
+ *((PULONG)(&Descriptors[0]) + 1),
+ Selector1,
+ *((PULONG)(&Descriptors[1])),
+ *((PULONG)(&Descriptors[1]) + 1)
+ );
+ if (NT_SUCCESS(Status)) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ LdtInformation = malloc(sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize);
+ LdtInformation->Start = registerAX;
+ LdtInformation->Length = ulLdtEntrySize;
+ CopyMemory(
+ &(LdtInformation->LdtEntries),
+ Descriptors,
+ ulLdtEntrySize
+ );
+
+ Status = NtSetInformationProcess(
+ NtCurrentProcess(),
+ ProcessLdtInformation,
+ LdtInformation,
+ sizeof(PROCESS_LDT_INFORMATION) + ulLdtEntrySize
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("DPMI: Failed to set selectors %lx\n", Status)
+ );
+ free(LdtInformation);
+ return FALSE;
+ }
+
+ free(LdtInformation);
+
+ return TRUE;
+}
+
+
+
+VOID
+switch_to_protected_mode(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches the dos applications context to protected mode.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PCHAR StackPointer;
+
+ StackPointer = Sim32GetVDMPointer(((getSS() << 16) | getSP()),
+ 0,
+ (UCHAR) (getMSW() & MSW_PE)
+ );
+
+ setCS(*(PUSHORT)(StackPointer + 12));
+
+ setEIP(*(PULONG)(StackPointer + 8));
+ setSS(*(PUSHORT)(StackPointer + 6));
+ setESP(*(PULONG)(StackPointer + 2));
+ setDS(*(PUSHORT)(StackPointer));
+ // Necessary to prevent loads of invalid selectors.
+ setES(0);
+ setGS(0);
+ setFS(0);
+ setMSW(getMSW() | MSW_PE);
+
+ //
+ // If we have fast if emulation in PM set the RealInstruction bit
+ //
+ if (VdmFeatureBits & PM_VIRTUAL_INT_EXTENSIONS) {
+ _asm {
+ mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
+ lock or dword ptr [eax], dword ptr RI_BIT_MASK
+ }
+ } else {
+ _asm {
+ mov eax, FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
+ lock and dword ptr [eax], dword ptr ~RI_BIT_MASK
+ }
+ }
+
+ //
+ // Turn off real mode bit
+ //
+ _asm {
+ mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
+ lock and dword ptr [eax], dword ptr ~RM_BIT_MASK
+ }
+
+}
+
+
+VOID
+switch_to_real_mode(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine services the switch to real mode bop. It is included in
+ DPMI.c so that all of the mode switching services are in the same place
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCHAR StackPointer;
+
+ StackPointer = Sim32GetVDMPointer(((getSS() << 16) | getSP()),
+ 0,
+ (UCHAR) (getMSW() & MSW_PE)
+ );
+
+ setDS(*(PUSHORT)(StackPointer));
+ setSP(*(PUSHORT)(StackPointer + 2));
+ setSS(*(PUSHORT)(StackPointer + 4));
+ setIP((*(PUSHORT)(StackPointer + 6)));
+ setCS(*(PUSHORT)(StackPointer + 8));
+ setMSW(getMSW() & ~MSW_PE);
+
+ //
+ // If we have v86 mode fast IF emulation set the RealInstruction bit
+ //
+
+ if (VdmFeatureBits & V86_VIRTUAL_INT_EXTENSIONS) {
+ _asm {
+ mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
+ lock or dword ptr [eax], dword ptr RI_BIT_MASK
+ }
+ } else {
+ _asm {
+ mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
+ lock and dword ptr [eax], dword ptr ~RI_BIT_MASK
+ }
+ }
+ //
+ // turn on real mode bit
+ //
+ _asm {
+ mov eax,FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
+ lock or dword ptr [eax], dword ptr RM_BIT_MASK
+ }
+}
+
+VOID DpmiGetFastBopEntry(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is the front end for the routine that gets the address. It
+ is necessary to get the address in asm, because the CS value is not
+ available in c
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+{
+ GetFastBopEntryAddress(&VdmTib.VdmContext);
+}
+
+UCHAR *
+Sim32pGetVDMPointer(
+ ULONG Address,
+ UCHAR ProtectedMode
+ )
+/*++
+
+Routine Description:
+
+ This routine converts a 16/16 address to a linear address.
+
+ WARNIGN NOTE - This routine has been optimized so protect mode LDT lookup
+ falls stright through. This routine is call ALL the time by WOW, if you
+ need to modify it please re optimize the path - mattfe feb 8 92
+
+Arguments:
+
+ Address -- specifies the address in seg:offset format
+ Size -- specifies the size of the region to be accessed.
+ ProtectedMode -- true if the address is a protected mode address
+
+Return Value:
+
+ The pointer.
+
+--*/
+
+{
+ ULONG Selector;
+ PUCHAR ReturnPointer;
+
+ if (ProtectedMode) {
+ Selector = (Address & 0xFFFF0000) >> 16;
+ if (Selector != 40) {
+ Selector &= ~7;
+ ReturnPointer = (PUCHAR)FlatAddress[Selector >> 3];
+ ReturnPointer += (Address & 0xFFFF);
+ return ReturnPointer;
+ // Selector 40
+ } else {
+ ReturnPointer = (PUCHAR)0x400 + (Address & 0xFFFF);
+ }
+ // Real Mode
+ } else {
+ ReturnPointer = (PUCHAR)(((Address & 0xFFFF0000) >> 12) + (Address & 0xFFFF));
+ }
+ return ReturnPointer;
+}
+
+
+PUCHAR
+ExpSim32GetVDMPointer(
+ ULONG Address,
+ ULONG Size,
+ UCHAR ProtectedMode
+ )
+/*++
+ See Sim32pGetVDMPointer, above
+
+ This call must be maintaned as is because it is exported for VDD's
+ in product 1.0.
+
+--*/
+
+{
+ return Sim32pGetVDMPointer(Address,(UCHAR)ProtectedMode);
+}
+
+
+
+VOID
+DpmiSetDebugRegisters(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called by DOSX when an app has issued DPMI debug commands.
+ The six doubleword pointed to by the VDM's DS:SI are the desired values
+ for the real x86 hardware debug registers. This routine lets
+ ThreadSetDebugContext() do all the work.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCHAR RegisterPointer;
+
+ setCF(0);
+
+ RegisterPointer = Sim32GetVDMPointer(((getDS() << 16) | getSI()),
+ 0,
+ (UCHAR) (getMSW() & MSW_PE)
+ );
+
+ if (!ThreadSetDebugContext((PULONG) RegisterPointer))
+ {
+ ULONG ClearDebugRegisters[6] = {0, 0, 0, 0, 0, 0};
+
+ //
+ // an error occurred. Reset everything to zero
+ //
+
+ ThreadSetDebugContext (&ClearDebugRegisters[0]);
+ setCF(1);
+ }
+
+}
diff --git a/private/mvdm/dpmi32/i386/dpmimem.c b/private/mvdm/dpmi32/i386/dpmimem.c
new file mode 100644
index 000000000..00eada990
--- /dev/null
+++ b/private/mvdm/dpmi32/i386/dpmimem.c
@@ -0,0 +1,266 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ name-of-module-filename
+
+Abstract:
+
+ This module contains the code for actually allocating memory for dpmi.
+ It uses the same suballocation pool as the xms code
+
+Author:
+
+ Dave Hastings (daveh) creation-date 09-Feb-1994
+
+Notes:
+
+ These functions claim to return NTSTATUS. This is for commonality on
+ x86 where we actually have an NTSTATUS to return. For this file, we
+ simply logically invert the bool and return that. Callers of these
+ functions promise not to attach significance to the return values other
+ than STATUS_SUCCESS.
+
+Revision History:
+
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+#include <softpc.h>
+#include <suballoc.h>
+#include <xmsexp.h>
+
+
+NTSTATUS
+DpmiAllocateVirtualMemory(
+ PVOID *Address,
+ PULONG Size
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates a chunk of extended memory for dpmi.
+
+Arguments:
+
+ Address -- Supplies a pointer to the Address. This is filled in
+ if the allocation is successfull
+ Size -- Supplies the size to allocate
+
+Return Value:
+
+ STATUS_SUCCESS if successfull.
+
+--*/
+{
+ return NtAllocateVirtualMemory(
+ NtCurrentProcess(),
+ Address,
+ 0L,
+ Size,
+ MEM_COMMIT,
+ PAGE_READWRITE
+ );
+}
+
+NTSTATUS
+DpmiFreeVirtualMemory(
+ PVOID *Address,
+ PULONG Size
+ )
+/*++
+
+Routine Description:
+
+ This function frees memory for dpmi. It is returned to the suballocation
+ pool.
+
+Arguments:
+
+ Address -- Supplies the address of the block to free
+ Size -- Supplies the size of the block to free
+
+Return Value:
+
+ STATUS_SUCCESS if successful
+--*/
+{
+ return NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ Address,
+ Size,
+ MEM_RELEASE
+ );
+
+}
+
+BOOL
+DpmiReallocateVirtualMemory(
+ PVOID OldAddress,
+ ULONG OldSize,
+ PVOID *NewAddress,
+ PULONG NewSize
+ )
+/*++
+
+Routine Description:
+
+ This function reallocates a block of memory for DPMI.
+
+Arguments:
+
+ OldAddress -- Supplies the original address for the block
+ OldSize -- Supplies the original size for the address
+ NewAddress -- Supplies the pointer to the place to return the new
+ address
+ NewSize -- Supplies the new size
+
+Return Value:
+
+ STATUS_SUCCESS if successfull
+--*/
+{
+ ULONG SizeChange;
+ ULONG BlockAddress;
+ ULONG NewPages, OldPages;
+ NTSTATUS Status;
+
+ #define FOUR_K (1024 * 4)
+
+ NewPages = (*NewSize + FOUR_K - 1) / FOUR_K;
+ OldPages = (OldSize + FOUR_K - 1) / FOUR_K;
+
+ if ((NewPages == OldPages) || (NewPages < OldPages)) {
+ *NewAddress = OldAddress;
+ return STATUS_SUCCESS;
+ }
+
+ BlockAddress = 0;
+ Status = NtAllocateVirtualMemory(
+ NtCurrentProcess(),
+ (PVOID)&BlockAddress,
+ 0L,
+ NewSize,
+ MEM_COMMIT,
+ PAGE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
+#endif
+ return Status;
+ }
+
+ *NewAddress = (PVOID) BlockAddress;
+ //
+ // Copy data to new block (choose smaller of the two sizes)
+ //
+ if (*NewSize > OldSize) {
+ SizeChange = OldSize;
+ } else {
+ SizeChange = *NewSize;
+ }
+
+ CopyMemory((PVOID)BlockAddress, OldAddress, SizeChange);
+
+ //
+ // Free up the old block
+ //
+ BlockAddress = (ULONG) OldAddress;
+ SizeChange = OldSize;
+ NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ (PVOID)&(OldAddress),
+ &SizeChange,
+ MEM_RELEASE
+ );
+
+ return Status;
+}
+
+VOID
+DpmiGetMemoryInfo(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine returns information about memory to the dos extender
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+{
+ MEMORYSTATUS MemStatus;
+ PDPMIMEMINFO MemInfo;
+ DWORD dwLargestFree;
+
+ //
+ // Get a pointer to the return structure
+ //
+ MemInfo = (PDPMIMEMINFO)Sim32GetVDMPointer(
+ ((ULONG)getES()) << 16,
+ 1,
+ TRUE
+ );
+
+ (CHAR *)MemInfo += (*GetDIRegister)();
+
+ //
+ // Initialize the structure
+ //
+ RtlFillMemory(MemInfo, sizeof(DPMIMEMINFO), 0xFF);
+
+ //
+ // Get the information on memory
+ //
+ MemStatus.dwLength = sizeof(MEMORYSTATUS);
+ GlobalMemoryStatus(&MemStatus);
+
+ //
+ // Return the information
+ //
+
+ //
+ // Calculate the largest free block. This information is not returned
+ // by NT, so we take a percentage based on the allowable commit charge for
+ // the process. This is really what dwAvailPageFile is. But we limit
+ // that value to a maximum of 15meg, since some apps (e.g. pdox45.dos)
+ // can't handle more.
+ //
+
+ // Filled in MaxUnlocked,MaxLocked,UnlockedPages fields in this structute.
+ // Director 4.0 get completlely confused if these fields are -1.
+ // MaxUnlocked is correct based on LargestFree. The other two are fake
+ // and match values on a real WFW machine. I have no way of making them
+ // any better than this at this point. Hell, it makes director happy.
+ //
+ // sudeepb 01-Mar-1995.
+
+ dwLargestFree = (((MemStatus.dwAvailPageFile*4)/5)/4096)*4096;
+
+ MemInfo->LargestFree = (dwLargestFree < 15*ONE_MB) ?
+ dwLargestFree : 15*ONE_MB;
+
+ MemInfo->MaxUnlocked = MemInfo->LargestFree/4096;
+ MemInfo->MaxLocked = 0xb61;
+ MemInfo->AddressSpaceSize = MemStatus.dwTotalVirtual / 4096;
+ MemInfo->UnlockedPages = 0xb68;
+ MemInfo->FreePages = MemStatus.dwAvailPhys / 4096;
+ MemInfo->PhysicalPages = MemStatus.dwTotalPhys / 4096;
+ MemInfo->FreeAddressSpace = MemStatus.dwAvailVirtual / 4096;
+ MemInfo->PageFileSize = MemStatus.dwTotalPageFile / 4096;
+
+}
diff --git a/private/mvdm/dpmi32/i386/dpmimisc.c b/private/mvdm/dpmi32/i386/dpmimisc.c
new file mode 100644
index 000000000..22b741c1d
--- /dev/null
+++ b/private/mvdm/dpmi32/i386/dpmimisc.c
@@ -0,0 +1,71 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dpmimisc.c
+
+Abstract:
+
+ This module contains misc 386 specific dpmi functions.
+
+Author:
+
+ Dave Hastings (daveh) creation-date 09-Feb-1994
+
+Revision History:
+
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+#include "softpc.h"
+#include "stdio.h"
+
+VOID
+DpmiDpmiInUse(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine does not do anything on x86
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+}
+
+VOID
+DpmiDpmiNoLongerInUse(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine does not do anything on x86
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+}