#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include "dev/pci/sis1100_var.h"
#include "sis3100_vme_calls.h"
#include "sharc_utils.h"


#define FPGA_DUALPORT_RAM_ADDR      0x40000000          /* size = 256 Lwords */ 
#define FPGA_DUALPORT_RAM_LWSIZE    0x100               /* size = 256 Lwords */ 



/*===========================================================================*/
/* Globals					  			     */
/*===========================================================================*/

#define MAX_NUMBER_OF_PRINTS 0x10      
#define MAX_NUMBER_LWORDS 0x400000       /* 16MByte */

u_int32_t wblt_data[MAX_NUMBER_LWORDS] ;
u_int32_t rblt_data[MAX_NUMBER_LWORDS] ;

u_int32_t test1_data[16] ;




/*===========================================================================*/
/* Prototypes					  			     */
/*===========================================================================*/

int memory_test_sharc(int ip_sharc, u_int32_t start_addr, u_int32_t no_of_lwords) ;


/****************************************************************************/
int main(int argc, char* argv[])
{

char* dsploader_path[60];


int p;
int p_sharc;
int offset ;
u_int32_t addr ;
u_int32_t no_of_lwords ;

int return_code ;

int i;
int error_cnt ;


test1_data[0]   =   0x12345678 ;
test1_data[1]   =   0x87654321 ;
test1_data[2]   =   0x11224488 ;
test1_data[3]   =   0x88442211 ;
test1_data[4]   =   0xAA559966 ;
test1_data[5]   =   0x66AA5599 ;
test1_data[6]   =   0x9966AA55 ;
test1_data[7]   =   0x559966AA ;
test1_data[8]   =   0xffffffff ;
test1_data[9]   =   0x00000000 ;
test1_data[10]  =   0xFF00FF00 ;
test1_data[11]  =   0x00FF00FF ;
test1_data[12]  =   0xFFFF0000 ;
test1_data[13]  =   0x0000FFFF ;
test1_data[14]  =   0xF0F0F0F0 ;
test1_data[15]  =   0x0F0F0F0F ;


/* open VME */
   if ((p=open("/tmp/sis1100", O_RDWR, 0))<0) {
     printf("error on opening VME environment\n");
     return -1;
   }
/* open SHARC */
   if ((p_sharc=open("/tmp/sis3100sharc", O_RDWR, 0))<0) {
     printf("error on sharc open");
     return -1;
   }



  printf("LED an \n");
  offset = 0x00000100;
  return_code = s3100_control_write(p, offset, 0x00000080) ; 
  if (return_code != 0) printf("s3100_control_write:   return_code = 0x%08x\n", return_code );         




/******************************************************************/
/*                                                                */
/* Test FPGA internal Dual Ported RAM from PCI                    */
/*                                                                */
/******************************************************************/
#ifdef xxx
    addr          = FPGA_DUALPORT_RAM_ADDR ;
    no_of_lwords  = FPGA_DUALPORT_RAM_LWSIZE  ;   
    return_code = memory_test_sharc(p_sharc, addr, no_of_lwords) ;
    if (return_code != 0)  {
        printf("Error in memory_test_sharc:  start_addr = 0x%08x   no_of_lwords = 0x%08x\n", addr, no_of_lwords );         
        return -1 ;
       }
    printf("Test FPGA_DUALPORT_RAM from PCI    OK\n");         


#endif


/**************************************************************************/
/*                                                                        */
/* Test FPGA internal Dual Ported RAM                                     */
/*  - write from SHARC an increment pattern                               */
/*  - read from PCI and check increment pattern                           */
/*                                                                        */
/**************************************************************************/


/* load and start SHARC */
  /* open SHARC loader file */
  /*   *dsploader_path =  argv[3] */ ; 
   *dsploader_path = "LoaderFiles/fram_t1.ldr" ;  

   if ((load_dsp(p,p_sharc, *dsploader_path)) != 0) {
     printf("error on loading DSP code\n");
     return -1;
   }
   usleep (1000) ; /* wait for SHARC booting */
   usleep (1000) ; /* wait for SHARC booting */

    /* read data */
    addr          = FPGA_DUALPORT_RAM_ADDR ;
    no_of_lwords  = FPGA_DUALPORT_RAM_LWSIZE  ;   
    return_code = s3100_sharc_read(p_sharc, addr, rblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4))   {
        printf("s3100_sharc_read:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

     /* check data */
     /* prepare data */
     for (i=0;i<no_of_lwords;i++)    { wblt_data[i] = i + 1 ;  } /* this data will be written from SHARC */

     error_cnt =  0 ;
     for (i=0;(i)<no_of_lwords;i++)
       {
          if (wblt_data[i] != rblt_data[i])  
           {
             printf(" Error at i = : 0x%08x    written = : 0x%08x   read = : 0x%08x\n", i, wblt_data[i], rblt_data[i]);
             error_cnt = error_cnt + 1;
             if (error_cnt > MAX_NUMBER_OF_PRINTS) return -1 ;
           }
       }


    if (error_cnt != 0)  {
        printf("Error Test FPGA_DUALPORT_RAM write increment from SHARC and read from PCI \n");         
        return -1 ;
       }
     else  {
        printf("Test FPGA_DUALPORT_RAM write increment from SHARC and read from PCI    OK\n");         
       } 




/**************************************************************************/
/*                                                                        */
/* Test FPGA internal Dual Ported RAM                                     */
/*  - write from SHARC a bit-shift pattern                                */
/*  - read from PCI and check bit-shift pattern                           */
/*                                                                        */
/**************************************************************************/

#ifdef xxx
/* load and start SHARC */
  /* open SHARC loader file */
  /*   *dsploader_path =  argv[3] */ ; 
   *dsploader_path = "LoaderFiles/fram_t2.ldr" ;  

   if ((load_dsp(p,p_sharc, *dsploader_path)) != 0) {
     printf("error on loading DSP code\n");
     return -1;
   }
   usleep (1000) ; /* wait for SHARC booting */

    /* read data */
    addr          = FPGA_DUALPORT_RAM_ADDR ;
    no_of_lwords  = FPGA_DUALPORT_RAM_LWSIZE  ;   
    return_code = s3100_sharc_read(p_sharc, addr, rblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4))   {
        printf("s3100_sharc_read:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

     /* check data */
     /* prepare data */
     for (i=0;i<no_of_lwords;i++)    { wblt_data[i] = (0x1 << (i&0x1f)) ;  }/* this data will be written from SHARC */

     error_cnt =  0 ;
     for (i=0;(i)<no_of_lwords;i++)
       {
          if (wblt_data[i] != rblt_data[i])  
           {
             printf(" Error at i = : 0x%08x    written = : 0x%08x   read = : 0x%08x\n", i, wblt_data[i], rblt_data[i]);
             error_cnt = error_cnt + 1;
             if (error_cnt > MAX_NUMBER_OF_PRINTS) return -1 ;
           }
       }

    if (error_cnt != 0)  {
        printf("Error Test FPGA_DUALPORT_RAM write shift from SHARC and read from PCI \n");         
        return -1 ;
       }
     else  {
        printf("Test FPGA_DUALPORT_RAM write shift from SHARC and read from PCI    OK\n");         
       } 





#endif



  printf("LED aus \n");
  offset = 0x00000100;
  return_code = s3100_control_write(p, offset, 0x00800000) ; 
  if (return_code != 0) printf("s3100_control_write:   return_code = 0x%08x\n", return_code );         

close(p);
close(p_sharc);

return 0 ;
}








/***************************************************/


int memory_test_sharc(int ip_sharc, u_int32_t start_addr, u_int32_t no_of_lwords)
{
/*
#define MAX_NUMBER_OF_PRINTS 0x10      
#define MAX_NUMBER_LWORDS 0x400000        
u_int32_t wblt_data[MAX_NUMBER_LWORDS] ;
u_int32_t rblt_data[MAX_NUMBER_LWORDS] ;
*/
u_int32_t addr ;

int i;
int error_cnt ;
int return_code ;



if (no_of_lwords > MAX_NUMBER_LWORDS)  {
     printf("no_of_lwords (0x%08x) must be lower then MAX_NUMBER_LWORDS (0x%08x)\n",no_of_lwords, MAX_NUMBER_LWORDS);
     return -1;
   }

if (no_of_lwords == 0)  {
     printf("no_of_lwords (0x%08x) must be higher then 1 \n",no_of_lwords);
     return -1;
   }



/******************************************************************/
/*                                                                */
/* step 1:   write increment pattern                              */
/*                                                                */
/******************************************************************/
    /* prepare data */
    for (i=0;i<no_of_lwords;i++)    { wblt_data[i] = i ;  }

    /* write data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_write(ip_sharc, addr, wblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4)) {
        printf("s3100_sharc_write:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

    /* read data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_read(ip_sharc, addr, rblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4))   {
        printf("s3100_sharc_read:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

     /* check data */
     error_cnt =  0 ;
     for (i=0;(i)<no_of_lwords;i++)
       {
          if (wblt_data[i] != rblt_data[i])  
           {
             printf(" Error at i = : 0x%08x    written = : 0x%08x   read = : 0x%08x\n", i, wblt_data[i], rblt_data[i]);
             error_cnt = error_cnt + 1;
             if (error_cnt > MAX_NUMBER_OF_PRINTS) return -1 ;
           }
       }




/******************************************************************/
/*                                                                */
/* step 2:   bit shift pattern                                    */
/*                                                                */
/******************************************************************/
    /* prepare data */
    for (i=0;i<no_of_lwords;i++)    { wblt_data[i] = (0x1 << (i&0x1f)) ;  }
/*   for (i=0;i<no_of_lwords;i++)    { printf("w = 0x%08x \n", wblt_data[i]);  } */

    /* write data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_write(ip_sharc, addr, wblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4)) {
        printf("s3100_sharc_write:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

    /* read data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_read(ip_sharc, addr, rblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4))   {
        printf("s3100_sharc_read:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

     /* check data */
     error_cnt =  0 ;
     for (i=0;(i)<no_of_lwords;i++)
       {
          if (wblt_data[i] != rblt_data[i])  
           {
             printf(" Error at i = : 0x%08x    written = : 0x%08x   read = : 0x%08x\n", i, wblt_data[i], rblt_data[i]);
             error_cnt = error_cnt + 1;
             if (error_cnt > MAX_NUMBER_OF_PRINTS) return -1 ;
           }
       }


/******************************************************************/
/*                                                                */
/* step 3:    pattern                                             */
/*                                                                */
/******************************************************************/
    /* prepare data */
    for (i=0;i<no_of_lwords;i++)    { wblt_data[i] =  test1_data[i&0xf] ;  }
/*    for (i=0;i<no_of_lwords;i++)    { printf("w = 0x%08x \n", wblt_data[i]);  }  */

    /* write data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_write(ip_sharc, addr, wblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4)) {
        printf("s3100_sharc_write:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

    /* read data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_read(ip_sharc, addr, rblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4))   {
        printf("s3100_sharc_read:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

     /* check data */
     error_cnt =  0 ;
     for (i=0;(i)<no_of_lwords;i++)
       {
          if (wblt_data[i] != rblt_data[i])  
           {
             printf(" Error at i = : 0x%08x    written = : 0x%08x   read = : 0x%08x\n", i, wblt_data[i], rblt_data[i]);
             error_cnt = error_cnt + 1;
             if (error_cnt > MAX_NUMBER_OF_PRINTS) return -1 ;
           }
       }




/******************************************************************/
/*                                                                */
/* step 4:    random                                              */
/*                                                                */
/******************************************************************/
    /* prepare data */
    for (i=0;i<no_of_lwords;i++)    { wblt_data[i] =  random() ;  }
/*    for (i=0;i<no_of_lwords;i++)    { printf("w = 0x%08x \n", wblt_data[i]);  }   */

    /* write data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_write(ip_sharc, addr, wblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4)) {
        printf("s3100_sharc_write:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

    /* read data */
    addr =  start_addr ;                     
    return_code = s3100_sharc_read(ip_sharc, addr, rblt_data, no_of_lwords) ;
    if (return_code != (no_of_lwords*4))   {
        printf("s3100_sharc_read:  return_code = 0x%08x  at address = 0x%08x\n", return_code, addr );         
        return -1 ;
      }

     /* check data */
     error_cnt =  0 ;
     for (i=0;(i)<no_of_lwords;i++)
       {
          if (wblt_data[i] != rblt_data[i])  
           {
             printf(" Error at i = : 0x%08x    written = : 0x%08x   read = : 0x%08x\n", i, wblt_data[i], rblt_data[i]);
             error_cnt = error_cnt + 1;
             if (error_cnt > MAX_NUMBER_OF_PRINTS) return -1 ;
           }
       }




  if (error_cnt == 0) {
     return 0 ; }
    else {
     return -1 ;}

}































