/****************************************************************************
**
**  Name:  dq306.c
**
**  Description:
**     This is a dequeuer for Motorola 68306
**
**
**  Status:
**
**
**  $Header:
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _DAD_SERVER_
#include "dasm.h"
#endif

#ifndef _DAD_DEFINE_
#include "daddef.h"
#endif

#ifndef _DQ306_
#include "dq306.h"
#endif

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

//#ifndef _STRING_
//#include "strlib.h"
//#endif

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

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

#ifndef _SDNUM_
#include "sdnum.h"
#endif


#ifndef _TRACE_
#include "trace.h"
#endif

#ifndef __STDIO_H
#include <stdio.h>
#endif

#ifndef __DOS_H
#include <dos.h>
#endif

#include "string.h"

                        /****************************
                         *                          *
                         *     DEFINITIONS          *
                         *                          *
                         ****************************/
#define MAX_READ_FRAME_LEN   0x40 // Read 64 frames data each times.
                        /****************************
                         *                          *
                         *     EXTERNALS            *
                         *                          *
                         ****************************/

extern HANDLE cliServerHandle;

                        /****************************
                         *                          *
                         *     LOCAL VARIABLES      *
                         *                          *
                         ****************************/
//U8 *spaceString[] = {"","UW",  "",  "",  "","SW",  "","AK",
//                     "","UR",  "","UP",  "","SR","SP",  ""};

S8 spaceString[][11] = {"","Data write",  "",  "",  "","Data write",  "","CPU",
                        "","Data read ",  "","UP",  "","Data read ","SP", "CPU"};
PROBE_TYPE gProcessor;
/*
** #define DEBUG_MEM_LEAKS 1
*/
extern U32 memAlloced;
extern U32 memFreed;

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

/////////////////////// Temporal function of trace //////////////////////////
/** no use **
VOID OutputStringToFile(LPSTR buffer,U16 textLen){
FILE *fStream;

   fStream = fopen("dqstring.log","w");
   fwrite(buffer, textLen, 1, fStream);
   fclose(fStream);
}
** no use **/
                        /****************************
                         *                          *
                         *     EXECUTABLE           *
                         *                          *
                         ****************************/


/****************************************************************************
**
** Name:  AdddqStateTable
**
****************************************************************************/
RETCODE AddDqStateTable(DESCRIPTOR dqStateId,S32 startReadFrame) {
DQ_STATE *dqState;
U32 numGotten;
U16 lp;
RETCODE err;
LPSTR buffer;

   if ((dqState = (DQ_STATE FAR *)dqStateId) == NULL)
      return ER_DAD_INVALID_ID_DESCRIPTOR;
   TrcReadFrameSet(dqState->traceId,startReadFrame);
   for (lp = 0; lp < MAX_FRAME_NO; lp++)
      dqState->frameArray[lp].frameNo = 0x7fffffffl;
   if ((err = TrcTraceReadRaw(dqState->traceId,64L,(U32 far *)&numGotten,
             &buffer)) != GOOD) return(err);
   for (lp = 0; lp < numGotten; lp++) {
      _fmemcpy(&(dqState->frameArray[lp]),
             (buffer+lp*TRACE_FRAME_WIDTH),TRACE_FRAME_WIDTH);
   }
   TFree(buffer);
   TrcReadFrameSet(dqState->traceId,startReadFrame);
   dqState->frameStart = dqState->frameArray[0].frameNo;
   dqState->frameEnd = dqState->frameArray[(U16)(numGotten - 1)].frameNo;
   return(GOOD);
}

