/****************************************************************************
**
**  Name:  mp_share.c
**
**  Description:
**     Contains the main functions of MICEpack
**
**  Status:  PRELIMINARY
**
**  $Log:   S:/tbird/arcppc/sds/mp_share.c_v  $
** 
**    Rev 1.18   08 Apr 1998 10:51:34   hera
** For PPC821
** 
**    Rev 1.17   19 Jan 1998 11:28:42   kevin
** 1. allow IW2 and IW3 to be used as breakpoints
** 2. To be able to handle RSTE, EXTIE, and DECIE exceptions while stepping
** 
**    Rev 1.16   05 Jan 1998 14:55:28   kevin
** SEIE affects GO only
** 
**    Rev 1.15   05 Dec 1997 16:13:12   kevin
** get firmware version from MICEpack to make sure the SLD is compatiable with
** FW
** 
** 
**  $Header:   S:/tbird/arcppc/sds/mp_share.c_v   1.18   08 Apr 1998 10:51:34   hera  $
**
*****************************************************************************/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
/* !!! Windows */
#define _WINDOWS_

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

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

#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

#ifndef _WHPTEXEC_
#include "whptexec.h"
#endif


#define INI_FILENAME "micepack.ini"

RETCODE PRIVATE Sds2AbiStepPreamble(VOID);
RETCODE reset(VOID);
RETCODE step(VOID);
RETCODE abortEmulation(VOID);
U32 SwapDwordOrder(U32 input);
U16 SwapWordOrder(U16 input);
void iceSetAccessSpace(ADDR_SPACE space);
VOID Sds2AbiInputAvailable(VOID);
VOID SdsClearSrcStepFlag(VOID);
BOOLEAN SdsSrcStepFlag(VOID);
RETCODE CheckIsRealBkpt(VOID);

STATUS   status;

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

typedef enum {
/* Assumption: if bkpt set to BX_NOT_BEING USED, the address descriptor
   is not valid; i.e. no memory has been alloc'ed for the address */
   BX_NOT_BEING_USED, /* breakpoint is available; not in use */
   BX_SET_FROM_ASM, /* originally set from the assembly level */
   BX_SET_FROM_CLI, /* originally set from the command line interface */
   BX_SET_FROM_SRC, /* originally set from the source level */
   BX_SET_INTERNAL, /* set from an internal breakpoint routine (temporary) */
   BX_SET_EXEC_BKPT,/* hardware bkpt */
   BX_BPTYPE_DUMMY = 0x7FFF /* force a 16 bit enum size */
} BX_BPTYPE;

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

I_WATCHPOINT gIwhpt, gHwIwhpt;
L_ADDR gLaddr;
L_DATA gLdata;
L_WATCHPOINT gLwhpt;
WATCHPOINT_COUNTER gWhptCounter;

BAD_MEMORY  badAddr1, badAddr2;
extern   BOOLEAN bkptHitFlag;  /* Set by bkpt handler when emul stops */
extern   U16   emulationState;
U16   MPBreakCause;
extern   U32  derMask; 
extern   BKPT_ENTRY *bkptHead;
extern   BKPT_ENTRY *bkptTail;
extern   BKPT_ENTRY *bkptFree;
extern   U16 SRSave;           /* Saved value of SR register */
extern   CPU_TYPE cpuType;


BKPT_OP_68K bkptOpcode = A_LINE;
static U16 MP_MAX_XBRKS;   /* Determined by MICEPack hardware */
                           /* note that this value can't exceed MAX_XBRKS */
extern   U16 numXbrks;   /* Number of execution breakpoints currently active */
extern   U32 xbrkAddr[];
extern   BOOLEAN SRModified;   /* Has SR been patched? */
extern   BOOLEAN bkptEnable;   /* Enables bkpt handler to run when emul stops*/

extern U16 hwbpFlag;    /* hardware bkpt flag chech for hwbp setting */
extern U32 hwbpAddr;    /* hold the hwbp address */

BOOLEAN flagRunaccStart = FALSE; // keep the state of run_access
BOOLEAN flagSrcStep = FALSE; // keep the source level step

