/* NVTV test -- Dirk Thierbach <dthierbach@gmx.de>
 *
 * This file is part of nvtv, a tool for tv-output on NVidia cards.
 * 
 * nvtv is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * nvtv is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 *
 * $Id: tester.c,v 1.3 2004/03/01 21:08:10 dthierbach Exp $
 *
 * Contents:
 *
 * Main test file for regression tests (on simulated hardware)
 *
 */

#include "local.h" /* before everything else */

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <stdarg.h>

#include "backend.h"
#include "back_test.h"
#include "back_unix.h"

#include "tester.h"

/* -------- -------- */

void raise_msg (int class, char *format, ...)
{
  va_list args;

#ifndef NVTV_DEBUG
  if (class >= MSG_DEBUG) return;
#endif
  switch (class) {
    case MSG_ABORT:
      fprintf (stderr, "Fatal: ");
      break;
    case MSG_WARNING:
      fprintf (stderr, "Warning: ");
      break;
  }
  va_start(args, format);
  vfprintf (stderr, format, args);
  va_end(args);
  fprintf (stderr, "\n");
  if (class == MSG_ABORT) exit (1);
}

/* -------- Options -------- */

Bool testopt_snoop = FALSE;
Bool testopt_log = FALSE;
Bool testopt_dump = FALSE;

int testopt_head = 0;
int testopt_default = 0;

static const char *short_options = "12dhi:ls";

static struct option long_options[] =
  {{"dump",	    no_argument,       NULL, 'd'},
   {"help",         no_argument,       NULL, 'h'},
   {"init",	    required_argument, NULL, 'i'},
   {"log",	    no_argument,       NULL, 'l'},
   {"snoop",        no_argument,       NULL, 's'},
   {NULL,           0,                 NULL, 0}
};

void usage (void)
{
  fprintf (stderr,
      "usage: tester [-options ...] program card encoder [heads]\n\n");
  fprintf (stderr,
      "where options include:\n");
  fprintf (stderr,
      "  -h --help             print this message\n");
  fprintf (stderr,
      "  -s --snoop            snoop real hardware interactions\n");
  fprintf (stderr,
      "  -l --log              log all hardware accesses\n");
  fprintf (stderr,
      "  -d --dump             dump registers at checkpoints\n");
  fprintf (stderr,
      "  -i --init 0/1         init bits to 0 or 1\n");
  fprintf (stderr,
      "  -1                    force usage of first head\n");
  fprintf (stderr,
      "  -2                    force usage of second head\n");
  exit (1);
}

/* -------- -------- */

BackAccessPtr back_access = NULL;  /* global backend */
BackCardPtr back_card = NULL;

CardPtr testOpen (char *card_id)
{
  CardPtr card;

  if (testopt_snoop) {
    if (! back_root_avail ()) {
      fprintf (stderr, "You are not root.\n"); exit (1);
    }
    printf ("==== config: ...\n");
    printf ("---- test init\n");
    card = back_root_init ();
    /* FIXME: substitute mapping */
  } else {
    printf ("==== config: ...\n");
    printf ("---- test init\n");
    card = back_test_init (card_id); // FIXME
  }
  if (!card) {
    fprintf (stderr, "Cannot find card\n"); exit (1);
  }
  return card;
}

void 
testOff (char *card_id)
{
  TVRegs main_regs;

  mmio_card = testOpen (card_id);
  recordPrint ("#### dump init");
  printf ("---- test open card\n");
  back_access->openCard (mmio_card);
  recordPrint ("#### dump open card");
  /*
  get_vidmode (main_dpy, main_screen, &opt_res_x, &opt_res_y, 
		     &main_regs.crtc, data_card_func(main_card->type)->make)
  ->setMode (&main_regs);
  */
}

