//###########################################################################
//
// FILE:    checksum.c    
//
// TITLE:   F2810/12 boot ROM checksum generator
//
// Functions:
//
//
// Notes:
//
//###########################################################################
//
//  Ver | dd mmm yyyy |     Who      | Description of changes
// =====|=============|==============|=======================================
//  0.1 |             | LH           | Original Release.
//      |             |              | 
//###########################################################################
#include "checksum.h"

void error(ui16 errorFlag);

// Tell the routine where the checkum is stored such that it can be
// compared with the calculated value. 

#define CHECKSUM_ADDR 0x003FFFBC

typedef struct {
       ui16 *firstAddr;
       ui16 *lastAddr;
} MEMORY_BLOCK;


// The memory blocks to include in the checksum must
// be identified here. 
// 
// In the case of the F2810/12 boot ROM, the checksum
// skips over the blocks reserved to store the checksum
// itself.  Note that the pointers are to 16-bit values. 
// This is because the routine itself will take care of
// the 32-bit addition using two 16-bit values.  
 
#define NUMBLOCKS 2

MEMORY_BLOCK memblock[NUMBLOCKS] = {
       (ui16 *)0x003FE000, (ui16 *)0x003FFFBB,
       (ui16 *)0x003FFFC0, (ui16 *)0x003FFFFF
};

// Use 4 32-bit values to represent the 64-bit checksum.
// This is done such that overflow can be monitored at 
// each step in the summation.   If overflow from the lower
// 16-bits occurs, then the overflow is added to the next
// significant word. 

typedef struct {
       ui32 highHalfMSW;
       ui32 highHalfLSW;
       ui32 lowHalfMSW;
       ui32 lowHalfLSW;
} ui64; 


// This main function performs a very simple 64 bit checksum routine.
// 4 32-bit values are used to calculate the checksum.  This is done so that
// no overflow is lost.  After each addition, the value is checked to see if
// it has overflowed the lower 16-bits.  If it has, then the overflow portion
// in the upper 16-bits is added to the next most significant portion of the
// checksum.  
//
// When the routine completes, the upper 16-bits of each portion of the checksum
// will be 0x000 - this portion should be discarded as it was only used to check
// for overflow and the checksum is then formed from the lower 16-bits. 
//
// For example:
//     lowHalfLSW  = 0x00001111
//     lowHalfMSW  = 0x00002222
//     highHalfLSW = 0x00003333
//     highHalfMSW = 0x00004444
//
//     would result in a 64-bit checksum of 0x44443333 22221111

#define WDCR 0x7029

main()
{
      ui16 *currentVal;
      ui16 *lastVal;
      ui64 checksum;
      ui16 i;
      ui16 count;
      
      count = 0;
      
      checksum.highHalfMSW = 0;
      checksum.highHalfLSW = 0;
      checksum.lowHalfLSW = 0;
      checksum.lowHalfMSW = 0;

    EALLOW;
	*(ui16 *)WDCR = 0x68;
	EDIS
         
    for(i = 0; i < NUMBLOCKS; i++) {
                                                              
      currentVal = memblock[i].firstAddr;
      lastVal = memblock[i].lastAddr;
      
      
      // For each value in the block perform 32-bit addition.
      while(currentVal <= lastVal) {

          count++;
          
          // On C28x, the LSW of a 32-bit value is stored
          // in the lower memory address.  This portion of the
          // routine will add the LSW of the 32-bit value to 
          // the checksum.  After the addition, each portion
          // is checked for overflow.  If overflow has occurred
          // then the overflow is added to the next most significant 
          // word in the checksum.  
          
          checksum.lowHalfLSW += *currentVal++;
      
          if(checksum.lowHalfLSW > 0xFFFF) {
      
              checksum.lowHalfMSW += checksum.lowHalfLSW >> 16;
              checksum.lowHalfLSW &= 0xFFFF;
          }
      
          if(checksum.lowHalfMSW > 0xFFFF) {
      
              checksum.highHalfLSW += checksum.lowHalfMSW >> 16;
              checksum.lowHalfMSW &= 0xFFFF;
          }

          if(checksum.highHalfLSW > 0xFFFF) {
      
              checksum.highHalfMSW += checksum.highHalfLSW >> 16;
              checksum.highHalfLSW &= 0xFFFF;
          }
      

          // On C28x, the MSW of a 32-bit value is stored
          // in the upper memory address.  This portion of the
          // routine will add the MSW of the 32-bit value to 
          // the checksum.  Because it is the MSW it is added
          // to the lowerHalfMSW of the checksum. After 
          // the addition, each portion is again checked for
          // overflow.  If overflow has occurred then 
          // the overflow is added to the next most significant 
          // word in the checksum.  
          
          checksum.lowHalfMSW += *currentVal++;
      
          if(checksum.lowHalfMSW > 0xFFFF) {
      
              checksum.highHalfLSW += checksum.lowHalfMSW >> 16;
              checksum.lowHalfMSW &= 0xFFFF;
          }

          if(checksum.highHalfLSW > 0xFFFF) {
      
              checksum.highHalfMSW += checksum.highHalfLSW >> 16;
              checksum.highHalfLSW &= 0xFFFF;
          }
      
       }
   }
   
   // Check that the calculated checksum is stored in memory
   // where it should be.   The checksum is stored in memory
   // in the following order
   //
   // low address:   lowHalfLSW
   //                lowHalfMSW
   //                highHalfLSW
   // high address:  highHalfMSW
   //
   
   currentVal = (ui16 *)CHECKSUM_ADDR;
   if(*currentVal++ != (ui16)checksum.lowHalfLSW)  error(1);
   if(*currentVal++ != (ui16)checksum.lowHalfMSW)  error(2);
   if(*currentVal++ != (ui16)checksum.highHalfLSW) error(3);
   if(*currentVal   != (ui16)checksum.highHalfMSW) error(4);     

   // check passed!   
   asm("    MOV AH,#0");
   asm("    MOV AL,#0xC001");   
   asm("    ESTOP0");   

}


void error(ui16 errorFlag) {

   // if an error happens check the
   // AL register for the errorFlag.
   
   asm("    MOV AH,#0");
   asm("    MOV AL,#0xBAAD");   
   asm("    ESTOP0");
}
// EOF --------
