/****************************************************************************
**
**  Name:  sds2abi.c
**
**  Description:
**     Contains the main entry/exit point of the SERVERS.DLL
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/mt2_68k/sds/sds2abi.c_v  $
** 
**    Rev 1.7   10 Feb 1998 11:56:18   Eric
** Added ICE_ERR_MN_CONFIG error code in iceMapError.
** 
**    Rev 1.6   12 May 1997 13:44:50   gene
** 
**    Rev 1.5   10 Apr 1997 09:47:44   gene
** 
**    Rev 1.4   31 Mar 1997 09:48:00   gene
** 
**    Rev 1.3   18 Mar 1997 10:10:10   gene
** 
**    Rev 1.2   10 Mar 1997 13:03:34   gene
** 
**    Rev 1.1   04 Mar 1997 13:00:40   gene
** 
**    Rev 1.0   13 Feb 1997 09:03:56   gene
** Initial revision.
** 
**    Rev 1.30   19 Jul 1996 11:58:02   kevin
** Modified sds2abigettraceframes() to be able to get frames under 8-bit mode
** 
**    Rev 1.29   18 Jun 1996 16:32:22   kevin
** initialize all signals to be high
** 
**    Rev 1.28   13 Jun 1996 09:31:06   gene
** added Sds2abiGetCoreType and modify Sds2AbiSetIntReg/Sds2AbiGetIntReg
** 
**    Rev 1.27   29 May 1996 17:50:30   kevin
** restored data2 and highword(misc) to uGroup
** 
**    Rev 1.26   10 May 1996 13:54:32   kevin
** added 302 case
** 
**    Rev 1.25   13 Feb 1996 16:49:48   kevin
** 
**    Rev 1.24   23 Jan 1996 09:09:40   kevin
** initialize SDN_LOAD_ACCESS member while executing Sds2AbiInitCoreMembers()
** 
**    Rev 1.23   19 Jan 1996 11:57:12   kevin
** modified iceMapError
** 
**    Rev 1.22   18 Jan 1996 14:17:32   kevin
** modified sds2abimemcompare()
** 
**    Rev 1.17   23 Nov 1995 10:38:42   kevin
** replaced some messages in iceMapError()
** 
**    Rev 1.16   20 Nov 1995 17:57:30   kevin
** modified iceMapError()
** 
**    Rev 1.15   17 Nov 1995 13:31:22   kevin
** added Sds2AbiSetVerify()
** 
**    Rev 1.14   16 Nov 1995 14:57:46   kevin
** removed iceSetMap() from SdsAbiInitCoreMembers()
** 
**    Rev 1.13   16 Nov 1995 14:44:42   kevin
** added no emm memory msg to iceMapError()
** 
**    Rev 1.12   15 Nov 1995 14:44:50   kevin
** put spare data of trace frames to TRACE_FRAME.Smsw in Sds2AbiGetTraceFrames
** 
**    Rev 1.11   06 Nov 1995 13:16:34   kevin
** added 68307 and 68328 cases in FwUnloadRegisters
** 
**    Rev 1.10   06 Nov 1995 10:26:00   kevin
** added 68307 and 68328 cases
** 
**    Rev 1.9   18 Oct 1995 10:40:58   kevin
** modified icemaperror()
** 
**    Rev 1.8   26 Sep 1995 10:48:02   kevin
** changed GetMapSize()
** 
**    Rev 1.7   22 Sep 1995 13:17:02   kevin
** modified memfill() to avoid download problem
** 
**    Rev 1.6   22 Sep 1995 11:32:00   kevin
** added compare
** 
**    Rev 1.5   14 Sep 1995 14:51:34   kevin
** 
**    Rev 1.4   14 Sep 1995 14:28:38   kevin
** added sds2abimemchecksum()
** 
**    Rev 1.3   13 Sep 1995 16:18:46   kevin
** modified FillMemAction()
** 
**    Rev 1.2   12 Sep 1995 18:20:36   kevin
** made two modification in memory fill function:
** 1. access size is always byte
** 2. fixed a bug while calculating misalignLen
** 
**    Rev 1.1   08 Sep 1995 13:02:46   kevin
** modified Sds2AbiFillMemAction() to handle odd boundary problem
** 
**    Rev 1.0   07 Sep 1995 11:12:10   gene
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_68k/sds/sds2abi.c_v   1.7   10 Feb 1998 11:56:18   Eric  $
**
*****************************************************************************/

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

/* !!! Windows */
#define _WINDOWS_

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifndef _BASEWIND_
#include "basewind.h"
#endif

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

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif

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

#ifndef _PVTASK_
#include "pvtask.h"
#endif

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

#ifndef _SDPROC_
#include "sdproc.h"
#endif

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

#ifndef _SHAREDAT_
#include "sharedat.h"
#endif

#ifndef _WSCOM_
#include "wscom.h"
#endif

#ifndef __TIME_H
#include "time.h"
#endif

#ifndef _VERSIONS_
#include "versions.h"
#endif

#ifndef  _SDS2ABI_
#include "sds2abi.h"
#endif

#include "mtat.h"

#define loword(x)  ((U16)((x)&0xffff))
#define hiword(x)  ((U16)(((x)>>16)&0xffff))
U32 SwapDwordOrder(U32 input);
U16 SwapWordOrder(U16 input);
void iceSetAccessSpace(ADDR_SPACE space);

STATUS   status;

typedef enum {
   BKPT_UNLOADED, BKPT_XBRK, BKPT_SWB, BKPT_STATUS_END=0x7fff
} BKPT_STATUS;

typedef struct BKPT_ENTRY_TAG {
   struct BKPT_ENTRY_TAG *next;
   struct BKPT_ENTRY_TAG *prev;
   U16 id;
   U16 opcode;
   U32 addr;
   ADDR_SPACE space;
   BKPT_STATUS status;
} BKPT_ENTRY;

BAD_MEMORY  badAddr1, badAddr2;
U16   MPBreakCause;

