/*****************************************************************************
**
**  Name: mapcli.c
**
**  Description: This is the cli inteface code for simple version of the
**      Map Server
**
**  Status: PRELIMINARY
**
**  $Log:   S:/tbird/mt2_186/map/mapcli.c_v  $
** 
**    Rev 1.2   18 Apr 1997 09:30:58   Judy
** 
**    Rev 1.1   26 Feb 1997 11:35:16   Judy
** No change.
** 
**    Rev 1.0   16 Dec 1996 14:09:24   Judy
** Initial revision.
** 
**    Rev 1.42   13 Oct 1994 11:06:44   dennis
** Added support for Save/Restore of Chip Select info for 386ex.
** 
**    Rev 1.41   10 Oct 1994 10:12:20   steve
** removed temp file, ~MAPTEMP.~AP, after restoring map settings.   --- kevin
** 
**    Rev 1.40   06 Oct 1994 10:55:02   ernie
** Restored PowerPack Intel space support.
** 
**    Rev 1.39   30 Sep 1994 13:54:40   steve
** disable space option
** 
**    Rev 1.38   07 Sep 1994 10:23:10   roy
** new fix from kevin
** 
**    Rev 1.37   10 Jun 1994 11:01:52   joyce
** Kevin modified:
** 1. All addresses are created or converted to PHYSICAL addresses instead of
**    VIRTUAL.
** 2. Fix a bug in parser; set offset2Flag TRUE when there is the 2nd address
**    offset.
** 
**    Rev 1.36   02 Jun 1994 15:45:12   steve
** Kevin's changes for pv 2.2 beta 386 build 3
** 
**    Rev 1.35   24 May 1994 07:47:46   tom
** Merged 1.34.2.1 onto trunk (Note:  1.34.1.2 still on branch).
** 
**    Rev 1.34.2.1   19 May 1994 17:00:28   tom
** Removed unused SPACE_TYPE declaration.
** 
**    Rev 1.34.2.0   19 May 1994 10:45:38   tom
** 5/18/94 PDL changes merged with 1.34 PV 2.2.
** 
**    Rev 1.34   22 Apr 1994 12:25:04   john
** Added SIM_VALID sd member
** 
**    Rev 1.33   20 Apr 1994 13:55:50   marilyn
** Updated to use AdrCreateAddressFromText interface for cli commands.
** 
**    Rev 1.32   24 Mar 1994 09:18:26   ernie
** 1. Changed 330 to use the same savecs table as 340.  It uses the same
**    registers in configcs, so the same ones must be saved.
** 2. Changed behavior of savecs and restorecs when MBAR is invalid.
**    Now a warning is issued when MBAR is invalid and no other registers
**    are processed.
** 
**    Rev 1.31   03 Mar 1994 11:10:36   john
** Added port A to the 340 save/restore table
** 
**    Rev 1.30   17 Dec 1993 13:06:58   ernie
** Fixed several bugs in savecs/restorecs functions:
** 1. Corrected byte swapping problems in the MBAR register.  This was
**    causing savecs and restorecs to read/write the wrong memory location,
**    resulting in unterminated memory cycles in some targets.
** 2. Changed byte swapping to use functions in memory server.
** 3. Changed savecs to get register values from the SIM referenced by
**    the current contents of MBAR instead of the simAddress shared data
**    member.  This will correctly save the chip selects even if no configcs
**    command was used.
** 
**    Rev 1.29.1.1   19 May 1994 10:25:10   tom
** 5/18/94 changes from PDL.
** 
**    Rev 1.31   4 Mar 1994 1:28:21   kevin
** Added saveMap/restoreMap routines
**
**    Rev 1.30   2 Mar 1994 9:41:33   kevin
** Modified the syntax of map shell command
**
**    Rev 1.29   20 Jul 1993 14:29:54   ernie
** Added 68HC16Y1 and 68360 capability to save/restore cs
** 
**    Rev 1.28   16 Jul 1993 11:51:34   ernie
** Removed error.h include.  All errors now in errcodec.h
** 
**    Rev 1.27   15 Jul 1993 16:38:10   ernie
** Added restoreCS capability for PowerScope
** 
**    Rev 1.26   13 Jul 1993 11:14:32   tom
** Added MapSaveCS, MapRestoreCS, and MapConfigCS entrypoints.
** 
**    Rev 1.25   13 Jul 1993 08:24:08   doug
** Use generic syntax error.
** 
**    Rev 1.24   09 Jun 1993 13:25:08   ron
** added _SH variants of processor types in MapCliSaveCs (corresponding to
** _TB types).
** 
**    Rev 1.23   25 May 1993 11:54:16   ernie
** Streamlined MapCliSaveCs()
** 
**    Rev 1.22   19 Apr 1993 10:21:52   ernie
** 1. Added F333 processor support.
** 2. Changed logic in restoreChipSelects() when the MBAR is marked
**    invalid.  This is not really an error since this is the power-on
**    state of the chip.  If the MBAR is invalid, the rest of the registers
**    are simply not written.
** 
**    Rev 1.21   16 Apr 1993 15:30:32   doug
** Mindy's save/restore CS changes
** 
**    Rev 1.20.1.1   11 Feb 1993 13:27:48   john
** Coded the 330/340 saveCS routines
** 
**    Rev 1.20.1.0   11 Feb 1993 10:24:48   john
** No change.
**
**    Rev 1.20   15 Dec 1992 13:05:44   ernie
** Converted to new Sized memory access calls
** 
**    Rev 1.19   02 Dec 1992 15:24:20   doug
** MemRead returns buffer even if error reported; free memory
** 
**    Rev 1.18   04 Nov 1992 15:22:26   john
** Changed map display back to old style.  This more closely matches
** what is displayed by the map presenter.
** Changed the algorithm for calculating the memory block size being set
** from the cli.
** 
**    Rev 1.17   02 Nov 1992 04:26:56   brucea
** Shorted: function names
** Fixed: bugs in RestoreChipSelects
** Added: saving write verify state, turn off write verifies before putting
**   values into registers, then restore state
** Fixed: cleanup code
** 
**    Rev 1.16   23 Oct 1992 21:21:40   brucea
** Added: chip select functions:
**    MapCliConfigEmuToChipSelectReg
**    MapCliSaveChipSelectRegisters
**    MapCliRestoreChipSelectRegisters
** Removed: local memory macros and put windows calls into SendCliMessage
** 
**
**    Rev 1.15   18 Aug 1992 10:41:08   john
** Modified map block display to be more consistent
** 
**    Rev 1.14   13 Aug 1992 11:44:54   john
** Fixed compile warnings
** 
**    Rev 1.13   12 Aug 1992 09:37:44   john
** Fixed a bug in setting the starting address and block size when
** specifying address ranges.
** Improved the error handling for some of the cli commands.
** 
**    Rev 1.12   08 Aug 1992 12:24:26   tom
** CLI Registration changes.
** 
**    Rev 1.11   05 Aug 1992 16:09:14   john
** fixed boolean error in cli parser
** 
**    Rev 1.10   04 Aug 1992 15:56:18   john
** Added code to prevent access to the map if no mem present
** 
**    Rev 1.9   31 Jul 1992 16:46:40   john
** 1.  Now using map.c's mapBlockSize, mapBlockGran, etc due to changes
** made to the function calls that supplied this info.  The functions
** were changed to allow actor to properly use them.
** 2.  Fixed block size and access rights bugs in the cli parser case 3:
** 
**    Rev 1.8   29 Jul 1992 13:55:04   john
** Made display map code only try to display NUM_MAP_BLOCKS entries.
** MapSet expects blocksize to be an ending address.  It then calculates 
** the actual blocksize.  The default blocksize is now set according to
** this behavior.
** 
**    Rev 1.7   27 Jul 1992 13:37:00   john
** Rewrote the code to display the map.  It now displays the blocks in 
** address order.
** Rewrote and completed the full cli syntax for mapping memory.
** 
**    Rev 1.6   22 Jul 1992 14:49:22   doug
** fixed minor bugs
** 
**    Rev 1.5   22 Jul 1992 12:32:12   john
** Added shared data template
** 
**    Rev 1.4   22 Jul 1992 10:42:20   john
** Modified the cli parsing to handle mapping multiple map blocks of 
** arbitrary size.  I have not completed this work.
** 
**    Rev 1.3   14 May 1992 15:30:30   courtney
** Clean up error returns; took out ADDR_BUF_SZ definition.
** 
**    Rev 1.2   08 May 1992 12:03:30   tom
** Must use SendMessage, not PostMessage, for CLI registration.
** 
**    Rev 1.1   27 Feb 1992 15:27:16   doug
** Simple map CLI
** 
**    Rev 1.0   23 Jan 1992 16:06:36   doug
** Initial revision.
** 
>>>>>>>>>>  mapcli.c  Rev 1.29.1.1
**  $Header:   S:/tbird/mt2_186/map/mapcli.c_v   1.2   18 Apr 1997 09:30:58   Judy  $
<<<<<<<<<<  mapcli.c  Rev 1.34
**  $Header:   S:/tbird/mt2_186/map/mapcli.c_v   1.2   18 Apr 1997 09:30:58   Judy  $
==========
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
******************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#ifndef _ADDR_
#include "addr.h"
#endif

#ifndef _CLISRV_
#include "clisrv.h"
#endif

#ifndef __CTYPE_H
#include "ctype.h"
#endif

#ifndef _MAP_
#include "map.h"
#endif

#ifndef _MAPCLI_
#include "mapcli.h"
#endif

#ifndef _MAPERR_
#include "maperr.h"
#endif

#ifndef _PROC_
#include "proc.h"
#endif

#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif

#ifndef _SSHARED_
#include "sshared.h"
#endif

#ifndef _SDPROBE_
#include "sdprobe.h"
#endif

#ifndef _SDTEMPL_
#include "sdtempl.h"
#endif

#ifndef __STDIO_H
#include "stdio.h"
#endif

#ifndef __STDLIB_H
#include "stdlib.h"
#endif

#ifndef __STRING_H
#include "string.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _MAPDLG_
#include "mapdlg.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

PRIVATE HANDLE cliServerHandle = (HANDLE)NULL;  /* force definition here */

