/****************************************************************************
**
**  Name:  LDATA.C
**
**  Description:
**      Process data part of IEEE 695 binary file.
**
**  Status:  CODED
**
**  $Log:   S:/tbird/mt2_68k/l695/ldata.c_v  $
** 
**    Rev 1.0   13 Feb 1997 08:50:46   gene
** Initial revision.
** 
**    Rev 1.7   01 Oct 1996 13:34:56   kevin
** Hera's revision
** 
**    Rev 1.6   19 Jan 1996 09:09:54   kevin
** GetLoadAddrSpace is using GetBaseType rather than SymGetBaseType
** 
**    Rev 1.5   22 Dec 1995 16:24:36   kevin
** fixed processVerifyError
** 
**    Rev 1.4   04 Dec 1995 16:11:54   kevin
** added one more parameter for getloadaddrspace()
** 
**    Rev 1.2   30 Oct 1995 08:35:02   gene
** modify load verify error message
** 
**    Rev 1.0   23 Oct 1995 14:28:38   gene
** Initial revision.
** 
**    Rev 1.1   04 Oct 1995 17:24:50   gene
** modify verify error message
** 
**    Rev 1.0   07 Sep 1995 10:32:06   gene
** Initial revision.
** 
**    Rev 1.46   01 Nov 1993 09:57:38   nghia
** Fixed PPR 8975 - Report memory verify error
** Added LdrProcessVerifyError() - It uses different SDS members than memory
** Added check to retrieve verify error at ProcessDataPart().
** 
**    Rev 1.45   30 Aug 1993 11:06:20   ron
** Changes for Load Progress dialog
** 
**    Rev 1.44   03 Aug 1993 17:34:22   nghia
** Removed LERR_xxxx to use standard error codes.
** 
**    Rev 1.43   13 Jul 1993 10:25:42   ernie
** TBIRDERR macro is obsolete
** 
**    Rev 1.42   13 Jul 1993 09:56:22   ernie
** Completely rewrote this module for loader performance enhancements
** 
**    Rev 1.38   25 May 1993 10:36:22   ernie
** Virtualized _llseek() calls in Seek695File when file buffering added.
** 
**    Rev 1.37   16 Apr 1993 13:54:26   nghia
** Never ending clean up.
** 
**    Rev 1.36   12 Apr 1993 16:20:36   nghia
** Revised Get695SRecord() to return record type.
** 
**    Rev 1.35   23 Mar 1993 17:07:04   nghia
** Updated to use the new MatchRecord and Match2Record.
** 
**    Rev 1.34   18 Mar 1993 17:09:38   nghia
** Fixed the "Intermec bug" - RE record > 128 bytes.
** Make AmountLeft - Macro AMOUNT_LEFT() for speed improvement.
** Removed global 'offset' - protential bug.
** Revised both Get695Stream() and Fill695Stream().
** CodeBuffers[] will only need to initialize once during the load, except some
** fields (ldr_offset, ...).
** 
**    Rev 1.33   08 Mar 1993 10:25:30   nghia
** Major cleanup (removed all underscores, remove tab characters, aligned source
** ). Revised and added typecast to remove compiler warnings.
** 
**    Rev 1.32   11 Feb 1993 08:56:50   nghia
** Fixed Tandberg bug: Loader failed to load after loading a RE record.
** - Added check to prevent loader from sending a 0 bytes packet to the box.
** - Cleanup and added comments.
** 
**    Rev 1.31   02 Nov 1992 14:34:22   doug
** allow dword to be consistent with other commands
** 
**    Rev 1.30   21 Oct 1992 16:33:08   courtney
** Cleaned up error reporting to use string resource.
** 
**    Rev 1.29   20 Oct 1992 13:03:40   doug
** use correct enumeration names and remove left over "return"
** 
**    Rev 1.28   19 Oct 1992 14:46:04   doug
** add loadsize command (_size is fixed for now)
** 
**    Rev 1.27   19 Oct 1992 13:19:52   doug
** send multiple write packets to box to increase performance; allow
** writing by longs, words, and bytes
** 
**    Rev 1.26   12 Oct 1992 14:41:30   doug
** new shared data interface for loader to reduce the number of bytes
** going across to the box (improve performance)
** 
**    Rev 1.25   25 Sep 1992 20:57:32   courtney
** Added comment.
** 
**    Rev 1.24   08 Sep 1992 13:28:20   courtney
** Always do cleanup before returning.
** RE fix for Kevin messed up loading data after it - fixed.  Note that
**   this support is beyond IEEE spec (RE greater than 128 bytes).
** 
**    Rev 1.23   25 Aug 1992 17:11:36   courtney
** Code section type RE (repeat bytes) formerly used a static buffer
** to fill the repeat pattern - now it is dynamically allocated so
** it can be arbitrarily large.
** 
**    Rev 1.22   21 Aug 1992 09:33:52   courtney
** Propagate return code for DoMemoryWrite.
** 
**    Rev 1.21   31 Jul 1992 19:16:48   courtney
** Casts on Mem Server call parameters.
** 
**    Rev 1.20   24 Jul 1992 15:33:08   doug
** get access and verify from memory server
** 
**    Rev 1.19   22 Jul 1992 16:42:24   doug
** conversion to generic shared data
** 
**    Rev 1.18   01 Jun 1992 20:10:34   courtney
** Add escape checking for code loading (PPR 5344).
** 
**    Rev 1.17   12 May 1992 09:19:24   courtney
** Inline build flags for FASTBUF.
** 
**    Rev 1.16   07 May 1992 15:47:28   courtney
** Implemented file buffering; keep byte count for status display.
** Fixes PPR #5656 and #5657.
** 
**    Rev 1.15   01 Apr 1992 15:55:44   courtney
** Coalescing all LD/RE chunks that are within a single SD/ASP
** section.  Write to SDS only occurs on completion of such a
** chunk, or, if the local buffer becomes full (SIZE_FILL_PATTERN_
** BUFFER, which is set to 256 bytes).
** Also fixes problem where certain code chunks were not loaded.
** 
**    Rev 1.12   21 Mar 1992 15:18:38   courtney
** Fixed 2 bugs regarding _Fill695_Stream (for $RE code records):
** does not break loop after handling $RE, so that $RE can be
** interspersed with $LD code records; updates PCvalue with count
** from number of bytes written in _Fill695_Stream.
** 
**    Rev 1.11   04 Mar 1992 12:49:02   doug
** use write command read response for fill
** 
**    Rev 1.10   18 Feb 1992 17:53:58   courtney
** Commented out code which checks SDS (thru callback) for response
** of previous write operation (doesn't work).. So download of code
** will just write write without checking !!
** 
**    Rev 1.9   17 Feb 1992 16:29:16   courtney
** Added support for code type $RE, repeating data.
** 
**    Rev 1.8   14 Feb 1992 13:22:32   courtney
** Changes to make code loading work with dummy shared data server.  Added
** callback LdrFillResult for completion of write command.
** 
**    Rev 1.7   10 Feb 1992 12:51:46   courtney
** Removed shared data headers (added to ldr.c).
** 
**    Rev 1.6   10 Feb 1992 08:56:04   courtney
** Revised the way sending shared data buffer is handled, now we wait
** for the previous operation to complete (command code is 0) until
** we write a new buffer.  This will hang if host-only (use nocode option).
** Also, fixed GetCodeBuf/FreeCodeBuf to work with a single code buffer.
** 
**    Rev 1.5   05 Feb 1992 15:01:16   courtney
** Write to memory command member which triggers actual write needs a data
** parameter.  The code has been revised to sit in a loop waiting for any
** previous operation to complete (by doing ReadMember on the command field).
** 
**    Rev 1.4   30 Jan 1992 15:50:52   courtney
** Changes to reflect write to actual memory buffer shared data members.
** These are MC68030-specific members.
** 
**    Rev 1.3   27 Jan 1992 15:49:48   courtney
** Write to shared data server stubbed out until correct SDS members
** are known (it causes UAE).
** 
**    Rev 1.2   17 Jan 1992 10:41:18   courtney
** Write to Shared Data members code is now active.
** 
**    Rev 1.1   09 Jan 1992 16:43:56   courtney
** Comment re: error checking.
** 
**    Rev 1.0   12 Dec 1991 13:37:46   courtney
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/l695/ldata.c_v   1.0   13 Feb 1997 08:50:46   gene  $
**
**  Copyright (C) 1991-1993 Microtek International.  All rights reserved.
**
*****************************************************************************/

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