/****************************************************************************
**
** Name:  CreatedqStateTable // Create Dis-continue Table
**
****************************************************************************/
RETCODE CreateDqStateTable (DESCRIPTOR dqStateId) {
DQ_STATE  *dqState;
S32 curFrame;
U16 tempBuffId;

   if ((dqState = (DQ_STATE FAR *)dqStateId) == NULL)
      return ER_DAD_INVALID_ID_DESCRIPTOR;
   TrcReadBufferGet(dqState->traceId,(U16 FAR *)&tempBuffId); // read current buffer ID
   dqState->traceBufId = tempBuffId; // read current buffer ID
   TrcReadFrameGet(dqState->traceId,&curFrame);
   AddDqStateTable(dqStateId,curFrame);

   return(GOOD);
}

/****************************************************************************
**
** Name:  DestroydqStateTable // Create
**
****************************************************************************/
RETCODE DestroyDqStateTable(DESCRIPTOR id) {
DQ_STATE *dqState;
RETCODE err;

   if ((dqState = (DQ_STATE FAR *)id) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);
   if ((err = TFree((LPSTR)dqState)) != GOOD)
      return err;
   return(GOOD);
}

/****************************************************************************
**
** Name:  CheckSpaceType
**
****************************************************************************/
RETCODE CheckSpaceType(SPACE_TYPE spaceType, U16 fcPin) {
   switch (spaceType) {
      case S_PROGRAM :
         if ((fcPin == F_SP) | (fcPin == F_UP)) return(GOOD);
         break;
      case S_DATA :
         if ((fcPin == F_UD) | (fcPin == F_SD) | (fcPin == F_CPU))
            return(GOOD);
         break;
      case S_DONT_CARE :
         return(GOOD);
      default :
         return(!GOOD);
   }
   return(!GOOD);
}
/****************************************************************************
**
** Name:  SkipTraceFrame
**
****************************************************************************/
RETCODE SkipTraceFrame
        (DESCRIPTOR dqStateId,
         S8 frameLen,
         S32 startSkipFrame,
         SPACE_TYPE spaceType){
DQ_STATE FAR *dqState;
U16 curOffset;
U8 count = 0;
U16 traceBuf;
S32 oldest, newest, trig;
RETCODE err;

   if ((dqState = (DQ_STATE FAR *)dqStateId) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);
   TrcReadBufferGet(dqState->traceId,&traceBuf);
   if ((err = TrcTraceBufferInfoGet(dqState->traceId,&oldest,&newest,&trig))
      != GOOD) return(err);

   if ((traceBuf != dqState->traceBufId) ||  // different buffer ID.
       (startSkipFrame < dqState->frameStart)||
       (startSkipFrame > dqState->frameEnd)) { 
      AddDqStateTable(dqStateId,startSkipFrame);
      dqState->traceBufId = traceBuf;
   }
   curOffset = (U16)(startSkipFrame - dqState->frameStart);

   count = 0;
   if (frameLen > 0) {
      do {
         if (CheckSpaceType
             (spaceType, dqState->frameArray[curOffset].fcPin) == GOOD)
            count++;
         curOffset++;
         if (dqState->frameArray[curOffset].frameNo >= dqState->frameEnd) {
            AddDqStateTable(dqStateId,dqState->frameEnd);
            curOffset = 0;
         }
         if (dqState->frameArray[curOffset].frameNo >= newest)
            break;
      }while (count < frameLen);
      TrcReadFrameSet(dqState->traceId,dqState->frameArray[curOffset].frameNo);
      DadSetDqOffset(dqStateId,0);
   }
   else {
      do {
         if (CheckSpaceType
             (spaceType, dqState->frameArray[(U16)curOffset].fcPin) == GOOD)
            count++;
         curOffset--;
         if (dqState->frameArray[curOffset].frameNo <= dqState->frameStart) {
            if ((dqState->frameStart-64) < oldest) {
               dqState->frameStart = oldest;
               curOffset = dqState->frameStart-oldest;
            }
            else {
               dqState->frameStart -=64;
               curOffset = 63;
            }
            AddDqStateTable(dqStateId,dqState->frameStart);
         }
         if (dqState->frameArray[curOffset].frameNo <= oldest)
            break;
      }while (count < frameLen);
      TrcReadFrameSet(dqState->traceId,dqState->frameArray[curOffset].frameNo);
      DadSetDqOffset(dqStateId,0);
   }
   return(GOOD);


}

