summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/host/src/x86_emm.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/softpc.new/host/src/x86_emm.c')
-rw-r--r--private/mvdm/softpc.new/host/src/x86_emm.c948
1 files changed, 948 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/host/src/x86_emm.c b/private/mvdm/softpc.new/host/src/x86_emm.c
new file mode 100644
index 000000000..cfb95047c
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/x86_emm.c
@@ -0,0 +1,948 @@
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+MODULE NAME : 'Lower layer' of Expanded Memory Manager
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
+ NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS INC.
+
+DESIGNER : Simon Frost
+DATE : March '92
+
+PURPOSE : NT specific code for EMS LIM rev 4.0
+ implementation.
+
+The Following Routines are defined:
+ 1. host_initialise_EM()
+ 2. host_deinitialise_EM()
+ 3. host_allocate_storage()
+ 4. host_free_storage()
+ 5. host_reallocate_storage()
+ 6. host_map_page()
+ 7. host_unmap_page()
+ 8. host_alloc_page()
+ 9. host_free_page()
+ 10. host_copy_con_to_con()
+ 11. host_copy_con_to_EM()
+ 12. host_copy_EM_to_con()
+ 13. host_copy_EM_to_EM()
+ 14. host_exchg_con_to_con()
+ 15. host_exchg_con_to_EM()
+ 16. host_exchg_EM_to_EM()
+ 17. host_get_access_key()
+
+=========================================================================
+*/
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "insignia.h"
+#include "host_def.h"
+#include "string.h"
+#include "stdlib.h"
+
+#ifdef LIM
+#ifdef MONITOR //x86 specific LIM functions
+
+#include "xt.h"
+#include "emm.h"
+#include "sas.h"
+#include "host_rrr.h"
+#include "debug.h"
+#include "umb.h"
+#include "host_emm.h"
+#include "nt_uis.h"
+
+/* Global Variables */
+
+/* Forward Declarations */
+BOOL hold_lim_page(USHORT segment);
+/* find this function in monitor/sas.c */
+extern BOOL HoldEMMBackFillMemory(ULONG Address, ULONG Size);
+
+
+/* Local Variables */
+
+LOCAL UTINY *EM_pagemap_address = NULL; /* address of start of pagemap */
+
+/* pagemap requires 1 bit per 16K page - i.e. 8 bytes per meg */
+LOCAL UTINY EM_pagemap[8*32];
+
+LOCAL VOID *BaseOfLIMMem = NULL; // start of expanded memory
+ULONG HolderBlockOffset; // holder block offset
+
+LOCAL HANDLE LIMSectionHandle;
+LOCAL HANDLE processHandle = NULL;
+
+LOCAL ULONG X86NumRoms = 0;
+
+#define PAGE_SEG_SIZE 0x400 /* size of page expressed as segment */
+
+#define CONFIG_DATA_STRING L"Configuration Data"
+#define KEY_VALUE_BUFFER_SIZE 2048
+
+#define EMMBASE 0xd0000
+#define EMMTOP 0xe0000
+
+#define SECTION_NAME L"\\BaseNamedObjects\\LIMSection"
+#define SECTION_NAME_LEN sizeof(SECTION_NAME)
+
+typedef struct _BIOS_BLOCK {
+ ULONG PhysicalAddress;
+ ULONG SizeInByte;
+} BIOS_BLOCK;
+
+
+/*
+Defines are:
+ EM_loads(from, to, length), copies length bytes from intel 24 bit
+ address from, to host 32 bit address to
+ EM_stores(to, from, length), copies length bytes from host 32 bit
+ address from to intel 24 bit address to
+ EM_moves(from, to, length), copies length bytes from intel 24 bit
+ address from to intel 24 bit address to
+ EM_memcpy(to, from, length), copies length bytes from host 32 bit
+ address from to host 32 bit address to
+*/
+
+
+#define EM_loads(from, to, length) memcpy(to, get_byte_addr(from), length)
+#define EM_stores(to, from, length) \
+ RtlCopyMemory(get_byte_addr(to), from, length)
+#define EM_moves(from,to,length) \
+ RtlMoveMemory(get_byte_addr(to), get_byte_addr(from), length)
+#define EM_memcpy(to, from, length) \
+ RtlMoveMemory(to, from, length)
+
+/*
+===========================================================================
+
+FUNCTION : host_initialise_EM
+
+PURPOSE : allocates the area of memory that is used for
+ expanded memory and sets up an area of memory to be used
+ for the logical pagemap allocation table.
+
+
+RETURNED STATUS : SUCCESS - memory allocated successfully
+ FAILURE - unable to allocate required space
+
+DESCRIPTION :
+
+
+=========================================================================
+*/
+int host_initialise_EM(short size)
+/* IN short size size of area required in megabytes */
+{
+ UTINY *pagemap_ptr; /* temp ptr. to logical pagemap */
+ int i; /* loop counter */
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objAttribs;
+ LARGE_INTEGER secSize;
+ ULONG viewSize;
+ USHORT PageSegment, Pages;
+ LONG EM_size;
+
+ SAVED UNICODE_STRING LIMSectionName =
+ {
+ SECTION_NAME_LEN,
+ SECTION_NAME_LEN,
+ SECTION_NAME
+ };
+
+
+ /* Nobody should call this function with size 0 */
+ ASSERT(size != 0);
+
+ EM_pagemap_address = &EM_pagemap[0];
+
+ /* initialise pagemap to 0's */
+
+ pagemap_ptr = EM_pagemap_address;
+ for(i = 0; i < 8*32; i++)
+ *pagemap_ptr++ = 0;
+
+ EM_size = ((long) size) * 0x100000;
+
+ if (!(processHandle = NtCurrentProcess()))
+ {
+ assert0(NO, "host_initialise_EM: cant get process handle");
+ return(FAILURE);
+ }
+
+ // create section for LIM
+
+ /* Fill the fields of the OBJECT_ATTRIBUTES structure. */
+ InitializeObjectAttributes(&objAttribs,
+ NULL, // was &LIMSectionName, but null means private
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Create the section. EMM_PAGE_SIZE for holder page */
+ secSize.LowPart = EM_size + EMM_PAGE_SIZE;
+ secSize.HighPart = 0;
+ HolderBlockOffset = EM_size;
+
+ // improvement - just reserve & commit as needed...
+ status = NtCreateSection(&LIMSectionHandle,
+ SECTION_MAP_WRITE|SECTION_MAP_EXECUTE,
+ &objAttribs,
+ &secSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_COMMIT,
+ NULL);
+ if (!NT_SUCCESS(status))
+ {
+ assert1(NO, "host_initialise_EM: LIM section creation failed (%x)", status);
+ return(FAILURE);
+ }
+
+ /* Map the section to the process' address space. */
+ BaseOfLIMMem = NULL;
+ viewSize = 0;
+
+ status = NtMapViewOfSection(LIMSectionHandle,
+ processHandle,
+ (PVOID *) &BaseOfLIMMem,
+ 0,
+ 0,
+ NULL,
+ &viewSize,
+ ViewUnmap,
+ 0, // do we need mem_top_down??
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(status))
+ {
+ assert1(NO, "host_initialise_EM: can't map view of LIM section (%x)", status);
+ return(FAILURE);
+ }
+
+ /* acquire page frame addresss space from UMB list */
+ if (!GetUMBForEMM()) {
+ host_deinitialise_EM();
+ return FAILURE;
+ }
+
+ /* attach page to holder so that we won't get killed if applications
+ * try to touch the page frames without mapping
+ */
+
+ for (Pages = get_no_phys_pages(); Pages ; Pages--) {
+ PageSegment = get_page_seg((unsigned char)(Pages - 1));
+ if (PageSegment <= 640 * 1024 / 16)
+ continue;
+ if (!hold_lim_page(PageSegment))
+ return FAILURE;
+
+ }
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_deinitialise_EM
+
+PURPOSE : frees the area of memory that was used for
+ expanded memory and memory used
+ for the logical pagemap allocation table.
+
+
+RETURNED STATUS : SUCCESS - memory freed successfully
+ FAILURE - error ocurred in freeing memory
+
+DESCRIPTION :
+
+
+=========================================================================
+*/
+int host_deinitialise_EM()
+{
+ ULONG len = 0x10000;
+ NTSTATUS status;
+
+ if (BaseOfLIMMem != NULL)
+ {
+ if (processHandle == NULL)
+ {
+ //As shutting down anyway then fail silently
+ return(FAILURE);
+ }
+
+ // lose section from our memory space
+ status = NtUnmapViewOfSection(processHandle, BaseOfLIMMem);
+ if (!NT_SUCCESS(status))
+ {
+ //As shutting down anyway then fail silently
+ return(FAILURE);
+ }
+
+ status = NtClose(LIMSectionHandle); // delete section
+ if (!NT_SUCCESS(status))
+ {
+ //As shutting down anyway then fail silently
+ return(FAILURE);
+ }
+
+ return(SUCCESS);
+ }
+}
+
+
+
+/*
+===========================================================================
+
+FUNCTION : host_allocate_storage
+
+PURPOSE : allocates an area of memory of requested size, to be
+ used as a general data storage area. The area is
+ to zeros.
+
+RETURNED STATUS : storage_ID - (in this case a pointer)
+ NULL - failure to allocate enough space.
+
+
+DESCRIPTION : returns memory initialised to zeros.
+ The storage ID returned is a value used to later reference
+ the storage area allocated. The macro USEBLOCK in
+ "host_emm.h" is used by the manager routines to convert
+ this ID into a char pointer
+
+=========================================================================
+*/
+long host_allocate_storage(int no_bytes)
+/* IN int no_bytes no. of bytes required */
+{
+ // should replace this (?) - dissasembling calloc seems to
+ // indicate it uses win funx...
+ return ((long)calloc(1, no_bytes));
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_free_storage
+
+PURPOSE : frees the area of memory that was used for
+ data storage
+
+
+RETURNED STATUS : SUCCESS - memory freed successfully
+ FAILURE - error ocurred in freeing memory
+
+DESCRIPTION : In this implementation storage_ID is simply a pointer
+
+
+=========================================================================
+*/
+int host_free_storage(long storage_ID)
+/* IN long storage_ID ptr to area of memory */
+{
+ if(storage_ID != (long)NULL)
+ free((char *)storage_ID);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_reallocate_storage
+
+PURPOSE : increases the size of memory allocated, maintaining the
+ contents of the original memory block
+
+
+RETURNED STATUS : storage_ID - memory reallocated successfully
+ NULL - error ocurred in reallocating memory
+
+DESCRIPTION : In this implementation storage_ID is simply a pointer
+ Note the value of storage_ID returned may or may not be the
+ same as the value given
+
+=========================================================================
+*/
+long host_reallocate_storage(LONG storage_ID, int size, int new_size)
+/*
+ IN
+long storage_ID ptr to area of memory
+int size original size - not used in this version
+ new_size new size required
+*/
+{
+ return((long)realloc((char *)storage_ID, new_size));
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : hold_lim_page
+
+PURPOSE : Puts some memory in one of the LIM page gaps in 16 bit
+ memory. Ensures nothing else in the process gets that
+ via malloc.
+
+
+RETURNED STATUS : TRUE - mapping OK.
+
+DESCRIPTION : Mapping achieved by mapping correct page from section into
+ Intel memory
+=========================================================================
+*/
+BOOL hold_lim_page(USHORT segment)
+/* IN
+int page page (0-3) of LIM gap
+*/
+
+{
+ PVOID to;
+ LARGE_INTEGER sec_offset;
+ ULONG viewSize;
+ NTSTATUS status;
+
+ if (BaseOfLIMMem != NULL)
+ {
+ to = (PVOID)effective_addr(segment, (word)0);
+
+ sec_offset.LowPart = HolderBlockOffset;
+ sec_offset.HighPart = 0;
+
+ viewSize = EMM_PAGE_SIZE;
+
+ status = NtMapViewOfSection(LIMSectionHandle,
+ processHandle,
+ &to,
+ 0,
+ EMM_PAGE_SIZE,
+ &sec_offset,
+ &viewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE);
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FALSE);
+ }
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_map_page
+
+PURPOSE : produces mapping from an Expanded Memory page to a
+ page in Intel physical address space
+
+
+RETURNED STATUS : SUCCESS - mapping completed succesfully
+ FAILURE - error ocurred in mapping
+
+DESCRIPTION : Mapping achieved by mapping correct page from section into
+ Intel memory
+=========================================================================
+*/
+int host_map_page(SHORT EM_page_no, USHORT segment)
+/* IN
+short EM_page_no Expanded Memory page to be mapped in
+unsigned short segment; segment in physical address space to map into
+*/
+
+{
+ PVOID to;
+ int tstpage;
+ LARGE_INTEGER sec_offset;
+ ULONG viewSize;
+ NTSTATUS status;
+
+ note_trace2(LIM_VERBOSE,"map page %d to segment 0x%4x", EM_page_no, segment);
+#ifdef EMM_DEBUG
+ printf("host_map_page, segment=%x, EMpage=%x\n",
+ segment, EM_page_no);
+#endif
+
+ if (BaseOfLIMMem != NULL)
+ {
+ to = (PVOID)effective_addr(segment, 0);
+
+ sec_offset.LowPart = EM_page_no * EMM_PAGE_SIZE;
+ sec_offset.HighPart = 0;
+
+ viewSize = EMM_PAGE_SIZE;
+
+ tstpage = (segment - get_base_address()) >> 10;
+
+ /* detach from EMM page section */
+ status = NtUnmapViewOfSection(processHandle, (PVOID)to);
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FALSE);
+ }
+
+ if (processHandle == NULL)
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,0,__FILE__,__LINE__);
+ return(FAILURE);
+ }
+
+ /* attach to the section */
+ status = NtMapViewOfSection(LIMSectionHandle,
+ processHandle,
+ &to,
+ 0,
+ EMM_PAGE_SIZE,
+ &sec_offset,
+ &viewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FAILURE);
+ }
+ return(SUCCESS);
+ }
+ return(FAILURE);
+}
+
+/*
+===========================================================================
+
+FUNCTION : host_unmap_page
+
+PURPOSE :unmaps pages from Intel physical address space to an
+ Expanded Memory page
+
+RETURNED STATUS : SUCCESS - unmapping completed succesfully
+ FAILURE - error ocurred in mapping
+
+DESCRIPTION : Unmapping achieved by unampping view of section from
+ Intel memory
+
+=========================================================================
+*/
+int host_unmap_page(USHORT segment, SHORT EM_page_no)
+/* IN
+unsigned short segment Segment in physical address space to unmap.
+short EM_page_no Expanded Memory page currently mapped in
+*/
+{
+ PVOID from;
+ NTSTATUS status;
+ unsigned short phys_page_no;
+
+ note_trace2(LIM_VERBOSE,"unmap page %d from segment 0x%.4x\n",EM_page_no,segment);
+
+
+ from = (PVOID)effective_addr(segment, 0);
+
+#ifdef EMM_DEBUG
+ printf("host_unmap_page, segment=%x, EMpage=%x\n",
+ segment, EM_page_no);
+#endif
+
+ /* detach from the LIM section */
+ status = NtUnmapViewOfSection(processHandle, from);
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FAILURE);
+ }
+
+ /* hold the block to avoid AV when applications touch unmapped pages */
+ if (segment < 640 * 1024 / 16) {
+ if (!HoldEMMBackFillMemory(segment * 16, EMM_PAGE_SIZE))
+ return FAILURE;
+ }
+ else {
+
+ if (!hold_lim_page(segment)) {
+ note_trace1(LIM_VERBOSE, "couldn't hold lim page %d",get_segment_page_no(segment));
+ return FAILURE;
+ }
+ }
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : host_alloc_page
+
+PURPOSE : searches the pagemap looking for a free page, allocates
+ that page and returns the EM page no.
+
+RETURNED STATUS :
+ SUCCESS - Always see note below
+
+DESCRIPTION : Steps through the Expanded memory Pagemap looking for
+ a clear bit, which indicates a free page. When found,
+ sets that bit and returns the page number.
+ For access purposes the pagemap is divided into long
+ word(32bit) sections
+
+NOTE : The middle layer calling routine (alloc_page()) checks
+ that all pages have not been allocated and therefore in
+ this implementation the returned status will always be
+ SUCCESS.
+ However alloc_page still checks for a return status of
+ SUCCESS, as some implementations may wish to allocate pages
+ dynamically and that may fail.
+=========================================================================
+*/
+SHORT host_alloc_page()
+{
+ SHORT EM_page_no; /* page number returned */
+ LONG *ptr; /* ptr to 32 bit sections in */
+ /* pagemap */
+ SHORT i; /* index into 32 bit section */
+
+ ptr = (LONG *)EM_pagemap_address;
+ i =0;
+ EM_page_no = 0;
+
+ while(*ptr & (MSB >> i++))
+ {
+ EM_page_no++;
+
+ if(i == 32)
+ /*
+ * start on next section
+ */
+ {
+ ptr++;
+ i = 0;
+ }
+ }
+ /*
+ * Set bit to show that page is allocated
+ */
+ *ptr = *ptr | (MSB >> --i);
+
+ return(EM_page_no);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_free_page
+
+PURPOSE : marks the page indicated as being free for further
+ allocation
+
+RETURNED STATUS :
+ SUCCESS - Always - see note below
+
+DESCRIPTION : clears the relevent bit in the pagemap.
+
+ For access purposes the pagemap is divided into long
+ word(32bit) sections.
+
+NOTE : The middle layer calling routine (free_page()) always
+ checks for invalid page numbers so in this implementation
+ the routine will always return SUCCESS.
+ However free_page() still checks for a return of SUCCESS
+ as other implementations may wish to use it.
+=========================================================================
+*/
+int host_free_page(SHORT EM_page_no)
+/* IN SHORT EM_page_no page number to be cleared */
+{
+ LONG *ptr; /* ptr to 32 bit sections in */
+ /* pagemap */
+ SHORT i; /* index into 32 bit section */
+
+ /*
+ * Set pointer to correct 32 bit section and index to correct bit
+ */
+
+ ptr = (long *)EM_pagemap_address;
+ ptr += (EM_page_no / 32);
+ i = EM_page_no % 32;
+
+ /*
+ * clear bit
+ */
+ *ptr = *ptr & ~(MSB >> i);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_copy routines
+ host_copy_con_to_con()
+ host_copy_con_to_EM()
+ host_copy_EM_to_con()
+ host_copy_EM_to_EM()
+
+PURPOSE : copies between conventional and expanded memory
+
+
+RETURNED STATUS :
+ SUCCESS - Always - see note below
+
+DESCRIPTION :
+ The middle layer calling routine always checks for a
+ return of SUCCESS as other implementations may
+ return FAILURE.
+=========================================================================
+*/
+int host_copy_con_to_con(int length, USHORT src_seg, USHORT src_off, USHORT dst_seg, USHORT dst_off)
+
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ sys_addr from, to; /* pointers used for copying */
+
+ from = effective_addr(src_seg, src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_moves(from, to, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_con_to_EM(int length, USHORT src_seg, USHORT src_off, USHORT dst_page, USHORT dst_off)
+
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ UTINY *to;
+ sys_addr from;
+
+ from = effective_addr(src_seg, src_off);
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_loads(from, to, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_EM_to_con(int length, USHORT src_page, USHORT src_off, USHORT dst_seg, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_page source page number
+ src_off source offset within page
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ UTINY *from;
+ sys_addr to;
+
+ from = (char *)BaseOfLIMMem + (src_page * EMM_PAGE_SIZE + src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_stores(to, from, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_EM_to_EM(int length, USHORT src_page, USHORT src_off, USHORT dst_page, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_page source page number
+ src_off source offset within page
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ unsigned char *from, *to; /* pointers used for copying */
+
+ from = (char *)BaseOfLIMMem + src_page * EMM_PAGE_SIZE + src_off;
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_memcpy(to, from, length);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_exchange routines
+ host_exchg_con_to_con()
+ host_exchg_con_to_EM()
+ host_exchg_EM_to_EM()
+
+PURPOSE : exchanges data between conventional and expanded memory
+
+
+RETURNED STATUS :
+ SUCCESS - Everything ok
+ FAILURE - Memory allocation failure
+
+DESCRIPTION :
+
+=========================================================================
+*/
+int host_exchg_con_to_con(int length, USHORT src_seg, USHORT src_off, USHORT dst_seg, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ UTINY *temp, *pointer;/* pointers used for copying */
+ sys_addr to, from;
+
+ if (length <= 64*1024)
+ temp = sas_scratch_address(length);
+ else
+ if ((temp = (unsigned char *)host_malloc(length)) == NULL)
+ return(FAILURE);
+
+ pointer = temp;
+
+ from = effective_addr(src_seg, src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_loads(from, pointer, length); /* source -> temp */
+ EM_moves(to, from, length); /* dst -> source */
+ EM_stores(to, pointer, length); /* temp -> dst */
+
+ if (length > 64*1024)
+ host_free(temp);
+
+ return(SUCCESS);
+}
+
+int host_exchg_con_to_EM(int length, USHORT src_seg, USHORT src_off, USHORT dst_page, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ UTINY *to, *temp, *pointer;/* pointers used for copying */
+ sys_addr from;
+
+ //STF - performance improvement: if 4k aligned & >= 4k then can use
+ // (un)mapview to do exchange.
+
+ if (length <= 64*1024)
+ temp = sas_scratch_address(length);
+ else
+ if ((temp = (unsigned char *)host_malloc(length)) == NULL)
+ return(FAILURE);
+
+ pointer = temp;
+
+ from = effective_addr(src_seg, src_off);
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_loads(from, pointer, length);
+ EM_stores(from, to, length);
+ EM_memcpy(to, pointer, length);
+
+ if (length > 64*1024)
+ host_free(temp);
+
+ return(SUCCESS);
+}
+
+int host_exchg_EM_to_EM(int length, USHORT src_page, USHORT src_off, USHORT dst_page, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_page source page number
+ src_off source offset within page
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ UTINY *from, *to, *temp, *pointer; /* pointers used for copying */
+
+ if (length <= 64*1024)
+ temp = sas_scratch_address(length);
+ else
+ if ((temp = (unsigned char *)host_malloc(length)) == NULL)
+ return(FAILURE);
+
+ pointer = temp;
+
+ from = (char *)BaseOfLIMMem + src_page * EMM_PAGE_SIZE + src_off;
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_memcpy(pointer, from, length);
+ EM_memcpy(from, to, length);
+ EM_memcpy(to, pointer, length);
+
+ if (length > 64*1024)
+ host_free(temp);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_get_access_key
+
+PURPOSE : produces a random access key for use with LIM function 30
+ 'Enable/Disable OS/E Function Set Functions'
+
+RETURNED STATUS : none
+
+DESCRIPTION : Two 16 bit random values are required for the 'access key'
+ We use the microsecond field from the get time of day routine
+ to provide this.
+
+=========================================================================
+*/
+void host_get_access_key(USHORT access_key[2])
+/* OUT USHORT access_key[2] source segment address */
+{
+ // do you think we need to seed the random # gen?
+ access_key[0] = rand() & 0xffff;
+ access_key[1] = rand() & 0xffff;
+
+ return;
+}
+#endif /* MONITOR */
+#endif /* LIM */