/*****************************************************************************
**
**  Name: mapcli.c
**
**  Description: This is the cli inteface code for simple version of the
**      Map Server
**
**  Status: PRELIMINARY
**
**  $Log:   S:/tbird/mt2_68k/map_lc/mapcli.c_v  $
** 
**    Rev 1.2   05 Jun 1998 14:22:02   Gene
** fixed a bug of map restore
** 
**    Rev 1.1   03 Apr 1998 18:07:56   Gene
** added MapGetCSBaseAddr
** 
**    Rev 1.0   26 Mar 1998 10:11:52   gene
** Initial revision.
** 
**    Rev 1.3   26 Mar 1998 10:07:26   Gene
** Added LC302
** 
**    Rev 1.2   23 Mar 1998 10:13:38   gene
** 
**    Rev 1.1   26 Aug 1997 14:07:06   gene
** modified for LC302
** 
**    Rev 1.0   25 Aug 1997 15:08:20   gene
** Initial revision.
** 
**    Rev 1.1   18 Mar 1997 10:09:16   gene
** 
**    Rev 1.0   13 Feb 1997 08:52:30   gene
** Initial revision.
** 
**    Rev 1.6   15 Aug 1996 11:06:18   kevin
** fixed bugs of CliMapMemoryMap
** 
**    Rev 1.5   21 Jun 1996 15:01:40   kevin
** In 302 case, it allows fc0, fc3, and fc4
** 
**    Rev 1.4   21 May 1996 16:43:08   kevin
** added 302 case
** 
**    Rev 1.3   21 May 1996 16:07:32   kevin
** After restored chip selects, send an event to peripheral and memory windows.
** 
**    Rev 1.2   21 May 1996 14:11:12   kevin
** added save/restore functions for chip select
** 
**    Rev 1.1   26 Sep 1995 15:04:48   kevin
** 9/26/95
** 
**    Rev 1.0   07 Sep 1995 11:27:56   gene
** Initial revision.
** 
**    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_68k/map_lc/mapcli.c_v   1.2   05 Jun 1998 14:22:02   Gene  $
<<<<<<<<<<  mapcli.c  Rev 1.34
**  $Header:   S:/tbird/mt2_68k/map_lc/mapcli.c_v   1.2   05 Jun 1998 14:22:02   Gene  $
==========
**
**  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 _MAPDEF_
#include "mapdef.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 _SDS2ABI_
#include "sds2abi.h"
#endif

#ifndef _ENLIB_
#include "enlib.h"
#endif

#ifndef _EVENTS_
#include "events.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    *
                        *                          *
                        ****************************/
U32 addrCS[5] = { 0xE00000l, 0xD00000l, 0xB00000l, 0x700000l, 0xE00000l};
PRIVATE CHAR szCS[5][4] = {"CS0","CS1","CS2","CS3","CS0"};

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

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

MAP_REGISTERS table302[] = {
   {"CSBASE0",FALSE,0x830L,2,FALSE,0L},
   {"CSOPT0", FALSE,0x832L,2,FALSE,0L},
   {"CSBASE1",FALSE,0x834L,2,FALSE,0L},
   {"CSOPT1", FALSE,0x836L,2,FALSE,0L},
   {"CSBASE2",FALSE,0x838L,2,FALSE,0L},
   {"CSOPT2", FALSE,0x83AL,2,FALSE,0L},
   {"CSBASE3",FALSE,0x83CL,2,FALSE,0L},
   {"CSOPT3", FALSE,0x83EL,2,FALSE,0L},
   {""}
};

MAP_REGISTERS table307[] = {
   {"CSBASE0",FALSE,0x40L,2,FALSE,0L},
   {"CSOPT0", FALSE,0x42L,2,FALSE,0L},
   {"CSBASE1",FALSE,0x44L,2,FALSE,0L},
   {"CSOPT1", FALSE,0x46L,2,FALSE,0L},
   {"CSBASE2",FALSE,0x48L,2,FALSE,0L},
   {"CSOPT2", FALSE,0x4AL,2,FALSE,0L},
   {"CSBASE3",FALSE,0x4CL,2,FALSE,0L},
   {"CSOPT3", FALSE,0x4EL,2,FALSE,0L},
   {""}
};

