#
#                             stb225 Project
#                   ---------------------------------
#
# Copyright (C) 2008 NXP B.V.
# All Rights Reserved.
#
# Filename: prjconfig2cmds.def.pl
#
# Converts .config variables into shell commands to set up the environment.
# This file is to be used as an argument 1 to the prjconfig2cmds.pl script.
# It must define a Perl subroutine called 'processConfig'.
#
#
#                      ! ! ! I M P O R T A N T ! ! !
#
#               Keep this file in step with the "Pconfig" file.
#
#                      ! ! ! I M P O R T A N T ! ! !
#
# Rev Date       Author      Comments
#-------------------------------------------------------------------------------
#   1 20060517   batelaan    Initial
#   2 20060518   batelaan    Add EXTRA_TMDIVERSITY; Allow unsetting _TMBSL.
#   3 20060609   batelaan    Add -DBOARD_TYPE_EV and _ev_ diversity.
#   6 20060712   batelaan    Removed _TMSITE setting. Now taken from user's environment.
#   7 20060802   batelaan    Moved board/cpu/crosscompile config settings into makefiles.
#   8 20061026   batelaan    Added Qmore stuff.
#   9 20061130   batelaan    All config vars now start with CONFIG_.
#                            Added memory setup checks.
#  10 20061208   batelaan    For DSP MIPS assume board has 256M, and calculate load address as
#                            256M - reservedhigh - dspsize.
#  11 20070110   batelaan    Add CONFIG_NAME; set BUILDROOT. Check PRJRELEASEBUILD.
#                            Suppress unwanted mem size debug output.
#  12 20070123   batelaan    Don't use refbuild_CONFIGURATION approach.
#  13 20070605   barnish     Add new diversities
#  14 20070913   burningh    Add _pnx8335m0a_ diversity
#  15 20070914   batelaan    Use $BUILDROOT_PATH_FMT for setting $BUILDROOT.
#  16 20071009   batelaan    Remove unused Linux-specific items under WinCE
#  17 20071030   neill       Add macrovision to build options
#  18 20071127   iwillis     Added CONFIG_H264_ENABLE
#  19 20071210   dmyers      Added CONFIG_AVS_ENABLE
#  20 20080218   batelaan    Ensure DSP kernel load address is aligned correctly.
#  21 20080226   batelaan    Remove PNX8335M0A option.
#  22 20080305   batelaan    Remove BOARD_TYPE_EV and _ev_ diversity.
#  23 20080311   ashetty     Add audio feedback option.
#21.1.1 20080326 batelaan    Add DSP_IP_SUBNET checking
#                            Check for network route.
#  24 20080326   batelaan    Merge
#  25 20080407   batelaan    Only check routing if DSP_NFSROOT is set.
#  26 20080415   batelaan    Remove CONFIG_DSP_NFSROOT
#  27 20080415   mowle       Add MPEG2 PS diversity
#  28 20080702   laird       Remove MPEG2 PS diversity
#  29 20080709   ashetty     Add diversity for WMAPRO Decoder
#  30 20080722   batelaan    Move generic code to prjconfig2cmds.pl
#  31 20080730   qmai        Add diversity for multi-channel AAC Decoder
#  32 20080905   amccurdy    Add diversity for _h263flv_ and _vp6_
#  33 20080905   ashetty     Add diversity for multichannel audio
#  34 20080909   batelaan    Calculate RESERVED_HIGH_MEM_SIZE
#  35 20080916   batelaan    Use --no-print-directory when invoking make.
#                            Add _multichannelaudio_ div back in.
#  36 20080919   batelaan    Use full path to $PRJROOT/src/comps/phStbKBufMgr
#  37 20081006   neill       Remove CONFIG_SMALLRAM option
#  38 20081020   amccurdy    Remove diversity for multichannel audio
#  39 20090520   ocourson    Add EAC3 diversity

use Math::BigInt;

