summaryrefslogtreecommitdiffstats
path: root/private/mvdm/v86/monitor/i386/sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/v86/monitor/i386/sas.c')
-rw-r--r--private/mvdm/v86/monitor/i386/sas.c1551
1 files changed, 1551 insertions, 0 deletions
diff --git a/private/mvdm/v86/monitor/i386/sas.c b/private/mvdm/v86/monitor/i386/sas.c
new file mode 100644
index 000000000..0549ad802
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/sas.c
@@ -0,0 +1,1551 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Monitor.c
+Abstract:
+
+ This module is the user mode portion of the x86 monitor
+
+Author:
+
+ Dave Hastings (daveh) 16 Mar 1991
+
+Environment:
+
+ User mode only
+
+Revision History:
+ William Hsieh 10-10-1992 Added A20 wrapping support
+--*/
+
+#define VDD_INTEG 1
+#include "monitorp.h"
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+
+// Tim Nov 92.
+void sas_connect_memory(
+ IN sys_addr Low,
+ IN sys_addr High,
+ IN int Type
+ );
+
+//BUGBUGBUGBUG Include file
+
+// from base\inc\sas.h
+/* memory types for sas */
+#define SAS_RAM 0
+#define SAS_VIDEO 1
+#define SAS_ROM 2
+#define SAS_WRAP 3
+#define SAS_INACCESSIBLE 4
+#define SAS_MAX_TYPE SAS_INACCESSIBLE
+
+#define SIXTYFOURK 0x10000L
+#define ONEMEGA 0x100000L
+
+void rom_init();
+void rom_checksum();
+void copyROM();
+
+USHORT get_lim_backfill_segment(void);
+BOOL HoldEMMBackfillMemory(ULONG Address, ULONG Size);
+
+#if DBG
+extern unsigned short get_emm_page_size(void);
+extern unsigned short get_intel_page_size(void);
+#endif
+
+/* SYNC THESE DEFINITIONS WITH BASE\EMM.H, or sas_init will assert */
+#define EMM_PAGE_SIZE 0x4000
+#define INTEL_PAGE_SIZE 0x1000
+
+typedef struct
+{
+ ULONG (*b_read) ();
+ ULONG (*w_read) ();
+ VOID (*str_read) ();
+} READ_POINTERS;
+
+// Internal Data
+PMEMTYPE MemType = NULL;
+
+// External Data
+extern READ_POINTERS read_pointers;
+
+// M variables used by video.lib
+
+host_addr Start_of_M_area; /* host addr (char *) of start of M */
+sys_addr Length_of_M_area; /* sys addr (long) offset of end of M */
+
+static HANDLE A20SectionHandle = NULL;
+static BOOL A20IsON = FALSE;
+static USHORT BackFillSegment;
+
+
+
+EXPORT
+VOID
+sas_init(
+ IN sys_addr Size
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the SAS module, and allocates the linear
+ address space for the VDM, and loads the ROM
+
+Arguments:
+
+ Size - Supplies the size of the VDMs linear address space.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NTSTATUS Status;
+ ULONG ViewSize;
+ PVOID BaseAddress;
+ OBJECT_ATTRIBUTES A20ObjAttr;
+ LARGE_INTEGER SectionSize;
+ UCHAR SectionAnsiName[80];
+ WCHAR SectionUnicodeName[80];
+ UNICODE_STRING UnicodeString;
+ USHORT Pages;
+ ULONG BackFillBase;
+
+#define CONVENTIONAL_MEM_SECTION "\\BaseNamedObjects\\VdmConventionalMemory"
+
+ //
+ // Create a name for the Convetional memory section
+ //
+ sprintf(
+ SectionAnsiName,
+ "%s%d",
+ CONVENTIONAL_MEM_SECTION,
+ GetCurrentProcessId()
+ );
+
+ if (MultiByteToWideChar(0, 0, SectionAnsiName, -1, SectionUnicodeName,80)
+ == 0
+ ) {
+#if DBG
+ DbgBreakPoint();
+#endif
+ // host_error(EG_MALLOC_FAILURE,ERR_QUIT,"");
+ TerminateVDM();
+ }
+
+ RtlInitUnicodeString(&UnicodeString, SectionUnicodeName);
+
+ InitializeObjectAttributes(
+ &A20ObjAttr,
+ &UnicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ SectionSize.HighPart = 0L;
+ SectionSize.LowPart = 640 * 1024 + 64 * 1024;
+
+ Status = NtCreateSection(
+ &A20SectionHandle,
+ SECTION_MAP_WRITE|SECTION_MAP_EXECUTE,
+ &A20ObjAttr,
+ &SectionSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_RESERVE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ // bugbug -williamh
+ // we should pop up an approiate message before we
+ // terminate the vdm.
+#if DBG
+ DbgPrint("sas_init: can not create himem section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ VdmSize = Size;
+
+ //
+ // N.B. We expect that process creation has reserved the first 16 MB
+ // for us already. If not, then this won't work worth a darn
+
+ // free the first 640KB virtual address.
+ // This is done because it has been resevered before sas_init get called
+ BaseAddress = (PVOID)1;
+ ViewSize = 640 * 1024 - 1;
+ Status = NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ &ViewSize,
+ MEM_RELEASE
+ );
+
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("sas_init: cannot free 1st 640k virtual address, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ BaseAddress =(PVOID) ONEMEGA;
+ ViewSize = SIXTYFOURK;
+ Status = NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ &ViewSize,
+ MEM_RELEASE
+ );
+
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("sas_init: can not free himem virtual address, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ BaseAddress = (PVOID)VDM_BASE_ADDRESS;
+ ViewSize = SIXTYFOURK - (ULONG)VDM_BASE_ADDRESS;
+ SectionSize.HighPart = SectionSize.LowPart = 0;
+
+ Status = NtMapViewOfSection(
+ A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ ViewSize,
+ &SectionSize,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of 1st 64K, status = %ls\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ BaseAddress = (PVOID) ONEMEGA;
+ ViewSize = SIXTYFOURK;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ ViewSize,
+ &SectionSize,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ // get emm back fill segment address from softpc
+ // we cut the backfill memory area into pieces in EMM_PAGE_SIZE unit.
+ // this is done so that EMM manager can grab the address space
+ // as EMM page frame.
+ // note that if EMM is disabled, the backfill segment will be
+ // (640 * 1024 / 16).
+
+ BackFillSegment = get_lim_backfill_segment();
+
+ ASSERT(BackFillSegment <= 640 * 1024 / 16);
+
+ //
+ // Map the rest of conventional memory
+ // only map up to the emm backfill segment.
+ BaseAddress = (PVOID) (64 * 1024);
+ ViewSize = BackFillSegment * 16 - 64 * 1024;
+ SectionSize.LowPart = 64 * 1024;
+ SectionSize.HighPart = 0;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ ViewSize,
+ &SectionSize,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+// if there are any backfill memory, map it to our section initially
+ if (BackFillSegment < 640 * 1024 / 16) {
+
+ /* make sure our constants are in sync with emm.h */
+#if DBG
+ ASSERT(EMM_PAGE_SIZE == get_emm_page_size());
+ ASSERT(INTEL_PAGE_SIZE == get_intel_page_size());
+#endif
+ if (!HoldEMMBackFillMemory(BackFillSegment * 16,
+ (640 * 1024) - BackFillSegment * 16)
+ ) {
+
+#if DBG
+ DbgPrint("sas_init: can not map backfill space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ }
+
+ //
+ // Allocate ROM area
+ //
+ BaseAddress = (PVOID)(640 * 1024);
+ ViewSize = 384 * 1024;
+ Status = NtAllocateVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0L,
+ &ViewSize,
+ MEM_COMMIT,
+ PAGE_READWRITE
+ );
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ A20IsON = FALSE;
+
+ Start_of_M_area = 0;
+ Length_of_M_area = VdmSize;
+ sas_connect_memory(0, VdmSize + 2*SIXTYFOURK -1, SAS_RAM);
+}
+
+#if VDD_INTEG
+
+EXPORT
+VOID
+sas_term(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Free memory prior to reallocing it
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ PVOID BaseAddress;
+ NTSTATUS Status;
+ ULONG Size;
+
+ BaseAddress = (PVOID)VDM_BASE_ADDRESS;
+ Size = VdmSize;
+ Status = NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ &Size,
+ MEM_DECOMMIT);
+
+ if (!NT_SUCCESS(Status)) {
+ VDprint(VDP_LEVEL_ERROR,
+ ("SoftPc: NtDeCommitVirtualMemory failed !!!! Status = %lx\n",
+ Status));
+ VDbreak(VDB_LEVEL_ERROR);
+ }
+}
+
+
+EXPORT
+sys_addr
+sas_memory_size(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the size of Intel memory
+
+Arguments:
+
+ none
+
+Return Value:
+
+ size of intel memory
+
+--*/
+{
+ return(VdmSize);
+}
+
+
+EXPORT
+VOID
+sas_connect_memory(
+ IN sys_addr Low,
+ IN sys_addr High,
+ IN int Type
+ )
+/*++
+
+Routine Description:
+
+ This routine sets up a type record for the specified address region.
+ If the specified address region was a different type, it is changed to
+ the new type.
+
+Arguments:
+
+ Low -- the starting address of the region
+ High -- the ending address of the region
+ Type -- the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM,
+ SAS_WRAP, SAS_INACCESSIBLE
+
+Return Value:
+
+ None.
+--*/
+{
+ //bugbug do we handle new block contained in old block correctly?
+ PMEMTYPE Current, Previous, New, Temp;
+
+ if (!MemType) {
+ MemType = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ MemType->Previous = NULL;
+ MemType->Next = NULL;
+ MemType->Start = Low;
+ MemType->End = High;
+ MemType->Type = (half_word)Type;
+ return;
+ }
+
+ Current = MemType;
+ while (Current && (Low > Current->Start)) {
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+ if ((Current) && (Low == Current->Start) && (High == Current->End)) {
+ Current->Type = (half_word)Type;
+ return;
+ }
+
+ if (!Current) {
+ // Block goes at end of list
+ New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ Previous->Next = New;
+ New->Previous = Previous;
+ New->Start = Low;
+ New->End = High;
+ New->Type = (half_word)Type;
+ New->Next = NULL;
+ } else {
+ // Block goes in front of Current
+ New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ New->Start = Low;
+ New->Type = (half_word)Type;
+ New->End = High;
+ New->Previous = Current->Previous;
+ New->Next = Current;
+ Current->Previous = New;
+ if (!New->Previous) {
+ MemType = New;
+ } else {
+ New->Previous->Next = New;
+ }
+ }
+
+
+ // Block overlaps one or more existing blocks
+
+ if (New->Previous) {
+ if (New->Previous->End > New->End) {
+ // block contained in exising block
+ Temp = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ Temp->Previous = New;
+ Temp->Next = New->Next;
+ New->Next = Temp;
+ if (Temp->Next) {
+ Temp->Next->Previous = Temp;
+ }
+ Temp->End = New->Previous->End;
+ New->Previous->End = New->Start - 1;
+ Temp->Start = New->End + 1;
+ Temp->Type = New->Previous->Type;
+ return;
+ } else if (New->Previous->End >= New->Start){
+ // block overlaps end of exising block
+ New->Previous->End = New->Start - 1;
+ }
+ }
+
+ // remove all blocks entirely contained in new block
+ while ((New->Next) && (New->Next->End <= New->End)) {
+ Temp = New->Next;
+ New->Next = New->Next->Next;
+ if (New->Next) {
+ New->Next->Previous = New;
+ }
+ free(Temp);
+ }
+
+ // remove portion of next block overlapping new block
+ if ((New->Next) && (New->Next->Start <= New->End)) {
+ New->Next->Start = New->End + 1;
+ }
+
+}
+
+
+EXPORT
+half_word
+sas_memory_type(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the type of memory at a specific address
+
+Arguments:
+
+ Address -- linear address to return type for.
+
+Return Value:
+
+ the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM,
+ SAS_WRAP, SAS_INACCESSIBLE
+--*/
+{
+ PMEMTYPE Current;
+
+ if (Address > VdmSize) {
+ return SAS_INACCESSIBLE;
+ }
+
+ Current = MemType;
+ while (Current && !((Address >= Current->Start) &&
+ (Address <= Current->End))) {
+ Current = Current->Next;
+ }
+ if (!Current) {
+ return SAS_INACCESSIBLE;
+ }
+ return Current->Type;
+}
+
+
+
+EXPORT
+VOID
+sas_enable_20_bit_wrapping(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine causes memory addresses to wrap at 1MB
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS Status;
+ PVOID BaseAddress;
+ ULONG Size;
+ LARGE_INTEGER SectionOffset;
+ // if A20 line is off already do nothing
+ if (A20IsON == FALSE){
+ return;
+ }
+ BaseAddress = (PVOID)ONEMEGA;
+ Size = SIXTYFOURK;
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ BaseAddress
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20OFF: Unable to unmap view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ SectionOffset.HighPart = SectionOffset.LowPart = 0;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ Size,
+ &SectionOffset,
+ &Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20OFF: Unable to map view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ A20IsON = FALSE;
+}
+
+EXPORT
+VOID
+sas_disable_20_bit_wrapping(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine causes addressing to NOT wrap at 1MB
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS Status;
+ PVOID BaseAddress;
+ ULONG Size;
+ LARGE_INTEGER SectionOffset;
+
+ // if A20 line is on already do nothing
+ if (A20IsON == TRUE){
+ return;
+ }
+ BaseAddress = (PVOID)ONEMEGA;
+ Size = SIXTYFOURK;
+
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ BaseAddress
+ );
+
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20ON: Unable to unmap view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = 640 * 1024;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ Size,
+ &SectionOffset,
+ &Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20ON: Unable to map view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ A20IsON = TRUE;
+}
+
+
+
+EXPORT
+half_word
+sas_hw_at(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the byte at the specified address
+
+Arguments:
+
+ Address -- address of byte to return
+
+Return Value:
+
+ value of byte at specified address
+
+--*/
+{
+ half_word RetVal;
+
+ if (Address > VdmSize) {
+ return 0xFE;
+ }
+
+ RetVal = *((half_word *)Address);
+ return RetVal;
+}
+
+
+EXPORT
+word
+sas_w_at(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the word at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+
+Return Value:
+
+ value of word at specified address
+
+--*/
+{
+ word RetVal;
+
+// DbgPrint("NtVdm : sas_w_at \n");
+ if (Address > VdmSize) {
+ return 0xFEFE;
+ }
+
+ RetVal = *((word *)Address);
+ return RetVal;
+}
+
+
+EXPORT
+double_word
+sas_dw_at(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the dword at the specified address
+
+Arguments:
+
+ Address -- address of dword to return
+
+Return Value:
+
+ value of dword at specified address
+
+--*/
+{
+ double_word RetVal;
+
+ //DbgPrint("NtVdm : sas_dw_at \n");
+ RetVal = (double_word)(((ULONG)sas_w_at(Address + 2) << 16) +
+ sas_w_at(Address));
+ return RetVal;
+}
+
+
+EXPORT
+VOID
+sas_load(
+ IN sys_addr Address,
+ IN half_word *Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the byte at the specified address in the supplied
+ variable
+
+Arguments:
+
+ Address -- address of byte to return
+ Value -- Variable to store the value in
+
+Return Value:
+
+ None.
+--*/
+{
+ //DbgPrint("NtVdm : sas_load \n");
+ if (Address > VdmSize) {
+ *Value = 0xFE;
+ return;
+ }
+
+ *Value = *((half_word *)Address);
+ return;
+}
+
+
+EXPORT
+VOID
+sas_loadw(
+ IN sys_addr Address,
+ IN word *Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the word at the specified address in the supplied
+ variable
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- Variable to store the value in
+
+Return Value:
+
+ None.
+--*/
+{
+ //DbgPrint("NtVdm : sas_loadw\n");
+ if (Address > VdmSize) {
+ *Value = 0xFEFE;
+ return;
+ }
+
+ *Value = *((word *)Address);
+ //DbgPrint("NtVdm : sas_loadw word at address %lx is %x (Not video)\n",Address,*Value);
+ return;
+}
+
+
+
+EXPORT
+VOID
+sas_store(
+ IN sys_addr Address,
+ IN half_word Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the specified byte at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- value to store
+
+Return Value:
+
+ None.
+--*/
+{
+ half_word Type;
+ //DbgPrint("NtVdm : sas_store\n");
+ if (Address <= VdmSize) {
+ Type = sas_memory_type(Address);
+ switch (Type) {
+ case SAS_ROM:
+ break;
+
+ default:
+ *((half_word *)Address) = Value;
+ //DbgPrint("NtVdm : sas_store put byte %x at address %lx\n",Value,Address);
+ break;
+ }
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_storew(
+ IN sys_addr Address,
+ IN word Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the specified word at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- value to store at the specified address
+
+Return Value:
+
+ None.
+--*/
+{
+
+ //DbgPrint("NtVdm : sas_storew\n");
+ if (Address + 1 <= VdmSize) {
+ switch (sas_memory_type(Address)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ *((word *)Address) = Value;
+ //DbgPrint("NtVdm : sas_storew put word %x at address %lx\n",Value,Address);
+ break;
+ }
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_storedw(
+ IN sys_addr Address,
+ IN double_word Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the specified dword at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- value to store at the specified address
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ sas_storew(Address, (word)(Value & 0xFFFF));
+ sas_storew(Address + 2, (word)((Value >> 16) & 0xFFFF));
+}
+
+
+EXPORT
+VOID
+sas_loads(
+ IN sys_addr Source,
+ IN host_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies the string from the specified intel address to the
+ specified host address
+
+Arguments:
+
+ Source -- Intel address to copy from
+ Destination -- host address to copy the string to
+ Length -- length of the string to copy
+
+Return Value:
+
+ None.
+--*/
+{
+
+ //DbgPrint("NtVdm : sas_loads\n");
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+}
+
+
+
+EXPORT
+VOID
+sas_stores(
+ IN sys_addr Destination,
+ IN host_addr Source,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies the string from the specified host address to the
+ specified intel address
+
+Arguments:
+
+ Destination -- intel address to copy the string to
+ Source -- host address to copy from
+ Length -- length of the string to copy
+
+Return Value:
+
+ None.
+--*/
+{
+
+ //DbgPrint("NtVdm : sas_stores\n");
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+ break;
+ }
+}
+
+
+EXPORT
+VOID
+sas_move_bytes_forward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in bytes)
+
+Return Value:
+
+ None.
+--*/
+{
+ //DbgPrint("NtVdm : sas_move_bytes_forward\n");
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+ break;
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_move_words_forward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in words)
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ Length <<= 1;
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+ break;
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_move_bytes_backward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in bytes)
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) (Destination - Length + 1),
+ (PVOID) (Source - Length + 1),
+ Length);
+ break;
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_move_words_backward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in words)
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ Length <<= 1;
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) (Destination - Length + 1),
+ (PVOID) (Source - Length + 1),
+ Length);
+ break;
+ }
+}
+
+EXPORT
+VOID
+sas_fills(
+ IN sys_addr Address,
+ IN half_word Value,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine fills a specified region of intel memory with a byte value
+
+Arguments:
+
+ Address -- address to fill at
+ Value -- value to fill with
+ Length -- length of region to fill
+
+Return Value:
+
+ None.
+--*/
+{
+ half_word Type;
+
+ //DbgPrint("NtVdm : sas_fills\n");
+ Type = sas_memory_type(Address);
+ switch (Type) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlFillMemory((PVOID) Address, Length, Value);
+ break;
+ }
+}
+
+EXPORT
+VOID
+sas_fillsw(
+ IN sys_addr Address,
+ IN word Value,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine fills a specified region of intel memory with a word value
+
+Arguments:
+
+ Address -- address to fill at
+ Value -- value to fill with
+ Length -- length of region to fill
+
+Return Value:
+
+ None.
+--*/
+{
+
+ word *p;
+ half_word Type;
+
+ //DbgPrint("NtVdm : sas_fillsw\n");
+ Type = sas_memory_type(Address);
+ switch (Type) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ p = (word *)Address;
+ while (Length--) {
+ *p++ = Value;
+ }
+ break;
+ }
+}
+
+host_addr scratch = NULL;
+
+EXPORT
+host_addr
+sas_scratch_address(
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine supplies a scratch buffer for short term use
+
+Arguments
+
+ Length -- length of buffer needed
+
+Return Value:
+
+ None.
+
+NOTE: Sudeepb 31-Oct-1993 Converted scratch to be allocated dynamically rather
+ than as a static array.
+--*/
+{
+ //DbgPrint("NtVdm : sas_scratch_address\n");
+ if (Length > 64 * 1024) {
+ //DbgPrint("SoftPc: sas_scratch_address requet for buffer larger than 64K\n");
+ return NULL;
+ }
+
+ if (scratch)
+ return scratch;
+
+ if ((scratch = (host_addr) malloc (64 * 1024)) == NULL)
+ return NULL;
+
+ return scratch;
+}
+
+EXPORT
+half_word
+sas_hw_at_no_check(
+ sys_addr addr
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_hw_at_no_check\n");
+ //DbgPrint("NtVdm : sas_hw_at_no_check byte at %lx is %x\n",addr,*((half_word *)addr));
+ return *((half_word *)addr);
+}
+
+EXPORT
+word
+sas_w_at_no_check(
+ sys_addr addr
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_w_at_no_check\n");
+ //DbgPrint("NtVdm : sas_w_at_no_check word at %lx is %x\n",addr,*((word *)addr));
+ return *((word *)addr);
+}
+EXPORT
+double_word
+sas_dw_at_no_check(
+ sys_addr addr
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_dw_at_no_check\n");
+ //DbgPrint("NtVdm : sas_dw_at_no_check double word at %lx is %lx\n",addr,*((double_word *)addr));
+ return *((double_word *)addr);
+}
+
+
+EXPORT
+VOID
+sas_store_no_check(
+ sys_addr addr,
+ half_word val
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_store_no_check\n");
+ *((half_word *)addr) = val;
+ //DbgPrint("NtVdm : sas_store_no_check stored byte %x at %lx\n",val,addr);
+}
+
+EXPORT
+VOID
+sas_storew_no_check(
+ sys_addr addr,
+ word val
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_storew_no_check\n");
+ *((word *)addr) = val;
+}
+EXPORT
+double_word
+effective_addr(
+ IN word Segment,
+ IN word Offset
+ )
+/*++
+
+Routine Description:
+
+ This routine maps effective_addr to Sim32GetVdmPointer
+
+Arguments:
+
+ Segment -- segment of address
+ Offset -- offset of address
+
+Return Value:
+
+ Actual Intel address corresponding to the address supplied
+--*/
+{
+ //DbgPrint("NtVdm : effective_addr\n");
+ return (ULONG)Sim32GetVDMPointer(((((ULONG)Segment) << 16) | Offset), 1,
+ (UCHAR) (getMSW() & MSW_PE ? TRUE : FALSE));
+}
+
+typedef enum
+{
+ RAM,
+ VIDEO,
+ ROM,
+ IN_FRAGMENT,
+ NEXT_FRAGMENT
+} mem_type;
+
+typedef struct
+{
+ VOID (*b_write)();
+ VOID (*w_write)();
+ VOID (*b_fill)();
+ VOID (*w_fill)();
+ VOID (*b_move)();
+ VOID (*w_move)();
+} MEM_HANDLERS;
+#define TYPE_RANGE ((int)SAS_INACCESSIBLE)
+#define write_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) )
+#define write_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) )
+#define write_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) )
+#define write_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) )
+#define init_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) )
+#define init_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) )
+#define init_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) )
+#define init_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) )
+#define read_b_write_ptrs( offset ) ( b_write_ptrs[(offset)] )
+#define read_w_write_ptrs( offset ) ( w_write_ptrs[(offset)] )
+#define read_b_page_ptrs( offset ) ( b_move_ptrs[(offset)] )
+#define read_w_page_ptrs( offset ) ( w_move_ptrs[(offset)] )
+#define read_b_move_ptrs( offset ) ( b_move_ptrs[(offset)] )
+#define read_w_move_ptrs( offset ) ( w_move_ptrs[(offset)] )
+#define read_b_fill_ptrs( offset ) ( b_fill_ptrs[(offset)] )
+#define read_w_fill_ptrs( offset ) ( w_fill_ptrs[(offset)] )
+
+/*
+* The main gmi data structures are defined here
+*/
+void (*(b_write_ptrs[TYPE_RANGE]))() ; /* byte write function */
+void (*(w_write_ptrs[TYPE_RANGE]))() ; /* word write function */
+void (*(b_fill_ptrs[TYPE_RANGE]))() ; /* byte str fill func */
+void (*(w_fill_ptrs[TYPE_RANGE]))() ; /* word str fill func */
+void (*(b_move_ptrs[TYPE_RANGE]))() ; /* byte str write func */
+void (*(w_move_ptrs[TYPE_RANGE]))() ; /* word str write func */
+
+void gmi_define_mem(type,handlers)
+mem_type type;
+MEM_HANDLERS *handlers;
+{
+ int int_type = (int)(type);
+ init_b_write_ptrs(int_type, (void(*)())(handlers->b_write));
+ init_w_write_ptrs(int_type, (void(*)())(handlers->w_write));
+ b_move_ptrs[int_type] = (void(*)())(handlers->b_move);
+ w_move_ptrs[int_type] = (void(*)())(handlers->w_move);
+ b_fill_ptrs[int_type] = (void(*)())(handlers->b_fill);
+ w_fill_ptrs[int_type] = (void(*)())(handlers->w_fill);
+}
+#endif
+BOOL sas_twenty_bit_wrapping_enabled() {
+ return (!A20IsON);
+}
+
+VOID sas_part_enable_20_bit_wrapping(){
+}
+VOID sas_part_disable_20_bit_wrapping(){
+}
+
+
+/*
+ * This function maps the given EMM backfill memory to DOS conventional
+ * memory. The function is provided to EMM manager to put back
+ * unmapped backfill memory(hold its contents while it is not mapped).
+ *
+ * NOTE: The very first caller will be sas_init.
+ *
+ * Input: ULONG BaseAddress -- the starting address, must be in INTEL page
+ * boundary
+ * ULONG Size -- size of the range, must be a multiple of
+ * EMM_PAGE_SIZE.
+ *
+ * According to LouP, a view costs about 400 bytes of memory. This is why
+ * I make these function strictly to work on EMM_PAGE_SIZE instead of 4KB.
+ */
+
+
+BOOL
+HoldEMMBackFillMemory(ULONG BaseAddress, ULONG Size)
+{
+ ULONG NewBase, Pages, i;
+ LARGE_INTEGER SectionOffset;
+ ULONG ViewSize;
+ NTSTATUS Status;
+
+ /* this function can only be called if there is backfill at all */
+ ASSERT(BackFillSegment < 640 * 1024 / 16);
+
+ // size must be EMM_PAGE_SIZE multiple
+ ASSERT((Size % EMM_PAGE_SIZE) == 0);
+
+ // address must be on INTEL page boundary
+ ASSERT((BaseAddress & (INTEL_PAGE_SIZE - 1)) == 0);
+
+ for (Pages = Size / EMM_PAGE_SIZE; Pages; Pages--) {
+ SectionOffset.LowPart = BaseAddress;
+ SectionOffset.HighPart = 0;
+ ViewSize = EMM_PAGE_SIZE;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&BaseAddress,
+ 0,
+ ViewSize,
+ &SectionOffset,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+ if (!NT_SUCCESS(Status))
+ break;
+ BaseAddress += EMM_PAGE_SIZE;
+ }
+ return (NT_SUCCESS(Status));
+}