CPU_REG  regMapTable[] =
   {
   R_PC, R_A7, R_A6,
   R_D0, R_D1, R_D2, R_D3, R_D4, R_D5, R_D6, R_D7,
   R_A0, R_A1, R_A2, R_A3, R_A4, R_A5,
   R_SR, R_SSP, R_USP
   }; // sfc, dfc, vbr

static ADDR  abiAddr1, abiAddr2;

/* Define symbol to exclude the WEP routine */
#define _BORLANDC_
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

/* Handle of the DLL instance */
HANDLE hLib;

                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/
U16 SwapWord(U16 src);

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

/**************************************************************************
**
** LibMain
**
** Description: Main entry point of the SERVERS.DLL
**
**      Parameters:
**    input:
**       hInstance:     Handle of the library instance
**       wDataSeg:      Value of Data Segment register
**       cbHeapSize:    Heap Size of the heap defined in the DEF
**       lpszCmdLine:   Command Line information (rarely used)
**
**    output:
**
***************************************************************************/
#pragma argsused
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize,
    LPSTR lpszCmdLine) {
    /* the LIBENTRY initializes the local heap by calling LocalInit() and
       then calls LibMain.  The LocalInit() locks the data segment of the
       library when initialize; therefore LibMain needs to unlock */
    if (cbHeapSize != 0) /* the DLL Data segment is MOVEABLE */
       UnlockData(0);
    ErrInitDLL(MODULE_SHARED_DATA,"sds2abi.dll");
    /* initialize successfully */
    hLib = hInstance;
    return(TRUE);
}

#ifndef _BORLANDC_
/**************************************************************************
**
** WEP {Windows Exit Procedure}
**
** Description: DLL exit procedure to perform cleanup for the DLL before it
**              is unloaded. - not to be used with BC++ compiler.
**
**      Parameters:
**    input:
**       nParam:     Message to indicate whether all of Windows is shutting
**                   down or just the DLL itself.
**
**    output:
**       return a 1 to indicate success
**
***************************************************************************/
void FAR PASCAL WEP(int nParam) {

   switch(nParam) {
      case WEP_SYSTEMEXIT:
         /* System shutdown in progress. Respond accordingly */
         break;
      case WEP_FREE_DLL:
         /* The DLL use count is 0 */
         break;
      default:
         /* Undefined value - ignore */
         break;
   }
   return(TRUE);
}
#endif

/*****************************************************************************
**
** (Probe) Interface Functions To MICEPack ABI
**
*****************************************************************************/
RETCODE EXPORT  Sds2AbiLoadMicePackFw(U16 port)
{
INITIAL_INFO initInfo;
RETCODE  ret;
S8    buf[64], buf2[16];
U8    BaseTime;

#define INI_FILENAME "micepack.ini"

   GetPrivateProfileString("SystemInfo", "MICEpack", "", buf, sizeof(buf), INI_FILENAME);
   GetPrivateProfileString("Comm", "BaseTime", "0xFF", buf2, sizeof(buf2), INI_FILENAME);
   BaseTime = (U8)atoi(buf2);
   if (BaseTime == 0) BaseTime = 0xFF;
   if (stricmp(buf, "68306")==0 || stricmp(buf, "68307")==0 || 
       stricmp(buf, "68328")==0 || stricmp(buf, "68302")==0 )
      {
        initInfo.portAddr    = port;      // I/O port address.
        initInfo.idFlag      = M68000;    // CPU type.
        initInfo.buffSize    = 0x400;     // buffer size of communication
        initInfo.testResult  = 0;         // clear data.
        initInfo.testFlag    = ON;        // do selftest.
        initInfo.timeOut     = BaseTime;      // 3 second.
//        initInfo.timeOut     = 0xff;      // 3 second.
        if (stricmp(buf, "68306")==0)
           strcpy(initInfo.fileName,"main306.bin"); // download file(include path).
        else if (stricmp(buf, "68307")==0)
           strcpy(initInfo.fileName,"main307.bin"); // download file(include path).
        else if (stricmp(buf, "68328")==0)
           strcpy(initInfo.fileName,"main328.bin"); // download file(include path).
        else if (stricmp(buf, "68302")==0)
           strcpy(initInfo.fileName,"main302.bin"); // download file(include path).

        ret = iceMapError(iceInitialize(&initInfo));
      return (ret);
      }
   else {
      return ER_PROC_TYPE_UNKNOWN;
      }
}

/*****************************************************************************
**
** Sds2AbiFwPingProbe
**
** description:
**    Send a command (essentially NOP) to probe to see if it's alive
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwPingProbe(VOID) {
   return(GOOD);
}

////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetMapBlocks
//
// description:
//    get the maximum number of blocks user can set in Map command
//
// Parameters:
//    Input:   <none>
//    Output:  <block> map blocks.
////////////////////////////////////////////////////////////////////////////
RETCODE EXPORT Sds2AbiFwGetMapBlocks(U32 *block)
{
   *block = (U32)16;
   return(GOOD);
}

////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetMapSize
//
// description:
//    get the size of each map blocks
//
// Parameters:
//    Input:   <none>
//    Output:  <size> block size
////////////////////////////////////////////////////////////////////////////
RETCODE GetMapSize(U32 *size) {
RETCODE  err;

   err = iceGetMapSize(size);
   return(err);
}

RETCODE EXPORT Sds2AbiFwGetMapSize(U32 *size) {
RETCODE  err;

   err = GetMapSize(size);
   return(err);
}

////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetMapGranularity
//
// description:
//    get the minimum granularity of a map block
//
// Parameters:
//    Input:   <none>
//    Output:  <gran> granularity.
////////////////////////////////////////////////////////////////////////////
RETCODE EXPORT Sds2AbiFwGetMapGranularity(U32 *gran)
{
   *gran = (U32)0x800L;
   return(GOOD);
}

/*****************************************************************************
**
** Sds2AbiFwLoadRegisters
**
** description:
**    Read register contents from shared data and write into chip.
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwLoadRegisters(VOID)
{
CPU_TYPE cpuType;

   Sds2AbiGetCpuType(&cpuType);
   if (cpuType==CPU306 || cpuType==CPU307 || cpuType==CPU328 || cpuType==CPU302) 
      return(Sds2AbiFwLoadRegistersCpu306());
   return(ER_NOT_CPU); //assertion fail -- by kevin
}

RETCODE  Sds2AbiFwLoadRegistersCpu306(VOID) {
RETCODE err;
LOOP_VAR i;
U32 reg;

   for (i=0; i<MAX_CPU_REG_NUM; i++)  // ABI hold CCR, discard this
      {
      if (i==1) continue;   /* skip A7 "register", covered by ssp/usp */
      if ((err = SdnReadMember(SDN_PC+i, (U8*)&reg)) != GOOD) return(err);
      if ((err = SetReg(regMapTable[i], reg)) != GOOD) return(err);
      }
   return(GOOD);
}