/****************************************************************************
**
** Name:  ReadTraceFrame
**
****************************************************************************/
RETCODE ReadTraceFrame
        (DESCRIPTOR dqStateId,
         S32 startReadFrame,
         DQ_FRAME *dqFrame){
DQ_STATE FAR *dqState;
U16 curOffset;
//U8 frameCount;
//U16 traceBuf;
//S32 oldest, newest, trig;
RETCODE err=GOOD;

   if ((dqState = (DQ_STATE FAR *)dqStateId) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);
//   TrcReadBufferGet(dqState->traceId,&traceBuf);
//   if ((err = TrcTraceBufferInfoGet(dqState->traceId,&oldest,&newest,&trig))
//      != GOOD) return(err);

   if ((startReadFrame < dqState->frameStart)||
       (startReadFrame > dqState->frameEnd)) 
      err = AddDqStateTable(dqStateId,startReadFrame);
   curOffset = (U16)(startReadFrame - dqState->frameStart);

   dqFrame->frameNo = dqState->frameArray[curOffset].frameNo;
   dqFrame->addr = dqState->frameArray[curOffset].addr;
   dqFrame->data = dqState->frameArray[curOffset].data;
   dqFrame->fcPin = dqState->frameArray[curOffset].fcPin;
   dqFrame->rwPin = dqState->frameArray[curOffset].rwPin;
   dqFrame->dsPin = dqState->frameArray[curOffset].dsPin;

   curOffset++;
   if (dqState->frameArray[curOffset].frameNo >= dqState->frameEnd) {
      err = AddDqStateTable(dqStateId,dqState->frameEnd); // read trace frames from hardware.
      curOffset = 0;
   }

//   if (startReadFrame+frameCount >= newest)
//      return(GOOD); // not find enough program frame.
   return(err);
}

/****************************************************************************
**
** Name:  ReadInstDataAndAddress
**
****************************************************************************/
RETCODE ReadInstDataAndAddress(DESCRIPTOR dqStateId,DQ_FRAME FAR *dqFrame) {
DQ_STATE FAR *dqState;
S32 curFrame;
RETCODE status;

   if ((dqState = (DQ_STATE FAR *)dqStateId) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);
   TrcReadFrameGet(dqState->traceId,&curFrame);
   status = ReadTraceFrame(dqStateId,curFrame,dqFrame);
   return(status);
}

/****************************************************************************
**
** Name:  CheckInterrupt
**
****************************************************************************/
INST_TYPE CheckInterrupt(DESCRIPTOR dqStateId, S32 nextFrame) {
DQ_FRAME dqFrame;
//U8 count;

   ReadTraceFrame(dqStateId,nextFrame,&dqFrame);

   if ((dqFrame.rwPin == 0) &&
       (dqFrame.fcPin == F_CPU) &&
       (dqFrame.rwPin == 0) &&
       (dqFrame.rwPin == 0) &&
       (dqFrame.rwPin == 1) &&
       (dqFrame.rwPin == 1))
       return(HW_INT);
   else return(NORMAL_INST);

}
/****************************************************************************
**
** Name:  PrintDataFrame
**
****************************************************************************/
RETCODE PrintDataFrame(DESCRIPTOR dqStateId, S32 frameNo, U32 data,
                U16 dataLen, ADDR_SPACE space, LPSTR string) {
   LPSTR tempBuff;
   U8 spaceText[8][3] = {"","UD","SD","","","UP","SP",""};

   if ((tempBuff = TMalloc(80)) == NULL) return(ER_OUT_OF_MEMORY);

   switch (dataLen) {
      case 1 : // Byte
         wsprintf(tempBuff,"    R/W - %02X  ", (U8)(data & 0x0FFl));
         break;
      case 2 : // Word
         wsprintf(tempBuff,"    R/W - %04X  ", (U16)(data & 0x0FFFFl));
         break;
      case 3 : // Three Byte
         wsprintf(tempBuff,"    R/W - %06lX  ", (data & 0x0FFFFFFl));
         break;
      case 4 : // Long
         wsprintf(tempBuff,"    R/W - %08lX  ", data);
   }
   lstrcat((LPSTR)string,(LPSTR)tempBuff);
   lstrcat((LPSTR)string,(LPSTR)spaceText[space]);
   TFree(tempBuff);
   return(GOOD);
}