BEGIN { print STDERR "Loading prjconfig2cmds.def.pl ...\n" if $opt_d; }

sub processConfig {
  $diversity = "";

  ####
  ####   A   B I G    W A R N I N G    A B O U T    A D D I N G   D I V E R S I T Y   ####
  ####
  ####   .... DON'T! (until you have talked with wouter.batelaan@nxp.com!)
  ####
  ####   Usually it is not necessary, since you can do the following:
  ####   #include "prjconfig.h"
  ####   #ifdef CONFIG_...
  ####   Only if we release multiple PRE-COMPILED libraries that implement different
  ####   configurations that customers can choose between do we need to add to _TMDIVERSITY.
  ####   (Maybe I will find time to purge any unnecessary diversities below!)

  if ($CONFIG_DVB)
  {
    $diversity .= "_dvb_";
  }
  elsif ($CONFIG_DSS)
  {
    $diversity .= "_dss_";
  }
  else
  {
    # Both
    $diversity .= "_dvb_dss_";
  }

  if ($CONFIG_HDDECODE_ENABLE)
  {
  	$diversity .= "_hddecode_";
  }

  if ($CONFIG_H264_ENABLE)
  {
  	$diversity .= "_h264_";
  }

  if ($CONFIG_AVS_ENABLE)
  {
  	$diversity .= "_avs_";
  }

  if ($CONFIG_REAL_ENABLE)
  {
  	$diversity .= "_real_";
  }

  if ($CONFIG_H263FLV_ENABLE)
  {
  	$diversity .= "_h263flv_";
  }

  if ($CONFIG_VP6_ENABLE)
  {
  	$diversity .= "_vp6_";
  }

  if ($CONFIG_MACROVISION_ENABLE)
  {
    $diversity .= "_macro_";
  }

  if ($CONFIG_WMV)
  {
  	$diversity .= "_wmv_";
  }

  if ($CONFIG_WMDRMPD)
  {
  	$diversity .= "_wmdrmpd_";
  }

  if ($CONFIG_AC3)
  {
  	$diversity .= "_ac3_";
  }

  if ($CONFIG_EAC3)
  {
  	$diversity .= "_eac3_";
  }

  if ($CONFIG_AUDIO_FEEDBACK)
  {
  	$diversity .= "_audiofeedback_";
  }

  if ($CONFIG_ENABLE_WMAPRO)
  {
  	$diversity .= "_enablewmapro_";
  }

  if ($CONFIG_ENABLE_AACMC)
  {
  	$diversity .= "_enableaacmc_";
  }

  ####
  ####   A   B I G    W A R N I N G    A B O U T    A D D I N G   D I V E R S I T Y   ####
  ####
  ####   .... DON'T! Until you have talked with wouter.batelaan@nxp.com
  ####   (and see above)

  memoryConfig();

  #Add extra diversity options from configutation options.
  $diversity .= "_${CONFIG_EXTRA_TMDIVERSITY}_";

  # collapse multiple underscores:
  $diversity =~ s/_+/_/g;
  #Set ENV variable EXTRA_TMDIVERSITY
  setEnv("EXTRA_TMDIVERSITY", $diversity);

  #Setup Build Type.
  my $rel;
  if    ($CONFIG_RELEASE_BUILD_TYPE_RETAIL) { $rel = 'retail'; }
  elsif ($CONFIG_RELEASE_BUILD_TYPE_ASSERT) { $rel = 'assert'; }
  elsif ($CONFIG_RELEASE_BUILD_TYPE_TRACE)  { $rel = 'trace'; }
  elsif ($CONFIG_RELEASE_BUILD_TYPE_DEBUG)  { $rel = 'debug'; }
  else { fatal("Release type selection problem (one of retail|assert|trace|debug should be selected)\n"); }
  setEnv("_TMTGTREL", $rel);

  $CONFIG_SDE_EXTRA_CFLAGS =~ s/^\s+//; # trim whitespace
  $CONFIG_SDE_EXTRA_CFLAGS =~ s/\s+$//;
  setEnvConditionally("_SDE_EXTRA_CFLAGS", $CONFIG_SDE_EXTRA_CFLAGS,
		      $CONFIG_SDE_EXTRA_CFLAGS ne "");

  setEnvConditionally("_TMECHO", "1", $CONFIG_TMECHO);

  setEnvConditionally("_TMTGTCPP", "1", $CONFIG_TMTGTCPP);

  fatal("SDE2 warnings should be 0-3\n") unless ($CONFIG_TMTGTWARNINGS >= 0 && $CONFIG_TMTGTWARNINGS <= 3);
  setEnv("_TMTGTWARNINGS", $CONFIG_TMTGTWARNINGS);

  # Clear existing _<item>_QMORE env vars:
  foreach my $v (keys %ENV) {
    unsetEnv($v) if $v =~ /^_.*_QMORE$/;
  }

  if ($CONFIG_DSP_IP_SUBNET !~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ ||
      $1 < 1 || $1 > 254 ||
      $2 < 0 || $2 > 254 ||
      $3 < 0 || $3 > 254) {
    fatal("DSP_IP_SUBNET ($CONFIG_DSP_IP_SUBNET) is invalid.
It should be: aaa.bbb.ccc, where:
1 <= aaa <= 254
0 <= bbb <= 254
0 <= ccc <= 254
");
  }

  # checkRoutingSetup();

  my @qmoreitems = split ' ', $CONFIG_QMORE_ITEMS;
  # Set _QMORE_ALL true if we want to run qmore, and the list of items is empty:
  setEnvConditionally("_QMORE_ALL", "true",
		      $CONFIG_QMORE_RUN && (@qmoreitems == 0));

  if ($CONFIG_QMORE_RUN) {
    # Set new _<item>_QMORE env vars:
    foreach my $item (@qmoreitems) {
      setEnv("_${item}_QMORE", "true");
    }
  }

  my $qmoreopts = $CONFIG_QMORE_OPTS;
  if ($CONFIG_QMORE_CHECKS =~ /\S/) { # does it contain non-whitespace?
    $qmoreopts .= " " if $qmoreopts ne "" && $qmoreopts !~ /\s$/; # ensure separating space
    $qmoreopts .= "-c $CONFIG_QMORE_CHECKS";
  }
  setEnv("_QMORE_OPTS", $qmoreopts);

  setEnvConditionally("_QMORE_CONTINUE", "true",
		      $CONFIG_QMORE_CONTINUE);
}


################################################################################
# Check if CONFIG_DSP_FILE_ACCESS is set, that
# CONFIG_DSP_IP_SUBNET is routed from the local PC.
sub checkRoutingSetup {
  # Only need to check this if DSP has telnetd.
  if ($CONFIG_DSP_TELNETD) {
    # Be flexible, use netstat or route program
    if (open(PIPE, "netstat -r 2>/dev/null |") || open(PIPE, "/sbin/route 2>/dev/null |")) {
      local $_;
      while (<PIPE>) {
        if (/^\Q$CONFIG_DSP_IP_SUBNET.0\E/o) {
          close PIPE;
          info("Found network route to $CONFIG_DSP_IP_SUBNET. Good.\n");
          return;
        }
      }
      close PIPE;
    } else {
      warning("$!: netstat or /sbin/route\n");
    }
    warning(<<EOT);
This PC does not seem to have a network route to the $CONFIG_DSP_IP_SUBNET subnet.
  See prjconfig option DSP_IP_SUBNET.
  This probably will prevent using telnet from this PC to the DSP.
EOT
  }
}

################################################################################
# Return 1 if $value is an integer multiple of $alignment.
sub alignmentOK ($$) {
  my ($value, $alignment) = @_;
  return (int($value / $alignment) * $alignment == $value);
}

################################################################################
# Fail with a fatal error message if $value is not an integer multiple of $alignment.
sub checkAlignment ($$$) {
  my ($var, $value, $alignment) = @_;
  if (!alignmentOK($value, $alignment)) {
    fatal(sprintf("Variable $var 0x%x (%d) is not aligned on 0x%x (%d)\n",
	  $value, $value, $alignment, $alignment));
  }
}

################################################################################
# Check and set Memory Map
sub memoryConfig {
  my $CAC_BASE = new Math::BigInt(hex '0x80000000');
  my $maxBoardMemSize = 256 * 1024 * 1024;
  my @memvars = qw(DSP_MIPS_MEM_SIZE_HUMAN);
  foreach my $varName (@memvars) {
    no strict 'refs';
    $$varName = getConfigInt($varName);
    printf STDERR "%28s = %8d 0x%08x %7.3fMB\n", $varName, $$varName, $$varName, $$varName/1024/1024 if $opt_d;
    checkAlignment($varName, $$varName, 0x1000);

    my ($nonHumanVarName) = $varName =~ /(.*)_HUMAN$/;
    addConfigFileHexVar($nonHumanVarName, $$varName) if defined $nonHumanVarName;
  }
  $MAIN_MIPS_LOAD_ADDR = $CAC_BASE + 0x1000;
  addConfigFileHexVar('MAIN_MIPS_LOAD_ADDR', $MAIN_MIPS_LOAD_ADDR) if $CONFIG_OS_LINUX;

  # For an unknown reason (at time of writing) the DSP Linux kernel does not start if
  # the start of its address range is not 128Kb aligned.
  # Fail here, if that happens, to prevent lots of wasted debugging time.
  # TODO this has probably been solved, it should be reduced to a page size.
  if (!alignmentOK($DSP_MIPS_MEM_SIZE, 128*1024)) {
    fatal("Variables RESERVED_HIGH_MEM_SIZE_HUMAN + DSP_MIPS_MEM_SIZE_HUMAN\n"
          . "cause DSP kernel address range start not to be alignment on 128Kb boundary.\n");
  }
  $DSP_MIPS_LOAD_ADDR = $MAIN_MIPS_LOAD_ADDR + $maxBoardMemSize - $DSP_MIPS_MEM_SIZE;
  addConfigFileHexVar('DSP_MIPS_LOAD_ADDR', $DSP_MIPS_LOAD_ADDR);

  # Calculate RESERVED_HIGH_MEM_SIZE
  phStbKBufMgr_Setup();
}

################################################################################

# Calculate RESERVED_HIGH_MEM_SIZE
sub phStbKBufMgr_Setup {
  my $debug = exists $ENV{'STBKBUFMGR_DEBUG'};
  my $cmd =
    "make --no-print-directory -s -C \$PRJROOT/src/comps/phStbKBufMgr"
    . " COPTS=\"-DCONFIG_DSP_MIPS_MEM_SIZE=$DSP_MIPS_MEM_SIZE\" CONFIGFILEDIR=$main::configFileDir"
    . " setup";
  print STDERR "Running: $cmd\n" if $debug;
  my $F;
  if (!open($F, "$cmd|")) {
    croak "$!: Returned error: $cmd\n";
  }
  my $output = <$F>;
  print STDERR ("Output:\n", $output) if $debug;
  if (!close($F)) {
    croak "$!: Returned error: $cmd\n";
  }
  eval $output;
  if ($@) {
    print STDERR "**ERROR: Running $cmd\n";
    croak "Eval error ($@): $line\n";
  }
  if (!defined($RESERVED_HIGH_MEM_SIZE)) {
    croak "Output did not define \$RESERVED_HIGH_MEM_SIZE: $cmd\n";
  }
  addConfigFileHexVar('RESERVED_HIGH_MEM_SIZE', $RESERVED_HIGH_MEM_SIZE);
}

################################################################################

BEGIN { print STDERR "Done loading prjconfig2cmds.def.pl\n" if $opt_d; }

1;
