/* $Header:   U:/engineer/sw/t2r/misc/setclock.c_v   1.1   01 Dec 1992 12:14:52   galen  $
 */

#include "needed.h"
#include "gxe.h"
#include "number9.h"

#define CRYSTAL_FREQUENCY       (14318180L * 2)
#define MIN_VCO_FREQUENCY       50000000L
#define MAX_POST_SCALE          285000000L

int clock_m;
int clock_n;
int clock_p;

long
n9set_clock(clock_value)
register long clock_value;              /* 7bits M, 7bits N, 2bits P */
{
  register long         index;
  long                  temp;
  register char         iotemp;
  int select;

  select = (clock_value >> 22) & 3;

  /* Unlock the S3 registers */
  outp(CRT_INDEX, LOCK_INDEX);
  outp(CRT_DATA, UNLOCK_PATTERN);

  /* Shut off screen */
  outp(0x3C4, 0x01);
  iotemp = inp(0x3C5);
  outp(0x3C5, iotemp | 0x20);

  /* set clock input to 11 binary */
  iotemp = inp(0x3CC);
  outp(0x3C2, iotemp | 0x0C);

  outp(CRT_INDEX, SSW_WRITE_INDEX);
  outp(CRT_DATA, 0);

  outp(CRT_INDEX, MODE_CTRL_INDEX);
  iotemp = inp(CRT_DATA) & 0xF0;

  /* Set up the softswitch write value */
#define CLOCK(x) outp(CRT_DATA, iotemp | (x))
#define C_DATA  2
#define C_CLK   1
#define C_BOTH  3
#define C_NONE  0

  /* Program the IC Designs 2061A frequency generator */
  CLOCK(C_NONE);

  /* Unlock sequence */
  CLOCK(C_DATA);
  for (index = 0; index < 6; index++)
    {
      CLOCK(C_BOTH);
      CLOCK(C_DATA);
    }
  CLOCK(C_NONE);
  CLOCK(C_CLK);
  CLOCK(C_NONE);
  CLOCK(C_CLK);
  
  /* Program the 24 bit value into REG0 */
  for (index = 0; index < 24; index++)
    {
      /* Clock in the next bit */
      clock_value >>= 1;
      if (clock_value & 1)
        {
          CLOCK(C_CLK);
          CLOCK(C_NONE);
          CLOCK(C_DATA);
          CLOCK(C_BOTH);
        }
      else
        {
          CLOCK(C_BOTH);
          CLOCK(C_DATA);
          CLOCK(C_NONE);
          CLOCK(C_CLK);
        }
    }

  CLOCK(C_BOTH);
  CLOCK(C_DATA);
  CLOCK(C_BOTH);

  /* If necessary, reprogram other ICD2061A registers to defaults */

  /* Select the CLOCK in the frequency synthesizer */
  CLOCK(C_NONE | select);

  /* Turn screen back on */
  outp(0x3C4, 0x01);
  iotemp = inp(0x3C5);
  outp(0x3C5, iotemp & 0xDF);

  return temp;
}

long
n9get_clock(clock_value)
register long clock_value;              /* 7bits M, 7bits N, 2bits P */
{
  long                  temp;
  register long         index;

  /* Unpack the clock value */
  clock_m = ((clock_value >>  1) & 0x7F) + 2;
  clock_n = ((clock_value >> 11) & 0x7F) + 3;
  clock_p = ((clock_value >>  8) & 0x03);

  temp = (((CRYSTAL_FREQUENCY / 2) * clock_n) / clock_m) << 1;
  temp >>= clock_p;

  return temp;
}