MAP_REGISTERS table328[] = {
   {"GRPBASEA",FALSE,0x100L,2,FALSE,0L},
   {"GRPBASEB",FALSE,0x102L,2,FALSE,0L},
   {"GRPBASEC",FALSE,0x104L,2,FALSE,0L},
   {"GRPBASED",FALSE,0x106L,2,FALSE,0L},
   {"GRPMASEA",FALSE,0x108L,2,FALSE,0L},
   {"GRPMASEB",FALSE,0x10AL,2,FALSE,0L},
   {"GRPMASEC",FALSE,0x10CL,2,FALSE,0L},
   {"GRPMASED",FALSE,0x10EL,2,FALSE,0L},
   {"CSA0",    FALSE,0x110L,4,FALSE,0L},
   {"CSA1",    FALSE,0x114L,4,FALSE,0L},
   {"CSA2",    FALSE,0x118L,4,FALSE,0L},
   {"CSA3",    FALSE,0x11CL,4,FALSE,0L},
   {"CSB0",    FALSE,0x120L,4,FALSE,0L},
   {"CSB1",    FALSE,0x124L,4,FALSE,0L},
   {"CSB2",    FALSE,0x128L,4,FALSE,0L},
   {"CSB3",    FALSE,0x12CL,4,FALSE,0L},
   {"CSC0",    FALSE,0x130L,4,FALSE,0L},
   {"CSC1",    FALSE,0x134L,4,FALSE,0L},
   {"CSC2",    FALSE,0x138L,4,FALSE,0L},
   {"CSC3",    FALSE,0x13CL,4,FALSE,0L},
   {"CSD0",    FALSE,0x140L,4,FALSE,0L},
   {"CSD1",    FALSE,0x144L,4,FALSE,0L},
   {"CSD2",    FALSE,0x148L,4,FALSE,0L},
   {"CSD3",    FALSE,0x14CL,4,FALSE,0L},
   {""}
};

#define MAX_REGISTER_SIZE 4   /* Largest single register */
#define MAX_NUM_PARAMETERS 15
#define MAX_MAPSTR_LEN 180

                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/
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;
extern PROBE_TYPE gProcessor;

                        /****************************
                         *                          *
                         *     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);

/*---------------------------------------------------------------------------
** 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);
}
/****************************************************************************
**
**  MapFindCSNum
**
*****************************************************************************/
RETCODE PRIVATE MapFindCSNum(LPSTR argStr, U8 *cs)
{
   U8 i;

   for (i=0; i<4; i++) {
     if (strcmpi(argStr, &(szCS[i])) == 0) {
        *cs = i;
        return (GOOD);
     }
   }
   return (ER_CLI_SYNTAX);
}

