/****************************************************************************
**
**  Name:  emumain.c
**
**  Description:
**     Michelle main(base) function routine. Include the control procedure.
**
**  Status:  preliminary
**
**  $Log:   S:/tbird/arcppc/fw/603e/emumain.c_v  $
** 
**    Rev 1.0   11 Feb 1997 16:16:54   kevin
** Initial revision.
** 
**    Rev 1.13   16 Dec 1996 10:59:48   gene
** change fw version
** 
**    Rev 1.12   29 Nov 1996 14:26:24   gene
** added SET_INT_REG/GET_INT_REG command
** 
**    Rev 1.11   24 Oct 1996 11:22:56   gene
** added TRACE_MODE flag initial value
** 
**    Rev 1.10   15 Oct 1996 19:23:32   gene
** added FW_VERSION information
** 
**    Rev 1.9   03 Oct 1996 19:50:20   gene
** added check sNo before execute command
** 
**    Rev 1.8   02 Oct 1996 17:15:30   gene
** remove GetCpuStatus() before process command
** 
**    Rev 1.7   10 Sep 1996 10:49:12   gene
** change TRACE_BREAK initial value to C_OFF
** 
**    Rev 1.6   06 Aug 1996 13:58:04   gene
** added GPEP_DELAY command ID
** 
**    Rev 1.5   02 Jul 1996 12:11:30   gene
** added IceFlag BUFFER_FILL initial value in InitialDataBase
** 
**    Rev 1.4   27 Jun 1996 10:56:34   gene
** added TRACE_RESET command 
** 
**    Rev 1.3   27 Jun 1996 09:04:22   gene
** mask invalid command 
** 
**    Rev 1.2   14 Jun 1996 13:54:10   gene
** remove TraceReset from InitFwControl
** 
**    Rev 1.1   11 Jun 1996 17:38:42   gene
** 
**    Rev 1.0   03 Jun 1996 14:19:00   gene
** Initial revision.
** 
** Copyright (C) 1992 Microtek International, Inc.
**
*****************************************************************************/

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

#ifndef _EMU_BASE_TYPES_
#include "emutypes.h"
#endif

#ifndef _EMU_GLOBAL_
#include "emuglb.h"
#endif

#ifndef _EMU_COMM_
#include "emucomm.h"
#endif

#ifndef _COMM_DATA_
#include "commdata.h"
#endif

#ifndef _FUNCTION_TEST_
#include "functest.h"
#endif

#ifndef _EMU_EMUL_
#include "emuemul.h"
#endif

#ifndef _EMU_MEM_
#include "emumem.h"
#endif

#ifndef _EMU_SETUP_
#include "emusetup.h"
#endif

#ifndef _EMU_TRACE_
#include "emutrace.h"
#endif

#ifndef _EMU_LIB_
#include "emulib.h"
#endif

#ifndef _EMU_LLFW_
#include "emullfw.h"
#endif

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

extern U8 timeOut;
extern U16 errorFlag;
extern U8 cpuFlag;
extern U32 bankSize;
extern BOOLEAN mtatExist;
           /****************************
            *                          *
            *     LOCAL DEFINITIONS    *
            *                          *
            ****************************/
// Firmware version = Major*10 + Minor
#define FW_VERSION 11
            /****************************
             *                          *
             *    EXTERNAL VARIABLES    *
             *                          *
             ****************************/

            /****************************
             *                          *
             *     LOCAL PROTOTYPES     *
             *                          *
             ****************************/
VOID InitFwControl(VOID);
VOID InitDataBase(VOID);
RETCODE ReceiveInputCommand(VOID);
RETCODE DispatchCommand(U16 *ac, U8 *av[], U8 *cmdStream);
RETCODE ProcessCommand(U16 ac, U8 *av[]);

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