//
RETCODE Sds2AbiFwInit(VOID)
{
S8 buf[64];
char    *stopString;

   switch (cpuType) {
   case CPU603E:
   case CPU860:
   case CPU821:
      MP_MAX_XBRKS = 2;
      break;
   default:
      MP_MAX_XBRKS = 2;
      // MICEPack-306 can handle up to 2 hardware execution breakpoint
   }

   GetPrivateProfileString("MICEPack-68k", "TrapCodeForEmulator", "0xa0", buf,
      sizeof(buf), INI_FILENAME);
   stopString = NULL;
   bkptOpcode = (BKPT_OP_68K)(strtoul(buf, &stopString, 0));
   if ((bkptOpcode != A_LINE) && (bkptOpcode != F_LINE))
      bkptOpcode = A_LINE;
   
   return(GOOD);
}
////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetBreakCause
//
// Description: get the cause break the emulation
//
// Parameters:
//    Input:   <none>
//    Output:  <cause> cause which break the emulation
////////////////////////////////////////////////////////////////////////////
RETCODE EXPORT Sds2AbiFwGetBreakCause(BREAK_CAUSE *cause)
{
   *cause = MPBreakCause;
   return(GOOD);
}

////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetEmuState
//
// Description: get current emulation state
//
// Parameters:
//    Input:   <none>
//    Output:  <state> emulation state
////////////////////////////////////////////////////////////////////////////
RETCODE EXPORT Sds2AbiFwGetEmuState(EMULATION_STATE *iceState)
{
RETCODE  err;

   err=SdnReadMember(SDN_EMULATION_STATE,(U8 *)iceState);
   return(err);
}

/*****************************************************************************
**
** Sds2AbiFwReset
**
** description:
**    Reset target processor and enter emulation mode.
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwReset(CPU_RESET typeOfReset) {
   RETCODE err,err2;
   EMULATION_STATE iceState;
   U32 sim;
   BOOLEAN simValid = FALSE;
   PROBE_TYPE  probeType;

   bkptEnable = FALSE;
   SRModified = FALSE;
   err = Sds2AbiFwLoadRegisters();  // ignore the return since reset is request
   err = reset();
   err2 = Sds2AbiFwUnloadRegisters(TRUE);
   if (!err) err = err2;
   err2 = Sds2AbiFwUnloadBreakpoints();
   if (!err) err = err2;
   err2 = SdnReadMember(SDN_EMULATION_STATE,(U8*)&iceState);
   if (!err) err = err2;

   err2 = SdnReadMember(SDN_PROBE_TYPE, (U8*)&probeType);
   if (!err) err = err2;
   switch (probeType)
      {
      case M68306_MP:
         sim = 0xfffff000ul;
         simValid = TRUE;
         err2  = SdnWriteMember(SDN_SIM_VALID,(U8*)&simValid,GOOD);
         if (!err) err = err2;
         err2 = SdnWriteMember(SDN_SIM_ADDRESS,(U8*)&sim,GOOD);
         break;
      case M68328_MP:
      case M68307_MP:
      case M68302_MP:
         sim = 0xfff000ul;
         simValid = TRUE;
         err2 = SdnWriteMember(SDN_SIM_VALID,(U8*)&simValid,GOOD);
         if (!err) err = err2;
         err2 = SdnWriteMember(SDN_SIM_ADDRESS,(U8*)&sim,GOOD);
         break;
     case PPC860_MP:
     case PPC603E_MP:
     case PPC821_MP:
         GetReg(R_IMMR,&sim);
         sim = sim & 0xffff0000ul;
         simValid = TRUE;
         err2 = SdnWriteMember(SDN_SIM_VALID,(U8*)&simValid,GOOD);
         if (!err) err = err2;
         err2 = SdnWriteMember(SDN_SIM_ADDRESS,(U8*)&sim,GOOD);
         break;
      default:
         break;
      }

   if (!err) err = err2;
   if (iceState!=EM_HALTED) {       /* Update cause if we were emulating */
      BREAK_CAUSE cause = CAUSE_RESET;
      err2 = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
      if (!err) err = err2;
   }
   if (typeOfReset==RESET_CPU_AND_UPDATE_STATUS) {
      iceState = EM_HALTED;
      err2 = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
      if (!err) err = err2;
      err2 = SdnWriteMember(SDN_EMULATION_RESULT,(U8*)&err,err);
      if (!err) err = err2;
   }
   return(err);
}