/*****************************************************************************
**
** Sds2AbiFwUnloadRegisters
**
** description:
**    Extract register contents from chip and write to shared data members
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwUnloadRegisters(BOOLEAN patchPCSP) {
RETCODE err;
CPU_TYPE cpuType;

   if ((err = Sds2AbiStepPostamble()) != GOOD) return(err);
   Sds2AbiGetCpuType(&cpuType);
   if (cpuType==CPU306 || cpuType==CPU307 || cpuType==CPU328 || cpuType==CPU302) 
      return(Sds2AbiFwUnloadRegistersCpu306(patchPCSP));
   return(ER_NOT_CPU); //assertion fail -- by kevin
}

RETCODE  Sds2AbiFwUnloadRegistersCpu306(BOOLEAN patchPCSP) {
RETCODE err;
LOOP_VAR i;
U32 reg;

   for (i=0; i<MAX_CPU_REG_NUM; i++) {
      if ((err = GetReg(regMapTable[i], &reg)) == GOOD)
         {
//         reg = SwapDwordOrder(reg);
         if (patchPCSP && (reg&1))
            {
            switch (i)
               {
               case SDN_PC-SDN_PC:
                  reg=0x400;        /* Set PC to 0x400 if odd (read failed) */
                  break;
               case SDN_A7-SDN_PC:
               case SDN_SSP-SDN_PC:
                  reg=0x1000;       /* Set SP to 0x1000 if odd (read failed)*/
                  break;
               }
            }
         if ((err = SdnWriteMemberNoCallback(SDN_PC+i,(U8*)&reg,GOOD))!=GOOD)
            break;
         }
      if (err) break;
      }
   return(GOOD);
}

/*****************************************************************************
**
** Sds2AbiFwPowerOn
**
** description:
**    Called when probe sends power-on byte.  This function sends either
**    a RESET command or GR command packet, depending on SD_EMULATION_STATE.
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwPowerOn(VOID) {
   RETCODE err;
   EMULATION_STATE iceState;
   if ((err = SdnReadMember(SDN_EMULATION_STATE,(U8*)&iceState)) != GOOD)
      return(err);
   if (iceState == EM_HALTED) return(Sds2AbiFwReset(RESET_CPU_AND_UPDATE_STATUS));
   else return(Sds2AbiFwGr(&iceState));
}

/**************************************************************************
**
** Sds2AbiFwFillMem
**
**************************************************************************/
RETCODE EXPORT Sds2AbiFwFillMem(U32 offset, ADDR_SPACE space, U32 length,
       U32 pLength, ACCESS_SIZE access, BOOLEAN verify,
       VERIFY_INFO *verifyInfo, U8 *data) {
   RETCODE err,err2;
   EMULATION_STATE runaccState;
   U32 regSave[2];


   if ((err = Sds2AbiRunaccStart(&runaccState,regSave)) != GOOD) return(err);
   err = Sds2AbiFillMemAction(offset,space,length,pLength,access,verify,verifyInfo,
      data);
   err2 = Sds2AbiRunaccFinish(runaccState,regSave);
   return(err?err:err2);
}

void iceSetAccessSpace(ADDR_SPACE space)
{
   abiAddr1.space = (U16)space;
   abiAddr2.space = (U16)space;
}

RETCODE EXPORT Sds2AbiFillMemAction(U32 offset, ADDR_SPACE space, U32 length,
       U32 pLength, ACCESS_SIZE access, BOOLEAN verify,
       VERIFY_INFO *verifyInfo, U8 *data) {
   RETCODE err;
   U8 pattern[128], i, p;
   U32 misalignLen;
   /*
   ** Phase 1: If request is not aligned, read entire item, change bytes,
   **   then write entire item.
   */

   if (space == SPACE_DONT_CARE) space = SPACE_SD;
   status = iceSetAccessSize(access);
   if ((err = iceMapError(status)) != GOOD) return(err);
   iceSetAccessSpace(space);

   abiAddr1.pos = offset;
   if (pLength == length) {
      if (space==SPACE_SD && offset>=0xFFFFF800) {
         if ((err = iceFill(&abiAddr1, pLength, data, pLength)) != GOOD)
            err = iceMapError(err);
      }
      else
         if ((err = iceSetMemN(abiAddr1, data, pLength)) != GOOD)
            err = iceMapError(err);
      return(err);
   }
   misalignLen = offset & ((U32)access-1);
   if (misalignLen > length) 
      misalignLen = length;
   
   if (misalignLen > 0) {
      for (i=0; i<misalignLen; i++)
         pattern[i] = data[i%pLength];
      if ((err = iceSetMemN(abiAddr1, pattern, misalignLen)) != GOOD)
         return(iceMapError(err));
      
      offset += misalignLen;
      length -= misalignLen;
   }
   for (i=0; i<pLength; i++)
      pattern[i] = data[(i+misalignLen)%pLength];
   
   if (length > 0) {
      misalignLen = length % access;
      abiAddr1.pos = offset; 
      if (length > misalignLen)
         if ((err = iceFill(&abiAddr1, length-misalignLen, pattern, pLength)) != GOOD)
            return(iceMapError(err));
      if (misalignLen > 0) {
         abiAddr1.pos = offset + length - misalignLen;
         p = abiAddr1.pos%pLength;
         for (i=0; i<pLength; i++)
            data[i] = pattern[(p+i)%pLength];
         for (i=0; i<misalignLen; i++)
            pattern[i] = data[i%pLength];
         if ((err = iceSetMemN(abiAddr1, pattern, misalignLen)) != GOOD)
            return(iceMapError(err));
      }
   }
   return(GOOD);
}