/* 330/340 CS definitions */
#define MBAR_REGISTER_ADDRESS 0x3FF00L

typedef struct {
   S8 regName[8];
   BOOLEAN VIR;         // Very Important Register - only MBAR for 340/330
   U32 offset;          // for VIR it's the address.
   U16 size;
   BOOLEAN restoreFound;
   U32 restoreValue;
} MAP_REGISTERS;

PRIVATE MAP_REGISTERS table340[] = {
   {"MBAR",TRUE,MBAR_REGISTER_ADDRESS,4,FALSE,0L},
   {"CS0MASK",FALSE,0x40L,4,FALSE,0L},
   {"CS0BASE",FALSE,0x44L,4,FALSE,0L},
   {"CS1MASK",FALSE,0x48L,4,FALSE,0L},
   {"CS1BASE",FALSE,0x4CL,4,FALSE,0L},
   {"CS2MASK",FALSE,0x50L,4,FALSE,0L},
   {"CS2BASE",FALSE,0x54L,4,FALSE,0L},
   {"CS3MASK",FALSE,0x58L,4,FALSE,0L},
   {"CS3BASE",FALSE,0x5CL,4,FALSE,0L},
   {"MCR",FALSE,0x0L,2,FALSE,0L},
   {"PPARB",FALSE,0x1FL,1,FALSE,0L},
   {"PPARA1",FALSE,0x15L,1,FALSE,0L},
   {"PPARA2",FALSE,0x17L,1,FALSE,0L},
   {""}
};

PRIVATE MAP_REGISTERS table360[] = {
   {"MBAR",TRUE,MBAR_REGISTER_ADDRESS,4,FALSE,0L},
   {"GMR",    FALSE,0x1040L,4,FALSE,0L},
   {"MSTAT",  FALSE,0x1044L,2,FALSE,0L},
   {"BR0",    FALSE,0x1050L,4,FALSE,0L},
   {"OR0",    FALSE,0x1054L,4,FALSE,0L},
   {"BR1",    FALSE,0x1060L,4,FALSE,0L},
   {"OR1",    FALSE,0x1064L,4,FALSE,0L},
   {"BR2",    FALSE,0x1070L,4,FALSE,0L},
   {"OR2",    FALSE,0x1074L,4,FALSE,0L},
   {"BR3",    FALSE,0x1080L,4,FALSE,0L},
   {"OR3",    FALSE,0x1084L,4,FALSE,0L},
   {"BR4",    FALSE,0x1090L,4,FALSE,0L},
   {"OR4",    FALSE,0x1094L,4,FALSE,0L},
   {"BR5",    FALSE,0x10A0L,4,FALSE,0L},
   {"OR5",    FALSE,0x10A4L,4,FALSE,0L},
   {"BR6",    FALSE,0x10B0L,4,FALSE,0L},
   {"OR6",    FALSE,0x10B4L,4,FALSE,0L},
   {"BR7",    FALSE,0x10C0L,4,FALSE,0L},
   {"OR7",    FALSE,0x10C4L,4,FALSE,0L},
   {""}
};

PRIVATE MAP_REGISTERS table332[] = {
   {"CSPAR0",FALSE,0x44L,2,FALSE,0L},
   {"CSPAR1",FALSE,0x46L,2,FALSE,0L},
   {"CSBARBT",FALSE,0x48L,2,FALSE,0L},
   {"CSORBT",FALSE,0x4AL,2,FALSE,0L},
   {"CSBAR0",FALSE,0x4CL,2,FALSE,0L},
   {"CSOR0",FALSE,0x4EL,2,FALSE,0L},
   {"CSBAR1",FALSE,0x50L,2,FALSE,0L},
   {"CSOR1",FALSE,0x52L,2,FALSE,0L},
   {"CSBAR2",FALSE,0x54L,2,FALSE,0L},
   {"CSOR2",FALSE,0x56L,2,FALSE,0L},
   {"CSBAR3",FALSE,0x58L,2,FALSE,0L},
   {"CSOR3",FALSE,0x5AL,2,FALSE,0L},
   {"CSBAR4",FALSE,0x5CL,2,FALSE,0L},
   {"CSOR4",FALSE,0x5EL,2,FALSE,0L},
   {"CSBAR5",FALSE,0x60L,2,FALSE,0L},
   {"CSOR5",FALSE,0x62L,2,FALSE,0L},
   {"CSBAR6",FALSE,0x64L,2,FALSE,0L},
   {"CSOR6",FALSE,0x66L,2,FALSE,0L},
   {"CSBAR7",FALSE,0x68L,2,FALSE,0L},
   {"CSOR7",FALSE,0x6AL,2,FALSE,0L},
   {"CSBAR8",FALSE,0x6CL,2,FALSE,0L},
   {"CSOR8",FALSE,0x6EL,2,FALSE,0L},
   {"CSBAR9",FALSE,0x70L,2,FALSE,0L},
   {"CSOR9",FALSE,0x72L,2,FALSE,0L},
   {"CSBAR10",FALSE,0x74L,2,FALSE,0L},
   {"CSOR10",FALSE,0x76L,2,FALSE,0L},
   {"",FALSE,0L,0,FALSE,0L}
};

