Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1544 lines
33 KiB

/*++
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;
USHORT Pages;
ULONG BackFillBase;
InitializeObjectAttributes(
&A20ObjAttr,
NULL,
0,
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));
if ( NULL == MemType ) {
goto ErrorSASC;
}
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;
}
New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
if ( NULL == New ) {
goto ErrorSASC;
}
if (!Current) {
// Block goes at end of list
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->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));
if(NULL == Temp) {
goto ErrorSASC;
}
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;
}
return;
ErrorSASC:
RcMessageBox(EG_MALLOC_FAILURE, NULL, NULL,
RMB_ICON_BANG | RMB_ABORT);
TerminateVDM();
}
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) {
return NULL;
}
if (scratch)
return scratch;
if ((scratch = (host_addr) malloc (64 * 1024)) == NULL){
RcMessageBox(EG_MALLOC_FAILURE, NULL, NULL,
RMB_ICON_BANG | RMB_ABORT);
TerminateVDM();
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 = STATUS_SUCCESS;;
/* 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));
}