/****************************************************************************
**
**  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
   U8 cs;

   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);
      return(GOOD);
   }

   // next argument must be the chipselect number
   if ((err = MapFindCSNum(&cmdString[(U16)argv[1]],&cs))!=GOOD) return(err);

   // next argument must be the beginning address
   if ((err = AdrCreateAddressFromText(&cmdString[(U16)argv[2]],
      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 = 3; 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) {
            if (gSystemType == PROC_MICEPACK)
               map.accessRights = MAP_ROM;
            else
               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]], "f0",
                   strlen(&cmdString[(U16)argv[argIndex]])) == 0) ||
                  (strncmpi(&cmdString[(U16)argv[argIndex]], "sp0",
                   strlen(&cmdString[(U16)argv[argIndex]])) == 0)) 
         {
            space |= MAP_SPC0;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if ((strncmpi(&cmdString[(U16)argv[argIndex]], "f3",
                   strlen(&cmdString[(U16)argv[argIndex]])) == 0) ||
                  (strncmpi(&cmdString[(U16)argv[argIndex]], "sp3",
                   strlen(&cmdString[(U16)argv[argIndex]])) == 0)) 
         {
            space |= MAP_SPC3;
            spaceFlag = TRUE;
            argumentRecognized = TRUE;
         }
         else if ((strncmpi(&cmdString[(U16)argv[argIndex]], "f4",
                   strlen(&cmdString[(U16)argv[argIndex]])) == 0) ||
                  (strncmpi(&cmdString[(U16)argv[argIndex]], "sp4",
                   strlen(&cmdString[(U16)argv[argIndex]])) == 0)) 
         {
            space |= MAP_SPC4;
            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[3]],
             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 ((gProcessor != M68302_MP) &&
                (gProcessor != M68302LC_MP) &&
                (space & (MAP_SPC0|MAP_SPC3|MAP_SPC4)) )
               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
   // added for LC302 <gene>
   offset1 = (offset1 & 0xFFFFFl) + addrCS[cs];

   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,j;
   U16 space;
   BOOLEAN blockFound = FALSE;
   S8 buf[ADDR_BUFF_SZ], buf1[(ADDR_BUFF_SZ*2)+SIZE_BUFF_TEXT],
      buf2[ADDR_BUFF_SZ];
   DESCRIPTOR addr;
   U8 cs;
   
   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);
      }

      // added for LC302
      cs = offset >> 20;
      offset = offset & 0xFFFFFl;
      for (j=0; j<4 && (cs&1); j++) {
         cs = cs >> 1;
      }
      cs = j;

      /* 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);
         }
       LC302 <gene> */
         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 0x%05lX 0x%05lX",
                         i, &(szCS[cs]), offset, offset2);
         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 (gSpaceType == SP_INTEL) {
            if (space&MAP_SMM) wsprintf(buf1, "%s SMM", buf1);
            if (space&MAP_USR) wsprintf(buf1, "%s User", buf1);
         }
         else {
            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_SPC0) wsprintf(buf1, "%s F0", buf1);
            if (space&MAP_SPC3) wsprintf(buf1, "%s F3", buf1);
            if (space&MAP_SPC4) wsprintf(buf1, "%s F4", 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];
      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"
   FILE    *inputFile;
   U32     simAddress;
   RETCODE err1, err2, firstErr = GOOD;
   MAP_REGISTERS *tblPtr, *posPtr, *savPosPtr;
   S8      inputStr[81];
   BOOLEAN verify, simAddressValid;

   switch (gProcessor) {
      case M68306_MP:
         return(ER_NOT_SUPPORTED);
      case M68302_MP:
      case M68302LC_MP:
         tblPtr = table302;
         break;
      case M68307_MP:
         tblPtr = table307;
         break;
      case M68328_MP:
         tblPtr = table328;
         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;
      }
      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 */
   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;
   /* create and fill in address descriptor in order to read memory */

   for( posPtr = tblPtr; strlen(posPtr->regName) != 0; posPtr++ ) {
      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;
            break;
         }
         continue;
      }
      if( simAddressValid || posPtr->VIR ) {
         if ((err2 = Sds2AbiSetIntReg(posPtr->offset, posPtr->size,
               posPtr->restoreValue, TRUE)) != GOOD) break;
      }
   }
   if (firstErr==GOOD && err2==GOOD)
      firstErr = EnlEventNotify(EVENT_MEM_EDIT);

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);
   return firstErr;
}  /* end of RestoreChipSelects */


/****************************************************************************
**
** 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];
   MAP_REGISTERS *tblPtr;
   BOOLEAN simAddressValid;
   
   switch (gProcessor) {
      case M68306_MP:
         return(ER_NOT_SUPPORTED);
      case M68302_MP:
      case M68302LC_MP:
         tblPtr = table302;
         break;
      case M68307_MP:
         tblPtr = table307;
         break;
      case M68328_MP:
         tblPtr = table328;
         break;
      default:
         return(ER_PROC_TYPE_UNKNOWN);
   }
   if (NULL == (outFile = fopen(fileName, "wt"))) {
      return ER_MAP_CANNOT_OPEN_FILE;
   }
   /* 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 ) {
      if ((err=Sds2AbiGetIntReg(tblPtr->offset, tblPtr->size, (U32 *)reg, TRUE))
           != GOOD) return(err);

      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[1], reg[0]); break;
         case 4:  fprintf(outFile, "0x%02X%02X%02X%02X\n", reg[3],
                          reg[2], reg[1], reg[0]); break;
      }
        /* Override SDN_SIM_ADDRESS if 330/340/360 */

      tblPtr++;
   }
