#include <stdint.h>
#include <stdlib.h>
#include <uclo.h>
#include <halMev2Api.h>

extern int tcp1_port;
extern int tcp2_port;

/* NOTE: for Ueng mask least significant 16 bits represent cluster 0
   and most significant 16 bits represent cluster 1 */

void StartMicroEngines( char *filename ) {
  void *handle;
  unsigned meMask;
  int i;
  
  /* Initialize ucode library */
  UcLo_InitLib();
  
  /* Initialize microengines, assume 4 MEs per cluster */
  UcLo_InitLibUeng( 0x000F000F );
  
  /* Read ucode from file to memory */
  if( UcLo_LoadObjFile((void **) &handle, filename ) != UCLO_SUCCESS) {
    printf( "Unable to load ucode from file\n" );
    return;
  }
  
  printf( "ME Mask = %x\n", (meMask = UcLo_GetAssignedMEs((void *) handle )));
  
  /* Patch cluster 0 */
  for( i = 1; i < 4; ++i ) {
    if( UcLo_MeBindSymbol((void *) handle, i, "tcp1_port", tcp1_port )
	!= UCLO_SUCCESS ) {
      printf( "Unable to bind symbol, tcp1_port, ME %d\n", i );
      return;
    }
    
    if( UcLo_MeBindSymbol((void *) handle, i, "tcp2_port", tcp2_port )
	!= UCLO_SUCCESS ) {
      printf( "Unable to bind symbol, tcp2_port, ME %d\n", i );
      return;
    }
  }

  /* Patch cluster 1 */
  for( i = 0; i < 4; ++i ) {
    if( UcLo_MeBindSymbol((void *) handle, i+0x10, "tcp1_port", tcp1_port )
	!= UCLO_SUCCESS ) {
      printf( "Unable to bind symbol, tcp1_port, ME %d\n", i+0x10 );
      return;
    }
    
    if( UcLo_MeBindSymbol((void *) handle, i+0x10, "tcp2_port", tcp2_port )
	!= UCLO_SUCCESS ) {
      printf( "Unable to bind symbol, tcp2_port, ME %d\n", i+0x10 );
      return;
    }
  }

  if( UcLo_WriteUimageAll((void *) handle ) != UCLO_SUCCESS ) {
    printf( "Unable to load ucode to MEs\n" );
    return;
  }

  /* Start MEs */
  for( i = 0; i < sizeof(meMask)*8; ++i ) {
    if((( meMask >> i ) & 1) == 1 ) {
      if( halMe_Start( i, 0xff /* All contexts */) != HALME_SUCCESS ) {
	printf( "Failed to start ME %d\n", i );
	return;
      } else {
	printf( "Successfully started ME %d\n", i );
      }
    }
  }
}
  

void StopMicroEngines() {
  /* Put all MEs and all contexts into reset */
  halMe_Reset( 0x000F000F, 1 );
  printf( "Microengines stopped\n" );
}