#ifndef _BASEWIND_
#include "basewind.h"
#endif

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

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

#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif

#ifndef __ERR__
#include "err.h"
#endif

#ifndef __LDR__
#include "ldr.h"
#endif

#ifndef _LQUEUE_
#include "lqueue.h"
#endif

#ifndef _LFLAGS_
#include "lflags.h"
#endif

#ifndef _CLIULIB_
#include "cliulib.h"
#endif

#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif

#ifndef __LSYM__
#include "lsym.h"
#endif

#include <io.h>

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/
extern HDR695 Hdr695;  /* Has file offsets for various 695 file sections */
extern LDRSTATBLOCK FAR *lstb; /* progress reporting status block */
extern U16 indexBufferError;   /* index of first buffer recording error */
extern U32 ldrFlags;   /* loader options */
                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
RETCODE PRIVATE ProcessDataAction(HANDLE hfile, U32 *bytesLoaded);
RETCODE EXPORT ReadBytes(VOID *info, U8 *dest, U16 count);
RETCODE PRIVATE LdrProcessVerifyError(VOID);
RETCODE PRIVATE GetLoadAddrSpace(BASE_INDEX baseIndex, U32 addr,
                                 ADDR_SPACE *addrSpace);

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

/****************************************************************************
**
**  ProcessDataPart
**
**  This function is called from ldr.c after the section info has
**  been obtained from Section Part of file.
**   
**  This function picks out LD (load constant byte) and RE (repeat)
**  records from the data section of the file and writes them to
**  memory.  ASP records indicate a change in address; otherwise
**  successive LD and RE records are contiguous in memory.
**
**  Note that this code supports LD and RE records of arbitrary size.
**  IEEE-695 specifies a maximum of 128 bytes in LD and RE records.
**  This support is needed since some compilers are not quite IEEE-compliant.
**
*****************************************************************************/
RETCODE ProcessDataPart(HANDLE hfile, U32 *bytesLoaded) {
   RETCODE err,err2;

   if ((err = LdrQueueInit()) != GOOD) return(err);
   err = ProcessDataAction(hfile, bytesLoaded);
   err2 = LdrQueueWait();

   // NOTES: Nghia - 10/28/93
   // Handle Loading verify error - retrieve the information to report  
   if ((err = (err ? err: err2)) == ER_MEMORY_VERIFY)
      LdrProcessVerifyError();
   return(err);
}