/**************************************************************************
**
** Sds2AbiFwReadMem
**
**************************************************************************/
RETCODE EXPORT Sds2AbiFwReadMem(U32 offset, ADDR_SPACE space, U32 length,
                          ACCESS_SIZE access, U8 *data) {
   RETCODE err,err2;
   EMULATION_STATE runaccState;
   U32 regSave[2];

   if ((err = Sds2AbiRunaccStart(&runaccState,regSave)) != GOOD) return(err);
   err = Sds2AbiReadMemAction(offset,space,length,access,data);
   err2 = Sds2AbiRunaccFinish(runaccState,regSave);
   return(err?err:err2);
}

RETCODE  Sds2AbiReadMemAction(U32 offset, ADDR_SPACE space, U32 length,
                          ACCESS_SIZE access, U8 *data) {
   RETCODE err;
   STATUS   status;
   U8 temp[4];
   U16 pktLength;
   U32 misalignAmount, misalignLength;

   if (space == SPACE_DONT_CARE) space = SPACE_SD;
   status = iceSetAccessSize(access);
   if ((err = iceMapError(status)) != GOOD) return(err);
   iceSetAccessSpace(space);
   if ((err = iceMapError(status)) != GOOD) return(err);

   /*
   ** Phase 1:  If start address is not aligned to boundary, read item
   **   at next lower boundary and extract bytes in requested range.
   */
   misalignAmount = offset & ((U32)access-1);
   misalignLength = min(length, access - misalignAmount);
   if (misalignAmount > 0)
      {
      pktLength = (U16)access;
      abiAddr1.pos = offset-misalignAmount;
      if ((err = iceGetMemN(abiAddr1, temp, pktLength)) != GOOD)
         return(iceMapError(err));
      memcpy(data,temp+(U16)misalignAmount,(U16)misalignLength);
      data += (U16)misalignLength;
      offset += misalignLength;
      length -= misalignLength;
      }
   if (length == 0) return(GOOD);
   /*
   ** Phase 2: Read bulk of request, up to the last boundary in the range
   */
   misalignAmount = length & ((U32)access-1);  /* bytes after last boundary */
   misalignLength = length - misalignAmount;
   for ( ; misalignLength>0; length-=pktLength,
          misalignLength-=pktLength, data+=pktLength, offset+=pktLength) {
      pktLength = (U16)min(ABI_MAX_READ, misalignLength);
      abiAddr1.pos = offset;
      if ((err = iceGetMemN(abiAddr1, data, pktLength)) != GOOD)
         return(iceMapError(err));
   }
   if (length == 0) return(GOOD);
   /*
   **  Phase 3: Finally, read item covering the last few bytes if the end
   **    address is not aligned.
   */
   pktLength = (U16)access;
   abiAddr1.pos = offset;
   if ((err = iceGetMemN(abiAddr1, temp, pktLength)) != GOOD)
      return(iceMapError(err));
   memcpy(data,temp,(U16)length);

   return(GOOD);
}

RETCODE EXPORT Sds2AbiFwSaveFCRegs(U32 *regs) {
   // ??? this should return NOT_SUPPORTED
   return(GOOD);
}

RETCODE EXPORT Sds2AbiFwRestoreFCRegs(U32 *regs) {
   // ??? this should return NOT_SUPPORTED
   return(GOOD);
}

RETCODE EXPORT SetReg(CPU_REG regId, U32 regValue)
{
   status = iceSetReg(M68K_REG, regId, regValue);
   return(iceMapError(status));
}

RETCODE EXPORT GetReg(CPU_REG regId, U32 *regValue)
{
   status = iceGetReg(M68K_REG, regId, regValue);
   return(iceMapError(status));
}