/*****************************************************************************
**
** Sds2AbiFwCpuReset
**
** description:
**    Reset the processor.  Does not update any registers or unload
**    breakpoints; therefore should be used only during initialization.
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwCpuReset(VOID) {
RETCODE  err;

   SRModified = FALSE;
   err = Sds2AbiFwLoadRegisters();
   if (err==GOOD)
      err=reset();

   return(err);
}

/*****************************************************************************
**
** Sds2AbiFwLoadWatchpoints
**
** description:
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwLoadWatchpoints(I_WATCHPOINT iwhpt,L_ADDR laddr,
   L_DATA ldata, L_WATCHPOINT lwhpt,WATCHPOINT_COUNTER whptCounter) {

    gIwhpt=iwhpt;
    gLaddr=laddr;
    gLdata=ldata;
    gLwhpt=lwhpt;
    gWhptCounter=whptCounter;

    return GOOD;
}

/*****************************************************************************
**
** Sds2AbiFwEnableWatchpoints
**
** description:
**
** parameters:
**    none
*****************************************************************************/
RETCODE Sds2AbiFwEnableWatchpoints() {
   int i;
   if (numXbrks) {
      for (i=2; i<4; i++) {
         gIwhpt.enable[i] = gHwIwhpt.enable[i];
         if (gHwIwhpt.enable[i]) {
            gIwhpt.condition[i]= gHwIwhpt.condition[i];
            gIwhpt.addr[i]     = gHwIwhpt.addr[i];
            gIwhpt.relation[i] = gHwIwhpt.relation[i];
         }
      }
   }

   iceSetWP(gIwhpt,gLaddr,gLdata,gLwhpt,gWhptCounter);

   return GOOD;
}


/*****************************************************************************
**
** Sds2AbiFwUnloadWatchpoints
**
** description:
**
** parameters:
**    none
*****************************************************************************/
RETCODE Sds2AbiFwUnloadWatchpoints(void) {
I_WATCHPOINT iwhpt;
L_ADDR laddr;
L_DATA ldata;
L_WATCHPOINT lwhpt;
WATCHPOINT_COUNTER whptCounter;
    iwhpt.enable[0]=iwhpt.enable[1]=iwhpt.enable[2]=iwhpt.enable[3]=0;
    lwhpt.enable[0]=lwhpt.enable[1]=0;
    whptCounter.enable[0]=whptCounter.enable[1]=0;

    iceSetWP(iwhpt,laddr,ldata,lwhpt,whptCounter);

    return GOOD;
}
/*****************************************************************************
**
** Sds2AbiFwGetUpm
**
** description:
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwGetUpm(U16 num,U32 *ptrBuff) {

    iceGetUpm(num,ptrBuff);

    return GOOD;
}
/*****************************************************************************
**
** Sds2AbiFwSetUpm
**
** description:
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwSetUpm(U16 num,U16 addr,U32 value) {

    iceSetUpm(num,addr,value);

    return GOOD;
}

void SetHwBkpt(U8 iw, U32 addr) {
   iw += 2; // should be iw2 or iw3
   gHwIwhpt.condition[iw] = 4;  //equal to
   gHwIwhpt.addr[iw] = addr;
   gHwIwhpt.enable[iw] = 1;
   gHwIwhpt.relation[iw] = 2;   // iw2 is C, iw3 is D
}
void GetHwBkptEnable(U8 *bHwBkpt) {
   char buf[20];

   GetPrivateProfileString("SourceInfo", "HwBkpt", "1", buf,
                        sizeof(buf), "micepack.ini");
   *bHwBkpt = buf[0] != '0'; //enable hardware breakpoints
}

/*****************************************************************************
**
** Sds2AbiFwLoadBreakpoints
**
** description:
**    Replace user opcodes at breakpoint addresses by BGND instructions
**
** parameters:
**    none
*****************************************************************************/
RETCODE  Sds2AbiFwLoadBreakpoints(BOOLEAN loadNow) {
RETCODE err,err2;
BKPT_ENTRY *entry;
U8 bkptOp[4];
BOOLEAN enable, bHwBkpt;
U32 FCRegs[2];
ADDR  abiAddr;

   switch (cpuType) {
   case CPU603E: /* PowerPC 603e */
   case CPU860: /* PowerPC 860 */
   case CPU821:
      bkptOp[0] = 0xFC;
      bkptOp[1] = 0x22;
      bkptOp[2] = 0x18;
      bkptOp[3] = 0x2A;
      break;
   default:
      bkptOp[0] = (U8)(bkptOpcode & 0xff);
      bkptOp[1] = 0;
      iceSetBkptCode(bkptOpcode);
   }
   if ((err = SdnReadMember(SDN_BKPT_ENABLE, (U8*)&enable)) != GOOD)
      return(err);
   if (enable || loadNow) {
      GetHwBkptEnable(&bHwBkpt);
      numXbrks = 0;
      gHwIwhpt.enable[2] = gHwIwhpt.enable[3] = 0; //!! only iw2 and iw3 can be used

      for (entry=bkptHead; entry; entry=entry->next) {
         if (entry->type==BX_SET_EXEC_BKPT) {
            entry->status=BKPT_XBRK;
            hwbpFlag=1;
            hwbpAddr=entry->addr;
         }
         else {
           /* First try setting swb.  If memory not writable, use hw bkpt.*/
             err = Sds2AbiFwReadMem(entry->addr, entry->space, 4, DWORD_SIZE,
                 (U8*)&entry->opcode);
             err=Sds2AbiFillMemAction(entry->addr, entry->space,4,4,DWORD_SIZE,
                   TRUE, NULL, bkptOp);
             if (!err) {
                entry->status = BKPT_SWB;
             }
            else {
              /* Write error, check if hardware execution breakpoint available */
               err=Sds2AbiFillMemAction(entry->addr, entry->space,4,4,DWORD_SIZE,
                      TRUE, NULL, (U8*)&entry->opcode);
               err=ER_END_OF_BUFFER; //can't set software breakpoint

              if (!bHwBkpt || numXbrks >= MP_MAX_XBRKS)
                 {
                 err = ER_TOO_MANY_XBRKS;
                 break;
                 }
              SetHwBkpt(numXbrks, entry->addr); // only IW2 and IW3 available
              xbrkAddr[numXbrks++] = entry->addr;
              entry->status = BKPT_XBRK;
              err = GOOD;
              hwbpFlag = 1;
              hwbpAddr = entry->addr;
              }
          }
      }
      err2 = Sds2AbiFwRestoreFCRegs(FCRegs);
      if (!err) err = err2;
      if (err) Sds2AbiFwUnloadBreakpoints();   /* Clear any bkpts set */
      iceEnableSwBkpt();
   }
   return(err);
}