PRIVATE MAP_REGISTERS table386ex[] = {
   {"P1CFG",FALSE,0xF820L,1,FALSE,0L},
   {"P2CFG",FALSE,0xF822L,1,FALSE,0L},
   {"P3CFG",FALSE,0xF824L,1,FALSE,0L},
   {"PINCFG",FALSE,0xF826L,1,FALSE,0L},
   {"DMACFG",FALSE,0xF830L,1,FALSE,0L},
   {"INTCFG",FALSE,0xF832L,1,FALSE,0L},
   {"TMRCFG",FALSE,0xF834L,1,FALSE,0L},
   {"SIOCFG",FALSE,0xF836L,1,FALSE,0L},
   {""}
};
#define MAX_REGISTER_SIZE 4   /* Largest single register */
#define MAX_NUM_PARAMETERS 15
#define MAX_MAPSTR_LEN 180

                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/
RETCODE EXPORT MemCliDiagnost(U8);
RETCODE EXPORT iceSetMap(U32 addr1, U32 addr2, U16 attr);
extern RETCODE CreateAddress(DESCRIPTOR *);
extern U32 *mapOrder;
extern U32 mapBlockGranularity;
extern U32 mapBlockSize;
extern U32 mapBlockCount;
extern SPACE_TYPE gSpaceType;
extern PROC_SYSTEM_TYPE gSystemType;
extern PROCESSOR_FAMILY gCpuFamily;


                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/

RETCODE PRIVATE SendCliMessage(HANDLE cliHandle, LPSTR msgPtr);
RETCODE PRIVATE DisplayMap(VOID);
RETCODE PRIVATE MapPreparser(LPSTR cmd, U32 *argc, U32 argv[]);
//RETCODE PRIVATE MapClearSettings(VOID);
VOID PRIVATE SetReMap(VOID);
VOID PRIVATE ResetReMap(VOID);
U16 PRIVATE GetReMapCfg(VOID);

/*---------------------------------------------------------------------------
** RestoreChipSelects
**
** Purpose: Reads file and converts ascii entries into values to be programmed
**    into internal 68332 chip select registers.
----------------------------------------------------------------------------*/
RETCODE PRIVATE RestoreChipSelects(LPSTR fileName);

                        /****************************
                         *                          *
                         *      EXECUTABLE CODE     *
                         *                          *
                         ****************************/


/****************************************************************************
**
**  InitCServer
**
*****************************************************************************/
RETCODE EXPORT InitCServer(HANDLE cliHandle, HANDLE dllHandle) {
   CSERVER_NEW_REGISTRATION FAR * msgBufPtr;

   cliServerHandle = cliHandle;
   msgBufPtr =
      (CSERVER_NEW_REGISTRATION FAR *)TMalloc(sizeof(CSERVER_VARIABLE_VALUE));
   if (msgBufPtr == NULL) {
      return(ER_OUT_OF_MEMORY);
   }

   msgBufPtr->stringResourceHandle = dllHandle;

   msgBufPtr->serverNameIndex = 30;
   msgBufPtr->dllNameIndex = 31;
   msgBufPtr->numberOfCommandsIndex = 32;
   msgBufPtr->commandStartIndex = 33;
   SendMessage(cliHandle, CLI_NEW_SVR_REGISTRATION, CLI_NEW_SVR_REGISTRATION,
      (DWORD)msgBufPtr);
   return(GOOD);
}

/*---------------------------------------------------------------------------
** SendCliMessage
**
** Purpose:
----------------------------------------------------------------------------*/
RETCODE PRIVATE SendCliMessage(HANDLE cliHandle, LPSTR msgPtr)
{
   HANDLE msgBufHandle;
   CSERVER_RESULTS FAR  *msgBufPtr;
   U16         msgTextSize, loop ;

   msgTextSize = lstrlen(msgPtr);
   msgBufHandle = GlobalAlloc(GMEM_MOVEABLE, 
                              (sizeof(CSERVER_RESULTS) + msgTextSize + 1));
   if (msgBufHandle == (HANDLE)NULL) {
      return(ER_OUT_OF_MEMORY); /* FAILED */
   }
   else if((msgBufPtr=(CSERVER_RESULTS *)GlobalLock(msgBufHandle)) == NULL) {
      return(ER_WINDOWS_MEMLOCK) ; /* FAILED */
   }
   msgBufPtr->target               = 0;
   msgBufPtr->variantCode          = CLI_SERVER_RESULTS;
   msgBufPtr->resultTextLength     = msgTextSize; /* message string length */
   for (loop = 0; loop < msgTextSize; loop++ ) {
      msgBufPtr->messageText[loop]  =  *msgPtr++;
   }
   msgBufPtr->messageText[loop]  =  '\0' ;

   SendMessage(cliHandle, CLI_SERVER_RESULTS,
               msgBufHandle, CLI_SERVER_RESULTS);
   return (GOOD);
}