RETCODE EXPORT iceMapError(STATUS status)
{
   switch (status)
      {
      case ICE_EP_PENDING:
      case ICE_WARN_START:
      case ICE_OK:                  return(GOOD);
      case ICE_NOT_READY:           return(ER_INTERNAL_TERMINATION);
      case ICE_NO_VCC:              return(ER_TARGET_VCC);
      case ICE_BUS_REQUEST:         return(ER_BUS_TIMEOUT);
      case ICE_STEP_ERROR:          return(ER_STEP_TIMEOUT);
      case ICE_MICE_HALT:           return(ER_WAIT_EMOFF_TIMEOUT);
      case ICE_TARGET_RESET:        return(ER_RESET_UNIT_FAILED);
      case ICE_BANK_FULL:           return(ER_NO_FREE_MAP_BLOCKS);
      case ICE_ADDR_RANGE_OVERFLOW: return(ER_BLOCK_TOO_LARGE);
      case ICE_ATTRIBUTE_MISMATCH:  return(ER_MAP_UNKNOWN_TYPE);
      case ICE_REC_TIME_OUT:        return(ER_COMM_PACKET_TIMEOUT);
      case ICE_HALT_USER:           return(GOOD); 
      case ICE_ERROR_WRITE:         return(ER_MEMORY_VERIFY);
      case ICE_EVENT_FULL:          return(ER_TOO_MANY_EVENTS);// need to redefined another error message
      case ICE_FILE_NOT_FOUND:      return(ER_FILE_NOT_FOUND);
      case ICE_MICE_LIMIT:          return(ER_WAIT_BDM_TIMEOUT);//!! by kevin
      case ICE_ERROR_BOUN:          return(ER_INPUT_OVERRUN);// error map boundary
      case ICE_MEM_GUARD:           return(ER_ADR_LDT_INVALID); // Access the guarded memory
      case ICE_MEM_PROTECT:         return(ER_ADR_NULL_GDT_DESCRIPTOR); // Access the protected memory
      case ICE_NO_EMM:              return(ER_NO_MEMORY_PRESENT);
      case ICE_ERROR_READ:          return(ER_INTERNAL_TERMINATION); // Memory read failure
      case ICE_NO_FOUND:            return(ER_KEY_TOKEN_NOT_FOUND);
      case ICE_BAD_REG:             return(ER_DAD_REG_INVALID);// Bad register number encountered
      case ICE_ERROR_COM:
      case ICE_TIME_OUT:            return(ER_COMM_PACKET_TIMEOUT);
      case ICE_ERROR_MICE:          return(ER_PROC_TYPE_UNKNOWN);  // linking incorrect MICE model
      case ICE_MAP_FAIL:              // memory map fail
      case ICE_EMM_SET_ERROR:         //
      case ICE_EMM_FAIL:            return(ER_BLOCK_UNMAPPABLE);
      case ICE_BREAK:                 // Break on memory access
      case ICE_BREAK_I:             return(ER_DASM_MEMORY);   // Break on instruction fetch
      case ICE_BAD_IN:              return(ER_CANT_DO_COMMAND);// Error encountered on user input
      case ICE_BAD_FRAME:           return(ER_INVALID_FRAME);
      case ICE_ABS_OVERFLOW:        return(ER_ADR_ADDRESS_TOO_LARGE);
      case ICE_COMMAND_ERROR:       return(ER_CMD_ABORT);
      case ICE_NO_TRACE_MODULE:     return(ER_INVALID_BUFFER);
      case ICE_BANK_MISMATCH:       return(ER_INVALID_MAP_BLOCK);
      case ICE_SPACE_MISMATCH:      return(ER_ADR_DIFFER_SPACES);
      case ICE_ADDR_MISMATCH:       return(ER_ADR_DIFFER_TYPES);
      case ICE_CNT_ERROR:           return(ER_BAD_COUNTER);
      case ICE_TIMER_ERROR:         return(ER_TIMER_NOT_AVAIL);
      case ICE_ERR_MN_CONFIG:       return(ER_DQ_NO_FRAMES_AVAILABLE);// Eric 2/4/98 for Bug ID#199
      case ICE_BUFFER_EMPTY:        return(ER_DAD_NO_FLUSH_FRAMES_FOUND);
      case ICE_INVALID_CPU:         return(ER_PROC_TYPE_UNKNOWN);
      case ICE_MCE16A_FAIL:
      case ICE_TEST_FAIL:
      case ICE_BROKE:                 // CPU stop
      case ICE_LINK_MICE_FAIL:
      case ICE_TRACE_BOARD_FAIL:
      case ICE_COV_RBW_FAIL:        return(ER_TEST_ABORT);
      case ICE_USER_CC:               // CC code by user
      case ICE_NO_DIFF:               // No difference in memory compare
      case ICE_CPU_RUN:               // CPU free running
      case ICE_BKPT1_HALT:            //
      case ICE_BKPT2_HALT:            //
      case ICE_VIOL_HALT:             //
      case ICE_RBW_HALT:              //
      case ICE_TRIG_HALT:             //
      case ICE_CPU_FLY:             return(GOOD);
      case ICE_INVALID_FLY_COMMAND: return(ER_CMD_ABORT);
      case ICE_INVALID_FIRMWARE:    return(ER_PROBE_FW_VERSION);
      default:
         return(ER_NOT_SUPPORTED);
      }
   return(!GOOD);
}

