/****************************************************************************
**
**  Name:  dq306.c
**
**  Description:
**     This is a dequeuer for Motorola 68306
**
**  $Log:   S:/tbird/mt2_68k/dad32/dq306.c_v  $
** 
**    Rev 1.2   10 Feb 1998 12:03:50   Eric
** Added return error code in CreatDqStateTable.
** 
**    Rev 1.1   19 Aug 1997 09:59:48   gene
** 
**    Rev 1.0   13 Feb 1997 08:45:14   gene
** Initial revision.
** 
**    Rev 1.24   12 Aug 1996 14:12:34   kevin
** got rid of some redundant code
** 
**    Rev 1.23   25 Jul 1996 08:26:14   kevin
** fixed some bugs in 8-bit mode
** 
**    Rev 1.22   03 Jul 1996 14:37:20   kevin
** support 8-bit mode
** 
**    Rev 1.21   02 Jul 1996 13:26:32   kevin
** inserted redudant code to BackwardDqInst() to avoid a bug of optimization
** 
**    Rev 1.20   28 Jun 1996 14:24:08   kevin
** added core type checking
** 
**    Rev 1.19   27 May 1996 10:55:04   kevin
** Modified spaceString table
** 
**    Rev 1.18   20 May 1996 16:59:24   kevin
** added PVCS header
**
**  Status:
**
**
**  $Header:   S:/tbird/mt2_68k/dad32/dq306.c_v   1.2   10 Feb 1998 12:03:50   Eric  $
**
**  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 _SDS2ABI_
#include "sds2abi.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  (1024/TRACE_FRAME_WIDTH)

                        /****************************
                         *                          *
                         *     EXTERNALS            *
                         *                          *
                         ****************************/

extern HANDLE cliServerHandle;

                        /****************************
                         *                          *
                         *     LOCAL VARIABLES      *
                         *                          *
                         ****************************/
S8 spaceString[][16] =
   {"Space0 Write","Data Write(UD)","",  "Space3 Write","Space4 Write","Data Write(SD)","",  "CPU",
    "Space0 Read", "Data Read(UD)", "UP","Space3 Read", "Space4 Read", "Data Read(SD)","SP","CPU"};

