/****************************************************************************
**
**  Name:  SDATA.C
**
**  Description:
**      Process Srecord data records.
**
**  Status:  CODED
**
**  $Log:   S:/tbird/mt2_68k/loader/srec/sdata.c_v  $
** 
**    Rev 1.0   30 Sep 1997 16:03:28   gene
** Initial revision.
** 
**    Rev 1.9   30 Aug 1993 11:13:16   ron
** Changes for Load Progress dialog
** 
**    Rev 1.8   26 Jul 1993 09:39:24   ernie
** TBIRDERR macro is obsolete
** 
**    Rev 1.7   13 Jul 1993 09:44:56   ernie
** Completely rewrote this module for load performance enhancements.
** 
**    Rev 1.6   04 Jun 1993 10:38:18   nghia
** Removed ErrDisplayError() call - PIP for Source.
** 
**    Rev 1.5   04 Jun 1993 10:11:18   nghia
** Revised to meet coding standard.
** Reported error using only the Warning() and WarningEx().
** PIP for Source.
** 
**    Rev 1.4   16 Apr 1993 14:38:10   ernie
** Added a call to flush any partially filled load buffers at the end
** of the srecord file.  Previously, the last load buffer was not being
** written to memory.
** 
**    Rev 1.3   12 Feb 1993 18:15:30   nghia
** Rewrite this module to utilize the new sharedata member to improve
** downloading performances (loading 17,800 bytes in 79sec to 26sec).
** Used table to convert Ascii Hex char to bin (improve about 10% the speed).
** Inline function call to reduce function call overhead.
** Fixed problem - set size long, load will get error memory bus error.
** Updated for release.
** 
**    Rev 1.2   25 Sep 1992 05:42:08   courtney
** Update to NextAddr, NextPair new interfaces; revise return
** codes; don't wipe out sds_buffer (descriptor!), but rather
** ldr_buffer (buffer area).
** 
**    Rev 1.1   21 Aug 1992 10:26:42   courtney
** Update to new SD calls.
** 
**    Rev 1.0   31 Dec 1991 09:36:08   courtney
** Initial revision.
** 
**  $Header:   S:/tbird/mt2_68k/loader/srec/sdata.c_v   1.0   30 Sep 1997 16:03:28   gene  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <ctype.h>
#include <stdio.h>

#ifndef _LQUEUE_
#include "lqueue.h"
#endif
#ifndef _SLDR_
#include "sldr.h"
#endif
#ifndef __ERR__
#include "err.h"
#endif
#ifndef _CLIULIB_
#include "cliulib.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
extern U8 mChar[256];
extern U8 lChar[256];
extern LDRSTATBLOCK FAR *lstb; /* loader status block */

                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
RETCODE PRIVATE ProcessDataAction(FILE *fHandle, U32 *bytesLoaded);
RETCODE EXPORT ReadSrecordBytes(VOID *info, U8 *bin, U16 count);

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

/****************************************************************************
**
**  ProcessDataPart
**
** theory:
**   The file pointer is positioned at the beginning of the first data record.
**   An S record is a string of hex digits and has the following format:
**     Sx nn dd dd dd dd ...  cc
**       Sx = record type
**       nn = number of bytes in this record (includes all bytes after nn)
**       dd = pairs of hex digits (interpretation depends on record type)
**   Record types:
**     S0 nn ... cc                header info (ignored)
**     S1 nn AA AA dd... cc        4-byte address data record
**     S2 nn AA AA AA dd ... cc    6-byte address data record
**     S3 nn AA AA AA AA dd... cc  8-byte address data record
**     S4                          ignored
**     S5                          ignored
**     S6                          ignored
**     S7                          end record
**     S8                          end record
**     S9                          end record
*****************************************************************************/
RETCODE ProcessDataPart(FILE *fHandle, U32 *bytesLoaded) {
   RETCODE err,err2;
   if ((err = LdrQueueInit()) != GOOD) return(err);
   err = ProcessDataAction(fHandle, bytesLoaded);
   err2 = LdrQueueWait();
   return(err?err:err2);
}  /* ProcessDataPart */

RETCODE PRIVATE ProcessDataAction(FILE *fHandle, U32 *bytesLoaded) {
   RETCODE err;
   BOOLEAN aborted;
   U32 currentLoadAddr;
   U32 addr, addrBitsChanged;
   U16 dataCount;
   U8 srecord[MAX_RECLEN];
   U16 addrSize;
   U16 i;

   currentLoadAddr = 0ul;
   *bytesLoaded = 0ul;

   while (GetSrec(fHandle, srecord) == S_RECORD) {
      if ((err = LdrQueueCheckLoadAbort()) != GOOD) return(err);
      if ((err = LdrQueueGetLoadAbort(&aborted)) != GOOD) return(err);
      if (aborted) return(LERR_USER_ABORT);
      switch (srecord[1]) {
         case ST_DATA1:    /* S1: 2-byte address */
            addrSize = 2;
            break;
         case ST_DATA2:    /* S2: 3-byte address */
            addrSize = 3;
            break;
         case ST_DATA3:    /* S3: 4-byte address */
            addrSize = 4;
            break;
         case ST_TERM1: case ST_TERM2: case ST_TERM3:
            return(LdrQueueFlush(currentLoadAddr));
         default:
            continue;      /* Skip this record */
      }
      for (addr=0, i=0; i<addrSize; i++)
         addr = (addr<<8) + mChar[srecord[4+i*2]] + lChar[srecord[5+i*2]];
      if ((addrBitsChanged = addr ^ currentLoadAddr) != 0) {
         if ((err = LdrQueueSetAddressRecord(addr,
            BYTES_TO_TRANSMIT(addrBitsChanged))) != GOOD) return(err);
         currentLoadAddr = addr;
      }
      dataCount = mChar[srecord[2]] + lChar[srecord[3]] - addrSize - 1;
      if ((err = LdrQueueDataRecord(srecord+4+addrSize*2, ReadSrecordBytes,
         currentLoadAddr, 1ul, (U32)dataCount)) != GOOD) return(err);
      *bytesLoaded += dataCount;
      currentLoadAddr += dataCount;
      if (lstb != NULL) {
         lstb->numBytes = *bytesLoaded;
         lstb->curLocation = ftell(fHandle);
      }
   }
   return(LdrQueueFlush(currentLoadAddr));
}

RETCODE EXPORT ReadSrecordBytes(VOID *info, U8 *bin, U16 count) {
   U8 *hex = (U8*)info;
   while (count--) {
      *bin++ = mChar[*hex] + lChar[*(hex+1)];
      hex += 2;
   }
   return(GOOD);
}

/********************************** E O F ***********************************/
