/*****************************************************************************
**
**  Name: abidrive.c
**
**  Description: This is the code for drivers of ABIs
**
**  Status: PRELIMINARY
**
**  $Log:   S:/tbird/mt2_68k/abi68k/abidrive.c_v  $
** 
**    Rev 1.4   10 Apr 1997 16:27:44   gene
** 
**    Rev 1.3   10 Apr 1997 09:47:22   gene
** 
**    Rev 1.2   18 Mar 1997 10:08:30   gene
** 
**    Rev 1.1   04 Mar 1997 13:03:36   gene
** 
**    Rev 1.0   13 Feb 1997 08:36:10   gene
** Initial revision.
** 
**    Rev 1.3   02 Aug 1996 10:45:00   kevin
** SLD will abort automatically if communication has problem
** 
**
**  $Header:   S:/tbird/mt2_68k/abi68k/abidrive.c_v   1.4   10 Apr 1997 16:27:44   gene  $
**
**  Copyright (C) 1991,1992 Microtek International.  All rights reserved.
**
*****************************************************************************/
#include <windows.h>

#ifndef _COMM_
#include "comm.h"
#endif

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

#ifndef _SD_ABI_DEF_
#include "sdabidef.h"
#endif

#ifndef _ABI_FUNC_
#include "abifunc.h"
#endif

#ifndef _COMMUNICATION_
#include "comm.h"
#endif

/* from windows.h for Windows 3.1 */
#ifndef HFILE
typedef int HFILE; /* Polymorphic with C runtime file handle type */
#define HFILE_ERROR ((HFILE)-1)
#endif

#ifndef SEEK_SET
#define SEEK_SET 0
#endif

#define LINK_TIMEOUT 5000

U8 BASE_TIME = 0xFF; /* gene */
extern int portId;
extern U16 printerPort;

/**************************************************************************
**
** Name : CheckFwStatus
**
** Function
**        Check the status of MICEpack. MICEpack have "COLD START", "NORMAL"
**        and "DIAGNOSTIC" status. the other status is not normal.
**
**    Input  :
**       None
**    Output :
**       None
** Notes:
**
**************************************************************************/
RETCODE EXPORT CheckFwStatus(VOID) {
U8 idData[MAX_ID];
int i, retID;
DWORD startTime;

   while (1) {
      startTime = GetCurrentTime();

      while ((GetCurrentTime()-startTime) < LINK_TIMEOUT) {

         if (chk_hlt() == ESC) return(ICE_HALT_USER); // check keyboard.
         // Ken, Replace chk_hlt() to your program . Allen.
         if (sendB('M') != GOOD) continue;
         if (sendB('I') != GOOD) continue;
         if (sendB('C') != GOOD) continue;
         if (sendB('E') != GOOD) continue;
         i = receiveB();
         if (i == ACK) {
            return(COLD_START);
         } else if (i == ':') {
            iceGetID(idData);
            if (idData[0] == 'D') return(DIAGNOSTIC_STATUS);
            else return(NORMAL_STATUS);
         } else if (i == '?') {
            return(HW_RESET_STATUS);
         }
      }
      ErrMessageBox((LPSTR)"MICEpack/SLD",(LPSTR)"MICEpack/SLD link MICE fail !!",
            MB_RETRYCANCEL | MB_ICONASTERISK,0,
            (S16 FAR *)&retID);   // gene*
      if (retID == IDCANCEL) break;
   }
   return(ICE_LINK_MICE_FAIL);
}

/**************************************************************************
**
** Name :
**
** Function
**
**    Input  :
**
**    Output :
**
** Notes:
**
**************************************************************************/
//#define FILE_SIZE     255
#define BUFF_UNIT     1024 // basic buffer unit.

U16 fileSize;

RETCODE EXPORT DownLoadFirmwareParallel(U8 *fileName,U16 buffSize,U8 timeOut);
RETCODE EXPORT DownLoadFirmwareSerial(U8 *fileName,U16 buffSize,U8 timeOut);

RETCODE EXPORT DownLoadFirmware(U8 *fileName,U16 buffSize,U8 timeOut) {

   if (strnicmp(fileName,"main",4) == 0)
      fileSize = 255;
   else
      fileSize = 127;
   if (printerPort == 2)
      return(DownLoadFirmwareSerial(fileName,buffSize,timeOut));
   else
      return(DownLoadFirmwareParallel(fileName,buffSize,timeOut));
}