/***************************************************************************
**
**  main()
**
**  Description: Michelle main routine, with its linear control process
**               sequence. We always think this fw process with one single
**               task.
**
**  Parameters:
**     input:
**        none
**     output:
**        none
**
****************************************************************************/
U8 sNo,preNo;
main() {
   U16 argc;
   U8 *argv[10];
   ERROR_NO errNo;
   char Normal[]={'M','I','C','E'};
   char Debug[] ={'D','B','U','G'};
   char WrROM[] ={'W','R','O','M'};
   char WinA[]={0xFC,0x1C,0xFC,0x1C};
   char WinB[]={0x1C,0x1C,0x1C,0x1C};
   char HexCh[] ={'H','E','X','C'};
   char *SyncPtn[]={ Normal, Debug, WrROM, WinA, WinB, HexCh, 0};

   switch(CommSync(4,SyncPtn))
   {
     case 0: /* Normal Operation */
       break;
     case 1: /* Debug */
     case 3:
       SetBaud();
       EngTest();
       FwReset();
     case 2: /* Write ROM */
     case 4:
       SetBaud();
       WROM();
       FwReset();
     case 5:
       HEXCH();
       FwReset();
   }

   fwId = EB;
   InitDataBase(); /* all data sets setting or default value. */
   InitFwControl(); // Initial hardware and firmware

   while (TRUE) {
      ReceiveStream(); /* read the input commands stream. */
      if(preNo!=sNo)
      {
        preNo=sNo;
        DispatchCommand(&argc, argv, commandStream); /* parser the input commands stream. */
        errNo = ProcessCommand(argc,argv); /* case switching the command tasks */
      }
      if (errNo == OK) TransmitStream();
      else EmuReportError(errNo);
   }
   return(GOOD);
}

VOID InitFwControl(VOID) {
   U8 status;
//   U16 lp;
   U32 baseReg[MAX_BASE_REG_NO];
//   U8 vccFlag;
//   U16 action[11],ev[11];
//   U32 mapAddr1,mapAddr2;
//   BUS_EVENT testEvent;
//   QUALIFY_LIST condition;
   U16 len = 8;
//   ADDR addr;
   
   status = GOOD;
   AccessIceFlag(WRITE_ONE,RESET_FLAG,&C_ON);
   idData[FIRMWARE_TYPE] = 'M'; // This is a MICEpack firmware.
   idData[FIRMWARE_VER] = FW_VERSION;
   idData[CPU_TYPE] = 9; // 4:306, 6:307, 7:328, 8:5202 9:5204
//   SetClockPhase();

   if (InitialReset(baseReg))
      OutputExceptReason(ON);
   idData[INIT_HW_STATUS] = (U8)(*(U16 *)outputStream);

//   if (iceStartFlag == 0xaaaa) { // Cold start
//      DisableControl();
//      FunctionTest();
//      EnableControl();
//   }
//   vccFlag = Reset(baseReg);
//   TraceReset(); // gene
//   if (iceStartFlag == 0xaaaa) { // Cold start & trace board exist.
//   }
   iceStartFlag = 0x0;
}

VOID InitDataBase(VOID) {
   U16 phyCpu,size,timerFlag = 0xff,brokeReason = BROKE;

   noUse = C_OFF = 0;
   C_ON = 1;
   noUseByte = 0;
   AccessIceFlag(READ_ONE,PHY_CPU_TYPE,&phyCpu);
   AccessIceFlag(CLEAR_ALL,noUse,&noUse);// special for timer flag
   AccessIceFlag(WRITE_ONE,PHY_CPU_TYPE,&phyCpu);
   AccessIceFlag(WRITE_ONE,FLY_RUN,&C_OFF);
   AccessIceFlag(WRITE_ONE,BROKE_REASON,&brokeReason);
   AccessIceFlag(WRITE_ONE,TIMER_FLAG,&noUse);
   //AccessIceFlag(WRITE_ONE,TRACE_BUFF,&bufNum);
   AccessIceFlag(WRITE_ONE,TRACE_BREAK,&C_OFF);
   AccessIceFlag(WRITE_ONE,VERIFY_FLAG,&C_ON);
   AccessIceFlag(WRITE_ONE,BUFFER_FILL,&C_ON);
   AccessStatusFlag(CLEAR_ALL,noUse,&noUse);
   size = S_BYTE;
   AccessIceFlag(WRITE_ONE,SIZE_FLAG,&size);
   AccessIceFlag(WRITE_ONE,TRACE_MODE,&C_OFF);
   //CommRecover();
}


//RETCODE ReceiveInputCommand(VOID) { /* Receive data from communication port */
//   ReceiveStream();
//   return(GOOD);
//}