/***************************************************************************
**
**  ProcessDataAction
**
*****************************************************************************/
RETCODE PRIVATE ProcessDataAction(HANDLE hfile, U32 *bytesLoaded) {
   RETCODE err;
   BOOLEAN aborted;
   U32 ASPaddr, addrBitsChanged;
   U16 sindex;   /* section number */
   U32 currentLoadAddr;
   ADDR_SPACE addrSpace;
   currentLoadAddr = 0ul;
   *bytesLoaded = 0ul;

   /*
   ** Seek to data part of file
   */
   if (Seek695File(hfile, Hdr695.hdr_data, SEEK_SET) == -1L)
      return (ER_BAD_SEEK);

   /* Process SB/ASP/{LD|RE}* records until encountering another type */
   while (1) {
      U16 cbyte;
      /* Expects record type SB or ASP (SR_AS_PREFIX:SR_ASP) */
      Peek695Byte(hfile, &cbyte);
      if (cbyte != RT_SB && cbyte != SR_AS_PREFIX)
         break;
      /* skip optional SB record - sets current section */
      if (cbyte == RT_SB)
         Get695Srecord(hfile, &sindex, &ASPaddr);  /* ignored */

      /* ASP record gives load address for this chunk of data */
      if (Get695Srecord(hfile, &sindex, &ASPaddr) != SR_ASP)
         /* didn't see ASP record--done with data loading */
         break;

      /* Send new address record, changing as few bytes as possible */
      if ((addrBitsChanged = ASPaddr ^ currentLoadAddr) != 0) {
         if ((err = LdrQueueSetAddressRecord(ASPaddr,
            BYTES_TO_TRANSMIT(addrBitsChanged))) != GOOD) return(err);
         currentLoadAddr = ASPaddr;
      }
      
      /* Set load addr space from base Hera 09/26/96*/
      /*if ((err = GetLoadAddrSpace(sindex, ASPaddr, &addrSpace)) != GOOD)
         return err;
      

      if ((err = LdrQueueSetAddressSpace(currentLoadAddr, addrSpace)) != GOOD)
         return(err);*/

      /* Now the file should have a sequence of LD and/or RE records */
      while (1) {
         if ((err = LdrQueueCheckLoadAbort()) != GOOD) return(err);
         if ((err = LdrQueueGetLoadAbort(&aborted)) != GOOD) return(err);
         if (aborted) return(ER_USER_ABORT);
         Peek695Byte(hfile, &cbyte);
         if (cbyte == RT_RE) {
            /*
            ** RE record : {RE}{repeat count}{LD}{byte count}{data}
            */
            U32 repCount, byteCount;
            if ((err = MatchRecord(hfile, RT_RE)) != GOOD) return(err);
            if ((err = Get695Offset(hfile, &repCount)) != GOOD) return(err);
            if ((err = MatchRecord(hfile, RT_LD)) != GOOD) return(err);
            if ((err = Get695Offset(hfile, &byteCount)) != GOOD) return(err);
            if ((err = LdrQueueDataRecord(&hfile, ReadBytes,
               currentLoadAddr, repCount, byteCount)) != GOOD) return(err);
            *bytesLoaded += repCount*byteCount;
            currentLoadAddr += repCount*byteCount;
         } else if (cbyte == RT_LD) {
            /*
            ** LD record : {LD}{byte count}{data}
            */
            U32 byteCount;
            if ((err = MatchRecord(hfile, RT_LD)) != GOOD) return(err);
            if ((err = Get695Offset(hfile, &byteCount)) != GOOD) return(err);
            if ((err = LdrQueueDataRecord(&hfile, ReadBytes,
               currentLoadAddr, 1ul, byteCount)) != GOOD) return(err);
            *bytesLoaded += byteCount;
            currentLoadAddr += byteCount;
         } else {
            /* Not LD or RE record */
            break;
         }
         if (lstb != NULL) {
            lstb->numBytes = *bytesLoaded;
            lstb->curLocation = tell(hfile);
         }
      }
   }
   /* send partially filled load buffer to box */
   return(LdrQueueFlush(currentLoadAddr));
}