/*****************************************************************************
**
** Sds2AbiFwUnloadBreakpoints
**
** description:
**    Restore user memory contents at all breakpoint addresses
**
** parameters:
**    none
*****************************************************************************/
RETCODE  Sds2AbiFwUnloadBreakpoints(VOID) {
   RETCODE err=GOOD, err2;
   BKPT_ENTRY *entry;
   RETCODE hwbp = FALSE;
   U32 curPC;

   numXbrks = 0;
   if (bkptHitFlag) {
      err = iceGetReg(M68K_REG,R_SRR0,&curPC);
      curPC -= 2;
   }
   for (entry=bkptTail; entry; entry=entry->prev) {
      if (entry->status == BKPT_SWB) {
         err2 = Sds2AbiFillMemAction(entry->addr, entry->space,4,4,DWORD_SIZE,FALSE,
            NULL, (U8*)&entry->opcode);
         if (!err) err = err2;
         if (bkptHitFlag && entry->addr == curPC) {
            err2 = iceSetReg(M68K_REG,R_SRR0,curPC);
         }
         if (!err) err = err2;
      }
      else {
         hwbp = TRUE;
         }
      entry->status = BKPT_UNLOADED;
   }
   if (hwbp) {
//!!      WhptSetIW(2, entry->addr, FALSE); // disable IW2
//!!      WhptSetIW(3, entry->addr, FALSE); // disable IW3
   }
   iceDisableSwBkpt();
   return(GOOD);
}