/****************************************************************************
**
**  MapCliMemoryMap
**
*****************************************************************************/
RETCODE EXPORT MapCliMemoryMap(LPSTR cmdString, U32 argc, U32 argv[])
{
   U16 argIndex;
   BOOLEAN overlay = TRUE;
   U16 space = 0;
   MEMORY_MAP_DATA map;
   U32 offset1, offset2;
   RETCODE err;
   BOOLEAN bCovered;
   BOOLEAN offset2Flag = FALSE;  // true when second offset processed
   BOOLEAN targetFlag = FALSE;  // true when target processed
   BOOLEAN accessFlag = FALSE;  // true when access processed
   BOOLEAN spaceFlag = FALSE;  // true when space processed
   BOOLEAN argumentRecognized;  // true when next argument recognized

   if (!GetMapPresent()) return(ER_NO_MEMORY_PRESENT);

   // handle "map"
   if (argc == 1) {
      if((err = DisplayMap())!=GOOD) return(err);
      return(GOOD);
   }

   // handle "map clear"
   if ((argc == 2) &&
      (strncmpi(&cmdString[(U16)argv[1]], "clear",
       strlen(&cmdString[(U16)argv[1]])) ==0))
   {
      if ((err = MapClear())!=GOOD) return(err);
      if ((err = DisplayMap())!=GOOD) return(err);
      iceSetMap(0L,0L,3);
      return(GOOD);
   }

   // make sure SDS members and map settings are consistent
   if ((err = GetNumMapSetting(&argIndex))!=GOOD)
      return(err);
   // next argument must be the beginning address
   if ((err = AdrCreateAddressFromText(&cmdString[(U16)argv[1]],
      NULL,&map.address))!=GOOD) return(err);
   if (gCpuFamily == FAMILY_X86) {
      if ((err=AdrConvertAddress(map.address, ADDR_PHYSICAL, &bCovered))
         != GOOD) {
         AdrDestroyAddress(map.address);
         return(err);
      }
   }
   map.accessRights = MAP_RAM;
   map.enabled = MAP_ENABLE;

   // handle the rest of the arguments
   for (argIndex = 2; argIndex < argc; ++argIndex) {

      argumentRecognized = FALSE;  // make sure token recognized

      // handle argument recognition in easiest first order...

      // handle "target"; illegal if target|access|space previously detected
      if (!targetFlag && !accessFlag && !spaceFlag) {
         if (strncmpi(&cmdString[(U16)argv[argIndex]], "target",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            if (targetFlag) return(ER_CLI_SYNTAX);
            // set target to map
            overlay = FALSE;   // target memory
            targetFlag = TRUE;
            argumentRecognized = TRUE;
         }
      }

      // test for access; illegal if access or space previously detected
      if (!argumentRecognized && !accessFlag && !spaceFlag) {
         if(strncmpi(&cmdString[(U16)argv[argIndex]], "off",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0) {
            map.accessRights = MAP_RAM;
            map.enabled = MAP_DISABLE;
            accessFlag = TRUE;
            argumentRecognized = TRUE;
         } else if(strncmpi(&cmdString[(U16)argv[argIndex]], "ram",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0) {
            map.accessRights = MAP_RAM;
            accessFlag = TRUE;
            argumentRecognized = TRUE;
         } else if(strncmpi(&cmdString[(U16)argv[argIndex]], "rom",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0 &&
            (gSystemType != PROC_MICEPACK) ) {
            map.accessRights = MAP_ROM_NOBRK;
            accessFlag = TRUE;
            argumentRecognized = TRUE;
         } else if(strncmpi(&cmdString[(U16)argv[argIndex]], "rombrk",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0) {
            map.accessRights = MAP_ROM;
            accessFlag = TRUE;
            argumentRecognized = TRUE;
         } else if(strncmpi(&cmdString[(U16)argv[argIndex]], "none",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0) {
            map.accessRights = MAP_NOACCESS;
            accessFlag = TRUE;
            argumentRecognized = TRUE;
         }
      }

      // test for space; multiple space designations OK
      if (!argumentRecognized) {
         if (strncmpi(&cmdString[(U16)argv[argIndex]], "up",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            space |= MAP_UP;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if(strncmpi(&cmdString[(U16)argv[argIndex]], "ud",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            space |= MAP_UD;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if(strncmpi(&cmdString[(U16)argv[argIndex]], "sp",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            space |= MAP_SP;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if(strncmpi(&cmdString[(U16)argv[argIndex]], "sd",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            space |= MAP_SD;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if(strncmpi(&cmdString[(U16)argv[argIndex]], "smm",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            space |= MAP_SMM;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if(strncmpi(&cmdString[(U16)argv[argIndex]], "user",
            strlen(&cmdString[(U16)argv[argIndex]])) == 0)
         {
            space |= MAP_USR;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
      }

      // test for second offset; illegal if second offset or access
      // or target or space previously detected
      if (!argumentRecognized && !offset2Flag && !accessFlag &&
          !targetFlag && !spaceFlag)
      {
         DESCRIPTOR secondAddr;
         ADDR_COMPARE results;

         if ((err = AdrGetAddrOffset(map.address, &offset1)) != GOOD) {
            AdrDestroyAddress(map.address);
            return(err);
         }
         if ((err = AdrCreateAddressFromText(&cmdString[(U16)argv[2]],
             NULL,&secondAddr)) != GOOD) {
            AdrDestroyAddress(map.address);
            return(err);
         }
         if (gCpuFamily == FAMILY_X86) {
            if ((err=AdrConvertAddress(secondAddr, ADDR_PHYSICAL, &bCovered))
               != GOOD)
            {
               AdrDestroyAddress(map.address);
               return(err);
            }
         }
         if ((err = AdrGetAddrOffset(secondAddr,&offset2)) != GOOD) {
            AdrDestroyAddress(map.address);
            AdrDestroyAddress(secondAddr);
            return (err);
         }
         if ((err = AdrCompareAddresses(map.address, secondAddr,
            &results)) != GOOD)
         {
            AdrDestroyAddress(map.address);
            AdrDestroyAddress(secondAddr);
            return (err);
         }
         if (results == FIRST_ADDR_GREATER) {
            AdrDestroyAddress(map.address);
            AdrDestroyAddress(secondAddr);
            return(ER_CLI_SYNTAX);
         }
         offset1 &= ~(mapBlockGranularity - 1);
         map.blockSize = ((~(mapBlockGranularity - 1) & offset2) |
                         (mapBlockGranularity - 1)) - offset1 + 1;
         if ((err = AdrDestroyAddress(secondAddr)) != GOOD) {
            AdrDestroyAddress(map.address);
            return(err);
         }
         offset2Flag = argumentRecognized = TRUE;
      }

      // bad syntax if nothing recognized this pass
      if (!argumentRecognized) {
         return (ER_CLI_SYNTAX);
      }
   }  // while

   // set up unspecified end range
   if (!offset2Flag) {
      if ((err = AdrGetAddrOffset(map.address, &offset1)) != GOOD) {
         AdrDestroyAddress(map.address);
         return(err);
      }
      offset1 &= ~(mapBlockGranularity - 1);
      // set the block size to the smallest amount available
      map.blockSize = mapBlockGranularity;
   }

   // apply overlay setting
   if (!overlay) map.accessRights |= MAP_TARGET;

   // apply space setting
   if (space) {
      switch (gSpaceType) {
         case SP_GENERIC:
            return(ER_MAP_INVALID_VALUE_INPUT);
         case SP_INTEL:
            if (space & (MAP_UD|MAP_UP|MAP_SD|MAP_SP))
               return(ER_MAP_INVALID_VALUE_INPUT);
            break;
         case SP_MOTOROLA:
            if (space & (MAP_SMM|MAP_USR))
               return(ER_MAP_INVALID_VALUE_INPUT);
            break;
      }
   }
   else {
      switch (gSpaceType) {
         case SP_INTEL:
            space = MAP_USR;
            break;
         case SP_MOTOROLA:
            if (gSystemType == PROC_MICEPACK)
               space = MAP_UD|MAP_UP|MAP_SD|MAP_SP;
            else
               space = MAP_SD;
            break;
      }
   }
   map.accessRights |= space;

   // set new offset
   if ((err = AdrSetAddrOffset(map.address, offset1)) != GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }

   if ((err = MapSet(&map))!=GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }
   if((err = DisplayMap())!=GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }
   if((err = AdrDestroyAddress(map.address)) != GOOD) return(err);

   return(GOOD);
}

/*---------------------------------------------------------------------------
** DisplayMap
**
** Purpose:
----------------------------------------------------------------------------*/
RETCODE PRIVATE DisplayMap(VOID) {

#define SIZE_BUFF_TEXT 50  /* arb. large buffer (min appears to be 46) */

   MEMORY_MAP_DATA map;
   BOOLEAN overlay;
   RETCODE err;
   U32 offset,offset2;
   U16 i=0;
   U16 space;
   BOOLEAN blockFound = FALSE;
   S8 buf[ADDR_BUFF_SZ], buf1[(ADDR_BUFF_SZ*2)+SIZE_BUFF_TEXT],
      buf2[ADDR_BUFF_SZ];
   DESCRIPTOR addr;
   
   if (!GetMapPresent()) return(ER_NO_MEMORY_PRESENT);
   
   /* create an address descriptor to allow display of the map block range */
   if ((err = CreateAddress(&addr)) != GOOD)
      return(err);
   if ((err = CreateAddress(&(map.address))) != GOOD)
      return(err);

   /* sequence through the map blocks in address order */
   while((mapOrder[i] != DUMMY_MAP_ORDER) && i < (U16)mapBlockCount) {
      map.blockNumber = mapOrder[i];
      if((err = MapGet(&map))!=GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      if ((err = AdrGetAddrOffset(map.address, &offset)) != GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      /* calculate ending address for the map block */
      offset2 = offset+map.blockSize-1L;
      
      /* put the ending offset of the map block into the address desc */
      if((err = AdrSetAddrOffset(addr, offset2)) != GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      /* this IF is redundant.  There are only ENABLED map blocks in
         the address ordered list */
      if(map.enabled == MAP_ENABLE) {
         blockFound = TRUE;
         if((err = AdrConvAddressToText(map.address, (LPSTR)buf))!=GOOD) {
            AdrDestroyAddress(addr);
            AdrDestroyAddress(map.address);
            return(err);
         }
         if((err = AdrConvAddressToText(addr, (LPSTR)buf2))!=GOOD) {
            AdrDestroyAddress(addr);
            AdrDestroyAddress(map.address);
            return(err);
         }
         if (map.accessRights & MAP_TARGET)
         {
            overlay = FALSE;
            map.accessRights ^= MAP_TARGET;
         }
         else
            overlay = TRUE;
         space = map.accessRights & 0xff00;
         map.accessRights ^= space;

         wsprintf(buf1, "Mapped block #%d: %s %s", i, buf, buf2);
         if (!overlay)
            wsprintf(buf1, "%s Target", buf1);
         switch (map.accessRights) {
            case (MAP_RAM):
                  wsprintf(buf1, "%s RAM", buf1);
                  break;
            case (MAP_ROM):
               wsprintf(buf1, "%s ROM/Break", buf1);
               break;
            case (MAP_ROM_NOBRK):
               wsprintf(buf1, "%s ROM/No Break", buf1);
               break;
            case (MAP_NOACCESS):
               wsprintf(buf1, "%s NONE", buf1);
               break;
         }

         if (space&MAP_UP) wsprintf(buf1, "%s UP", buf1);
         if (space&MAP_UD) wsprintf(buf1, "%s UD", buf1);
         if (space&MAP_SP) wsprintf(buf1, "%s SP", buf1);
         if (space&MAP_SD) wsprintf(buf1, "%s SD", buf1);
         if (space&MAP_SMM) wsprintf(buf1, "%s SMM", buf1);
         if (space&MAP_USR) wsprintf(buf1, "%s User", buf1);

         if((err = SendCliMessage(cliServerHandle, buf1))!=GOOD) {
            AdrDestroyAddress(addr);
            AdrDestroyAddress(map.address);
            return(err);
         }
      }
      i++;
   }

   if ((err = AdrDestroyAddress(addr)) != GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }

   if ((err = AdrDestroyAddress(map.address)) != GOOD) return(err);

   if (!blockFound) {
      S8 buf[30];
      iceSetMap(0L,0L,3); /* Initialize FW MAP table */
      wsprintf(buf, "All memory mapped to target");
      if((err = SendCliMessage(cliServerHandle, buf))!=GOOD) return(err);
   }
   return(GOOD);
}

/*---------------------------------------------------------------------------
** MapCliConfigCS
**
** Purpose: Sends command to chassis to program the probe hardware to match
**    the 683XX internal chip select registers.
**    If no parameters, simply sends the command.
**    if one parameter and is filename, does a restore of the registers from
**    this ascii file first, then sends the command to program the probe HW.
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT
MapCliConfigCS(LPSTR cmdString, U32 argc, U32 argv[]) {

   RETCODE err = GOOD;

   if (argc > 2)
      return ER_CLI_SYNTAX;
   if (argc == 2) {
      /* pass file string to function to restore chip select registers */
      if (GOOD != (err = RestoreChipSelects((LPSTR)&cmdString[(U16)argv[1]])))
         return err;
   }
   /* fall thru and send command to set up emulator chip select hardware */
   if (err != GOOD)
      return err;

   return MapConfigCS();

}  /* end of MapCliConfigCS */


/*---------------------------------------------------------------------------
** MapCliSaveCS
**
** Purpose: Gets the 683XX internal chip select registers from the processor
**    and outputs the values in ascii to the entered filename.
**
** Design:
**    Open file, return error if error
**    Get base address of registers
**    Read unique registers and store locally
**    loop
**       read common base and option registers for 0-10 registers
**    Output unique register names and hex values
**    loop
**       Generate register name; generate hex value; output to file
**    Close file
**
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT
MapCliSaveCS(LPSTR cmdString, U32 argc, U32 argv[]) {

   if (argc != 2) return ER_CLI_SYNTAX;

   return MapSaveCS((LPSTR)&cmdString[(U16)argv[1]]);
}  /* end of MapCliSaveCS */


/*---------------------------------------------------------------------------
** MapCliRestoreCS
**
** Purpose: CLI interface to restore chip selects; calls RestoreChipSelects
**
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT
MapCliRestoreCS(LPSTR cmdString, U32 argc, U32 argv[]) {
   if (argc != 2) return ER_CLI_SYNTAX;
   return MapRestoreCS((LPSTR)&cmdString[(U16)argv[1]]);
}  /* end of MapCliRestoreCS

/*---------------------------------------------------------------------------
** RestoreChipSelects
**
** Purpose: Reads file and converts ascii entries into values to be programmed
**    into internal chip select registers.
**
** Design:
**    Open file, return error if error
**    Get base address of registers
**    loop
**       read line
**       parse into register name and value; if error output error and linenum
**    until eof reached
**    write only registers that were found to hardware
----------------------------------------------------------------------------*/
RETCODE PRIVATE RestoreChipSelects(LPSTR fileName) {
#define LINE_LEN 80
#define TOKSTR " \n\r"
   DESCRIPTOR     simAddressDesc;
   FILE          *inputFile;
   U32            simAddress;
   U32            MBARValue;
   RETCODE        err1, err2, firstErr = GOOD;
   MAP_REGISTERS *tblPtr, *posPtr, *savPosPtr;
   S8             inputStr[81];
   BOOLEAN        verify, simAddressValid;
   PROBE_TYPE     processor;
   U32            MBARMask;
   BOOLEAN        isIntel = FALSE;
   ADDR_SPACE     spaceType;
   U16            remap;

   if ((err1 = ProcReturnSpecificProcessor(&processor)) != GOOD) return(err1);
   switch (processor) {
      case M68HC16Y1_TB: case M68HC16Y1_SH:
      case M68HC16Z1_TB: case M68HC16Z1_SH:
      case M68HC16Z2_TB: case M68HC16Z2_SH:      // same sim as 332.
      case M68332_TB: case M68332_SH:
      case M68333_TB: case M68333_SH:
      case M68331_TB: case M68331_SH:   tblPtr = table332; break;
      case M68330_TB: case M68330_SH:
         tblPtr = table340;
         MBARMask = 0xfffff000L;
         break;
      case M68340_TB: case M68340_SH:
         tblPtr = table340;
         MBARMask = 0xfffff000L;
         break;
      case M68360_TB: case M68360_SH:
         tblPtr = table360;
         MBARMask = 0xffffe000L;
         break;
      case I80386EX_TB: case I80386EX_SH:
         tblPtr = table386ex;
         isIntel = TRUE;
         break;
      default:          return(ER_PROC_TYPE_UNKNOWN);
   }
   
   for( posPtr = tblPtr; lstrlen(posPtr->regName) != 0; posPtr++ )
      posPtr->restoreFound = FALSE;
   posPtr = tblPtr;
   if (NULL == (inputFile = fopen((LPSTR)fileName, "rt"))) {
      return ER_MAP_CANNOT_OPEN_FILE;
   }
   while( fgets(inputStr, LINE_LEN - 2, inputFile) != NULL ) {
      S8 *regPtr, *valPtr;
      char *endPtr;
      BOOLEAN matched;
      if( (regPtr=strtok(inputStr,TOKSTR)) == NULL) {
         err1 = ER_MAP_VALUE_MISSING;
         goto CLEANUP3;
      }
      if( (valPtr=strtok(NULL,TOKSTR)) == NULL) {
         err1 = ER_MAP_VALUE_MISSING;
         goto CLEANUP3;
      }
      if( strtok(NULL,TOKSTR) != NULL) {
         err1 = ER_MAP_TOO_MANY_INPUT_LINES;
         goto CLEANUP3;
      }
      matched = FALSE;
      savPosPtr = posPtr;
      while( lstrlen(posPtr->regName) != 0 ) {
         if( strcmpi(regPtr,posPtr->regName) == 0 ) {
             matched = TRUE;
             break;
         }
         posPtr++;
      }
      if( !matched ) {
         // if not found start from beginning of table and search to
         // where we started.
         posPtr = tblPtr;
         while( posPtr != savPosPtr ) {
            if( strcmpi(regPtr,posPtr->regName) == 0 ) {
               matched = TRUE;
               break;
            }
            posPtr++;
         }
      }
      if( !matched ) {
         err1 = ER_MAP_INVALID_REGNAME;
         goto CLEANUP3;
      }
      posPtr->restoreValue = strtoul((valPtr), &endPtr, 16);
      if (*endPtr != 0) {
         err1 = ER_MAP_INVALID_VALUE_INPUT;
         goto CLEANUP3;
      }
      if( ((posPtr->size == 1) && (posPtr->restoreValue > 0xffL))
          || ((posPtr->size == 2) && (posPtr->restoreValue > 0xffffL)) ) {
         err1 = ER_MAP_VALUE_TOO_BIG;
         goto CLEANUP3;
      }
      // need to swap around bytes in the word and long word values
      // because memory server expects ascending byte order.
      if (!isIntel) {
         if( posPtr->size == 2 ) {
            posPtr->restoreValue = MemSwapBytesInWord(posPtr->restoreValue);
         }
         else if( posPtr->size == 4 ) {
            posPtr->restoreValue = MemSwapBytesInLong(posPtr->restoreValue);
         }
      }         
      posPtr->restoreFound = TRUE;

      // save time for next search by assuming next entry is below
      // the previous in the table
      posPtr++;
   }
   
   /*-----------------------------------------------*/
   /* write all the registers found into the target */
   /*-----------------------------------------------*/
   /* save verify mode and change to no verify */
   if (GOOD != (err1 = MemGetVerifyWrites(&verify)))
      goto CLEANUP3;
   if (GOOD != (err1 = MemSetVerifyWrites(FALSE)))
      goto CLEANUP3;

/*--------- end of err1 usage, CLEANUP3; start of err2 usage -----------*/

   /* get the System Integration Module base address */
   if (!isIntel) {
      simAddressValid = FALSE;
      if ((err2 = SdnReadMember(SDN_SIM_VALID, (U8 *)&simAddressValid)) != GOOD)
         goto CLEANUP2;
      if (!simAddressValid) {
         err2 = ER_SIM_UNREADABLE;
         goto CLEANUP2;
      }
      if ((err2 = SdnReadMember(SDN_SIM_ADDRESS, (U8 FAR *)&simAddress)) != GOOD)
         goto CLEANUP2;
   }
   else {
      simAddress = 0;
      simAddressValid = TRUE;
   }

   /* create and fill in address descriptor in order to read memory */
   if (GOOD != (err2 = CreateAddress(&simAddressDesc)))
      goto CLEANUP2;

/*------------ end of CLEANUP2, start of CLEANUP1 -------------*/

   if (isIntel)
      spaceType = SPACE_IO;
   else
      spaceType = SPACE_SD;

   if (GOOD != (err2 = AdrSetAddrSpace(simAddressDesc, spaceType)))
      goto CLEANUP1;

   if (isIntel) {
      remap = GetReMapCfg();
      if ((remap & 0x8000) == 0)
         SetReMap();
   }

   for( posPtr = tblPtr; strlen(posPtr->regName) != 0; posPtr++ ) {
      U32 offset;
      ACCESS_SIZE accSize;
      if( !posPtr->restoreFound ) {
         if( posPtr->VIR ) {
            // Currently MBAR is the only VIR - if not defined we don't
            // know where to put the other sim registers so error out.
            err2 = ER_MAP_VALUE_MISSING;
            goto CLEANUP1;
         }
         continue;
      }
      if( posPtr->VIR ) {
         // Currently MBAR is the only VIR - if bit0 not set,
         // remaining registers cannot be written.
         MBARValue = MemSwapBytesInLong(posPtr->restoreValue);
         if((MBARValue & 0x1) == 0) {
            simAddressValid = FALSE;
         } else {
            // MBAR defines sim address for other registers.
            simAddress = MBARValue & MBARMask;
            simAddressValid = TRUE;
         }
         if((err2 = AdrSetAddrSpace(simAddressDesc, SPACE_CPU))!=GOOD)
            goto CLEANUP1;
         offset = posPtr->offset;
      } else {
         if((err2 = AdrSetAddrSpace(simAddressDesc, spaceType))!=GOOD)
            goto CLEANUP1;
         offset = simAddress + posPtr->offset;
      }
      if( simAddressValid || posPtr->VIR ) {
         if((err2=AdrSetAddrOffset(simAddressDesc,offset))!=GOOD)
            goto CLEANUP1;
         accSize = (posPtr->size < 2) ? BYTE_SIZE : WORD_SIZE;
         // Am using fill instead of write because fill allows me to point
         // to local memory - write memory needs a pointer to global
         // memory.
         if((err2=MemFillSized(simAddressDesc, posPtr->size,
            (U8 FAR *)&posPtr->restoreValue, posPtr->size,accSize))!=GOOD)
            goto CLEANUP1;
      }
      if( posPtr->VIR ) {
         if((MBARValue & 0x1) == 0) {
            err2 = ER_SAVECS_MBAR_INVALID;   /* Only MBAR will be restored */
            break;
         }
      }
   }

CLEANUP1:
   firstErr = err2;
   err2 = AdrDestroyAddress(simAddressDesc);

CLEANUP2:
   if(GOOD == firstErr) firstErr = err2;
   /* return state of verify at time of function start */
   err2 = MemSetVerifyWrites(verify);

CLEANUP3:
   if (GOOD == firstErr) firstErr = err1;
   fclose(inputFile);

   if (isIntel && ((remap & 0x8000) == 0))
      ResetReMap();

   return firstErr;
}  /* end of RestoreChipSelects332 */


/****************************************************************************
**
** MapConfigCS
**
*****************************************************************************/
RETCODE EXPORT MapConfigCS(void) {

   BOOLEAN timedOut;
   BOOLEAN true = TRUE;

   return SdnWriteCmdReadResponse(SDN_CONFIG_CS_HW_CMD,
                                  (U8 FAR *)&true,
                                  GOOD,
                                  SDN_CONFIG_CS_HW_RESULT,
                                  0L,
                                  &timedOut);
   
}  /* end of MapConfigCS */


/****************************************************************************
**
** MapSaveCS
**
*****************************************************************************/
RETCODE EXPORT MapSaveCS(LPSTR fileName) {
   RETCODE err=GOOD;
   U32     simAddress;
   FILE    *outFile;
   U8      reg[MAX_REGISTER_SIZE];
   PROBE_TYPE processor;
   MAP_REGISTERS *tblPtr;
   ADDR_SPACE space;
   U32 MBARMask;
   BOOLEAN simAddressValid;
   BOOLEAN isIntel = FALSE;
   U16 remap;
   
   if ((err = ProcReturnSpecificProcessor(&processor)) != GOOD) return(err);
   switch (processor) {
      case M68HC16Y1_TB: case M68HC16Y1_SH:
      case M68HC16Z1_TB: case M68HC16Z1_SH:
      case M68HC16Z2_TB: case M68HC16Z2_SH:      // same sim as 332.
      case M68332_TB:    case M68332_SH:   
      case M68333_TB:    case M68333_SH:   
      case M68331_TB:    case M68331_SH:    tblPtr = table332; break;
      case M68330_TB:    case M68330_SH:
         tblPtr = table340;
         MBARMask = 0xfffff000L;
         break;
      case M68340_TB:    case M68340_SH:
         tblPtr = table340;
         MBARMask = 0xfffff000L;
         break;
      case M68360_TB:    case M68360_SH:
         tblPtr = table360;
         MBARMask = 0xffffe000L;
         break;
      case I80386EX_TB: case I80386EX_SH:
         tblPtr = table386ex;
         isIntel = TRUE;
         break;
      default:          return(ER_PROC_TYPE_UNKNOWN);
   }
   if (NULL == (outFile = fopen(fileName, "wt"))) {
      return ER_MAP_CANNOT_OPEN_FILE;
   }
   if (isIntel) {
      simAddress = 0;
      simAddressValid = TRUE;
      remap = GetReMapCfg();
      if ((remap & 0x8000) == 0)
         SetReMap();
   } else {
      /* get the System Integration Module base address */
      if ((err = SdnReadMember(SDN_SIM_VALID, (U8 *) &simAddressValid)) != GOOD)
         goto CLEANUP2;

      if (!simAddressValid) {
         err = ER_SIM_UNREADABLE;
         goto CLEANUP2;
      }
   
      if((err=SdnReadMember(SDN_SIM_ADDRESS,(U8 FAR *)&simAddress))!=GOOD)
         goto CLEANUP2;
   }

   while( lstrlen(tblPtr->regName) != 0 ) {
      U32 addrOffset;
      ACCESS_SIZE accSize;
      if( tblPtr->VIR ) {
         addrOffset = tblPtr->offset;
         space = SPACE_CPU;
      }
      else {
         addrOffset = simAddress + tblPtr->offset;
         if (isIntel)
            space = SPACE_IO;
         else
            space = SPACE_SD;
      }
      accSize = WORD_SIZE;
      if( tblPtr->size < 2 ) accSize = BYTE_SIZE;
      if((err=MemReadQuick(addrOffset,space,tblPtr->size,reg,accSize,
         CACHE_BYPASS)) != GOOD) goto CLEANUP2;
      fprintf(outFile, "%8s    ",tblPtr->regName);
      switch(tblPtr->size) {
         case 1:  fprintf(outFile, "0x%02X\n", reg[0]); break;
         case 2:  fprintf(outFile,"0x%02X%02X\n", reg[0], reg[1]); break;
         case 4:  fprintf(outFile, "0x%02X%02X%02X%02X\n", reg[0],
                          reg[1], reg[2], reg[3]); break;
      }
        /* Override SDN_SIM_ADDRESS if 330/340/360 */
      if (tblPtr->VIR) {
         if ((reg[3] & 1) == 0) {
            err = ER_SAVECS_MBAR_INVALID;
            break;
         }
         simAddress = MemSwapBytesInLong(*((U32*)reg))&MBARMask;
      }
      tblPtr++;
   }
CLEANUP2:
   fclose(outFile);

   if (isIntel && ((remap & 0x8000) == 0))
      ResetReMap();

   return(err);
}  /* end of MapSaveCS */


/*-------------------------------------------------------------------------
** GetReMapCfg
---------------------------------------------------------------------------*/
U16 PRIVATE GetReMapCfg(VOID) {
   U32 ReMapCfgAddress = 0x022;
   LPU8 memBufPtr= NULL;
   DESCRIPTOR desc = NULL;
   U16 tmpValue;

   if (CreateAddress(&desc) != GOOD) {
      return 0;
   }
   if ((AdrSetAddrSpace(desc,SPACE_IO) != GOOD) ||
      (AdrSetAddrOffset(desc,ReMapCfgAddress) != GOOD)) {
      AdrDestroyAddress(desc);
      return 0;
   }
   // 05/05/94 - Nghia
   // always re-read from HW to make sure that the value is current   
   if (MemReadSized(desc,2,&memBufPtr,
         WORD_SIZE,CACHE_BYPASS) != GOOD) {
      AdrDestroyAddress(desc);
      // MemRead always returns a buffer even with an error
      // 05/05/94 - Nghia
      // only free if the buffer is allocated
      if (memBufPtr)
         TFree(memBufPtr);
      return 0;
   }
   tmpValue = *((U16 *)memBufPtr);
   // 04/19/94 - Nghia
   // destroy the returned memBufPtr
   TFree(memBufPtr);
   AdrDestroyAddress(desc);
   return (tmpValue);
}

/*---------------------------------------------------------------------------
** SetReMap  
----------------------------------------------------------------------------*/
VOID PRIVATE SetReMap(VOID) {
   PERIPHERAL_CMD cmd;
   RETCODE        retBuffer;
   BOOLEAN        timedOut;

   cmd = PERIPHERAL_CMD_GET;
   retBuffer = SdnWriteCmdReadResponse(SDN_PERIPHERAL_CMD, &cmd, GOOD,
      SDN_PERIPHERAL_RESULT, 0, &timedOut);
   return;
}

/*-----------------------------------------------------------------------
** ResetReMap  
-----------------------------------------------------------------------*/
VOID PRIVATE ResetReMap(VOID) {
   PERIPHERAL_CMD cmd;
   RETCODE        retBuffer;
   BOOLEAN        timedOut;

   // Now restore the previous MBAR or REMAPCFG registers.
   cmd = PERIPHERAL_CMD_RESTORE;
   retBuffer = SdnWriteCmdReadResponse(SDN_PERIPHERAL_CMD, &cmd,
      GOOD, SDN_PERIPHERAL_RESULT, 0, &timedOut);
   return;
}

/****************************************************************************
**
** MapRestoreCS
**
*****************************************************************************/
RETCODE EXPORT MapRestoreCS(LPSTR fileName) {
   return RestoreChipSelects(fileName);
}  /* end of MapRestoreCS

/*---------------------------------------------------------------------------
** MapCliSaveMap
**
** Purpose: CLI interface to save map setting
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT
MapCliSaveMap(LPSTR cmdString, U32 argc, U32 argv[]) {

   if (argc != 2) return ER_CLI_SYNTAX;

   return MapSaveMap((LPSTR)&cmdString[(U16)argv[1]]);
}  /* end of MapCliSaveMap */


/*---------------------------------------------------------------------------
** MapCliRestoreMap
**
** Purpose: CLI interface to restore map setting
----------------------------------------------------------------------------*/
#pragma argsused
RETCODE EXPORT
MapCliRestoreMap(LPSTR cmdString, U32 argc, U32 argv[]) {
   if (argc != 2) return ER_CLI_SYNTAX;
   return MapRestoreMap((LPSTR)&cmdString[(U16)argv[1]]);
}  /* end of MapCliRestoreMap

/****************************************************************************
**
** MapSaveMap
**
*****************************************************************************/
RETCODE EXPORT MapSaveMap(LPSTR fileName) {
#define SIZE_BUFF_TEXT 50  /* arb. large buffer (min appears to be 46) */

   BOOLEAN overlay;
   U16 space;
   RETCODE err=GOOD;
   FILE  *fp;
   MEMORY_MAP_DATA map;
   U32 offset,offset2;
   U16 i=0;
   S8 buf[ADDR_BUFF_SZ], buf1[(ADDR_BUFF_SZ*2)+SIZE_BUFF_TEXT],
      buf2[ADDR_BUFF_SZ];
   DESCRIPTOR addr;

   if ((fp=fopen(fileName, "wt")) == NULL)
      return ER_MAP_CANNOT_OPEN_FILE;

   if (!GetMapPresent()) return(ER_NO_MEMORY_PRESENT);

   /* create an address descriptor to allow display of the map block range */
   if ((err = CreateAddress(&addr)) != GOOD)
      return(err);
   if ((err = CreateAddress(&map.address)) != GOOD)
      return(err);

   /* sequence through the map blocks in address order */
   while((mapOrder[i] != DUMMY_MAP_ORDER) && i < (U16)mapBlockCount) {
      map.blockNumber = mapOrder[i];
      if((err = MapGet(&map))!=GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      if ((err = AdrGetAddrOffset(map.address, &offset)) != GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      /* calculate ending address for the map block */
      offset2 = offset+map.blockSize-1L;

      /* put the ending offset of the map block into the address desc */
      if((err = AdrSetAddrOffset(addr, offset2)) != GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      /* this IF is redundant.  There are only ENABLED map blocks in
         the address ordered list */
      if(map.enabled == MAP_ENABLE) {
         if((err = AdrConvAddressToText(map.address, (LPSTR)buf))!=GOOD) {
            AdrDestroyAddress(addr);
            AdrDestroyAddress(map.address);
            return(err);
         }
         if((err = AdrConvAddressToText(addr, (LPSTR)buf2))!=GOOD) {
            AdrDestroyAddress(addr);
            AdrDestroyAddress(map.address);
            return(err);
         }
         if (map.accessRights & MAP_TARGET)
         {
            overlay = FALSE;
            map.accessRights ^= MAP_TARGET;
         }
         else
            overlay = TRUE;
         space = map.accessRights & 0xff00;
         map.accessRights ^= space;

         wsprintf(buf1, "MAP %s %s", buf, buf2);
         if (!overlay)
            wsprintf(buf1, "%s Target", buf1);
         switch (map.accessRights) {
            case (MAP_RAM):
                  wsprintf(buf1, "%s RAM", buf1);
                  break;
            case (MAP_ROM):
               wsprintf(buf1, "%s ROMBRK", buf1);
               break;
            case (MAP_ROM_NOBRK):
               wsprintf(buf1, "%s ROM", buf1);
               break;
            case (MAP_NOACCESS):
               wsprintf(buf1, "%s NONE", buf1);
               break;
         }

         if (space&MAP_UP) wsprintf(buf1, "%s UP", buf1);
         if (space&MAP_UD) wsprintf(buf1, "%s UD", buf1);
         if (space&MAP_SP) wsprintf(buf1, "%s SP", buf1);
         if (space&MAP_SD) wsprintf(buf1, "%s SD", buf1);
         if (space&MAP_SMM) wsprintf(buf1, "%s SMM", buf1);
         if (space&MAP_USR) wsprintf(buf1, "%s USER", buf1);

         err = fprintf(fp, "%s\n", buf1);
      }
      i++;
   }

   if ((err = AdrDestroyAddress(addr)) != GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }

   if ((err = AdrDestroyAddress(map.address)) != GOOD) return(err);

   fclose(fp);
   return(err);
}  /* end of MapSaveMap */


/****************************************************************************
**
** MapRestoreMap
**
*****************************************************************************/
RETCODE EXPORT MapRestoreMap(LPSTR fileName) {
   RETCODE err;
   FILE  *fp;
   char cmd[MAX_MAPSTR_LEN];
   U32  argc, argv[MAX_NUM_PARAMETERS];

   if (strncmpi(fileName, "~maptemp.~ap", strlen(fileName)) != 0 )
      MapSaveMap("~maptemp.~ap");
   if ((fp=fopen(fileName, "rt")) == NULL) {
      remove("~maptemp.~ap");
      return ER_MAP_CANNOT_OPEN_FILE;
   }

   err = MapClearSettings();
   while ((err==GOOD) && (fgets(cmd, MAX_MAPSTR_LEN, fp))) {
      cmd[strlen(cmd)-1] = '\0';
      SendCliMessage(cliServerHandle, cmd);
      MapPreparser((LPSTR)cmd, &argc, argv);
      if (argc > 0) {
         if (strncmpi(&cmd[(U16)argv[0]], "map", strlen(&cmd[(U16)argv[0]]))
             == 0 ) {
            err = MapCliMemoryMap((LPSTR)cmd, argc, argv);
         }
         else
            err = ER_CLI_SYNTAX;
      }
   }

   if (err != GOOD) {
      SendCliMessage(cliServerHandle, "Restore previous map settings");
      MapClearSettings();
      MapRestoreMap("~maptemp.~ap");
   }

   fclose(fp);
   remove("~maptemp.~ap");
   return(err);
}  /* end of MapRestoreMap

/****************************************************************************
**
** MapPreparser
**
*****************************************************************************/
RETCODE PRIVATE MapPreparser(LPSTR cmd, U32 *argc, U32 argv[]) {
   U16 i;

   *argc = 0;
   
   i = 0;
   while (cmd[i]) {
      if (isalnum(cmd[i])) {
         argv[(U16) *argc] = i;
         (*argc)++;
         while (isalnum(cmd[i]))
            i++;
      }
      while (cmd[i] && !isalnum(cmd[i])) {
         cmd[i] = '\0';
         i++;
      }
   }
   return(GOOD);
}

/****************************************************************************
**
** MapClearSettings
**
*****************************************************************************/
RETCODE EXPORT MapClearSettings(VOID) {
   S16 i;
   U16 num;
   RETCODE err;
   MAPINFO MapInfo;

   GetNumMapSetting(&num);
   for (i=num-1; i>=0; i--) {
      if ((err=GetMapInfo(i, &MapInfo)) == GOOD)
         err = SetMapInfo(MapInfo, FALSE, 0); // remove the setting
      if (err != GOOD) return(err);
   }
   return(GOOD);
}

RETCODE EXPORT MapCliDiagnost(LPSTR cmdString, U32 argc, U32 argv[]) {
   switch(argc) {
     case 1:
          MemCliDiagnost(0);
          break;
     case 2:
          if (strncmpi(&cmdString[(U16)argv[1]], "mce",
             strlen(&cmdString[(U16)argv[1]])) ==0)
             MemCliDiagnost(1);
          else if (strncmpi(&cmdString[(U16)argv[1]],"mtat",
             strlen(&cmdString[(U16)argv[1]])) ==0)
             MemCliDiagnost(2);
          else
             return (ER_CLI_SYNTAX);
          break;
     default:
          return (ER_CLI_SYNTAX);
   }
   iceSetMap(0L,0L,3); /* Initialize FW MAP table */
   MapClear();
   iceSetMap(0L,0L,3); /* Initialize FW MAP table again */
   return GOOD;
}

/******************************** E O F ***********************************/