/***************************************************************************
**
**  DispatchCommand
**
**  Description: Dispath the input command stream.
**         Note: Please refer input command protocol format.
**
**  Parameters:
**     input:
**        commandStream : input command stream.
**     output:
**        ac      : argument counter.
**        av      : argument position.
**
****************************************************************************/
RETCODE DispatchCommand(U16 *ac, U8 *av[], U8 *cmdStream) {

   *ac = 1;   /* Initial argument. */
   av[0] = cmdStream;
   cmdStream++;
   while ((*cmdStream) && (*cmdStream != 0xff)){
      av[(*ac)++] = cmdStream;
      cmdStream += *cmdStream + 1;
   }
   return(GOOD);
}

/***************************************************************************
**
**  ProcessCommand
**
**  Description: Idnetidy then command ID and call FW function.
**
**  Parameters:
**     input:
**        commandStream : input command stream.
**        ac            : argument counter.
**        av            : argument position.
**     output:
**        outputStream  : the message of executive result.
**
****************************************************************************/
RETCODE ProcessCommand(U16 ac, U8 *av[]) {
   U16 dataLen,flyFlag;
   U32 data[10];
   LOOP_VAR lp;
   STATUS status;

   for (lp = 1; lp < (LOOP_VAR)ac; lp++) {
      dataLen = *(av[lp]);
      switch (dataLen) {
         case 1 : /* byte */
            data[lp] = *(U8 *)(av[lp]+1);
           break;
         case 2 : /* word */
            data[lp] = *(U16 *)(av[lp]+1);
            break;
         case 3 : /* 3 byte */
            data[lp] = *(U32 *)(av[lp]+1) & 0x00ffffff;
            break;
         case 4 : /* long */
            data[lp] = *(U32 *)(av[lp]+1);
            break;
         case 0xff : /* more than 255 */
            data[lp] = *(U16 *)(av[lp]+1);
            break;
         default : /* do nothing */
            data[lp] = 0;
            break;
      }
   }

   if (!ac) return(FALSE);
   status = GOOD;
   AccessIceFlag(READ_ONE,FLYING,&flyFlag);
//   if (flyFlag) EmuGetCpuStatus();
   switch ((COMMAND_ID)(*av[0])) {
      case CHECKSUM :
         EmuChecksum((ADDR *)(av[1]+1),(U32)data[2]);
         break;
      case CLR_EVENT :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else EmuClrEvent((U16)data[1]);
         break;
      case CLR_TRIG :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else
            EmuClrTrig((U16)data[1]);
         break;
      case COMPARE :
         EmuCompare((ADDR *)(av[1]+1), (U32)data[2], (ADDR *)(av[3]+1));
         break;
      case COPY :
         EmuCopy((ADDR *)(av[1]+1), (U32)data[2], (ADDR *)(av[3]+1));
         break;
      //case FUNCTION_TEST :
      //   EmuFunctionTest((U16)data[1]);
      //   break;
      /*  only use at run command
      case ESC_COMMAND :
         break;
      */
      case FILL :
         EmuFill((ADDR *)(av[1]+1), (U32)data[2], (U8 *)(av[3]+1), *av[3]);
         break;
      case GET_ID :
         EmuGetID();
         break;
      //case GET_ALL_REG :
      //   EmuGetAllReg();
      //   break;
      //case GET_ALL_INTERNAL_REG :
      //   EmuGetAllIntReg();
      //   break;
      //case GET_DEPTH :
      //   if (flyFlag) status = INVALID_FLY_COMMAND;
      //   else {
      //      if (mtatExist) EmuGetTraceDepth((U16)data[1]);
      //      else OutputStatus(NO_TRACE_MODULE,ON);
      //   }
      //   break;
      case GET_LAST_BUFF :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else {
            EmuGetTraceInfo();
         }
         break;
      case GET_EVENT :
         EmuGetAllEvent();
         break;
      //case GET_MODE :
      //   EmuGetMode();
      //   break;
      case GET_REG :
         EmuGetReg((REG_MODE)data[1], (U16)data[2]);
         break;
      case GET_SIZE :
         EmuGetAccessSize();
         break;
      //case GET_STAT :
      //   EmuGetStatus();
      //   break;
      //case GET_SYNC :
      //   EmuGetSync();
      //   break;
      case GET_VERIFY :
         EmuGetVerify();
         break;
      //case GET_WAIT :
      //   EmuGetWait();
      //   break;
      case GO_COMMAND :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else {
            EmuGo((S16)data[1]);
            return(GOOD);
         }
         break;
      case HALT :
         EmuHalt();
         break;
      //case INPUT :
      //   EmuInput((U16)data[1], (U16)data[2], (U16)data[3]);
      //   break;
      case LIST_TRACE :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else
            EmuListTrace((U8)data[1]);
         break;
      //case OUTPUT :
      //   EmuOutput((U16)data[1], (U8 *)(av[2]+1), (U16)data[3], (U16)data[4]);
      //   break;
      case READ_MEM_N :
         EmuReadMemN((ADDR *)(av[1]+1), (U16)data[2]);
         break;
      case RESET :
         EmuReset();
         AccessIceFlag(READ_ONE,FLYING,&flyFlag);
         break;
      case SEARCH :
         EmuSearch((ADDR *)(av[1]+1), (U32)data[2], (U8 *)(av[3]+1), *av[3]);
         break;
      case SET_EVENT :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else EmuSetEvent((U16)data[1], (U8 *)(av[2]+1));
         break;
      //case SET_ALL_EVENT :
      //   if (flyFlag) status = INVALID_FLY_COMMAND;
      //   else EmuSetAllEvent((U8 *)(av[1]+1),(U8 *)(av[2]+1),(U8 *)(av[3]+1));
      //   break;
      case SET_EX_BKPT :
         EmuSetExBkpt((U16)data[1], (ADDR *)(av[2]+1));
         break;
      //case SET_EXT_EVENT :
      //   EmuSetExtEvent((U16)data[1]);
      //   break;
      //case SET_ID :
      //   EmuSetID((U16)data[1]);
      //   break;
      case SET_MEM_N :
         EmuSetMemN((ADDR *)(av[1]+1), (U8 *)(av[2]+1),(U16)*av[2]);
         break;
      case SET_REG :
         EmuSetReg((REG_MODE)data[1], (U16)data[2],(U32)data[3]);
         break;
      case SET_SIZE :
         EmuSetAccessSize((U16)data[1]);
         break;
      //case SET_SYNC :
      //   EmuSetSync((U16)data[1]);
      //   break;
      case SET_TRACE_BREAK :
         EmuSetTraceBreak((U16)data[1]);
         break;
      case SET_TRIG :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else
            EmuSetTrig((U16)data[1],(U16 *)(av[2]+1),(U16 *)(av[3]+1),(U16)(data[4]));
         break;
      case GET_TRIG :
         EmuGetAllTrig();
         break;
      //case SET_TIME_COUNT :
      //   EmuSetTimerCounter((U16)data[1],(U32)data[2]);
      //   break;
      //case SET_TIMER_REG :
      //   EmuEpTimer((U16)data[1]);
      //   break;
      case SET_VERIFY :
         EmuSetVerify((U16)data[1]);
         break;
      //case SET_WAIT :
      //   EmuSetWait((U16)data[1]);
      //   break;
      case STEP :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else EmuStepRange((ADDR *)(av[1]+1),(ADDR *)(av[2]+1));
         break;
      case STEP_ONE :
         if (flyFlag) status = INVALID_FLY_COMMAND;
         else EmuStepRange(0,0);
         break;
      case TEST :
         EmuTest((ADDR *)(av[1]+1), (U32)data[2]);
         break;
      case GET_CPU_STATUS :
         EmuGetCpuStatus();
         break;
      case ABORT :
         EmuAbort();
         AccessIceFlag(READ_ONE,FLYING,&flyFlag);
         break;
      //case DIAGNOSTIC :
      //   EmuDiagnostic();
      //   break;
      case ENABLE_SW_BKPT :
         EmuEnSwBkpt();
         break;
      case DISABLE_SW_BKPT :
         EmuDisSwBkpt();
         break;
      case SET_BKPT_CODE :
         EmuSetBkptCode((BKPT_OP_CODE)data[1]);
         break;
      case TRACE_RESET :
         EmuTraceReset();
         break;
      case GOEP_DELAY :
         EmuGoEpDelay((BOOLEAN)data[1]);
         break;
      case SET_INT_REG :
         EmuSetIntReg((U16)data[1],(U16)data[2],(U32)data[3],(BOOLEAN)data[4]);
         break;
      case GET_INT_REG :
         EmuGetIntReg((U16)data[1],(U16)data[2],(BOOLEAN)data[3]);
         break;
      default :
         EmuReportError(COMMAND_ERROR);
   } /* end switch *data[0]. */
//   AccessIceFlag(READ_ONE,FLYING,&flyFlag);
//   if (flyFlag) EmuGetCpuStatus();
//   AccessIceFlag(READ_ONE,FLYING,&flyFlag);
//   if (status == INVALID_FLY_COMMAND) OutputStatus(status,ON);
//   else if (flyFlag && CheckEpStop()) {
//        for (lp = 0; lp < 1000; lp++);
//        StartGo(FLY_RUN);
//   }
   
   return(GOOD);
}