/*****************************************************************************
**
** Sds2AbiFwBkptHit
**
** description:
**    Called when the probe stops emulation.  Unloads registers into shared
**    data members, updates SD_BREAK_CAUSE, and sets SD_EMULATION_STATE.
**
** parameters:
**    byte  comm byte received from probe (one of PCOM_BKPTHIT, PCOM_STEPBKPT,
**          or PCOM_STEPFAIL).
*****************************************************************************/
RETCODE  Sds2AbiFwBkptHit()
{
   RETCODE err=GOOD,err2;
   EMULATION_STATE iceState;
   BREAK_CAUSE cause=CAUSE_NONE;

   err = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,err);
   err2 = Sds2AbiFwUnloadBreakpoints();
   if (!err) err = err2;
   err2 = Sds2AbiFwUnloadRegisters(FALSE);
   if (!err) err = err2;
   iceState=EM_HALTED;
   err2 = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
   if (!err) err = err2;
   err = SdnWriteMember(SDN_EMULATION_RESULT,(U8*)&err,err);
   return(err);
}

RETCODE  Sds2AbiFwStep(U32 count) {
   RETCODE err, stepErr;
   BOOLEAN  abortFromEsc;
   BREAK_CAUSE cause = CAUSE_STEP;
   U32    der;

//!! SEIE affects GO only.
//!!   der = 0x31467C0F & derMask;
   der = 0x73667C0F;
   SetReg(R_DER,der);

   bkptEnable=FALSE;

   while (count--) {
      if ((err = Sds2AbiStepPreamble()) != GOOD) return(err);
      bkptHitFlag=FALSE;
      stepErr = step(); 
      if ((err = Sds2AbiStepPostamble()) != GOOD) return(err);
      if ((err = TskCheckAbort(&abortFromEsc)) != GOOD) return(err);
      if (abortFromEsc!=0) break;
   }
   if ((err = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD)) != GOOD)
      return(err);
   if (stepErr!=GOOD)
      return(stepErr);
   else
      return(err);
}

RETCODE PRIVATE Sds2AbiStepPreamble(VOID) {
   RETCODE err;
   BOOLEAN stepMask;
   if ((err = SdnReadMember(SDN_STEP_MASK, (U8*)&stepMask)) != GOOD)
      return(err);
/*****
   if (stepMask)
      {
      U32 result;
      if ((err = GetReg(R_SR, &result)) != GOOD) return(err);
      result = SwapDwordOrder(result);
      SRSave = (U16)(result & 0xffffL);
      result |= 0x0700;
      if ((err = SetReg(R_SR, result)) != GOOD) return(err);
      SRModified = TRUE;
      }
****/
   return(GOOD);
}

RETCODE EXPORT Sds2AbiStepPostamble(VOID) {
   RETCODE err=GOOD;
/****
   if (SRModified)
      {
      U32 result;
      if ((err = GetReg(R_SR, &result)) != GOOD) return(err);
      result = ((U16)SwapDwordOrder(result) & 0xf8ff) | (SRSave & 0x0700);
      if ((err = SetReg(R_SR, result)) != GOOD) return(err);
      SRModified=FALSE;
   }
****/
   return(err);
}

RETCODE  Sds2AbiFwGo(EMULATION_STATE *iceState) {
   RETCODE err=GOOD;
   BOOLEAN bool=TRUE;
   RUN_MODE goMode = 0;
   U32    der;

   der = 0x0000400f & derMask;

   SetReg(R_DER, der);
   bkptEnable=TRUE;
   *iceState = EM_HALTED;
   if (SdsSrcStepFlag()) goMode = SRCSTEP_RUN;
   if (numXbrks == 0) {
      if ((err = SdnWriteMember(SDN_TRIC_DIAGNOSTIC_MODE,&bool,err)) != GOOD) return(err);
      err = iceMapError(iceGo(goMode));
      SdsClearSrcStepFlag();
      if (err != GOOD) return(err);
      *iceState = EM_RUNNING;
   } else {
      if ((err = Sds2AbiStepPreamble()) != GOOD) return(err);
      if ((err = SdnWriteMember(SDN_TRIC_DIAGNOSTIC_MODE,&bool,err)) != GOOD) return(err);
// 1/17/96      Sds2AbiFwLoadBreakpoints(TRUE);
      err = iceMapError(iceGo(goMode));
      SdsClearSrcStepFlag();
      if (err != GOOD) return(err);
      *iceState = EM_RUNNING;
   }
   if ((err=SdnWriteMember(SDN_FW_TRACING_STATUS, &bool, err)) != GOOD) return(err);
   if ((err=SdnWriteMember(SDN_TRACING, &bool, err)) != GOOD) return(err);
   return(GOOD);
}