RETCODE EXPORT DownLoadFirmwareParallel(U8 *fileName,U16 buffSize,U8 timeOut) {
//U8 *dataBuff,blockNo,firstBlock; // basic unit : 1K.
U8 dataBuff[0x400],blockNo,firstBlock; // basic unit : 1K.
S32 filePos;
S16 lp,lp3,lp5,aa,buffLen;
S32 count;
//FILE *fStream;
HFILE fStream;
//OFSTRUCT ofStruct;
U32 startAddr;
RETCODE status;
//OFSTRUCT ofStruct;  


   if ((buffSize = (buffSize/BUFF_UNIT)) == 0) buffSize = 1; // Set buffer size. Minimum 1K.
   //if ((dataBuff = (U8 *)malloc(buffSize*BUFF_UNIT)) == NULL) {// Set buffer size.
   //   status = SendAddrLen(0L,0L); // Notify MICEpack re-download.
   //   return(-1);
   //}
//   if (firstBlock = FILE_SIZE % buffSize) blockNo = (FILE_SIZE/buffSize)+1;
   if (firstBlock = fileSize % buffSize) blockNo = (fileSize/buffSize)+1;
   else {
//      blockNo = (FILE_SIZE/buffSize);
      blockNo = (fileSize/buffSize);
      firstBlock = buffSize;
   }
//   if ((fStream = fopen((U8 far *)fileName,"rb")) == NULL) {
   if ((fStream = _lopen(fileName,READ)) == HFILE_ERROR) {
      status = SendAddrLen(0L,0L); // Notify MICEpack re-download.
      //free(dataBuff);
      return(ICE_FILE_NOT_FOUND);
   }
   for (lp5 = 0; lp5 < 5; lp5++) { // Try 5 times. If download failed, return failed.
      filePos = 0;
      startAddr = 0x400;
      for (lp = 0; lp < blockNo; lp++) {
         (lp) ? (buffLen = buffSize) : (buffLen = firstBlock);
         buffLen *= BUFF_UNIT; // each transmit buffer size.
         status = SendAddrLen(startAddr,buffLen);
         startAddr += buffLen;
         if (status != GOOD) { // if the data of address and length download fail. Re-download them.
            lp--;
            startAddr -= buffLen;
            continue;
         }
         do {
            if ((aa = receiveWait(timeOut)) == ICE_TIME_OUT) {
               //free(dataBuff);
               return(ICE_TIME_OUT);
            }
         } while ((aa != ACK) && (aa != NACK));
         if (aa == NACK) {
            lp--;
            startAddr -= buffLen;
            continue;
         }
         //count = fread((U8 *)dataBuff,sizeof(U8),buffLen,fStream);
         count = _lread(fStream,(void _huge*)dataBuff,buffLen);
         for (lp3 = 0; lp3 < count; lp3++)
            if ((aa = sendB(dataBuff[lp3])) != GOOD) break;
         if (aa != GOOD) {
            lp--;
            startAddr -= (buffLen);
            continue;
         }
         do {
            if ((aa = receiveWait(timeOut)) == ICE_TIME_OUT) {
               //free(dataBuff);
               return(ICE_TIME_OUT);
            }
         } while ((aa != ACK) && (aa != NACK));
         if (aa == NACK) {
            //fseek(fStream,filePos,SEEK_SET);
            _llseek(fStream,filePos,SEEK_SET);
            lp--;
            startAddr -= buffLen;
         }
         else filePos += (U32)buffLen;
      }
      SendAddrLen(0l,0l);
      //fclose(fStream);
      _lclose(fStream);
      do {
         if ((aa = receiveWait(timeOut)) == ICE_TIME_OUT) {
            //free(dataBuff);
            return(ICE_TIME_OUT);
         }
      } while ((aa != ACK) && (aa != NACK));
      if (aa == ACK) break;
   }
   // Firmware loading completed.
   //free(dataBuff);
   return(GOOD);
}