///***************************************************************************
//**
//**  Download H/W Program
//**
//**  Description:
//**
//**  Parameters:
//**     input:
//**     output:
//**
//****************************************************************************/
//U16 hex2bin(U8 *hex,U8 *bin)
//{ if(('0'<=hex[0])&&(hex[0]<='9'))
//    *bin=hex[0]-'0';
//  else if(('A'<=hex[0])&&(hex[0]<='F'))
//    *bin=hex[0]-'A'+10;
//  else if(('a'<=hex[0])&&(hex[0]<='f'))
//    *bin=hex[0]-'f'+10;
//  else
//    return 1;
//  *bin=(*bin)<<4;
//  if(('0'<=hex[1])&&(hex[1]<='9'))
//    *bin+=hex[1]-'0';
//  else if(('A'<=hex[1])&&(hex[1]<='F'))
//    *bin+=hex[1]-'A'+10;
//  else if(('a'<=hex[1])&&(hex[1]<='f'))
//    *bin+=hex[1]-'f'+10;
//  else
//    return 1;
//  return 0;
//}
//
//
//U16 get_addr_len(U8 *buf,U16 *addr,U8 *len)
//{ *len=0xff;
//  if(hex2bin(buf+4,(U8*)addr))
//    return 1;
//  if(hex2bin(buf+2,((U8*)addr)+1))
//    return 1;
//  if(hex2bin(buf,len)==0)
//    return 0;
//  *len=0xff;
//  return 1;
//}
//
//U8 get_chk_sum(U8 *buf,U16 addr,U8 len)
//{ U8 i,*s,*d;
//  U8 sum;
//  for(s=d=buf,i=0;i<len;i++,s+=2,d++)
//    if(hex2bin(s,d))
//      return 1;
//  sum=len-1+(addr&255)+(addr>>8);
//  for(i=0;i<len;i++)
//    sum+=buf[i];
//  return sum;
//}
//
//void GTOR(void)
//{ U8 buf[36];
//  int i;
//  U16 addr;
//  U8 len;
//  ClearLocalMem();
//  TransmitByte(7);
//  TransmitByte(13);
//  SetWatchDog(2);
//  for(timeOut=0;timeOut==0;);
//  for(;;)
//  {
//    SetDmaCount(1);
//    if(*buf=ReceiveByte())
//      TransmitByte(*buf);
//    if(*buf!=':')
//      continue;
//    SetDmaCount(6);
//    for(i=0;i<6;i++)
//    { buf[i]=ReceiveByte();
//      if(timeOut)
//        return;
//      else
//        TransmitByte(buf[i]); }
//    if(get_addr_len(buf,&addr,&len))
//      return;
//    if((len==0)||(len>36))
//      break;
//    SetDmaCount(2*len+3);
//    for(i=0;i<(2*len+3);i++)
//    { buf[i]=ReceiveByte();
//      if(timeOut)
//        return;
//      else
//        TransmitByte(buf[i]); }
//    if(get_chk_sum(buf,addr,len+1))
//      return;
//    if(addr>0xfc0)
//      return;
//    SetLocalMem(buf,addr<<4,len);
//  }
//  if(len)
//    return;
//  if(ChkSumLocalMem()){
//    TransmitByte('C');
//    TransmitByte('h');
//    TransmitByte('k');
//    TransmitByte('S');
//    TransmitByte('u');
//    TransmitByte('m');
//    TransmitByte('E');
//    TransmitByte('r');
//    TransmitByte('r');
//  }else
//    GoToLocalMem();
//}
/******************************** E O F ***********************************/