RETCODE EXPORT Sds2AbiFwGr(EMULATION_STATE *iceState) {
   return(Sds2AbiFwGo(iceState));
}

RETCODE  Sds2AbiFwHalt(VOID) {
   return(abortEmulation());
}

RETCODE EXPORT Sds2AbiRunaccStart(EMULATION_STATE *iceState, U32 *regs) {
   RETCODE err;
   STATIC EMULATION_STATE preEmState=EM_HALTED;

   if (flagRunaccStart) {
      *iceState = preEmState;
      return(GOOD);
   }
   err = SdnReadMember(SDN_EMULATION_STATE,(U8*)iceState);
   if ((!err) && (*iceState != EM_HALTED)) {
      flagRunaccStart = TRUE;
      preEmState = *iceState;
      bkptEnable=FALSE;
      err = abortEmulation();
      if (/* (!err) && */(regs!=NULL)) err = Sds2AbiFwSaveFCRegs(regs);
   }
   return(err);
}

RETCODE EXPORT Sds2AbiRunaccFinish(EMULATION_STATE iceState, U32 *regs) {
   RETCODE err=GOOD;

   if (iceState != EM_HALTED) {
      flagRunaccStart = FALSE;
      if (regs!=NULL) err = Sds2AbiFwRestoreFCRegs(regs);
      if ((!err) || (regs == NULL)) {
//       err = Sds2AbiFwGo(&iceState);
//       if (err) return(err);
         iceGo(0);
         return (SdnWriteMember(SDN_EMULATION_STATE, (U8 *)&iceState, GOOD));
      }
   }
   return(err);
}

RETCODE reset(VOID)
{
   status = iceReset();
   return(iceMapError(status));
}

RETCODE step(VOID)
{
RETCODE  err, firstErr;
ADDR  startPC;
U32      pc;

   if ((err = SdnReadMember(SDN_PC, (U8*)&pc)) != GOOD) return(err);
   startPC.pos = pc;
   startPC.space = SPACE_DONT_CARE;
   firstErr = iceStepRange(startPC, startPC);
   if (firstErr != ICE_OK) firstErr = iceMapError(firstErr);
   status = GetReg(R_SRR0, &pc);
   if (status != ICE_OK) status = iceMapError(status);
   err = SdnWriteMember(SDN_PC, (U8*)&pc, GOOD);
   err = SdnReadMember(SDN_PC, (U8*)&pc);
   if (firstErr != GOOD)
      err = firstErr;
   else if (status != GOOD)
      err = status;

   return(err);
}

RETCODE abortEmulation(VOID)
{
   S16 buttonID;

   status = iceAbort(0);
   status = iceMapError(status);
   if (status == ER_WAIT_EMOFF_TIMEOUT) {
      ErrDisplayErrorEx(status, FORCE_POPUP, MB_TYPE_OKCANCEL,
             (S16 FAR *)&buttonID);
      if (buttonID == IDOK) {
         status = iceAbort(1);
         status = iceMapError(status);
      }
   }
   return(status);
}