void
testSimple (char *card_id)
{
  TVMode mon_mode, tv_mode;
  int main_head;

  mmio_card = testOpen (card_id);
  recordPrint ("#### dump init");
  printf ("---- test open card\n");
  back_access->openCard (mmio_card);
  recordPrint ("#### dump open card");
  printf ("---- test encoder\n");
  if (mmio_card->chips) {
    printf ("  -- found %s\n", mmio_card->chips->name);
  } else {
    printf ("  -- found none\n");
  }
  printf ("---- test findBySize\n");
  if (!back_card->findBySize (TV_SYSTEM_PAL, 800, 600, "Small", &tv_mode)) 
  {
    printf ("  -- no mode found\n");
    return;
  }
  if (testopt_head != 0)
  {
    back_card->getHeads (&main_head, NULL, NULL, NULL);
    back_card->setHeads (-1, testopt_head, testopt_head);
    printf ("---- test head %i --> %i\n", main_head, testopt_head);
    /* FIXME do getTwinView, initSharedView */
  }
  printf ("---- test getMode\n");
  back_card->getMode (&mon_mode.regs);
  if (testopt_snoop) sleep (1);
  printf ("---- test setMode/tv\n");
  back_card->setMode (&tv_mode.regs);
  recordPrint ("#### dump set mode/tv");
  if (testopt_snoop) sleep (5);
  printf ("---- test setMode/mon\n");
  back_card->setMode (&mon_mode.regs);
  recordPrint ("#### dump set mode/mon");
  if (testopt_snoop) sleep (5);
  printf ("---- test closeCard\n");
  back_access->closeCard ();
  recordPrint ("#### dump close card");
}

int main (int argc, char *argv [])
{
  int c = '?';
  char* opt_prog;
  char* opt_card;
  char* opt_enc;
  char* opt_head;
  int i;

  opterr = 0;
  while ((c = getopt_long (argc, argv, short_options, 
                long_options, NULL)) != EOF) 
  {
    switch(c) 
    {
      case 'h': /* Print usage */
      case '?':
        usage(); 
	break;
      case 's':
        testopt_snoop = TRUE;
	break;
      case 'd':
        testopt_dump = TRUE;
	break;
      case 'l':
        testopt_log = TRUE;
	break;
      case 'i':
	if (strcmp (optarg, "1") == 0) testopt_default = ~0;
	break;
      case '1':
	testopt_head = 1;
	break;
      case '2':
	testopt_head = 2;
	break;
    }
  }
  if (!testopt_log && !testopt_dump) {
    testopt_log = TRUE;
    testopt_dump = TRUE;
  }
  i = optind;
  if (i < argc) opt_prog = argv[i++]; else opt_prog = "simple";
  if (i < argc) opt_card = argv[i++]; else opt_card = "nv11";
  if (i < argc) opt_enc  = argv[i++]; else opt_enc  = "ch1";
  if (i < argc) opt_head = argv[i++]; else opt_head = "mon";
  configSetup (opt_card, opt_enc, opt_head);
  if (strcmp (opt_prog, "simple") == 0)
    testSimple (opt_card);
  else {
    fprintf (stderr, "Unknown test %s\n", opt_prog);
  }
}


/*

back_card->getHeads
back_card->setHeads
back_card->setChip (chip, TRUE);
back_card->setMode (&main_regs);
back_card->setModeSettings (&main_mode.regs, &opt_set);
back_card->getSettings (&opt_set);

Regression tests are:

init
get mode
find tv mode
set tv mode on
set different tv mode
set tv mode off

all on different architectures/encoders
generate text files, and do diff...


Bus 0: 0x88=PH1, 0x8A=BT, 0xEA=CH1
Bus 1: 0x88=PH2, 0x8A=CX, 0xEA=CH2

Specials:

CX1 status read, error on 0xff subaddr
CX2 status regs r/o, read on 0x01 never zero

CH1/2 0xc0|0x0a check

*/

/*

encoder
  ch1, ch2, cx1, cx2, ph1, ph2, all

heads
  mon, tv, mon_tv, off_fp, tv_fp


test simple nv11 ch1
test simple nv11 ch2
test simple nv11 cx1
test simple nv11 cx2
test simple nv11 ph1
test simple nv11 ph2

test simple nv4 cx1 ; nv15, nv17, nv18, nv20, nv25

test simple nv11 cx1 tv
test simple nv11 cx1 mon_tv
test simple nv11 cx1 off_fp
test simple nv11 cx1 tv_fp

test simple tdfx cx1

test simple i810 ch1
test simple i830 ch1
test simple i845 ch1

*/



syntax highlighted by Code2HTML, v. 0.9.1