/*
 *------------------------------------------------------------------
 *
 * $Source: /u1/jis/gw/cgw/gw/in/RCS/rvd.c,v $
 * $Revision: 1.2 $
 * $Date: 87/06/24 14:48:34 $
 * $State: Exp $
 * $Author: jon $
 * $Locker:  $
 *
 * $Log:	rvd.c,v $
 * Revision 1.2  87/06/24  14:48:34  jon
 * forgot rcs_id ...
 * 
 * Revision 1.1  87/06/24  14:09:52  jon
 * Initial revision
 * 
 * 
 * 
 *------------------------------------------------------------------
 */

#ifndef lint
static char *rcsid_statd_c = "$Header: rvd.c,v 1.2 87/06/24 14:48:34 jon Exp $";
#endif	lint

#include <types.h>
#include <sys.h>
#include "../src/defs.h"
#include "in.h"
#include "inext.h"
#include "rvd.h"
#include "../opcon/opcon.h"
#include "../src/const.h"

ext int good_password;

void rvd_list_command (), rvd_change_command ();

char *rvd_packet_names[] = {
  "spin", "down", "read", "write", "stat", "host", "respin", "authspin",
  "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", 
  "unknown", "spinack", "error", "downack", "block", "writeack", "sstat",
  "hstat"};

static subcommand rvd_scmd[] = {
  { "list", "list rvd flushing state",
      rvd_list_command, 0},
  { "set", "set rvd flushing state",
      rvd_change_command, 1},
  { "clear", "clear rvd flushing state",
      rvd_change_command, 0},
  { NULL, NULL, NULL, 0 },
};

static command rvd_cmd = {NULL, "rvd",
			    "RVD flushing", rvd_scmd };

initrvdcommands ()
{
  opcon_register (&rvd_cmd);
}

print_rvd_mode (devp, rvd_mode)
     dct *devp;
     bitf rvd_mode;
{
  int second;
  second = 0;

  if (rvd_mode == 0) {
    fprintf (devp, "unknown/unset mode.\n");
    return;
  }    
  if (rvd_mode & RVDMRO) {
    fprintf (devp, "read-only");
    second = 1;
  }
  if (rvd_mode & RVDMSHR) {
    if (second++) fprintf (devp, ", ");
    fprintf (devp, "shared");
  }
  if (rvd_mode & RVDMEXC) {
    if (second++) fprintf (devp, ", ");
    fprintf (devp, "execlusive");
  }

  if (second > 1) fprintf (devp, " modes.\n");
  else fprintf (devp, " mode.\n");
}

rvd_list_command (devp, arg, jcl)
dct *devp;
int arg;
char *jcl;
{
  int i;

  if (in_flush_rvd == FLUSH_RVD_NOTHING) {
    fprintf (devp, "RVD flushing disabled.\n");
    return;
  }

  if (in_flush_rvd == FLUSH_RVD_ALL) {
    fprintf (devp, "RVD flushing enabled for all packet types.\n");
    return;
  }

  for (i = 0; i < RVDLAST; i++) {
    if (in_flush_rvd & (1<<i)) {
      if (((i+1) == RVDSPIN) || ((i+1) == RVDAUTHSPIN)) {
	fprintf (devp, "RVD %s flushing enabled for ", rvd_packet_names[i]);
	print_rvd_mode (devp, in_flush_rvd_spin_mode);
      }
      else if (strcmp (rvd_packet_names[i], "unknown") != 0)
	fprintf (devp, "RVD %s flushing enabled.\n", rvd_packet_names[i]);
    }
  }
}

change_attr (set_flag, attr_word, attr_bit)
     int set_flag;
     unsl *attr_word;
     unsl attr_bit;
{
  if (set_flag)
    *attr_word |= attr_bit;
  else
    *attr_word &= ~attr_bit;
}

rvd_change_command (devp, set, jcl)
dct *devp;
int set;
char *jcl;
	
{
  int i;

  if (jcl == NULL) {
    fprintf (devp, "One of all, rmode, smode, xmode,");
    for (i = 0; i < RVDLAST; i++) {
      if (strcmp (rvd_packet_names[i], "unknown") != 0) {
	if (i != 0) fprintf (devp, ",");
	fprintf (devp, " %s", rvd_packet_names[i]);
      }
    }
    fprintf (devp, ".\n");
    return;
  }

  if (!good_password) {
    fprintf(devp, "Not allowed\n");
    return;
  }

  if (strcmp (jcl, "all") == 0) {
    in_flush_rvd = (set ? FLUSH_RVD_ALL : FLUSH_RVD_NOTHING);
    return;
  }
  else if (strcmp (jcl, "rmode") == 0) {
    change_attr (set, &in_flush_rvd_spin_mode, RVDMRO);
    return;
  }
  else if (strcmp (jcl, "smode") == 0) {
    change_attr (set, &in_flush_rvd_spin_mode, RVDMSHR);
    return;
  }
  else if (strcmp (jcl, "xmode") == 0) {
    change_attr (set, &in_flush_rvd_spin_mode, RVDMEXC);
    return;
  }

  for (i = 0; i < RVDLAST; i++) {
    if (strcmp (jcl, rvd_packet_names[i]) == 0) {
      change_attr (set, &in_flush_rvd, 1<<i);
      return;
    }
  }
    
  fprintf (devp, "%s is unknown. Give no args for valid types.\n", jcl);

}