RETCODE EXPORT DownLoadFirmwareSerial(U8 *fileName,U16 buffSize,U8 timeOut) {
U8 dataBuff[0x400],blockNo,firstBlock; // basic unit : 1K.
S32 filePos;
S16 lp,lp3,lp5,aa,buffLen;
S32 count;
HFILE fStream;
U32 startAddr;
RETCODE status;
U32 checksumLen;
U16 checksum;


   if ((buffSize = (buffSize/BUFF_UNIT)) == 0) buffSize = 1; // Set buffer size. Minimum 1K.
//   if (firstBlock = FILE_SIZE % buffSize) blockNo = (FILE_SIZE/buffSize)+1;
   if (firstBlock = fileSize % buffSize) blockNo = (fileSize/buffSize)+1;
   else {
//      blockNo = (FILE_SIZE/buffSize);
      blockNo = (fileSize/buffSize);
      firstBlock = buffSize;
   }
   if ((fStream = _lopen(fileName,READ)) == HFILE_ERROR) {
      status = SendAddrLen(0L,0L); // Notify MICEpack re-download.
      return(ICE_FILE_NOT_FOUND);
   }
   for (lp5 = 0; lp5 < 5; lp5++) { // Try 5 times. If download failed, return failed.
      filePos = 0;
      startAddr = 0x400;
      for (lp = 0; lp < blockNo; lp++) {
         if (printerPort == 2) {
            FlushComm(portId,0);
            FlushComm(portId,1);
         }
         (lp) ? (buffLen = buffSize) : (buffLen = firstBlock);
         buffLen *= BUFF_UNIT; // each transmit buffer size.
         count = _lread(fStream,(void _huge*)dataBuff,buffLen);
         checksum = 0;
         for (lp3 = 0; lp3 < count; lp3++)
            checksum += dataBuff[lp3];
//         checksum = ~checksum + 1;
         checksumLen = (((U32)checksum) << 16) + (U32)buffLen;
         status = SendAddrLen(startAddr,checksumLen);
         startAddr += buffLen;
         if (status != GOOD) { // if the data of address and length download fail. Re-download them.
            lp--;
            startAddr -= buffLen;
            continue;
         }
         do {
            if ((aa = receiveWait(timeOut)) == ICE_TIME_OUT) {
               return(ICE_TIME_OUT);
            }
         } while ((aa != ACK) && (aa != NACK));
         if (aa == NACK) {
            lp--;
            startAddr -= buffLen;
            _llseek(fStream,filePos,SEEK_SET);
            continue;
         }
         for (lp3 = 0; lp3 < count; lp3++)
            if ((aa = sendB(dataBuff[lp3])) != GOOD) break;
         if (aa != GOOD) {
            lp--;
            startAddr -= (buffLen);
            _llseek(fStream,filePos,SEEK_SET);
            continue;
         }
         do {
            if ((aa = receiveWait(timeOut)) == ICE_TIME_OUT) {
               return(ICE_TIME_OUT);
            }
         } while ((aa != ACK) && (aa != NACK));
         if (aa == NACK) {
            _llseek(fStream,filePos,SEEK_SET);
            lp--;
            startAddr -= buffLen;
         }
         else filePos += (U32)buffLen;
      }
      SendAddrLen(0l,0l);
      _lclose(fStream);
      do {
         if ((aa = receiveWait(timeOut)) == ICE_TIME_OUT) {
            return(ICE_TIME_OUT);
         }
      } while ((aa != ACK) && (aa != NACK));
      if (aa == ACK) break;
   }
   return(GOOD);
}


/**************************************************************************
**
** Name :
**
** Function
**
**    Input  :
**
**    Output :
**
** Notes:
**
**************************************************************************/

RETCODE EXPORT linkMICE(INITIAL_INFO *initialInfo) {
RETCODE status;
U8 idInfo[MAX_ID];

   status = DownLoadFirmware(initialInfo->fileName,initialInfo->buffSize,initialInfo->timeOut);
   if (status != GOOD) return(status);
   iceGetID(idInfo);
   return (GOOD);
}   // end of linkMice()

/**************************************************************************
**
** Name :
**
** Function
**
**    Input  :
**
**    Output :
**
** Notes:
**
**************************************************************************/

RETCODE EXPORT iceInitialize(INITIAL_INFO *initialInfo) {
   RETCODE status;
   //U16 lp, testSeq[] = { MCE16A, EMM1, EMM2, EMM3, EMM4, TRACE_BOARD};
   U32 retData;
   U8 retID;

   if (SetComm(initialInfo->portAddr) != GOOD) return(ICE_TIME_OUT);
   BASE_TIME = initialInfo->timeOut;
   status = CheckFwStatus();
   switch (status) {
      case DIAGNOSTIC_STATUS :
         DiagnosticFunction(END_DIAG,&retData,&retID);
         CheckFwStatus();
         status = linkMICE(initialInfo); // for cold start and diagnostic
         break;
      case COLD_START :
         status = linkMICE(initialInfo); // for cold start and diagnostic
         break;
      case NORMAL_STATUS :
      case HW_RESET_STATUS :
         status = ICE_WARN_START;
      case ICE_HALT_USER :
         return(status);
      default:
         return(ICE_TIME_OUT);
   }
/*   if (status == GOOD) { // COLD_START and download OK.
      if (initialInfo->testFlag == TRUE) {
         for (lp = 0; lp < sizeof(testSeq)/sizeof(testSeq[0]); lp++) {
            if (chk_hlt() == ESC) break;
            status2 = iceSelfTest(testSeq[lp]);
            switch (status2) {
               case GOOD :
                  break;
               case ICE_NO_EMM :
                  initialInfo->testResult |= 4; // No EMM.
                  lp = 5;
                  break;
               case ICE_NO_TRACE_MODULE :
                  initialInfo->testResult |= 2; // No EMM.
                  break;
               default :
                  switch (lp) {
                     case 0 :
                        initialInfo->testResult |= 0x10; // MCE16A failed
                        break;
                     case 1: case 2: case 3: case 4:
                        initialInfo->testResult |= 8; // EMM failed
                        break;
                     case 5 :
                        initialInfo->testResult |= 1; // MTAT failed
                     // case record RAM
                  }
            }
         }
         iceSelfTest(END_TEST);
      }
      else iceSelfTest(END_TEST);
   } */
   return(status);
}