/****************************************************************************
**
** Name:  DqInst
**
****************************************************************************/
RETCODE DqInst(DESCRIPTOR id,U32 *numInst,S32 FAR *startFrame,
               S32 FAR *endFrame, LPSTR *buffer, LPSTR *buffIndex, U16 *indexLen) {
BOOLEAN dasmSym;
//U16 trcBuffer,
U16 lp;
DASM_INFO dasmInfo;
S32 oldest,newest,trig,nextFrame;
U32 numFrames;
DQ_STATE FAR *dqState;
DQ_FRAME dqFrame;
RETCODE status;
LPSTR bufferPtr;
U8 tempBuffer[80];
ADDR_SPACE space;

   if ((dqState = (DQ_STATE FAR *)id) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);

   if ((status = TrcFrameDisplayModeSet(dqState->traceId,TRIGGER_ALIGN))
         != GOOD) 
      return(status);
   
   if ((status = DadGetDasmSymbol(&dasmSym)) != GOOD)  
      return(status);
   
   if ((status=TrcNumFramesGet(dqState->traceId, &numFrames))!=GOOD) 
      return(status);
   
   if ( !numFrames ) 
      return(ER_DQ_NO_FRAMES_AVAILABLE); /* no frames just get out! */

/*
** Retrieve information about trace buffer limits and requested range
*/
   
   if ((status = TrcTraceBufferInfoGet(dqState->traceId,&oldest,&newest,&trig))
      != GOOD) return(status);
   
//   if ((status = TrcReadFrameGet(dqState->traceId, &firstFrame)) != GOOD) 
//      return(status);
   
//   if ((status = TrcReadBufferGet(dqState->traceId, &trcBuffer)) != GOOD)
//      return(status);
   
   dasmInfo.bytesUsed = 0;
   *indexLen = 0;
   nextFrame = *startFrame;
   bufferPtr = *buffer;
   status = GOOD;
   for ( lp = 0; (nextFrame <= *endFrame) ; ) {

      if (ReadInstDataAndAddress(id,&dqFrame) != GOOD) {
         status = ER_DQ_NO_FRAMES_AVAILABLE;
         break;
      }

      buffIndex[lp++] = bufferPtr + lstrlen(bufferPtr);
      wsprintf(tempBuffer," %7ld  ",dqFrame.frameNo);
      lstrcat((LPSTR)bufferPtr,(LPSTR)tempBuffer);

      space = dqFrame.fcPin;
      if (dqFrame.data == 0) {
         wsprintf(tempBuffer,"%08lX", dqFrame.addr);
         lstrcat((LPSTR)bufferPtr,(LPSTR)tempBuffer);
         space = dqFrame.fcPin;
         if (TraceBufInst(dqFrame.addr,
                       dasmSym,bufferPtr,&dasmInfo,space) != GOOD) break;
      } else
         PrintDataFrame(id,dqFrame.frameNo,dqFrame.addr,dqFrame.data,
                          space,bufferPtr);

      (*indexLen)++;
      wsprintf(bufferPtr+lstrlen(bufferPtr),"\r\n");
      nextFrame++;
      //Read the instruction that numbers of R/W cycle
      switch (dasmInfo.instType) {
         case MODIFY_SR :
         case BRANCH :
         case TRAP :
         case ILLEGAL :
         case RETURN :
         case TRANSFER_INST :
         default :
            break;
      }

      if (nextFrame > newest) break;

      TrcReadFrameSet(dqState->traceId,nextFrame);
   }
   if (lp < *numInst)
      *numInst = lp;
   
   return(status);

}