VOID Sds2AbiInputAvailable(VOID) {
   EMULATION_STATE iceState;
   BREAK_CAUSE cause;
   U8 goStatus;
   BOOLEAN  bool;
   RETCODE  err;
   S16 buttonID;
   STATIC BOOLEAN pending = FALSE;

   status = iceGetCpuStatus(&goStatus);
   if (goStatus == 0) {
      if (pending) {
         pending = FALSE;
         iceState = EM_RUNNING;
         err = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
      }
      return;
   }
   switch (status) {
      case ICE_USER_CC:     // illegal code
      case ICE_SW_BKPT_HIT: // SW breakpoint
      case ICE_BKPT1_HALT:  // I-Watchpoint
      case ICE_BKPT2_HALT:  // L-Watchpoint
         if (status == ICE_USER_CC || status == ICE_SW_BKPT_HIT) {
            err=CheckIsRealBkpt(); // only for SW breakpoints
            Sds2AbiFwUnloadWatchpoints();
            if (err != GOOD) {
               ErrDisplayError(err,FORCE_POPUP);
               break;
            }
            cause = CAUSE_BKPT;
         }
         else if (status == ICE_BKPT1_HALT)
            cause = CAUSE_IBKPT;
         else // status == ICE_BKPT2_HALT
            cause = CAUSE_LBKPT;

         bkptHitFlag = TRUE;
         if (bkptEnable) Sds2AbiFwBkptHit();
         bool = FALSE;
         SdnWriteMember(SDN_FW_TRACING_STATUS, &bool, GOOD);
         SdnWriteMember(SDN_TRACING, &bool, GOOD);
         SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
         Sds2AbiFwUnloadWatchpoints();
         return;
      case ICE_TRIG_HALT:
         cause=CAUSE_BUSBRK;
         break;
      case ICE_HALT_USER:
         bkptHitFlag = TRUE;
         cause = CAUSE_HALT;
         break;
      case ICE_RBW_HALT:      // vincent: powerviews doesn't support this
      case ICE_BROKE:
         break;
      case ICE_VIOL_HALT:
         ErrDisplayErrorEx(ER_MEMORY_VERIFY, FORCE_POPUP, MB_TYPE_OK,
                (S16 FAR *)&buttonID);
         cause = CAUSE_OVERLAY_ACCESS;
         break;
      case ICE_EP_PENDING :
         cause = CAUSE_PENDING;
         if (!pending) {
            pending = TRUE;
            iceState = EM_RUNNING;
            err = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
         }
         SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
         return;
      case ICE_NO_VCC :
         status = ICE_BROKE;
         cause=CAUSE_NONE;
         ErrDisplayErrorEx(ER_TARGET_VCC, FORCE_POPUP, MB_TYPE_OK,
                (S16 FAR *)&buttonID);
         break;
      default:
         cause=CAUSE_NONE;
         break;
      }
   SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
   Sds2AbiFwUnloadRegisters(FALSE);
   if (bkptEnable) Sds2AbiFwUnloadBreakpoints();
   Sds2AbiFwUnloadWatchpoints();
   iceState = EM_HALTED;
   err = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
   SdnWriteMember(SDN_EMULATION_RESULT,(U8*)&err,GOOD);
   bool = FALSE;
   SdnWriteMember(SDN_FW_TRACING_STATUS, &bool, GOOD);
   SdnWriteMember(SDN_TRACING, &bool, GOOD);
}

RETCODE PRIVATE GetID(U8 *id) {
   status = iceGetID(id);
   return(iceMapError(status));
}

/*****************************************************************************
**
** Sds2AbiFwUpdateProbeVersion
**
** description:
**    Send version packet to probe and write results to shared data members
**
** parameters:
**    none
*****************************************************************************/
RETCODE Sds2AbiFwUpdateProbeVersion(VOID) {
   RETCODE err;
   U8 result[7], firmwareVer, majorVer, minorVer, compatVer;
   S8 cpu[64];
   PROBE_TYPE probeType = PROBE_NONE;

   /* find out which processor is installed...tests must be in this order */
   if ((err = GetID(result)) != GOOD) return(err);

   if ((result[1] & 0xff) != CUR_FW_VER) return(ER_PROBE_FW_VERSION);
//vvv   if ((err = SdatSetBerrRetry(TRUE)) != GOOD) return(err);

/*  added for 5202, 5204
   cpuType = result[2];
*/

   GetPrivateProfileString("SystemInfo", "MICEpack", "PPC603E", cpu,
      sizeof(cpu), INI_FILENAME);

   if (stricmp(cpu, "PPC603E") == 0)
      cpuType = CPU603E;
   else if (stricmp(cpu, "PPC860") == 0)
      cpuType = CPU860;
   else if (stricmp(cpu, "PPC821") == 0)
      cpuType = CPU821;
   else if (stricmp(cpu, "5202") == 0)
      cpuType = CPU5202;
   else if (stricmp(cpu, "5204") == 0)
      cpuType = CPU5204;
   else
      return(ER_NOT_SUPPORTED);

   if ((err = Sds2AbiFwCpuReset()) != GOOD) return(err);

   switch (cpuType) {
      case CPU5202:
           probeType = MCF5202_MP;
         break;
      case CPU5204:
           probeType = MCF5204_MP;
         break;
      case CPU603E:
           probeType = PPC603E_MP;
         break;
      case CPU860:
           probeType = PPC860_MP;
         break;
      case CPU821:
           probeType = PPC821_MP;
         break;
      default:
         break;
   }      
   if((err=SdnWriteMember(SDN_PROBE_TYPE,(U8*)&probeType,GOOD)) != GOOD)
      return(err);

   // a section of version update code might need to be added here
   firmwareVer = result[1];
   majorVer = firmwareVer / 10;
   minorVer = firmwareVer % 10;
   compatVer = ' ';
   if((err=SdnWriteMember(SDN_FIRMWARE_MAJOR_VERSION,(U8*)&majorVer,GOOD)) != GOOD)
      return(err);
   if((err=SdnWriteMember(SDN_FIRMWARE_MINOR_VERSION,(U8*)&minorVer,GOOD)) != GOOD)
      return(err);
   if((err=SdnWriteMember(SDN_FIRMWARE_COMPATIBILITY,(U8*)&compatVer,GOOD)) != GOOD)
      return(err);
   return(GOOD);
}