CLEANUP2:
   fclose(outFile);
   return(err);
}  /* end of MapSaveCS */


/****************************************************************************
**
** 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, j;
   S8 buf[ADDR_BUFF_SZ], buf1[(ADDR_BUFF_SZ*2)+SIZE_BUFF_TEXT],
      buf2[ADDR_BUFF_SZ];
   DESCRIPTOR addr;
   U8 cs;

   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;

      /* changed for LC302 map syntax <gene> 5/27/98 */
      cs = (U8)(offset >> 20);
      for (j = 0; j<4 && cs&1; j++) {
        cs = cs >> 1;
      }
      cs = j;

      offset &= 0xfffffl;
      offset2 &= 0xfffffl;
      if((err = AdrSetAddrOffset(map.address, offset)) != GOOD) {
         AdrDestroyAddress(addr);
         AdrDestroyAddress(map.address);
         return(err);
      }

      /* 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 %s", szCS[cs], 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 (gSpaceType == SP_INTEL) {
            if (space&MAP_SMM) wsprintf(buf1, "%s SMM", buf1);
            if (space&MAP_USR) wsprintf(buf1, "%s USER", buf1);
         }
         else {
            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_SPC0) wsprintf(buf1, "%s F0", buf1);
            if (space&MAP_SPC3) wsprintf(buf1, "%s F3", buf1);
            if (space&MAP_SPC4) wsprintf(buf1, "%s F4", 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 PRIVATE 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);
}

/****************************************************************************
**
** MapCliDiagnost
**
*****************************************************************************/
RETCODE EXPORT MapCliDiagnost(LPSTR cmdString, U32 argc, U32 argv[]) {

   if(argc > 1) return(ER_CLI_SYNTAX);
   MemCliDiagnost();
   iceSetMap(0L,0L,3); /* Initialize FW MAP table */
   MapClear();
   iceSetMap(0L,0L,3); /* Initialize FW MAP table again */
   return GOOD;
}

/****************************************************************************
**
** MapCovtAddrToCS
**   Mapping address setting to chip-selector setting.
**   This function is added for LC302
**
*****************************************************************************/
#define MAX_CS_REG_NO 8
RETCODE EXPORT MapCovtAddrToCS(U32 *dest, U32 src) {
   RETCODE err=GOOD;
   U32     reg[MAX_CS_REG_NO], BaseAddr, MaskAddr;
   MAP_REGISTERS *tblPtr;
   U8      idx, RegNo;
   
   tblPtr = table302;
   RegNo  = 8;

   for (idx = 0; idx < RegNo; idx++ ) {
      if ((err=Sds2AbiGetIntReg(tblPtr->offset, tblPtr->size, &(reg[idx]), TRUE))
           != GOOD) return(err);
      tblPtr++;
   }

   *dest = (src & 0xFFFFFl);
   for (idx = 0; idx < (RegNo/2); idx++) {
      BaseAddr = (reg[2*idx] & 0x1FFC) << 11;
      MaskAddr = (reg[2*idx+1] & 0x1FFC) << 11;
      if ((BaseAddr&MaskAddr) == (src&MaskAddr)) {
         *dest += ((U32)((0x1<<idx)^0xF) << 20);
         break;
      }
   }

   if (idx == (RegNo/2))
      *dest += 0xF00000l;

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

/****************************************************************************
**
** MapGetCSBaseAddr
**   Get the base address of current chip-selector setting.
**   This function is added for LC302
**
*****************************************************************************/
RETCODE EXPORT MapGetCSBaseAddr(U8 cs, U32 *addr) {
   RETCODE err=GOOD;
   U32     reg;
   MAP_REGISTERS *tblPtr;
   U8      idx;
   
   if (cs >= 4) cs = 0;
   tblPtr = table302 + 2 * cs;
   if ((err=Sds2AbiGetIntReg(tblPtr->offset, tblPtr->size, &reg, TRUE))
           != GOOD) return(err);

   *addr = (reg & 0x1FFC) << 11;

   return(err);
}  /* end of MapGetCSBaseAddr */
/******************************** E O F ***********************************/