/****************************************************************************
**
** Name:  DadForwardDqInst
**
****************************************************************************/
RETCODE EXPORT DadForwardDqInst(DESCRIPTOR id,U32 numInst,S32 FAR *startFrame,
                        S32 FAR *endFrame, LPSTR *buffer, U16 FAR *textLen) {

U32 instNo = numInst;
S32 curFrame,oldest,newest,trig;
DQ_STATE FAR *dqState;
RETCODE status;
LPSTR buffIndex[100],tempBuffer;
U16 indexLen = 0,bufferDepth;

#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   *textLen = 0;
   ProcReturnSpecificProcessor(&gProcessor);
   if ((dqState = (DQ_STATE FAR *)id) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);

   if ((status = TrcReadFrameGet(dqState->traceId, &curFrame)) != GOOD)
      return(status);
   if ((status = TrcTraceBufferInfoGet(dqState->traceId,&oldest,&newest,&trig))
      != GOOD) return(status);

   *startFrame = curFrame;
   if ((*endFrame = curFrame + numInst - 1) > newest)
      *endFrame = newest;

   bufferDepth = 80 * numInst;
   if ((tempBuffer = TMalloc(bufferDepth)) == NULL)
      return(ER_OUT_OF_MEMORY);
   _fmemset(tempBuffer,'\0',bufferDepth); /* initialize string */

#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   if ((status = DqInst(id,&instNo,startFrame,endFrame,&tempBuffer,buffIndex,&indexLen))
         != GOOD) {
      TFree(tempBuffer);
      return(status);
   }
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif

   if ((status = TrcReadFrameSet(dqState->traceId, curFrame)) != GOOD) {
      TFree(tempBuffer);
      return(status);
   }
   
   if (instNo == 0) {
      *textLen = 0;
      *tempBuffer = NULL;
      *startFrame = *endFrame = curFrame;
   } else {
      *textLen = lstrlen(tempBuffer);
   }
   if ((*buffer = TMalloc(*textLen+1)) == NULL)
      return(ER_OUT_OF_MEMORY);
   _fmemcpy(*buffer,tempBuffer,*textLen+1);
   TFree(tempBuffer);

   //OutputStringToFile(*buffer,*textLen);
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif

   return(GOOD);

}

/****************************************************************************
**
** Name:  SearchTermination
**
****************************************************************************/
//RETCODE SearchTermination(LPSTR *headPtr,LPSTR tempBuff, S32 curFrame,
//                          U32 numInst,S32 FAR *startFrame, S32 FAR *endFrame,
//                          LPSTR *buffIndex,U16 *indexLen){
//S32 firstFrame,secondFrame;
//U16 lp;
//
//   lp = 0;
//   while(indexLen > lp) {
//      sscanf(buffIndex[lp]," %ld",&firstFrame);
//      sscanf(buffIndex[lp+1]," %ld",&secondFrame);
//      if (curFrame == firstFrame) break;
//      else if((firstFrame < curFrame) && (secondFrame > curFrame)) break;
//      lp++;
//   };
//   if ((indexLen- lp) > numInst) {
//      buffIndex[lp+numInst] = 0;
//      sscanf(buffIndex[lp+numInst-1]," %ld",endFrame);
//   }
//   else
//      sscanf(&(buffIndex[indexLen - lp])," %ld",endFrame);
//   _fmemcpy(tempBuff,buffIndex[lp],lstrlen(buffIndex[lp]));
//   *(tempBuff+ lstrlen(buffIndex[lp])) = 0;
//   //*textLen = lstrlen(tempBuff);
//   sscanf(tempBuff," %ld",startFrame);
//   *headPtr = tempBuff;