//main() {
//INITIAL_INFO initInfo;
//RETCODE status;
//U8 coReg[10],*buff;
//U16 allCpuReg[REG_NO],regData2,lp;
//U32 regData;
//
//   initInfo.portAddr       = 0x200;     // I/O port address.
//   initInfo.idFlag         = I80C186XL; // CPU type.
//   initInfo.buffSize       = 0x400;     // buffer size of communication
//   initInfo.testResult     = 0;         // clear data.
//   initInfo.testFlag       = ON;        // do selftest.
//   initInfo.timeOut        = 0xff;         // 3 second.
//   sprintf(initInfo.fileName,"%s","main186.bin"); // download file(include path).
//
//   status = iceInitialize(&initInfo);  // Initial MICEpack.
//
//   iceFill(0x400,0x100,"abcedf",5);
//   iceSetReg(I86_REG,AX ,123l); // Set AX register.
//   iceSetReg(I86_REG,BX ,456l); // Set BX register.
//   iceSetReg(I86_REG,CX ,789l); // Set CX register.
//   iceSetReg(I86_REG,DX ,111l); // Set DX register.
//   iceSetReg(I86_REG,RSP,222l); // Set SP register.
//   iceSetReg(I86_REG,BP ,333l); // Set BP register.
//   iceSetReg(I86_REG,SI ,444l); // Set SI register.
//   iceSetReg(I86_REG,DI ,555l); // Set DI register.
//   iceSetReg(I86_REG,DS ,666l); // Set DS register.
//   iceSetReg(I86_REG,SS ,777l); // Set SS register.
//   iceSetReg(I86_REG,ES ,888l); // Set ES register.
//   iceSetReg(I86_REG,CS ,123l); // Set CS register.
//   iceSetReg(I86_REG,IP ,400l); // Set IP register.
//   iceSetReg(I86_REG,FLAGS,002l);//Set FS register.
//   iceGetAllReg(allCpuReg); // Get all cpu registers.
//   iceStepOne();
//   iceGetReg(I86_REG,AX ,&regData); // Set AX register.
//   iceGetReg(I86_REG,BX ,&regData); // Set BX register.
//   iceGetReg(I86_REG,CX ,&regData); // Set CX register.
//   iceGetReg(I86_REG,DX ,&regData); // Set DX register.
//   iceGetReg(I86_REG,RSP,&regData); // Set SP register.
//   iceGetReg(I86_REG,BP ,&regData); // Set BP register.
//   iceGetReg(I86_REG,SI ,&regData); // Set SI register.
//   iceGetReg(I86_REG,DI ,&regData); // Set DI register.
//   iceGetReg(I86_REG,DS ,&regData); // Set DS register.
//   iceGetReg(I86_REG,SS ,&regData); // Set SS register.
//   iceGetReg(I86_REG,ES ,&regData); // Set ES register.
//   iceGetReg(I86_REG,CS ,&regData); // Set CS register.
//   iceGetReg(I86_REG,IP ,&regData); // Set IP register.
//   iceGetReg(I86_REG,FLAGS,&regData);//Set FS register.
//
//   iceSetReg(INTERNAL_REG,POLL,0x124); // Set POLL register.
//   iceGetCoReg(ST0,coReg);  // Get ST0 register.
//   regData2 = 0x1234;
//   iceSetCoReg(TAGW,&regData2); // set TAGW register.
//
//   iceSetMap(0,0,0); // map all external
//   iceSetMap(0,0x7ffff,0x061); /* map 0 7ffff intetnal */
//
//   buff = malloc(20);
//   for(lp = 0; lp < 20; lp++)
//      buff[lp] = lp;
//   iceSetMemN(0x12002412,buff,0x10); // Fill memory form 1200:2412, length = 0x10.
//
//   for(lp = 0; lp < 20; lp++)
//      buff[lp] = 0xff;
//   iceGetMemN(0x12002412,buff,0x10);// Get memory from 1200:0400, length = 0x20.
//
//   free(buff);
//   return(GOOD);
//}