/****************************************************************************
**
**  Sds2AbiInitCoreMembers
**
**  Description:
**
**     Initialize all the shared data members in sdinit.h.
**
**  Parameters:
**     input:
**        none
**     output:
**        none
**
*****************************************************************************/
RETCODE EXPORT Sds2AbiInitCoreMembers(VOID) {
   RETCODE err;
//   DESCRIPTOR desc;
   TBIRD_STATUS tbirdStatus;
   BOOLEAN slotPresent;
   U8 sdData;
   /*
   ** initialize configuration information
   */
   /*
   ** initialize motherboard configuration
   */
   slotPresent = TRUE;
   if((err = SdnWriteMember(SDN_MOM_PRESENT, &slotPresent, GOOD))!=GOOD)
      return(err);
   sdData = (U8)(1);
   if((err = SdnWriteMember(SDN_MOM_MAJOR_VERSION, &sdData, GOOD))!=GOOD)
      return(err);
   sdData = (U8)(0);
   if((err = SdnWriteMember(SDN_MOM_MINOR_VERSION,&sdData, GOOD))!=GOOD)
      return(err);
   sdData = (U8)(1);
   if((err = SdnWriteMember(SDN_MOM_COMPATIBILITY, &sdData, GOOD))!=GOOD)
      return(err);

   /*
   ** initialize SWAT present/version
   */
   slotPresent = FALSE;
   if((err = SdnWriteMember(SDN_SWAT_PRESENT, &slotPresent, GOOD))!=GOOD)
      return(err);
   if (slotPresent) {
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_SWAT_MAJOR_VERSION, &sdData, GOOD))!=GOOD)
         return(err);
      sdData = (U8)(0);
      if((err = SdnWriteMember(SDN_SWAT_MINOR_VERSION, &sdData, GOOD))!=GOOD)
         return(err);
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_SWAT_COMPATIBILITY, &sdData, GOOD))!=GOOD)
         return(err);
   }

   /*
   ** initialize TMOD R present/version
   */
   slotPresent = TRUE;
   if((err =SdnWriteMember(SDN_TRACE_0_SLOT_PRESENT,&slotPresent,GOOD))!=GOOD)
      return(err);
   if (slotPresent) {
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_0_MAJOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(0);
      if((err = SdnWriteMember(SDN_TRACE_0_MINOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_0_COMPATIBILITY,&sdData,GOOD))!=GOOD)
         return(err);
   }

   /*
   ** initialize TMOD S present/version
   */
   slotPresent = TRUE;
   if((err =SdnWriteMember(SDN_TRACE_1_SLOT_PRESENT,&slotPresent,GOOD))!=GOOD)
      return(err);
   if (slotPresent) {
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_1_MAJOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(0);
      if((err = SdnWriteMember(SDN_TRACE_1_MINOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_1_COMPATIBILITY,&sdData,GOOD))!=GOOD)
         return(err);
   }

   /*
   ** initialize TMOD T present/version
   */
   slotPresent = TRUE;
   if((err =SdnWriteMember(SDN_TRACE_2_SLOT_PRESENT,&slotPresent,GOOD))!=GOOD)
      return(err);
   if (slotPresent) {
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_2_MAJOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(0);
      if((err = SdnWriteMember(SDN_TRACE_2_MINOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_2_COMPATIBILITY,&sdData,GOOD))!=GOOD)
         return(err);
   }

   /*
   ** initialize TMOD U present/version
   */
   slotPresent = FALSE;    // MICEpack 306, 302 and 186 has less than 96 channels
   if((err =SdnWriteMember(SDN_TRACE_3_SLOT_PRESENT,&slotPresent,GOOD))!=GOOD)
      return(err);
   if (slotPresent) {
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_3_MAJOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(0);
      if((err = SdnWriteMember(SDN_TRACE_3_MINOR_VERSION,&sdData,GOOD))!=GOOD)
         return(err);
      sdData = (U8)(1);
      if((err = SdnWriteMember(SDN_TRACE_3_COMPATIBILITY,&sdData,GOOD))!=GOOD)
         return(err);
   }

   /*
   ** initialize probe type and version numbers
   */
   {
      U32 prbData;
//      if((err = RdPrbType(&prbData))!=GOOD) sdData=(U8)PROBE_NONE;
//         else sdData = (U8)prbData;
      sdData = PROBE_NONE;
      if((err = SdnWriteMember(SDN_PROBE_TYPE, &sdData, GOOD))!=GOOD)
         return(err);
      if(sdData != (U8)PROBE_NONE) {
//         if((err = RdPrbHWRev(&prbData))!=GOOD) return(err);
//         sdData = (U8)((prbData >> HW_MAJOR_SHIFT) & 0xffl);
//         if((err = SdnWriteMember(SDN_PROBE_MAJOR_VERSION,&sdData,GOOD))!=GOOD)
//            return(err);
//         sdData = (U8)((prbData >> HW_MINOR_SHIFT) & 0xffl);
//         if((err =SdnWriteMember(SDN_PROBE_MINOR_VERSION,&sdData,GOOD))!=GOOD)
//            return(err);
//         if((err = RdPrbSWCompat(&prbData))!=GOOD) return(err);
//         sdData = (U8)(prbData & 0xffl);
//         if((err =SdnWriteMember(SDN_PROBE_COMPATIBILITY,&sdData,GOOD))!=GOOD)
//            return(err);
      }
   }
   /*
   ** initialize connecting
   */
   tbirdStatus = AT_RESET;
   if((err = SdnWriteMember(SDN_TBIRD_STATUS, (U8 *)&tbirdStatus, GOOD))!=GOOD)
      return(err);
//   if((err = SdRegister(SD_CONNECT, ConnectRequest, &desc))!=GOOD)
//      return(err);
   /*
   ** initialize the number of bytes in shared data
   */
   {
      U32 numBytes = BYTES_IN_SHARED_DATA;
      if((err = SdnWriteMember(SDN_NUM_SHARED_DATA_BYTES, (U8 *)&numBytes, GOOD))
         !=GOOD) return(err);
   }

   {
      BOOLEAN true=TRUE;
      if ((err=SdnWriteMember(SDN_FW_TRACING_STATUS,&true,GOOD)) != GOOD)
         return(err);
      if((err=SdnWriteMember(SDN_CLK_SIG,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_RESET_SIG,&true,GOOD)) !=GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG02,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG03,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG04,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG05,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG06,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG07,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG08,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG09,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG0A,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG0B,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG0C,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG0D,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG0E,&true,GOOD)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIG0F,&true,GOOD)) != GOOD) return(err);
   }

   {
      U32 temp;
      BREAK_CAUSE cause=CAUSE_NONE;
      EMULATION_STATE iceState = EM_HALTED;

      if ((err = Sds2AbiFwGetMapBlocks(&temp)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_NUM_MAP_BLOCKS,(U8*)&temp,GOOD))!=GOOD)
         return(err);
      if ((err = Sds2AbiFwGetMapSize(&temp)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_SIZE_MAP_BLOCK,(U8*)&temp,GOOD))!=GOOD)
         return(err);
      if ((err = Sds2AbiFwGetMapGranularity(&temp)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_GRAN_MAP_BLOCK,(U8*)&temp,GOOD))!=GOOD)
         return(err);

      if ((err = Sds2AbiFwGetBreakCause(&cause)) != GOOD) return(err);
      if ((err=SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD)) != GOOD)
         return(err);
      
      if ((err = Sds2AbiFwGetEmuState(&iceState)) != GOOD) return(err);
      if((err=SdnWriteMember(SDN_EMULATION_STATE,(U8*)(&iceState),GOOD))
         != GOOD) return(err);
   }
   {
      ACCESS_SIZE loadSize = SIZE_WORD;
      if ((err=SdnWriteMember(SDN_LOAD_ACCESS,(U8*)&loadSize,GOOD)) != GOOD)
         return(err);
   }


   //iceSetMap(0ul, 0ul, 0x0f00); // init all map to external, all space
   return(GOOD);
}

RETCODE EXPORT Sds2AbiConvertTraceMode(TRACE_MODE traceMode, U16 *mpTraceMode)
{
   switch (traceMode)
      {
      case TRACE_PRE:
         *mpTraceMode = 1;
         break;
      case TRACE_POST:
         *mpTraceMode = 0;
         break;
      case TRACE_CENTER:
         *mpTraceMode = 2;
         break;
      }
   return(GOOD);
}

RETCODE EXPORT Sds2AbiSetEvent(U16 evID, BUS_EVENT *bus)
{
   /* always 0xffffffff, only used for both range & mask address */
   bus->addrRangeMask = 0xffffffffl;
   status = iceSetEvent(evID, bus);
   return (iceMapError(status));
}

