summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/base/dos
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/softpc.new/base/dos')
-rw-r--r--private/mvdm/softpc.new/base/dos/emm_mngr.c2129
-rw-r--r--private/mvdm/softpc.new/base/dos/makefile6
-rw-r--r--private/mvdm/softpc.new/base/dos/sources58
3 files changed, 2193 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/base/dos/emm_mngr.c b/private/mvdm/softpc.new/base/dos/emm_mngr.c
new file mode 100644
index 000000000..847a1f4a5
--- /dev/null
+++ b/private/mvdm/softpc.new/base/dos/emm_mngr.c
@@ -0,0 +1,2129 @@
+#include "insignia.h"
+#include "host_def.h"
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+SccsID : @(#)emm_mngr.c 1.24 08/31/93 Copyright Insignia Solutions Ltd.
+FILE NAME : emm_mngr.c
+MODULE NAME : 'Middle 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 : J.P.Box
+DATE : April '88
+
+PURPOSE : Contains all the routines that communicate with
+ the arrays and data structures that hold the
+ necessary Expanded Memory Manager Data.
+
+
+The Following Routines are defined:
+ 1. init_expanded_memory()
+ 2. free_expanded_memory()
+ 3. get_new_handle()
+ 4. free_handle()
+ 5. reallocate_handle()
+ 6. handle_ok()
+ 7. set_no_pages()
+ 8. set_EM_pageno()
+ 9. set_map()
+ 10. set_name()
+ 11. get_no_pages()
+ 12. get_EM_pageno()
+ 13. get_map()
+ 14. get_name()
+ 15. alloc_page()
+ 16. free_page()
+ 17. map_page()
+ 18. unmap_page()
+ 19. map_saved()
+ 20. save_map()
+ 21. restore_map()
+ 22. copy_exchange_data()
+ 23. page_status()
+ The following routines just return variables to the top layer
+ 24. get_total_pages()
+ 25. get_unallocated_pages()
+ 26. get_base_address()
+ 27. get_total_handles()
+ 28. get_total_open_handles()
+ 29. get_no_phys_pages()
+ 30. get_page_seg()
+ 31. get_map_size()
+
+=========================================================================
+
+AMMENDMENTS :
+
+=========================================================================
+*/
+
+
+#ifdef LIM
+
+#ifdef SEGMENTATION
+/*
+ * The following #include specifies the code segment into which this
+ * module will by placed by the MPW C compiler on the Mac II running
+ * MultiFinder.
+ */
+#include "SOFTPC_LIM.seg"
+#endif
+
+
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(NTVDM) && defined(MONITOR)
+#include <malloc.h>
+#endif
+
+#include TypesH
+
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "host_emm.h"
+#include "emm.h"
+#include "gmi.h"
+#include "debug.h"
+#ifndef PROD
+#include "trace.h"
+#endif
+#include "timer.h"
+
+#ifdef NTVDM
+#include "error.h"
+#endif /* NTVDM */
+
+typedef enum
+{
+ BYTE_OP,
+ WORD_OP,
+ STR_OP
+} MM_LIM_op_type;
+
+#ifdef NTVDM
+/* Local Variables */
+static long
+ handle[MAX_NO_HANDLES], /* Array containing unique ID's */
+ /* for each handle, these are */
+ /* usually pointers, but this */
+ /* is host dependant */
+ backfill; /* backfill memory size */
+static unsigned short
+ total_pages = 0, /* no. of EM pages available */
+ unallocated_pages = 0, /* no. of unallocated EM pages */
+ total_handles, /* no of handles available */
+ total_open_handles, /* no. of allocated handles */
+ *EM_page_mapped_array = NULL, /* EMM page mapped array */
+ *EM_page_mapped = NULL, /* Expanded Memory pages */
+ /* currently mapped in */
+ page_offset, /* offset in handle data at */
+ /* which page numbers start */
+ map_size, /* no of bytes rq'd to store map*/
+ no_phys_pages = 0, /* no. of phys. pages available */
+ no_altreg_sets = 0; /* no of alternative reg sets */
+static unsigned short
+ physical_page[MAX_NO_PAGES]; /* array containing segment */
+ /* addresses of physical pages */
+
+static unsigned short
+ EM_start, EM_end;
+static IU8
+ * altreg_alloc_mask; /* altref allocate mask */
+static unsigned short
+ next_free_altreg_set, /* next free altreg set #, 0 based */
+ free_altreg_sets, /* number of free altreg */
+ active_altreg_set = 0; /* current active alt reg set */
+static char
+ name[NAME_LENGTH]; /* for storing handle name */
+
+#define GET_EM_PAGE_MAPPED_PTR(set) (EM_page_mapped_array + \
+ (set * no_phys_pages))
+
+/* get emm parameters, initialize housekeeping structures and
+ * reserve page frames.
+ */
+
+boolean lim_page_frame_init(PLIM_CONFIG_DATA lim_config_data)
+{
+ int i;
+ unsigned short altreg_alloc_mask_size; /* altreg allocation mask array size */
+
+ no_phys_pages = get_lim_page_frames(physical_page, lim_config_data);
+
+ /* The first 4 pages must be continuous and locate above 640KB
+ * (the EMM primary page frame(physical pages 0, 1, 2 and 3)).
+ * It is then followed by other pages located above 640KB and then
+ * pages below 640KB(back fill)
+ */
+ if (!no_phys_pages)
+ return FALSE;
+
+ no_altreg_sets = lim_config_data->total_altreg_sets;
+ backfill = lim_config_data->backfill;
+
+
+ /* each mapping register set has no_phys_pages pages */
+ EM_page_mapped_array = host_malloc(no_phys_pages * no_altreg_sets *
+ sizeof(short));
+ if (EM_page_mapped_array == NULL) {
+ host_error(EG_MALLOC_FAILURE, ERR_CONT, "");
+ return FALSE;
+ }
+ /* one bit for each altreg set */
+ altreg_alloc_mask_size = (no_altreg_sets + 7) / 8;
+ altreg_alloc_mask = host_malloc(altreg_alloc_mask_size);
+ if (altreg_alloc_mask == NULL) {
+ host_free(EM_page_mapped_array);
+ host_error(EG_MALLOC_FAILURE, ERR_CONT, "");
+ return FALSE;
+ }
+
+ /* all altreg sets are free at this moment */
+ for (i = 0; i < altreg_alloc_mask_size; i++)
+ altreg_alloc_mask[i] = 0;
+
+ next_free_altreg_set = 0;
+ free_altreg_sets = no_altreg_sets;
+ return TRUE;
+}
+#else
+
+
+/* Local Variables */
+static long
+#ifdef macintosh
+ *handle;
+#else
+ handle[MAX_NO_HANDLES]; /* Array containing unique ID's */
+ /* for each handle, these are */
+ /* usually pointers, but this */
+ /* is host dependant */
+#endif /* !macintosh */
+
+static short
+ total_pages = 0, /* no. of EM pages available */
+ unallocated_pages = 0, /* no. of unallocated EM pages */
+ total_handles, /* no of handles available */
+ total_open_handles, /* no. of allocated handles */
+ EM_page_mapped[MAX_NO_PAGES], /* Expanded Memory pages */
+ /* currently mapped in */
+ page_offset, /* offset in handle data at */
+ /* which page numbers start */
+ map_size, /* no of bytes rq'd to store map*/
+ no_phys_pages; /* no. of phys. pages available */
+
+static unsigned int
+ EM_start, /* start segment for EM mapping */
+ EM_end; /* 1st segment past end of EM */
+
+static unsigned short
+ physical_page[MAX_NO_PAGES]; /* array containing segment */
+ /* addresses of physical pages */
+
+static char
+ name[NAME_LENGTH]; /* for storing handle name */
+
+#endif
+
+/*
+===========================================================================
+
+FUNCTION : init_expanded_memory
+
+PURPOSE : This routine calls the routine to allocate the expanded
+ memory pages and then sets up the arrays and variables that
+ are used by the Expanded Memory Manager(EMM).
+
+RETURNED STATUS : SUCCESS - manager initialised succesfully
+ FAILURE - Failure to allocate space for Expanded Memory
+ pages.
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL int init_expanded_memory IFN2(int, size, /* size of area in megabytes */
+ int, mem_limit /* limit of conventional memory
+ * 256, 512 or 640KB */ )
+
+{
+ short
+ pages_above_640, /* no of mappable locations */
+ pages_below_640, /* available either side of 640*/
+ EM_page_no, /* page no. within exp. memory */
+ physical_page_no; /* page no. within map region */
+ unsigned short
+ base; /* start segment of mappable */
+ /* memory below 640 KB */
+
+ int i, j; /* loop counters */
+
+
+ if (!no_phys_pages)
+ return FAILURE;
+
+ /* get space for expanded memory pages */
+
+ if(host_initialise_EM(size) != SUCCESS)
+ {
+#ifdef NTVDM
+ host_error(EG_EXPANDED_MEM_FAILURE, ERR_QU_CO, NULL);
+#endif /* NTVDM */
+ return(FAILURE);
+ }
+
+#ifdef macintosh
+ if (!handle)
+ {
+ handle = (long *)host_malloc(MAX_NO_HANDLES*sizeof(long));
+ }
+#endif /* macintosh */
+
+ /* Initialise EMM variables */
+
+#ifndef NTVDM
+ EM_start = 0xd000;
+ EM_end = 0xe000;
+#else
+ EM_start = physical_page[0];
+ EM_end = physical_page[0] + EMM_PAGE_SIZE * 4;
+#endif
+ total_pages = unallocated_pages = size * 0x100000 / EMM_PAGE_SIZE;
+
+ /* always allow max handles (Used to be 32 handles/Meg expanded mem) */
+ total_handles = MAX_NO_HANDLES;
+ total_open_handles = 0;
+ for(i = 0; i < total_handles; i++)
+ handle[i] = (long) NULL;
+
+#ifdef NTVDM
+ map_size = no_phys_pages * NSIZE;
+ page_offset = MAP_OFFSET + map_size;
+ pages_below_640 = backfill / EMM_PAGE_SIZE;
+ pages_above_640 = no_phys_pages - pages_below_640;
+
+ /* initialize active mapping register to set 0 */
+ EM_page_mapped = EM_page_mapped_array;
+ allocate_altreg_set(&active_altreg_set);
+
+ for (i = 0; i < no_phys_pages; i++)
+ EM_page_mapped[i] = (unsigned short)EMPTY;
+
+ if (get_new_handle(0) != 0)
+ return FAILURE;
+ set_no_pages(0, 0);
+#else
+
+ pages_above_640 = (effective_addr(EM_end,0) - effective_addr(EM_start,0)) / EMM_PAGE_SIZE;
+ pages_below_640 = ((640 - mem_limit) * 1024) / EMM_PAGE_SIZE;
+ no_phys_pages = pages_above_640 + pages_below_640;
+
+ map_size = no_phys_pages * NSIZE;
+ page_offset = MAP_OFFSET + map_size;
+
+ /*
+ * set up addresses and mapping status of physical pages
+ */
+ for( i = 0; i < pages_above_640; i++ )
+ {
+ physical_page[i] = EM_start + (i * EMM_PAGE_SIZE >> 4);
+ EM_page_mapped[i] = EMPTY;
+ }
+ base = mem_limit * 64;
+
+ for(i = pages_above_640, j = 0; i < no_phys_pages; i++)
+ {
+ physical_page[i] = base + (j++ * EMM_PAGE_SIZE >> 4);
+ EM_page_mapped[i] = EMPTY;
+ }
+ /*
+ * Allocate handle 0 with any pages required for back filling
+ */
+ if(get_new_handle(pages_below_640) != 0)
+ return(FAILURE);
+
+ for(i = 0, physical_page_no = pages_above_640; i < pages_below_640; i++)
+ {
+ if((EM_page_no = alloc_page()) == FAILURE)
+ return (FAILURE);
+
+ set_EMpage_no(0, i, EM_page_no);
+
+ if(map_page(EM_page_no, physical_page_no++) == FAILURE)
+ return(FAILURE);
+ }
+ set_no_pages(0, pages_below_640);
+#endif /* NTVDM */
+
+ /*
+ * Set up necessary variables in Top level EMM function code
+ */
+ reset_emm_funcs();
+
+ /*
+ ** Map the address space taken up by LIM to RAM.
+ ** Without LIM it would be ROM.
+ ** The range seems to be fixed at segment D000 to F000.
+ ** Assumed that AT's have GMI and XT's do not.
+ ** XT's can use the old fashioned memset calls in
+ ** delta:manager:init_struc.c
+ */
+#ifdef NTVDM
+ /* every physical page must be connected as RAM */
+ for (i = 0; i < pages_above_640; i++)
+ sas_connect_memory(effective_addr(physical_page[i], 0),
+ effective_addr(physical_page[i], EMM_PAGE_SIZE - 1),
+ SAS_RAM
+ );
+#else
+
+ sas_connect_memory(effective_addr(EM_start,0) , effective_addr(EM_end,0) -1 , SAS_RAM );
+#endif
+
+ sure_note_trace3(LIM_VERBOSE,"initialised EMM, total pages= %#x, pages above 640= %#x, pages below 640 = %#x",no_phys_pages, pages_above_640, pages_below_640);
+
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : free_expanded_memory
+
+PURPOSE : This routine calls frees all memory allocated for the
+ expanded memory manager and resets the variables that
+ are used by the Expanded Memory Manager(EMM).
+
+RETURNED STATUS : SUCCESS -
+
+DESCRIPTION : If total_pages = 0, this indicates that expanded
+ memory hasn't been initialised, so the routine simply
+ does nothing and returns.
+
+=========================================================================
+*/
+GLOBAL void free_expanded_memory IFN0()
+
+{
+ short handle_no;
+
+ if(total_pages == 0)
+ return;
+
+ /* free space allocated for each handle */
+
+ handle_no = 0;
+ while(total_open_handles > 0)
+ {
+ while(!handle_ok(handle_no))
+ handle_no++;
+
+ free_handle(handle_no++);
+ }
+ /*
+ * Free space for expanded memory pages
+ */
+ host_deinitialise_EM();
+
+ total_pages = 0;
+
+ return;
+}
+
+/*
+===========================================================================
+
+FUNCTION : get_new_handle()
+
+PURPOSE : Finds the next free handle no., allocates storage space
+ for recording the EMM data associated with this handle,
+ and stores the 'storage ID' in the handle array.
+
+RETURNED STATUS : SUCCESS - new handle allocated successfully
+ FAILURE - Error occurred in trying to allocate storage
+ space for handle data
+
+DESCRIPTION : see emm.h for a description of space required for
+ storing handle data e.g. PAGE_OFFSET & NSIZE
+
+
+=========================================================================
+*/
+GLOBAL short get_new_handle IFN1(short, no_pages) /* No.of pages to store in handle */
+
+{
+ short i; /* loop count */
+ short handle_no;
+ int data_size; /* no. of bytes of data storage */
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+
+ sure_note_trace2(LIM_VERBOSE,"new handle request, current total handles= %d, pages requested = %d",total_handles, no_pages);
+
+ handle_no = 0;
+
+ do
+ if (handle[handle_no] == (long) NULL)
+ break;
+ while(++handle_no < total_handles);
+
+ if(handle_no >= total_handles)
+ return(FAILURE);
+
+ data_size = page_offset + (no_pages * NSIZE);
+
+ if ((storage_ID = host_allocate_storage(data_size)) == (long) NULL)
+ return(FAILURE);
+
+ handle[handle_no] = storage_ID;
+
+ for (i=0 ; i < no_phys_pages ; i++) {
+ set_map_no(handle_no, i, FREE);
+ }
+
+ total_open_handles++;
+
+ sure_note_trace1(LIM_VERBOSE,"allocation OK, return handle=%d",handle_no);
+
+ return(handle_no);
+}
+
+/*
+===========================================================================
+
+FUNCTION : free_handle
+
+PURPOSE : frees the storage space allocated to the handle number.
+ Decrements the handles open count
+
+RETURNED STATUS : SUCCESS - space freed
+ FAILURE - unable to free space
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL int free_handle IFN1(short, handle_no) /* No.of handle to be freed */
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+
+ sure_note_trace2(LIM_VERBOSE, "free handle %d request, total handles = %d",handle_no, total_handles);
+
+ storage_ID = handle[handle_no];
+
+ if(host_free_storage(storage_ID) != SUCCESS)
+ return(FAILURE);
+
+ handle[handle_no] = (long) NULL;
+
+ total_open_handles--;
+
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : reallocate_handle
+
+PURPOSE : changes the number of pages allocated to a given handle
+
+RETURNED STATUS : SUCCESS - handle reallocated
+ FAILURE - unable to get space for new handle data
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL int reallocate_handle IFN3(short, handle_no, /* handle to be reallocated */
+ short, old_page_count,/* current pages in handle */
+ short, new_page_count)/* required pages for handle*/
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+
+ short size, /* size of handle data area */
+ new_size; /* size of new handle data area */
+
+
+ size = page_offset + (old_page_count * NSIZE);
+ new_size = page_offset + (new_page_count * NSIZE);
+ storage_ID = handle[handle_no];
+
+ sure_note_trace3(LIM_VERBOSE,"reallocate pages for handle %d, old size=%#x, new size= %#x",handle_no, size, new_size);
+
+ if((storage_ID = host_reallocate_storage(storage_ID, size, new_size)) ==
+ (long) NULL)
+ return(FAILURE);
+
+ handle[handle_no] = storage_ID;
+
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : handle_ok
+
+PURPOSE : checks to see if the handle no. is valid - this should
+ be called before every routine that uses a handle number
+ to retrieve or set data in the handle data area
+
+RETURNED STATUS : TRUE - Handle no. is valid
+ FALSE - Handle no. is invalid
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL boolean handle_ok IFN1(short, handle_no)
+
+{
+#ifdef NTVDM
+/* some *** applicaitons feed us a negtive handle number. Catch it and
+ throw it to the hell*/
+
+ if ((unsigned short)handle_no >= (unsigned short)total_handles) {
+#else
+ if(handle_no >= total_handles || handle_no < 0) {
+#endif
+
+ sure_note_trace1(LIM_VERBOSE,"invalid handle %d",handle_no);
+ return(FALSE);
+ }
+
+ if(handle[handle_no] == (long) NULL){
+ sure_note_trace1(LIM_VERBOSE,"invalid handle %d",handle_no);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+/*
+===========================================================================
+
+FUNCTION : set_no_pages
+
+PURPOSE : sets the no of pages variable in the specified handle
+
+RETURNED STATUS :
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL void set_no_pages IFN2(short, handle_no, short, no_pages)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ byte *ptr; /* pointer to storage area */
+
+ storage_ID = handle[handle_no];
+ ptr = USEBLOCK(storage_ID);
+
+ *(short *)ptr = no_pages;
+
+ FORGETBLOCK(storage_ID)
+
+ return;
+}
+
+/*
+===========================================================================
+
+FUNCTION : set_EMpage_no
+
+PURPOSE : sets Expanded Memory page that is used for the specified
+ logical page into the handle data storage area
+
+RETURNED STATUS :
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL void set_EMpage_no IFN3(short, handle_no,
+ short, logical_page_no,
+ short, EM_page_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ byte *ptr; /* pointer to storage area */
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += (page_offset +(logical_page_no * NSIZE));
+ *(short *)ptr = EM_page_no;
+
+ FORGETBLOCK(storage_ID)
+
+ return;
+}
+
+/*
+===========================================================================
+
+FUNCTION : set_map_no
+
+PURPOSE : sets Expanded Memory page number in the map section of
+ the handle data storage area
+
+RETURNED STATUS :
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL void set_map_no IFN3(short, handle_no,
+ unsigned char, physical_page_no,
+ short, EM_page_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ unsigned char *ptr; /* pointer to storage area */
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += (MAP_OFFSET +(physical_page_no * NSIZE));
+ *(short *)ptr = EM_page_no;
+
+ FORGETBLOCK(storage_ID)
+
+ return;
+}
+
+/*
+===========================================================================
+
+FUNCTION : set_name
+
+PURPOSE : writes a name into the name section of the handle data
+ storage area
+
+RETURNED STATUS :
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL void set_name IFN2(short, handle_no,
+ char *, new_name)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ unsigned char *ptr; /* pointer to storage area */
+
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += NAME_OFFSET;
+ strncpy((char *)ptr, new_name, NAME_LENGTH);
+
+ FORGETBLOCK(storage_ID)
+
+ return;
+}
+
+/*
+===========================================================================
+
+FUNCTION : get_no_pages
+
+PURPOSE : gets the number of pages assigned to the specified handle
+
+RETURNED STATUS : no of pages returned
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL short get_no_pages IFN1(short, handle_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ byte *ptr; /* pointer to storage area */
+ short no_pages; /* no. of pages in handle */
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+
+ no_pages = *(short *)ptr;
+
+ FORGETBLOCK(storage_ID)
+
+ return(no_pages);
+}
+
+/*
+===========================================================================
+
+FUNCTION : get_EMpage_no
+
+PURPOSE : returns the Expanded Memory page no. used for the
+ specified logical page in the given handle
+
+RETURNED STATUS : Expanded Memory page no. returned
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL short get_EMpage_no IFN2(short, handle_no,
+ short, logical_page_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ byte *ptr; /* pointer to storage area */
+ short EM_page_no; /* Expanded Memory page number */
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += (page_offset +(logical_page_no * NSIZE));
+ EM_page_no = *(short *)ptr;
+
+ FORGETBLOCK(storage_ID)
+
+ return(EM_page_no);
+}
+
+/*
+===========================================================================
+
+FUNCTION : get_map_no
+
+PURPOSE : returns the Expanded Memory page no. saved in the map
+ attached to the given handle
+
+RETURNED STATUS : page no. in map returned
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL short get_map_no IFN2(short, handle_no,
+ unsigned char, physical_page_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ unsigned char *ptr; /* pointer to storage area */
+ short EM_page_no; /* Expanded Memory page number */
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += (MAP_OFFSET +(physical_page_no * NSIZE));
+ EM_page_no = *(short *)ptr;
+
+ FORGETBLOCK(storage_ID)
+
+ return(EM_page_no);
+}
+
+/*
+===========================================================================
+
+FUNCTION : get_name
+
+PURPOSE : returns a pointer to the name assigned to the given handle
+
+RETURNED STATUS :
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL char *get_name IFN1(short, handle_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ unsigned char *ptr; /* pointer to storage area */
+
+ storage_ID = handle[handle_no];
+
+ ptr = USEBLOCK(storage_ID);
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += NAME_OFFSET;
+ strncpy(name, (char *)ptr, NAME_LENGTH);
+
+ FORGETBLOCK(storage_ID)
+
+ return(name);
+}
+
+/*
+===========================================================================
+
+FUNCTION : alloc_page
+
+PURPOSE : allocates a page from expanded memory
+
+RETURNED : >=0 = SUCCESS - EM page no. returned
+ <0 = FAILURE - error occured in trying to allocate page
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL short alloc_page IFN0()
+
+{
+ short EM_page_no; /* EM_page_no to be returned */
+
+
+ if ((EM_page_no = host_alloc_page()) == FAILURE)
+ return(FAILURE);
+
+ unallocated_pages--;
+
+ return(EM_page_no);
+}
+
+/*
+===========================================================================
+
+FUNCTION : free_page
+
+PURPOSE : frees a page of expanded memory for further use
+
+RETURNED : SUCCESS - page freed successfully
+ FAILURE - unable to free page
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL int free_page IFN1(short, EM_page_no)
+
+{
+
+ short physical_page_no;
+
+ if (EM_page_no > total_pages)
+ return(FAILURE);
+
+ /* Removed from mapped pages table */
+
+ for (physical_page_no=0; physical_page_no < no_phys_pages; physical_page_no++) {
+
+ if (EM_page_mapped[physical_page_no] == EM_page_no) {
+ EM_page_mapped[physical_page_no] = UNMAPPED;
+ break;
+ }
+
+ }
+
+ if (host_free_page(EM_page_no) != SUCCESS)
+ return(FAILURE);
+
+ unallocated_pages++;
+
+ return(SUCCESS);
+}
+
+#ifndef NTVDM
+/*
+========================================================================
+
+FUNCTION : page_already_mapped
+
+PURPOSE : function to determine whether a EMM page is already
+ mapped to a different physical page within intel
+ memory
+
+RETURNED : count of number of pages in addition to the page
+ passed which are mapped to the same logical page.
+ The page number of one of these mirror pages is
+ also returned via the pointer passed as an argument.
+
+DESCRIPTION :
+
+========================================================================
+*/
+
+GLOBAL ULONG
+page_already_mapped IFN2(short, EM_page_no,
+ unsigned char *, physical_page_no)
+
+{
+ unsigned char page, orig_page;
+ ULONG map_count;
+
+ map_count = 0;
+ orig_page = *physical_page_no;
+
+ for( page = 0; page < (unsigned char) no_phys_pages; page++ )
+ {
+ if ((EM_page_mapped[page] == EM_page_no) &&
+ (page != orig_page ))
+ {
+ sure_note_trace2( LIM_VERBOSE,
+ "log page %x mapped to phys page %x",
+ EM_page_no, page);
+
+ *physical_page_no = page;
+ map_count++;
+ }
+ }
+
+ return( map_count );
+}
+
+
+LOCAL VOID
+connect_MM_LIM_page IFN2( USHORT, segment, SHORT, EM_page_no )
+{
+ ULONG eff_addr;
+
+#ifdef PROD
+ UNUSED(EM_page_no);
+#endif
+
+ assert2( NO, "Connecting multi-mapped page, %d, at %x",
+ EM_page_no, segment );
+
+ eff_addr = effective_addr( segment, 0 );
+ sas_connect_memory( eff_addr, eff_addr + EMM_PAGE_SIZE - 1,
+ SAS_MM_LIM );
+}
+
+LOCAL VOID
+disconnect_MM_LIM_page IFN4( USHORT, segment, SHORT, EM_page_no,
+ ULONG, map_count, unsigned char, physical_page_no )
+{
+ ULONG eff_addr;
+
+#ifdef PROD
+ UNUSED(EM_page_no);
+#endif
+
+ sure_note_trace2(LIM_VERBOSE,
+ "Unmapping multi-mapped page, %d, at %x",
+ EM_page_no, segment );
+
+ eff_addr = effective_addr( segment, 0 );
+ sas_connect_memory( eff_addr, eff_addr + EMM_PAGE_SIZE - 1, SAS_RAM );
+
+ if( map_count == 1 )
+ {
+ /*
+ * We have to disconnect the last page of this group,
+ * by connecting it as SAS_RAM.
+ */
+
+ segment = physical_page[physical_page_no];
+ eff_addr = effective_addr( segment, 0 );
+
+ sure_note_trace2(LIM_VERBOSE,
+ "Unmapping last multi-mapped page, %d, at %x",
+ EM_page_no, segment );
+
+ sas_connect_memory( eff_addr, eff_addr + EMM_PAGE_SIZE - 1,
+ SAS_RAM );
+ }
+}
+
+#endif /* !NTVDM */
+
+/*
+========================================================================
+
+FUNCTION : map_page
+
+PURPOSE : maps a page from expanded memory into Intel physical
+ address space
+
+RETURNED : SUCCESS - page mapped successfully
+ FAILURE - unable to map page
+
+DESCRIPTION :
+
+========================================================================
+*/
+GLOBAL int map_page IFN2(short, EM_page_no,
+ unsigned char, physical_page_no)
+
+{
+ USHORT segment; /* segment address of page in */
+ /* physical address space */
+ unsigned char phys_page;
+ ULONG map_count;
+
+ segment = physical_page[physical_page_no];
+
+ /*
+ * make sure that a page is not already mapped in
+ * if it is - return it to Expanded Memory
+ */
+ sure_note_trace2(LIM_VERBOSE,
+ "map page %#x to phys page %#x",
+ EM_page_no,physical_page_no);
+
+ if(EM_page_mapped[physical_page_no] != EMPTY)
+ {
+ sure_note_trace1(LIM_VERBOSE,
+ "phys page already mapped to page %#x",
+ EM_page_mapped[physical_page_no]);
+
+ if(EM_page_mapped[physical_page_no] == EM_page_no)
+ {
+ sure_note_trace0(LIM_VERBOSE,
+ "remap of same page, so do nothing");
+
+ return(SUCCESS);
+ }
+
+#ifndef NTVDM
+ /*
+ * We want to return the current contents of this physical
+ * page to the logical page ( to sync up the logical page ).
+ * We have to check first that this physical page is not a
+ * mirror of some other page - if it is we have to disconnect
+ * it from the group of pages it is mirroring.
+ */
+
+ phys_page = physical_page_no;
+
+ if( map_count = page_already_mapped(
+ EM_page_mapped[physical_page_no], &phys_page))
+ {
+ disconnect_MM_LIM_page( segment, EM_page_no,
+ map_count, phys_page );
+ }
+
+ /*
+ * We can now unmap the physical page and indicate
+ * that it is really unmapped.
+ */
+ if(host_unmap_page(segment,
+ EM_page_mapped[physical_page_no]) != SUCCESS)
+ {
+ return(FAILURE);
+ }
+ EM_page_mapped [physical_page_no] = EMPTY;
+#endif
+
+ }
+#ifndef NTVDM
+
+ /*
+ * If this logical page is already mapped, make sure the
+ * new mapping has an up to date copy
+ */
+
+ phys_page = physical_page_no;
+
+ if (page_already_mapped(EM_page_no, &phys_page))
+ {
+ /*
+ * We now want to get the LIM logical page up to date with
+ * the physical pages that are currently mapped to it. We
+ * don't want to set EM_page_mapped [phys_page] to EMPTY
+ * after the host_unmap_page(). If we did we wouldn't notice
+ * that we had a multiply-mapped page and the patch up code
+ * wouldn't get called.
+ */
+
+ host_update_logical_page( physical_page[phys_page],
+ EM_page_no );
+
+ /*
+ * Connect new page and "mirror" page as MM_LIM. This may
+ * mean some pages get connected as MM_LIM multiple times
+ * - inefficient but not wrong otherwise. This connection
+ * has to be made for all hosts - even those that can do
+ * mapping themselves. This is to make sure that the CPU
+ * data structures associated with all pages get updated
+ * when a multi-mapped write occurs.
+ */
+
+ connect_MM_LIM_page( segment, EM_page_no );
+
+ connect_MM_LIM_page( physical_page[phys_page], EM_page_no );
+ }
+#endif
+ if(host_map_page(EM_page_no, segment) != SUCCESS)
+ return(FAILURE);
+
+ EM_page_mapped[physical_page_no] = EM_page_no;
+
+ sure_note_trace0(LIM_VERBOSE,"map OK");
+ return(SUCCESS);
+}
+
+/*
+========================================================================
+
+FUNCTION : unmap_page
+
+PURPOSE : unmaps a page from Intel physical address space back to
+ expanded memory
+
+RETURNED : SUCCESS - page unmapped successfully
+ FAILURE - error in unmapping page
+
+DESCRIPTION :
+
+========================================================================
+*/
+GLOBAL int unmap_page IFN1(unsigned char, physical_page_no)
+
+{
+ short EM_page_no; /* EM_page_no currently mapped */
+ unsigned short segment; /* segment address of page in */
+ /* physical address space */
+ SHORT phys_page;
+ ULONG map_count;
+
+ sure_note_trace1( LIM_VERBOSE,
+ "unmap phys page %#x",physical_page_no);
+
+ segment = physical_page[physical_page_no];
+
+ if((EM_page_no = EM_page_mapped[physical_page_no]) == EMPTY)
+ {
+ /*
+ * Already done
+ */
+ sure_note_trace0( LIM_VERBOSE,
+ "already unmapped, so do nothing");
+
+ return(SUCCESS);
+ }
+
+ phys_page = physical_page_no;
+
+#ifndef NTVDM
+ if( map_count = page_already_mapped( EM_page_no, (unsigned char *)&phys_page ))
+ {
+ disconnect_MM_LIM_page( segment, EM_page_no,
+ map_count, phys_page );
+ }
+#endif
+
+ if(host_unmap_page(segment, EM_page_no) != SUCCESS)
+ return(FAILURE);
+
+ EM_page_mapped[physical_page_no] = EMPTY;
+
+ sure_note_trace0(LIM_VERBOSE,"unmap OK");
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : map_saved
+
+PURPOSE : Checks to see if a map has been saved for the specified
+ handle
+
+RETURNED STATUS : TRUE - A map is saved for this handle
+ FALSE - No map has been saved
+
+DESCRIPTION : checks the first entry in the map for the value 'FREE'
+
+=========================================================================
+*/
+GLOBAL boolean map_saved IFN1(short, handle_no)
+
+{
+ long storage_ID; /* host dependant storage */
+ /* identifier, usually a ptr. */
+ unsigned char *ptr; /* pointer to storage area */
+ short status; /* value read from map */
+
+ storage_ID = handle[handle_no];
+ ptr = USEBLOCK(storage_ID);
+
+ /*
+ * offset pointer to correct position
+ */
+
+ ptr += MAP_OFFSET;
+ status = *(short *)ptr;
+
+ FORGETBLOCK(storage_ID)
+
+ return((status == FREE) ? FALSE : TRUE);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : save_map
+
+PURPOSE : takes a copy of the EM_page_mapped array and store it in
+ the map section of the handle data storage area
+
+RETURNED STATUS : SUCCESS - everything OK
+ FAILURE - invalid segment no. passed in src array
+
+DESCRIPTION : if handle_no is >= 0 the map is stored in the data area
+ assigned to that handle
+ if handle_no == -1 the map is stored in the array pointed
+ to by dst_segment:dst_offset
+ if handle_no == -2 only the pages specified by the segment
+ addresses in the src array (pointed to by
+ src_segment:src_offset) are saved in the dst array
+ (pointed to by dst_segment:dst_offset).
+
+=========================================================================
+*/
+GLOBAL int save_map IFN5(short, handle_no,
+ unsigned short, dst_segment,
+ unsigned short, dst_offset,
+ unsigned short, src_segment,
+ unsigned short, src_offset)
+
+{
+ unsigned short offset, /* temp offset variable */
+ segment; /* segment address to be saved */
+ short i, /* loop counter */
+ page_no, /* physical page no. */
+ no_to_save; /* no of pages in src array */
+
+ if(handle_no >= 0)
+ for (i = 0; i < no_phys_pages; i++)
+ set_map_no(handle_no, i, EM_page_mapped[i]);
+
+ else if(handle_no == -1)
+ for(i = 0; i < no_phys_pages; i++)
+ {
+ write_intel_word(dst_segment, dst_offset, EM_page_mapped[i]);
+ dst_offset +=2;
+ }
+
+ else if(handle_no == -2)
+ {
+ offset = dst_offset;
+ for(i = 0; i < no_phys_pages; i++)
+ {
+#ifdef NTVDM
+ write_intel_word(dst_segment, offset, LEAVE);
+#else
+ write_intel_word(dst_segment, offset, EMPTY);
+#endif
+ offset += 2;
+ }
+ read_intel_word(src_segment, src_offset, (word *)&no_to_save);
+ for (i = 0; i < no_to_save; i++)
+ {
+ src_offset += 2;
+ read_intel_word(src_segment, src_offset, &segment);
+ /*
+ * Find Physical page no.
+ */
+ page_no = 0;
+ do
+ if(segment == physical_page[page_no])
+ break;
+ while(++page_no < no_phys_pages);
+
+ if(page_no >= no_phys_pages)
+ return (FAILURE);
+ /*
+ * Save EM page number in destination array
+ */
+ offset = dst_offset + (page_no * 2);
+ write_intel_word(dst_segment, offset, EM_page_mapped[page_no]);
+ }
+ }
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : restore_map
+
+PURPOSE : reads the specified map and returns 2 arrays specifying
+ which pages have to be mapped out and which ones have to be
+ mapped in
+
+RETURNED STATUS : SUCCESS - Map read successfully
+
+
+DESCRIPTION : A +ve handle number indicates that the map is stored
+ within the handle data area.
+ If the handle number is -ve the map will be read from the
+ data pointed to by segment:offset
+
+ Only page out - if there is a page currently mapped in and
+ it is not being replaced by a copy of itself or an empty
+ page
+ Only page in - if new page is different to existing one
+ and it is not empty
+
+=========================================================================
+*/
+#ifdef ANSI
+GLOBAL int restore_map (short handle_no,
+ unsigned short segment,
+ unsigned short offset,
+ short pages_out[],
+ short pages_in[])
+#else
+GLOBAL int restore_map (handle_no, segment, offset, pages_out, pages_in)
+short handle_no;
+unsigned short segment;
+unsigned short offset;
+short pages_out[];
+short pages_in[];
+#endif /* ANSI */
+{
+ short i, /* loop counter */
+ new_page, /* page number read from map */
+ old_page; /* existing page number */
+
+ for(i = 0; i < no_phys_pages; i++)
+ {
+ if(handle_no >= 0)
+ new_page = get_map_no(handle_no, i);
+ else
+ {
+ read_intel_word(segment, offset, (word *)&new_page);
+ offset += 2;
+#ifdef NTVDM
+ if(new_page < LEAVE || new_page >= total_pages)
+#else
+ if(new_page < EMPTY || new_page >= total_pages)
+#endif /* NTVDM */
+ return(FAILURE);
+ }
+ old_page = EM_page_mapped[i];
+
+/*
+ if(old_page != EMPTY && new_page != EMPTY && old_page != new_page )
+*/
+/* need to do unmap to empty state case to update the page copy in the LIM
+ space in case of new maps of that page to other LIM slots. */
+#ifdef NTVDM
+ if(old_page != EMPTY && old_page != new_page && new_page != LEAVE)
+#else
+ if(old_page != EMPTY && old_page != new_page )
+#endif
+ pages_out[i] = old_page;
+ else
+ pages_out[i] = EMPTY;
+
+#ifdef NTVDM
+ if(new_page != EMPTY && new_page != old_page && new_page != LEAVE)
+#else
+ if(new_page != EMPTY && new_page != old_page)
+#endif
+ pages_in[i] = new_page;
+ else
+ pages_in[i] = EMPTY;
+ }
+ if(handle_no >= 0)
+ set_map_no(handle_no, 0, FREE);
+
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : copy_exchange_data
+
+PURPOSE : copies or exchanges data between conventional and
+ expanded memory
+
+RETURNED STATUS : SUCCESS - everything ok
+ FAILURE - Error ocurred in copying data
+
+DESCRIPTION : type - uses a bit pattern, bit 0 represents destination,
+ bit 1 represents source, a set bit means expanded, a clear
+ bit means conventional memory
+ bit 2 represents exchange if set or move if it is clear
+
+ e.g. 0 (0000) = move conventional to conventional
+ 1 (0001) = move conventional to expanded
+ 6 (0110) = exchange expanded to conventional
+ 7 (0111) = exchange expanded to expanded
+
+=========================================================================
+*/
+GLOBAL int copy_exchange_data IFN8(unsigned char, type,
+ short, src_handle,
+ unsigned short, src_seg_page,
+ unsigned short, src_offset,
+ short, dst_handle,
+ unsigned short, dst_seg_page,
+ unsigned short, dst_offset,
+ unsigned long, length)
+
+{
+ short dst_EMpage, /* EM page no . of destination */
+ src_EMpage; /* EM page no. of source */
+ int page_no; /* phys. page no. of mapped page*/
+
+ /*
+ * First check to see if the expanded memory page is mapped
+ * if it is - change the type to deal directly with the
+ * physical page that it is mapped to
+ */
+ if( type & 1)
+ {
+ dst_EMpage = get_EMpage_no(dst_handle, dst_seg_page);
+ if((page_no = page_status(dst_EMpage)) != UNMAPPED )
+ {
+ dst_seg_page = physical_page[page_no];
+ type &= 6;
+ }
+ }
+ if( type & 2)
+ {
+ src_EMpage = get_EMpage_no(src_handle, src_seg_page);
+ if((page_no = page_status(src_EMpage)) != UNMAPPED )
+ {
+ src_seg_page = physical_page[page_no];
+ type &= 5;
+ }
+ }
+
+ switch(type)
+ {
+ case 0: if(host_copy_con_to_con(length, src_seg_page, src_offset,
+ dst_seg_page, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 1: if(host_copy_con_to_EM(length, src_seg_page, src_offset,
+ dst_EMpage, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 2: if(host_copy_EM_to_con(length, src_EMpage, src_offset,
+ dst_seg_page, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 3: if(host_copy_EM_to_EM(length, src_EMpage, src_offset,
+ dst_EMpage, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 4: if(host_exchg_con_to_con(length, src_seg_page, src_offset,
+ dst_seg_page, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 5: if(host_exchg_con_to_EM(length, src_seg_page, src_offset,
+ dst_EMpage, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 6: if(host_exchg_con_to_EM(length, dst_seg_page, dst_offset,
+ src_EMpage, src_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ case 7: if(host_exchg_EM_to_EM(length, src_EMpage, src_offset,
+ dst_EMpage, dst_offset) != SUCCESS)
+ return(FAILURE);
+ break;
+
+ default: return(FAILURE);
+ }
+ return(SUCCESS);
+}
+
+/*
+========================================================================
+
+FUNCTION : page_status
+
+PURPOSE : checks if a particular EM page is mapped or not
+
+RETURNED STATUS : page_no - physical page no returned if mapped
+ UNMAPPED - returned if not mapped
+
+DESCRIPTION :
+
+========================================================================
+*/
+
+GLOBAL int page_status IFN1(short, EMpage_no)
+{
+ short physical_page_no = 0;
+ /* position of page in physical memory */
+
+ do
+ if(EM_page_mapped[physical_page_no] == EMpage_no)
+ break;
+ while(++physical_page_no < no_phys_pages );
+
+ if(physical_page_no >= no_phys_pages)
+ return(UNMAPPED);
+ else
+ return(physical_page_no);
+}
+
+/*
+========================================================================
+
+FUNCTION : phys_page_from_addr
+
+PURPOSE : determines the physical page number of a LIM page
+ from its Intel address.
+
+RETURNED STATUS : The physical page containing the LIM address.
+
+DESCRIPTION :
+
+=======================================================================
+*/
+
+LOCAL SHORT
+phys_page_from_addr IFN1( sys_addr, address )
+
+{
+ sys_addr start;
+
+ start = effective_addr( EM_start, 0x0 );
+
+ return( (ULONG)(( address - start ) / EMM_PAGE_SIZE ));
+}
+
+/*
+========================================================================
+
+FUNCTION : get_total_pages
+ get_unallocated_pages
+ get_base_address
+ get_total_handles
+ get_total_open_handles
+ get_no_phys_pages
+ get_page_seg
+ get_map_size
+
+PURPOSE : simply returns the reqested variables, to avoid
+ having to use globals
+
+
+RETURNED STATUS : the following variables are returned , depending upon
+ the routine called:-
+ total_pages
+ unallocated_pages
+ base_address
+ total_handles
+ total_open_handles
+ no_phys_pages
+ physical_page[i]
+ map_size
+
+DESCRIPTION :
+
+========================================================================
+*/
+
+#ifdef SEGMENTATION
+/*
+ * The following #include specifies the code segment into which this
+ * module will by placed by the MPW C compiler on the Mac II running
+ * MultiFinder.
+ */
+#include "SOFTPC_LIM2.seg"
+#endif
+
+GLOBAL short get_total_pages IFN0()
+{
+ return(total_pages);
+}
+
+#ifdef SEGMENTATION
+/*
+ * The following #include specifies the code segment into which this
+ * module will by placed by the MPW C compiler on the Mac II running
+ * MultiFinder.
+ */
+#include "SOFTPC_LIM.seg"
+#endif
+
+GLOBAL short get_unallocated_pages IFN0()
+{
+ return(unallocated_pages);
+}
+
+GLOBAL unsigned short get_base_address IFN0()
+{
+#ifdef NTVDM
+ return(physical_page[0]);
+#else
+ return(EM_start);
+#endif
+}
+
+GLOBAL short get_total_handles IFN0()
+{
+ return(total_handles);
+}
+
+GLOBAL short get_total_open_handles IFN0()
+{
+ return(total_open_handles);
+}
+
+GLOBAL short get_no_phys_pages IFN0()
+{
+ return(no_phys_pages);
+}
+
+GLOBAL unsigned short get_page_seg IFN1(unsigned char, page_no)
+{
+ return(physical_page[page_no]);
+}
+
+GLOBAL short get_map_size IFN0()
+{
+ return(map_size);
+}
+
+#ifdef NTVDM
+GLOBAL short get_segment_page_no(unsigned short segment)
+{
+#if defined(LARGE_FRAME) && !defined(MONITOR)
+ short i
+ for (i = 0; i < no_phys_pages; i++)
+ if (physical_page[i] == segment)
+ break;
+ return(i);
+#else
+ return((segment - physical_page[0]) / EMM_PAGE_SIZE);
+#endif
+
+}
+GLOBAL unsigned short get_no_altreg_sets(void)
+{
+ return(no_altreg_sets);
+}
+
+GLOBAL unsigned short get_active_altreg_set(void)
+{
+ return(active_altreg_set);
+}
+
+GLOBAL boolean altreg_set_ok(unsigned short set)
+{
+ return(set < no_altreg_sets &&
+ (altreg_alloc_mask[set >> 3] & (1 << (set & 0x07))));
+
+}
+
+#if defined (NTVDM) && defined(MONITOR) && !defined(PROD)
+/* these functions are provided for monitor to verify that
+ * it has the same definitions of EMM_PAGE_SIZE and INTEL_PAGE_SIZE as
+ * ours.
+ */
+
+GLOBAL unsigned short get_emm_page_size(void)
+{
+ return ((unsigned short)EMM_PAGE_SIZE);
+}
+GLOBAL unsigned short get_intel_page_size(void)
+{
+ return ((unsigned short) INTEL_PAGE_SIZE);
+}
+#endif
+
+/* allocate a free alt mapping register set */
+
+GLOBAL boolean allocate_altreg_set(unsigned short *altreg_set)
+{
+ short byte_offset, bit_offset;
+ short *page_mapped_ptr;
+ IU8 mask;
+ int i;
+ /* this check is very important because we ** probably ** have
+ * several unused bits in the allocation mask array
+ */
+ if (free_altreg_sets == 0)
+ return (FALSE);
+
+ /* use quick and dirty way to allocate a set */
+ if (next_free_altreg_set < no_altreg_sets) {
+ altreg_alloc_mask[next_free_altreg_set >> 3] |=
+ (0x1 << (next_free_altreg_set & 0x07));
+ *altreg_set = next_free_altreg_set++;
+ }
+ else {
+ for (byte_offset = 0; byte_offset < no_altreg_sets; byte_offset++) {
+ if (altreg_alloc_mask[byte_offset] != 0xFF) {
+ mask = altreg_alloc_mask[byte_offset];
+ bit_offset = 0;
+ while (mask & (1 << bit_offset))
+ bit_offset++;
+ break;
+ }
+ }
+ altreg_alloc_mask[byte_offset] |= (1 << bit_offset);
+ *altreg_set = byte_offset * 8 + bit_offset;
+ }
+ /* a new alt reg set is just allocated, initialize its
+ * mapping register to the current active set
+ */
+ page_mapped_ptr = GET_EM_PAGE_MAPPED_PTR(*altreg_set);
+ for (i = 0; i < no_phys_pages; i++)
+ page_mapped_ptr[i] = EM_page_mapped[i];
+ return TRUE;
+}
+/* free the given alt mapping register set */
+GLOBAL boolean deallocate_altreg_set(short set)
+{
+
+ /* can not deallocate set 0 or active set */
+ if (set != 0 && set != active_altreg_set && set < no_altreg_sets &&
+ altreg_alloc_mask[set >> 3] & (1 << (set &0x07))) {
+
+ altreg_alloc_mask[set >> 3] &= (0xFE << (set & 0x07));
+ free_altreg_sets++;
+ if (free_altreg_sets == (no_altreg_sets - 1))
+ next_free_altreg_set = 1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* This function activate the given alt mapping register set
+ * input: alt reg set to be activated.
+ * output: TRUE if the given set is activated.
+ * FALSE if the given set is not activated.
+ */
+
+GLOBAL boolean activate_altreg_set(unsigned short set, short * page_in)
+{
+ int i;
+ short * page_out, *page_in_ptr;
+ short new_page, old_page, segment;
+
+
+ if (active_altreg_set == set && page_in == NULL)
+ return TRUE;
+
+ /* get the mapping array to be mapped in*/
+ page_in_ptr = GET_EM_PAGE_MAPPED_PTR(set);
+
+ /* if no page-in override, use the altreg set current mapping */
+ if (page_in == NULL)
+ page_in = page_in_ptr;
+
+ /* the active altreg is being paged out */
+ page_out = GET_EM_PAGE_MAPPED_PTR(active_altreg_set);
+ for ( i = 0; i < no_phys_pages; i++) {
+ new_page = page_in[i];
+ old_page = page_out[i];
+ segment = physical_page[i];
+
+ if (old_page != EMPTY && old_page != new_page) {
+ if (host_unmap_page(segment, old_page) != SUCCESS)
+ return FALSE;
+ }
+ if(new_page != EMPTY && new_page != old_page) {
+ if (host_map_page(new_page, segment) != SUCCESS)
+ return FALSE;
+ }
+ /* update the active-to-be set mapping */
+ page_in_ptr[i] = new_page;
+ }
+ active_altreg_set = set;
+ EM_page_mapped = page_in_ptr;
+ return TRUE;
+}
+#endif /* NTVDM */
+
+#ifndef NTVDM
+
+/*
+========================================================================
+
+FUNCTION : LIM_b_write,
+ LIM_w_write,
+ LIM_str_write
+ patch_pages
+
+PURPOSE : LIM byte, word & string - called from write check
+ failure code in the CPU when a write to a multi-mapped
+ LIM page is detected.
+ patch_pages - generic code called from the other
+ three routines.
+
+RETURNED STATUS : None.
+
+DESCRIPTION :
+
+========================================================================
+*/
+
+LOCAL VOID
+patch_one_page_partial IFN4( sys_addr, intel_addr, sys_addr, eff_addr,
+ MM_LIM_op_type, type, ULONG, data )
+
+{
+ ULONG check_len;
+
+ UNUSED( intel_addr ); /* Used in patch_one_page_full() */
+
+ switch( type )
+ {
+ case BYTE_OP:
+ check_len = 1;
+ break;
+
+ case WORD_OP:
+ check_len = 2;
+ break;
+
+ case STR_OP:
+ check_len = data;
+ break;
+ }
+
+ sas_overwrite_memory( eff_addr, check_len );
+}
+
+LOCAL VOID
+patch_one_page_full IFN4( sys_addr, intel_addr, sys_addr, eff_addr,
+ MM_LIM_op_type, type, ULONG, data )
+
+{
+ sys_addr check_addr;
+ ULONG check_len;
+
+ switch( type )
+ {
+ case BYTE_OP:
+ check_addr = eff_addr;
+ check_len = 1;
+ sas_store_no_check( eff_addr, data );
+ break;
+
+ case WORD_OP:
+ check_addr = eff_addr;
+ check_len = 2;
+ sas_storew_no_check( eff_addr, data );
+ break;
+
+ case STR_OP:
+ check_addr = eff_addr;
+ check_len = data;
+ do
+ {
+ sas_store_no_check( eff_addr,
+ sas_hw_at_no_check(
+ intel_addr ));
+ intel_addr++;
+ eff_addr++;
+ }
+ while( --data );
+ break;
+ }
+
+ sas_overwrite_memory( check_addr, check_len );
+}
+
+LOCAL VOID
+patch_pages IFN6( MM_LIM_op_type, type, ULONG, offset,
+ SHORT, EM_page_no, SHORT, phys_page_no,
+ ULONG, data, sys_addr, intel_addr )
+
+{
+ LONG cnt01;
+ sys_addr eff_addr;
+
+ for( cnt01 = 0; cnt01 < get_no_phys_pages(); cnt01++ )
+ {
+ if(( EM_page_mapped[cnt01] == EM_page_no ) &&
+ ( cnt01 != phys_page_no ))
+ {
+ eff_addr = effective_addr( get_page_seg(cnt01),
+ offset );
+
+ host_patch_one_page( intel_addr, eff_addr, type, data );
+
+ sure_note_trace1(LIM_VERBOSE,
+ "MM LIM write type %d", type );
+ sure_note_trace2(LIM_VERBOSE,
+ "log page 0x%x, phs page 0x%x",
+ EM_page_no, cnt01 );
+ }
+ }
+}
+
+GLOBAL VOID
+LIM_b_write IFN1( sys_addr, intel_addr )
+
+{
+ ULONG limdata;
+ SHORT EM_page_no, phys_page_no;
+ word offset;
+
+ phys_page_no = phys_page_from_addr( intel_addr );
+
+ offset = intel_addr -
+ effective_addr( get_page_seg(phys_page_no), 0x0 );
+
+ EM_page_no = EM_page_mapped[phys_page_no];
+
+ /*
+ * Get the data written in order to patch up this
+ * page's buddy pages.
+ */
+
+ limdata = (ULONG) sas_hw_at_no_check( intel_addr );
+ patch_pages( BYTE_OP, offset, EM_page_no, phys_page_no,
+ limdata, intel_addr );
+
+ /*
+ * Tell the CPU that this page has been written to.
+ */
+
+ sas_overwrite_memory( intel_addr, 1 );
+}
+
+GLOBAL VOID
+LIM_w_write IFN1( sys_addr, intel_addr )
+
+{
+ ULONG limdata;
+ SHORT EM_page_no, phys_page_no;
+ word offset;
+
+ phys_page_no = phys_page_from_addr( intel_addr );
+
+ offset = intel_addr -
+ effective_addr( get_page_seg(phys_page_no), 0x0 );
+
+ EM_page_no = EM_page_mapped[phys_page_no];
+
+ limdata = (ULONG) sas_w_at_no_check( intel_addr );
+ patch_pages( WORD_OP, offset, EM_page_no, phys_page_no,
+ limdata, intel_addr );
+
+ sas_overwrite_memory( intel_addr, 2 );
+}
+
+GLOBAL VOID
+LIM_str_write IFN2( sys_addr, intel_addr, ULONG, length )
+
+{
+ SHORT EM_page_no, phys_page_no;
+ word offset;
+
+ phys_page_no = phys_page_from_addr( intel_addr );
+
+ offset = intel_addr -
+ effective_addr( get_page_seg(phys_page_no), 0x0 );
+
+ EM_page_no = EM_page_mapped[phys_page_no];
+
+ patch_pages( STR_OP, offset, EM_page_no, phys_page_no,
+ length, intel_addr );
+
+ sas_overwrite_memory( intel_addr, length );
+}
+#endif /* !NTVDM */
+
+#ifndef PROD
+/*
+===========================================================================
+
+FUNCTION : print_handle_data
+
+PURPOSE : used for debugging only - prints all the data stored
+ for a given handle
+
+RETURNED STATUS : none
+
+DESCRIPTION :
+
+=========================================================================
+*/
+GLOBAL void print_handle_data IFN1(short, handle_no)
+
+{
+ long storage_ID;
+ byte *ptr;
+ short no_pages, i;
+ char *name_ptr;
+ short *map_ptr;
+ short *page_ptr;
+
+ if ((storage_ID = handle[handle_no]) == 0)
+ {
+ printf("Unassigned handle - No. %d\n",handle_no);
+ return;
+ }
+ ptr = USEBLOCK(storage_ID);
+ name_ptr = (char *)ptr + NAME_OFFSET;
+ map_ptr = (short *)(ptr + MAP_OFFSET);
+ page_ptr = (short *)(ptr + page_offset);
+
+ no_pages = *(short *)ptr;
+ printf("Handle No. %d\n",handle_no);
+ printf("No. of Pages = %d\n",no_pages);
+ printf("Name = '");
+ for(i=0;i<8;i++)
+ printf("%c",*name_ptr++);
+ printf("'\n");
+ printf("Map = ");
+ for(i=0;i<no_phys_pages;i++)
+ printf(" %d",*map_ptr++);
+ printf("\n");
+ for(i=0;i<no_pages;i++)
+ printf("Page (%d) = %d\n",i,*page_ptr++);
+
+ FORGETBLOCK(storage_ID);
+
+ return;
+}
+#endif /* !PROD */
+#endif /* LIM */
diff --git a/private/mvdm/softpc.new/base/dos/makefile b/private/mvdm/softpc.new/base/dos/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/mvdm/softpc.new/base/dos/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/mvdm/softpc.new/base/dos/sources b/private/mvdm/softpc.new/base/dos/sources
new file mode 100644
index 000000000..fab270e4b
--- /dev/null
+++ b/private/mvdm/softpc.new/base/dos/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+
+MAJORCOMP=spcbase
+MINORCOMP=dos
+
+TARGETNAME=dos
+
+TARGETPATH=obj
+
+
+NTPROFILEINPUT=yes
+
+# Pick one of the following and delete the others
+TARGETTYPE=LIBRARY
+
+
+TARGETLIBS=
+
+SOFTPC_TREE=$(BASEDIR)\private\mvdm\softpc.new
+
+INCLUDES=$(SOFTPC_TREE)\host\inc;$(SOFTPC_TREE)\base\inc
+
+!IF $(ALPHA)
+GPSIZE=0
+!ELSE
+GPSIZE=0
+!ENDIF
+
+
+
+SOURCES=emm_mngr.c
+
+!INCLUDE $(SOFTPC_TREE)\obj.vdm\CDEFINE.INC
+
+UMTYPE=console