#define SCRATCH_RWS_OFFSET 0xCA000000
#define SCRATCH_SUB_OFFSET 0xCB000000

#define MAX_COUNTER 64

#define XLAT_ERROR 0xFFFFFFFF

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

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

#include "bpf.h"

extern int tcp1_port;
extern int tcp2_port;

void ZeroCount( void ) {
  uint32_t *pcount;
  int i;

  /* Initialize HAL lib */
  if( halMe_Init( 0 ) != HALME_SUCCESS ) {
    printf( "Failed to initialize HAL library\n" );
    exit( EXIT_FAILURE );
  }

  /* Get pointer to counters */
  if(( pcount = (uint32_t *)
       halMe_GetVirAddr( SCRATCH_RWS_OFFSET )) == (uint32_t *) XLAT_ERROR ) {
    printf( "Error getting counter virtual address\n" );
    exit( EXIT_FAILURE );
  }

  for( i = 0; i < MAX_COUNTER; ++i ) {
    *(pcount++) = 0;
  }
}

void PrintCount( void ) {
  uint32_t *pcount;
  uint32_t counts[MAX_COUNTER];
  int i;

  /* Initialize HAL lib */
  if( halMe_Init( 0 ) != HALME_SUCCESS ) {
    printf( "Failed to initialize HAL library\n" );
    exit( EXIT_FAILURE );
  }

  /* Get pointer to counters for reading */
  if(( pcount = (uint32_t *)
       halMe_GetVirAddr( SCRATCH_RWS_OFFSET )) == (uint32_t *) XLAT_ERROR ) {
    printf( "Error getting counter virtual address: read\n" );
    exit( EXIT_FAILURE );
  }

  for( i = 0; i < MAX_COUNTER; ++i ) {
    counts[i] = *(pcount++);
  }

  /* Get pointer to counters for atomic subtract */
  if(( pcount = (uint32_t *)
       halMe_GetVirAddr( SCRATCH_SUB_OFFSET )) == (uint32_t *) XLAT_ERROR ) {
    printf( "Error getting counter virtual address: subtract\n" );
    exit( EXIT_FAILURE );
  }

  for( i = 0; i < MAX_COUNTER; ++i ) {
    *(pcount++) = counts[i];
  }

  /* Finally print the counts to screen */
  /* Divide offsets by 4 since they are in bytes not words */
  printf( "pkts: " );
  printf( "caught:%u : ", counts[PKT_COUNT_ADDR/4] );
  printf( "drops:%u : ", counts[DROP_COUNT_ADDR/4] );
  printf( "caught2:%u : ", UNUSED_COUNTER );
  printf( "drop2:%u\n", UNUSED_COUNTER );

  printf( "fixed_ipproto: " );
  printf( "tcp:%u : ", counts[TCP_BYTE_COUNT_ADDR/4] );
  printf( "udp:%u : ", counts[UDP_BYTE_COUNT_ADDR/4] );
  printf( "icmp:%u : ", counts[ICMP_BYTE_COUNT_ADDR/4] );
  printf( "xtra:%u:\n", counts[IP_OTHER_BYTE_COUNT_ADDR/4] );

  printf( "fixed_tcp3: " );
  printf( "%d:%u : ", tcp1_port, counts[TCP1_BYTE_COUNT_ADDR/4] );
  printf( "%d:%u : ", tcp2_port, counts[TCP2_BYTE_COUNT_ADDR/4] );
  printf( "xtra:%u:\n", counts[TCP_XTRA_BYTE_COUNT_ADDR/4] );

  printf( "fixed_cast: " );
  printf( "mcast:%u : ", counts[L2_MCAST_BYTE_COUNT_ADDR/4] );
  printf( "ucast:%u : ", counts[L2_UCAST_BYTE_COUNT_ADDR/4] );
  printf( "bcast:%u : ", counts[L2_BCAST_BYTE_COUNT_ADDR/4] );
  printf( "xtra:%u:\n", UNUSED_COUNTER );

  printf( "fixed_size: " );
  printf( "tiny:%u : ", counts[TINY_PKT_COUNT_ADDR/4] );
  printf( "small:%u : ", counts[SMALL_PKT_COUNT_ADDR/4] );
  printf( "med:%u : ", counts[MEDIUM_PKT_COUNT_ADDR/4] );
  printf( "big:%u:\n", counts[LARGE_PKT_COUNT_ADDR/4] );
}
  