RETCODE EXPORT Sds2AbiClearEvent(U16 evID)
{
   status = iceClearEvent(evID);
   return (iceMapError(status));
}

RETCODE EXPORT Sds2AbiSetTrig(U16 trigLevel, MP_TRIGGER *trig)
{
   status = iceSetTrig(trigLevel, trig);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiClearTrig(U16 trigLevel)
{
   status = iceClearTrig(trigLevel);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiGetTraceInfo(U16 *level, U16 *subBuf,
         U32 *cnt0, U32 *cnt1, U16 *maxBuf)
{
U16   last, maxSubBuf;

   status = iceGetTraceInfo(&last, cnt0, cnt1, &maxSubBuf);
   if (status != ICE_OK) return(iceMapError(status));
   *maxBuf = last-1;
   *subBuf = last-1;
   *level = 0; // vincent: can firmware support this?
   return(GOOD);
}

RETCODE EXPORT Sds2AbiGetTraceBufferInfo(U16 buffer, U32 *beforeFrames,
            U32 *afterFrames, U32 *trigFrame)
{
S32   start, end;
   status = iceGetTraceBufferInfo(buffer, &start, &end);
   if (status != ICE_OK) return(iceMapError(status));
   *beforeFrames = -(start);
   *trigFrame = 0;
   *afterFrames = end;
   return(GOOD);
}

RETCODE EXPORT Sds2AbiGetTraceBufferLogicInfo(U16 buffer, S32 *start, S32 *end)
{
   status = iceGetTraceBufferInfo(buffer, start, end);
   return (iceMapError(status));
}

BOOLEAN EXPORT Sds2AbiIsTraceBufferEmpty(U16 buffer)
{
S32   start, end;
   status = iceGetTraceBufferInfo(buffer, &start, &end);
   if (status == ICE_BUFFER_EMPTY) return(TRUE);
   else return(FALSE);
}

U32 EXPORT Sds2AbiGetTriggerFrame(U16 buffer)
{
   U32   frame;
   status = iceGetTriggerFrame(buffer, &frame);
   return(frame);
}

RETCODE EXPORT Sds2AbiGetTraceFrames(U16 buffer, U32 frameNo,
               U32 *framesRead, TRACE_FRAME *frames)
{
MP_TRACE_INFO  traceData[48];
U32   num;
U8    frameLen;
QUALIFY_LIST   qList;
S32   start;
U16   coreType;
PROBE_TYPE processor;

   if ((status=ProcReturnSpecificProcessor(&processor)) != GOOD)
      return(status);
   coreType = 2; // 16-bit mode
   if (processor == M68302_MP && ((status=Sds2AbiGetCoreType(&coreType)) != GOOD))
      return(status);

   start = (S32)frameNo;
   frameLen = *framesRead & 0xff;
   *framesRead = 0;
   qList.qFlag=MP_QUALIFY_OFF;
   status = iceGetTraceFrame(buffer, start, &qList, (U8 *)&frameLen, &traceData);
   if (status != ICE_OK) return(iceMapError(status));
   if (frameLen == (U8)0) return(GOOD);
   *framesRead = (U32)frameLen;
   for (num = 0; num < *framesRead; num++)
      {
      start++;
      frames->groupRlsw = loword(traceData[num].addr);
      frames->groupRmsw = hiword(traceData[num].addr);
      if (coreType == 1)
         frames->groupSlsw = loword(traceData[num].data) & 0xFF;
      else
         frames->groupSlsw = SwapWord(loword(traceData[num].data));
         // change high, low byte order
      frames->groupSmsw = (U16)traceData[num].tbit;
      frames->groupTlsw = traceData[num].stat;
      frames->groupTmsw = (U16)((traceData[num].TPort >> 16) & 0xfffful); // port A
      frames->groupUlsw = (U16)((traceData[num].data >> 16) & 0xfffful);  // port B
      frames->groupUmsw = 0;
//      frames->groupUmsw = traceData[num].data2;

      /* added for mtat2 trace data <gene> */
      frames->groupTS = traceData[num].tstamp;
      frames->groupTSH = traceData[num].tstampMSB;
      frames->groupLE = (((U16)traceData[num].seqLevel) << 8) +
                            ((U16)traceData[num].evtMatch);

      frames++;
      }
   return(GOOD);
}

VOID EXPORT Sds2AbiIsTraceBufferFull(U16 buffer, BOOLEAN *full)
{
   status = iceIsTraceBufferFull(buffer, full);
   *full = FALSE;
}

RETCODE EXPORT Sds2AbiSetNumTraceBuffers(U16 bufNo)
{
   status = iceSetTraceBuffer(bufNo);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiSetTimerCounter(U16 tc, U32 tcValue1,U32 tcValue2)
{
   status = iceSetTimerCounter(tc, tcValue1, tcValue2);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiSetMap(DESCRIPTOR desc) {
   RETCODE err;
   MEMBER_INDEX index;
   BOOLEAN enable;
   U16   protect;       // this has beend redefined by Kevin to be
                        // comtible with PoerPack which has type of
                        // MAP_PROTECT and use only two least
                        // significant bits (enum with 4 entities)
   U32 addr, addr2, length;
   U8 target;
   U16   attrib;

   err = SdGetMemberIndex(desc,&index);
   if (err) return(err);
   if ((err = SdnReadMember(SDN_MAP_LENGTH+index,&length)) != GOOD)
      return(err);
   if ((err = SdnReadMember(SDN_MAP_ENABLE+index,&enable)) != GOOD)
      return(err);
   if ((err = SdnReadMember(SDN_MAP_PROTECT+index,&protect)) != GOOD)
      return(err);
   if ((err = SdnReadMember(SDN_MAP_ADDR+index,&addr)) != GOOD) return(err);
   target = protect & 0x0080;
   attrib = protect & 0xff00;
   protect &= 0x007f;
   addr2 = addr + (length - 1);
   if (enable)
      {
      switch (protect)
         {
         case 0: // RAM
            if (target) attrib |= 3;
            else attrib |= 1;
            break;
         case 1: // ROM with break
            if (target) attrib |= 2;
            break;
         case 3: // None
            attrib |= 4;
            break;
         default:
            return(ER_MAP_UNKNOWN_TYPE);
         }
      }
   else attrib |= 3;
   err = iceSetMap(addr, addr2, attrib);
   err = iceMapError(err);
   return(SdnWriteMember(SDN_MAP_RESULTS+index, &err, err));
}

RETCODE PRIVATE FwBxMapAction(DESCRIPTOR desc, MEMBER_INDEX index) {
   RETCODE err;
}

RETCODE EXPORT Sds2AbiSetBreakOnFull(BOOLEAN enable)
{  RETCODE err;

   if ((err=iceSetTraceBreak((U16)(enable & 0x01))) != GOOD)
      return(iceMapError(err));
   if ((err=iceSetTraceOff((U16)((enable & 0x02) >> 1))) != GOOD)
      return(iceMapError(err));
   return(GOOD);
}

RETCODE EXPORT Sds2AbiSetControl(U16 control)
{
   return (iceMapError(iceSetControl(control)));
}

RETCODE EXPORT Sds2AbiSetExtEvent(U16 ext)
{
   return (iceMapError(iceSetExtEvent(ext)));
}

RETCODE EXPORT Sds2AbiMemChecksum(ADDR addr, U32 length, U32 *sum)
{
   return (iceMapError(iceChecksum(addr, length, sum)));
}

RETCODE EXPORT Sds2AbiMemCompare(ADDR addr1, ADDR addr2, U32 len, 
                                 RET_ADDR *retAddr1, RET_ADDR *retAddr2,
                                 BOOLEAN *result)
{
   status = iceCompare(addr1,len,addr2,retAddr1,retAddr2);
   if (status == ICE_NO_DIFF) {
      *result = TRUE; 
      status = ICE_OK;
   }
   else if (status == ICE_DIFF_FOUND) {
      *result = FALSE;
      status = ICE_OK;
   }
   return (iceMapError(status));
}

RETCODE EXPORT Sds2AbiSetVerify(U16 verifyFlag)
{  
   return (iceMapError(iceSetVerify(verifyFlag)));
}

RETCODE EXPORT Sds2abiSetIntReg(U16 offset,U16 len,U32 value,BOOLEAN reloc)
{
   status = iceSetIntReg(offset,len,value,reloc);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2abiGetIntReg(U16 offset,U16 len,U32 FAR *value,BOOLEAN reloc)
{
   status = iceGetIntReg(offset,len,value,reloc);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiSetQualTrace(U32 addr,U32 addrMask,U16 qStatus,
           U16 qStatusMask)
{
   status = iceSetQualTrace(addr,addrMask,qStatus,qStatusMask);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiDisableQual(VOID)
{
   status = iceDisableQual();
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiGetCoreType(U16 *coreType)
{
   status = iceGetCoreType(coreType);
   return(iceMapError(status));
}

RETCODE EXPORT Sds2AbiReadFRom(U8 *data)
{
 return(iceMapError(iceRFROM(data)));
}

RETCODE EXPORT Sds2AbiWriteFRom(U8 *data)
{
 return(iceMapError(iceWFROM(data)));
}

RETCODE EXPORT Sds2AbiReadFrameStamp(U16 bufID, U32 frameNo, U32 *stamp,U8 *stampMSB)
{
   return(iceMapError(iceReadFrameStamp(bufID, frameNo, stamp,stampMSB)));
}

RETCODE EXPORT Sds2AbiReadLastStamp(U16 bufID, U32 *stamp,U8 *stampMSB)
{
   return(iceMapError(iceReadLastStamp(bufID, stamp,stampMSB)));
}

RETCODE EXPORT Sds2AbiSetTracing(U8 action)
{
   return(iceMapError(iceTraceAction((U8)action)));
}

/*******  SPA utility functions *******/
/* <Judy 8/26/96> */
RETCODE EXPORT Sds2AbiSpaSetRange(U8 type, U8 id, U32 start, U32 end,
                    ADDR_SPACE space)
{
   ADDR addr1, addr2;

   addr1.pos = start;
   addr2.pos = end;
   addr1.space = addr2.space = space;
   return(iceMapError(iceSPASetRange(type, id, addr1, addr2)));
}

/* <Judy 8/26/96> */
RETCODE EXPORT Sds2AbiSpaClearRange(U8 type)
{
 return(iceMapError(iceSPAClearRange(type)));
}

/* <Judy 8/26/96> */
RETCODE EXPORT Sds2AbiSpaGetMAInfo(U32 *stamp, MA_INFO_NODE *info,BOOLEAN *flag)
{
 return(iceMapError(iceSPAGetMAInfo(stamp, info, flag)));
}

/* <Judy 8/26/96> */
RETCODE EXPORT Sds2AbiSpaGetTAInfo(U32 *stamp, U16 *info,BOOLEAN *flag)
{
 return(iceMapError(iceSPAGetTAInfo(stamp, info, flag)));
}

/* <Judy 8/26/96> */
RETCODE EXPORT Sds2AbiSpaGetCCInfo(ADDR start, ADDR end, U8 FAR *ptr,BOOLEAN *flag)
{
 return(iceMapError(iceSPAGetCCInfo(start, end, ptr, flag)));
}

/* <Judy 8/26/96> */
RETCODE EXPORT Sds2AbiSpaGo(U8 type)
{
 return(iceMapError(iceGo((U16)type)));
}

RETCODE EXPORT Sds2AbiSpaClose()
{
 return(iceMapError(iceSPAClose()));
}

RETCODE EXPORT Sds2AbiSpaOpen()
{
 return(iceMapError(iceSPAOpen()));
}

RETCODE EXPORT Sds2AbiSpaSetBkpt(U8 flag, ADDR addr)
{
 return(iceMapError(iceSPASetBkpt(flag ,addr)));
}
/*******  local utility functions *******/

U16 SwapWord(U16 src) {
   U16 dest;

   dest = (src >> 8) + ((src & 0xFF) << 8);
   return(dest);
}