extern PROBE_TYPE gProcessor;

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

                        /****************************
                         *                          *
                         *     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,(S32)MAX_READ_FRAME_LEN,
        (U32 far *)&numGotten,
             &buffer)) != GOOD) return(err);

   for (lp = 0; lp < numGotten; lp++) {
      _fmemcpy(&(dqState->frameArray[lp]),
             (buffer+lp*TRACE_FRAME_WIDTH),sizeof(TRC_FRAME));
             // raw data have 4*5 bytes, but TRC_FRAME is less than 20 bytes
   }
   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); //modify return by Eric 2/5/98
   //return(GOOD);
   return(AddDqStateTable(dqStateId,curFrame));//Eric 2/5/98
}

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

   programSpace = ((fcPin == F_SP) | (fcPin == F_UP)) ? 1 : 0;
   switch (spaceType) {
      case S_PROGRAM :
         if (programSpace) return(GOOD);
         break;
      case S_DATA :
         if (!programSpace) return(GOOD);
         break;
      case S_DONT_CARE :
         return(GOOD);
      default :
         return(!GOOD);
   }
   return(!GOOD);
}

/****************************************************************************
**
** Name:  DqReadTraceFrame
**
****************************************************************************/
RETCODE DqReadTraceFrame
        (DESCRIPTOR dqStateId,
         S8 frameLen,
         S32 startReadFrame,
         DQ_FRAME *dqFrame,
         SPACE_TYPE spaceType,
         U8 *count){
DQ_STATE FAR *dqState;
U16 curOffset;
U8 frameCount;
U16 traceBuf;
S32 oldest, newest, trig;
RETCODE err;

   *count = 0;
   if ((dqState = (DQ_STATE FAR *)dqStateId) == NULL)
      return (ER_DAD_INVALID_ID_DESCRIPTOR);
   TrcReadBufferGet(dqState->traceId,&traceBuf);
   _fmemset(dqFrame,0x7f,sizeof(DQ_FRAME)); /* initialize struct */
   if ((err = TrcTraceBufferInfoGet(dqState->traceId,&oldest,&newest,&trig))
      != GOOD) return(err);

   if ((startReadFrame < dqState->frameStart)||
       (startReadFrame > dqState->frameEnd))
      AddDqStateTable(dqStateId,startReadFrame);
   curOffset = (U16)(startReadFrame - dqState->frameStart);
   *count = frameCount = 0;
   do {
      if (CheckSpaceType
          (spaceType, dqState->frameArray[curOffset].fcPin) == GOOD) {
         if ((*count == 1) &&
             (dqFrame->addr[0] != dqState->frameArray[curOffset].addr - 2) &&
             (dqState->frameArray[curOffset].fcPin == F_SP ||
              dqState->frameArray[curOffset].fcPin == F_UP)
            ) {
            if (dqState->coreType != MODE_8BITS ||
               (dqFrame->addr[0] != dqState->frameArray[curOffset].addr - 1))
               *count = 0; /* remove 1st up/sp frame, if first two frame isn't cnontigous */
         }
         dqFrame->frameNo[*count] = dqState->frameArray[curOffset].frameNo;
         dqFrame->addr[*count] = dqState->frameArray[curOffset].addr;
         dqFrame->data[*count] = dqState->frameArray[curOffset].data;
         dqFrame->fcPin[*count] = dqState->frameArray[curOffset].fcPin;
         dqFrame->rwPin[*count] = dqState->frameArray[curOffset].rwPin;
         dqFrame->dsPin[*count] = dqState->frameArray[curOffset].dsPin;
         if (dqState->coreType == MODE_8BITS &&
             spaceType == S_PROGRAM &&
             (dqState->frameArray[curOffset].addr%2) != 0) {
            dqFrame->data[*count-1] <<= 8;
            dqFrame->data[*count-1] += dqFrame->data[*count];
         }
         else
            (*count)++;
      }
      frameCount++;
      curOffset++;
      if (dqState->frameArray[curOffset].frameNo >= dqState->frameEnd) {
         AddDqStateTable(dqStateId,dqState->frameEnd); // read trace frames from hardware.
         curOffset = 0;
      }                                        
      if (startReadFrame+frameCount >= newest)
         return(GOOD); // not find enough program frame.
   }while ((*count < frameLen) && (frameCount < MAX_READ_FRAME_LEN));
   return(GOOD);
}