//S8 far *frameStr;
//S8 far *tempPtr;
//LPSTR endPtr;
//LPSTR nullPtr;
//U16 lp,cutLen;
//S32 lp2;
//   if ((frameStr = TMalloc(10)) == NULL) return(ER_OUT_OF_MEMORY);
//   for (lp2 = (curFrame+1); lp2 > (curFrame - 11); lp2--){
//      wsprintf(frameStr," %5d  ",lp2);
//      endPtr = _fstrstr(tempBuff,frameStr);
//      if (endPtr != NULL) {
//         nullPtr = _fstrchr(endPtr,'\r\n');
//         *nullPtr = 0;
//         *endFrame = curFrame;
//         break;
//      }
//      else {
//         //search end frame
//      }
//   }
//
//   lp = 0;
//   tempPtr = tempBuff;
//   while (tempPtr != NULL){
//      tempPtr++;
//      tempPtr = _fstrstr(tempPtr,"us");
//      lp++;
//   };
//
//   tempPtr = tempBuff;
//   if (lp > numInst) {
//      cutLen = lp - (U16)numInst;
//      for (lp = 0; lp < cutLen; lp++) {
//         tempPtr++;
//         tempPtr = _fstrstr(tempPtr,"us");
//      }
//      tempPtr -= 17;
//   }
//   *headPtr = tempPtr;
//   sscanf(tempPtr," %ld",startFrame);
//
//   TFree(frameStr);
//
//}
/****************************************************************************
**
** Name:  DadBackwardDqInst
**
****************************************************************************/
RETCODE EXPORT DadBackwardDqInst(DESCRIPTOR id,U32 numInst,S32 FAR *startFrame,
                        S32 FAR *endFrame, LPSTR *buffer, U16 FAR *textLen) {
U32 instNo = numInst;
S32 curFrame;
DQ_STATE FAR *dqState;
RETCODE status;
LPSTR tempBuffer;
S32 oldest,newest,trig;
LPSTR buffIndex[100];
U16 indexLen;
U16 bufferDepth;

#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   ProcReturnSpecificProcessor(&gProcessor);
   if ((dqState = (DQ_STATE FAR *)id) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);

   if ((status = TrcReadFrameGet(dqState->traceId, &curFrame)) != GOOD)
      return(status);
   
   if ((status = TrcTraceBufferInfoGet(dqState->traceId,&oldest,&newest,&trig))
      != GOOD) return(status);

   if ((*startFrame = curFrame - numInst) < oldest)
      *startFrame = oldest;
   if ((status = TrcReadFrameSet(dqState->traceId, *startFrame)) != GOOD)
      return(status);
   *endFrame = curFrame - 1;
   
   bufferDepth = 80 * numInst;
   if ((tempBuffer = TMalloc(bufferDepth)) == NULL)
      return(ER_OUT_OF_MEMORY);
   _fmemset(tempBuffer,'\0',bufferDepth); /* initialize string */
   
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   if ((status = DqInst(id,&instNo,startFrame,endFrame,&tempBuffer,
         buffIndex,&indexLen)) != GOOD) {
      TFree(tempBuffer);
      return(status);
   }
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
  
   if ((status = TrcReadFrameSet(dqState->traceId, curFrame)) != GOOD) {
      TFree(tempBuffer);
      return(status);
   }
   if (curFrame == *startFrame) { 
     *textLen = 0;
     *tempBuffer = NULL;
   } else {
      *textLen = lstrlen(tempBuffer);
   }
   if ((*buffer = TMalloc(*textLen+1)) == NULL)
      return(ER_OUT_OF_MEMORY);
   _fmemcpy(*buffer,tempBuffer,*textLen+1);
   TFree(tempBuffer);
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   return(GOOD);
}

/****************************************************************************
**
**  DadDqFlush
**
****************************************************************************/
#pragma argsused
RETCODE EXPORT DadDqFlush(DESCRIPTOR id) {
   return(GOOD);
}