VOID EXPORT Sds2AbiGetCpuType(CPU_TYPE *cpu)
{
   *cpu = cpuType;
}

RETCODE EXPORT SdsCliSync(LPSTR cmdString, U32 argc, U32 argv[])
{
U16   sync, mask;
S8    buf[64];
RETCODE  err;

   switch (argc)
      {
      case 1:
         err = iceMapError(iceGetSync(&sync));
         if (err != GOOD) return(err);
         wsprintf(buf, "Sync start in %s", (sync & 0x01) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         wsprintf(buf, "Sync slave out %s", (sync & 0x02) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         break;
      case 2:
         if (stricmp(&cmdString[(int)argv[1]], "input") == 0)
            {
            err = iceMapError(iceGetSync(&sync));
            if (err != GOOD) return(err);
            wsprintf(buf, "Sync start in %s", (sync & 0x01) ? "on" : "off");
            if ((err = SendMessageToCli(buf)) != GOOD) return(err);
            }
         else if (stricmp(&cmdString[(int)argv[1]], "output") == 0)
            {
            err = iceMapError(iceGetSync(&sync));
            if (err != GOOD) return(err);
            wsprintf(buf, "Sync slave out %s", (sync & 0x02) ? "on" : "off");
            if ((err = SendMessageToCli(buf)) != GOOD) return(err);
            }
         else return(ER_CLI_SYNTAX);
         break;
      case 3:
         if ((status = iceGetSync(&sync)) != ICE_OK) return(iceMapError(status));
         if (!stricmp(&cmdString[(int)argv[1]], "input")) mask = 0x01;
         else if (!stricmp(&cmdString[(int)argv[1]], "output")) mask = 0x02;
               else return(ER_CLI_SYNTAX);
         if (!stricmp(&cmdString[(int)argv[2]], "on")) sync |= mask;
         else if (!stricmp(&cmdString[(int)argv[2]], "off")) sync &= (~mask);
               else return(ER_CLI_SYNTAX);
         if ((status = iceSetSync(sync)) != ICE_OK) return(iceMapError(status));
         wsprintf(buf, "Sync start in %s", (sync & 0x01) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         wsprintf(buf, "Sync slave out %s", (sync & 0x02) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         break;
      default:
         return (ER_CLI_SYNTAX);
      }
   return(GOOD);
}

VOID EXPORT SdsSetSrcStepFlag() {
   flagSrcStep = TRUE;
}

VOID SdsClearSrcStepFlag() {
   flagSrcStep = FALSE;
}

BOOLEAN SdsSrcStepFlag() {
   return(flagSrcStep);
}
RETCODE CheckIsRealBkpt() {
U32 regValue;
RETCODE err=1;
BKPT_ENTRY *entry;
   GetReg(R_SRR0,&regValue);
   for (entry=bkptHead; entry; entry=entry->next)
      if (entry->addr == regValue)
         return GOOD;
   return ER_ADR_DIFFER_SEGMENTS; // forged code for invalid instruction
}

/*****************************************************************************
**
** Sds2AbiFwSetISCT_SER
**
** description:
**
** parameters:
**    U16 value
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwSetISCT_SER(U16 value) {

    iceSetISCT_SER(value);

    return GOOD;
}

/*****************************************************************************
**
** Sds2AbiFwSetBkptNonmask
**
** description:
**
** parameters:
**    U16 enable
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwSetBkptNonmask(U16 enable) {

    iceSetBkptNonmask(enable);

    return GOOD;
}
/******************************** E O F ***********************************/