/****************************************************************************
**
** Name:  ReadInstDataAndAddress
**
****************************************************************************/
RETCODE ReadInstDataAndAddress(DESCRIPTOR dqStateId,DQ_FRAME FAR *dqFrame,
                               U8 FAR *count) {
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 = DqReadTraceFrame(dqStateId,MAX_INST_LEN + 2,curFrame,
                           dqFrame,S_PROGRAM,count);
   return(status);
}

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

   DqReadTraceFrame(dqStateId,6,nextFrame,&dqFrame,S_DATA,&count);

   if ((dqFrame.rwPin[0] == 0) &&
       (dqFrame.fcPin[1] == F_CPU) &&
       (dqFrame.rwPin[2] == 0) &&
       (dqFrame.rwPin[3] == 0) &&
       (dqFrame.rwPin[4] == 1) &&
       (dqFrame.rwPin[5] == 1))
       return(HW_INT);
   else return(NORMAL_INST);

}
/****************************************************************************
**
** Name:  PrintRemainsFrame
**
****************************************************************************/
RETCODE PrintRemainsFrame(DESCRIPTOR dqStateId,
                       S32 startFrame,S32 endFrame, LPSTR string) {
S32 offset;
U16 lp;
DQ_FRAME printFrame;
S8 strPos;
LPSTR tempBuff;
U8 count;

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

   offset = endFrame - startFrame;
   for (lp = 0; lp < offset; lp++, startFrame++){
      DqReadTraceFrame(dqStateId,1,startFrame,&printFrame,S_DONT_CARE,&count);
      strPos = ((printFrame.rwPin[0] << 3) & 0x8) + printFrame.fcPin[0];
      if ((printFrame.fcPin[0] != F_SP) &&
          (printFrame.fcPin[0] != F_UP)) {
         wsprintf(tempBuff," %7ld  ", printFrame.frameNo[0]);
         lstrcat((LPSTR)string,(LPSTR)tempBuff);
         if (gProcessor == M68306_MP)
            wsprintf(tempBuff,"%08lX    ", printFrame.addr[0]);
         else
            wsprintf(tempBuff,"%06lX    ", printFrame.addr[0]);
         lstrcat((LPSTR)string,(LPSTR)tempBuff);
         wsprintf(tempBuff,"%s: ", spaceString[strPos]);
         lstrcat((LPSTR)string,(LPSTR)tempBuff);
         switch (printFrame.dsPin[0] & 3) {
            case 0 : //Word
               wsprintf(tempBuff,"%04X\r\n", printFrame.data[0]);
               break;
            case 1 : // High Byte
               wsprintf(tempBuff,"%02X\r\n", (U8)(printFrame.data[0] >> 8));
               break;
            case 2 : // Low Byte
               wsprintf(tempBuff,"%02X\r\n", (U8)printFrame.data[0]);
               break;
            case 3 : // Low Byte
               wsprintf(tempBuff,"????\r\n");
         }
         lstrcat((LPSTR)string,(LPSTR)tempBuff);
      }
   }
   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, showTS;
U16 trcBuffer,lp;
DASM_INFO dasmInfo;
S32 oldest,newest,trig,nextFrame, prevFrame; /* <Judy 7/22/97> */
U32 numFrames;
DQ_STATE FAR *dqState;
DQ_FRAME dqFrame;
RETCODE status;
LPSTR bufferPtr;
U8 count,tempBuffer[80];
U32 FrameTS;  /* Judy 7/22/97> */
U8 FrameTSM;  /* Judy 7/22/97> */

   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;
   prevFrame=nextFrame = *startFrame;
   bufferPtr = *buffer;
   status = GOOD;
   TrcTimestampGet(dqState->traceId, &showTS);
   for ( lp = 0; nextFrame < *endFrame; ) {
      if (ReadInstDataAndAddress(id,&dqFrame,&count) != GOOD) {
         status = ER_DQ_NO_FRAMES_AVAILABLE;
         break;
      }
      if (!lp) {
         if (dqFrame.frameNo[0] == 0x7f7f7f7fl) { // no frame data
            *startFrame = *endFrame = 0;
            *numInst = 0;
            return(GOOD); // maybe return another error. Allen
         }
         else *startFrame = dqFrame.frameNo[0]; // start frame at first inst.
      }

      buffIndex[lp++] = bufferPtr + lstrlen(bufferPtr);
      wsprintf(tempBuffer," %7ld  ",dqFrame.frameNo[0]);
      lstrcat((LPSTR)bufferPtr,(LPSTR)tempBuffer);
      /* <Judy 7/22/97> */
      if(showTS==TRUE) {
        Sds2AbiReadFrameStamp(0, dqFrame.frameNo[0], &FrameTS, &FrameTSM);
        if((status=TrcGetTimestampText(dqState->traceId,FrameTS,FrameTSM,
                  prevFrame,bufferPtr)) != GOOD ) return(status);
        prevFrame=dqFrame.frameNo[0];
      }
      /* eof <Judy 7/22/97> */

      if (gProcessor == M68306_MP)
         wsprintf(tempBuffer,"%08lX", dqFrame.addr[0]);
      else
         wsprintf(tempBuffer,"%06lX", dqFrame.addr[0]);
      lstrcat((LPSTR)bufferPtr,(LPSTR)tempBuffer);

      if (TraceBufInst((U16 FAR *)dqFrame.data,dqFrame.addr[0],
                       dasmSym,bufferPtr,&dasmInfo,count*2) != GOOD) break;
      else {
         (*indexLen)++;
         wsprintf(bufferPtr+lstrlen(bufferPtr),"\r\n");
         if (dasmInfo.bytesUsed)
            nextFrame = dqFrame.frameNo[dasmInfo.bytesUsed/2];
         else
            nextFrame = dqFrame.frameNo[1];
         //Read the instruction that numbers of R/W cycle
         switch (dasmInfo.instType) {
            case MODIFY_SR :
               nextFrame = dqFrame.frameNo[dasmInfo.bytesUsed/2 + 1];
               break;
            case BRANCH :
            case TRAP :
            case ILLEGAL :
            case RETURN :
            case TRANSFER_INST :
               if (dqFrame.addr[dasmInfo.bytesUsed/2 + 1] !=
                        (dqFrame.addr[dasmInfo.bytesUsed/2] + 2))
                   nextFrame = dqFrame.frameNo[dasmInfo.bytesUsed/2 + 1];
               break;
            default :
               // if (nextFrame > newest) break;
               if (CheckInterrupt(id,nextFrame) == HW_INT) {
               // if prev inst length =2 then delete prev inst
               }
               break;
         }
         {
             // put frameNo address data status.
             // put dasm inst string.

             // bufferPtr,tempBuffer,dqFrame); // out the executed instruction.
         }

         if (nextFrame > newest) break;
         if (nextFrame > (dqFrame.frameNo[0]+1) ) 
            PrintRemainsFrame(id,dqFrame.frameNo[0]+1,nextFrame,bufferPtr);
         
         TrcReadFrameSet(dqState->traceId,nextFrame);
      }
   }
   if (lp < *numInst) *numInst = lp;
   *endFrame = dqFrame.frameNo[dasmInfo.bytesUsed/2 - 1];
   
   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;

   *textLen = 0;
   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);

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

   *startFrame = curFrame;
   if ((*endFrame = curFrame + numInst * 2) > newest)
      *endFrame = newest;
   if ((status = DqInst(id,&instNo,startFrame,endFrame,&tempBuffer,buffIndex,&indexLen))
         != GOOD) {
      TFree(tempBuffer);
      return(status);
   }

   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) {
      TFree(tempBuffer);
      return(ER_OUT_OF_MEMORY);
   }
   _fmemcpy(*buffer,tempBuffer,*textLen+1);
   TFree(tempBuffer);

   //OutputStringToFile(*buffer,*textLen);

   return(GOOD);

}

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

   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*2 + 1) < oldest)
      *startFrame = oldest;
   if ((status = TrcReadFrameSet(dqState->traceId, *startFrame)) != GOOD)
      return(status);
   *endFrame = curFrame;

   bufferDepth = 80 * numInst * 2;
   if ((tempBuffer = TMalloc(bufferDepth)) == NULL)
      return(ER_OUT_OF_MEMORY);
   _fmemset(tempBuffer,'\0',bufferDepth); /* initialize string */
   
   if (curFrame > *startFrame) { 
      if ((status = DqInst(id,&instNo,startFrame,endFrame,&tempBuffer,
             buffIndex,&indexLen)) != GOOD) {
         TFree(tempBuffer);
         return(status);
      }
   }
   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) {
      TFree(tempBuffer);
      return(ER_OUT_OF_MEMORY);
   }
   _fmemcpy(*buffer,tempBuffer,*textLen+1);
   TFree(tempBuffer);
   return(GOOD);
}

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