/***************************************************************************
**
**  ReadBytes
**
*****************************************************************************/
RETCODE EXPORT ReadBytes(VOID *info, U8 *dest, U16 count) {
   return(Get695Bytes(*((HANDLE*)info), dest, count));
}

/***************************************************************************
**
**  LdrProcessVerifyError
**
*****************************************************************************/
RETCODE PRIVATE LdrProcessVerifyError(VOID) {
//   U32 verifyOffset;
//   U32 expectedData, actualData;
//   U16 addrSpace;
   S8 verBuf[ADDR_BUFF_SZ], spaceBuf[4];
   DESCRIPTOR addr;
   CHAR verifyErrorString[E_ERRSIZE];
   RETCODE err;
   BAD_MEMORY verifyErrorInfo;

   /* Make sure that we are not going to crash */
   if (indexBufferError >= NUM_LOAD) 
      return(GOOD);
      
   /* collect information of the indexBufferError */
//   SdnReadMember(SDN_LVERIFY_OFFSET+indexBufferError, (U8 *)&verifyOffset);
//   SdnReadMember(SDN_LVERIFY_EXPECTED+indexBufferError ,(U8 *)&expectedData);
//   SdnReadMember(SDN_LVERIFY_ACTUAL+indexBufferError, (U8 *)&actualData);
//   SdnReadMember(SDN_LVERIFY_SPACE+indexBufferError, (U8 *)&addrSpace);

   iceGetVerifyErrorInfo(&verifyErrorInfo);
   
   if ((err = AdrCreateAddress(&addr)) != GOOD)
      return(err);
   AdrSetAddrOffset(addr, verifyErrorInfo.offset);
   AdrConvAddressToTextWithParams(addr, TRUE, TRUE, verBuf);
   AdrDestroyAddress(addr);

   /* format message */
   switch (verifyErrorInfo.space) {
      case SPACE_UNDEF0:
         wsprintf(spaceBuf,"U0 ");
      break;
      case SPACE_UD:
         wsprintf(spaceBuf,"UD ");
      break;
      case SPACE_UP:
         wsprintf(spaceBuf,"UP ");
      break;
      case SPACE_UNDEF3:
         wsprintf(spaceBuf,"U3 ");
      break;
      case SPACE_UNDEF4:
         wsprintf(spaceBuf,"U4 ");
      break;
      case SPACE_SD:
         wsprintf(spaceBuf,"SD ");
      break;
      case SPACE_SP:
         wsprintf(spaceBuf,"SP ");
      break;
      case SPACE_CPU:
         wsprintf(spaceBuf,"CPU");
      break;
      case SPACE_DONT_CARE:
         wsprintf(spaceBuf,"   ");
      break;
   }
   wsprintf(verifyErrorString,
      "address: %s %s, expected: 0x%04X, actual: 0x%04X",
       verBuf, spaceBuf, (U16)verifyErrorInfo.expected,
       (U16)verifyErrorInfo.actual);

   /* send error text in error text server */
   return(ErrSaveMemoryVerifyInfo((LPSTR)verifyErrorString));
}

/***************************************************************************
**
**  SetLoadAddrSpace
**
****************************************************************************/
RETCODE PRIVATE GetLoadAddrSpace(BASE_INDEX baseIndex, U32 addr,
                                 ADDR_SPACE *addrSpace) {
BASE_TYPE baseType;
RETCODE err;

   if (addr < 0x8L)  // reset vector -- must be loaded into SP
      *addrSpace = SPACE_SP;
   else if (addr <= 0x3FCL) // other vectors -- must be loaded into SD
      *addrSpace = SPACE_SD;
   else {
      /* Find base attribute CODE or DATA */
      if ((err=GetBaseType(baseIndex, &baseType)) != GOOD)
         return(err);
      *addrSpace = 3-baseType;  // convert baseType into data:1, code:2
      if (LdrSpaceMode() == SUPERVISOR_MODE)
         *addrSpace += 4;
   }
   return(GOOD);
}
/******************************** E O F ***********************************/
