/*  SVGATextMode -- An SVGA textmode manipulation/enhancement tool
 *
 *  Copyright (C) 1995  Koen Gadeyne
 *
 *  This program 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.
 *
 *  This program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


/***
 *** xfree_compat: misc. stuff to get the XFREE code to compile. This is junk :-(
 *** Written by Koen Gadeyne (kmg@barco.be)
 ***
 ***/
 


#include "common/compiler.h"   /* this will use the INVERTED outb() function! */
#include "xfree_compat.h"
#include "../misc.h"

/***************************************************************************/

/* next block is taken from xfree86/os-support/linux/lnx_video.c it was to
 * idiot to include the entire os-support/linux dir here, since these
 * functions were so simple... [kmg] changing "Bool" to "int" for
 * xf86DisableInterrupts() is a bad hack, but the only way I could think of
 * getting the damn thing through the compiler WITHOUT changing any XFREE
 * code
 */

int xf86DisableInterrupts()
{
        return(TRUE);
}

void xf86EnableInterrupts()
{
        return;
}



/***************************************************************************/


/* next block is from xfree/accel/s3/s3TiCursor.c. It was cut out and placed
 * here because it looked like a big effort to get that .c file to compile under
 * SVGATextMode, and I needed only a few functions.
 * some stuff from s3.c (from same dir) was added.
 */

#include "accel/s3/s3Ti3020.h"
extern int vgaIOBase;

#define vgaCRIndex  (vgaIOBase+4)
#define vgaCRReg    (vgaIOBase+5)

/*
 * s3OutTiIndReg() and s3InTiIndReg() are used to access the indirect
 * 3020 registers only.
 */

#ifdef __STDC__
void s3OutTiIndReg(unsigned char reg, unsigned char mask, unsigned char data)
#else
void s3OutTiIndReg(reg, mask, data)
unsigned char reg;
unsigned char mask;
unsigned char data;
#endif
{
   unsigned char tmp, tmp1, tmp2 = 0x00;

   /* High 2 bits of reg in CR55 bits 0-1 (1 is cleared for the TI ramdac) */
   outb(vgaCRIndex, 0x55);
   tmp = inb(vgaCRReg) & 0xFC;
   outb(vgaCRReg, tmp | 0x01);  /* toggle to upper 4 direct registers */
   tmp1 = inb(TI_INDEX_REG);
   outb(TI_INDEX_REG, reg);

   /* Have to map the low two bits to the correct DAC register */
   if (mask != 0x00)
      tmp2 = inb(TI_DATA_REG) & mask;
   outb(TI_DATA_REG, tmp2 | data);

   /* Now clear 2 high-order bits so that other things work */
   outb(TI_INDEX_REG, tmp1);  /* just in case anyone relies on this */
   outb(vgaCRReg, tmp);
}

#ifdef __STDC__
unsigned char s3InTiIndReg(unsigned char reg)
#else
unsigned char s3InTiIndReg(reg)
unsigned char reg;
#endif
{
   unsigned char tmp, tmp1, ret;

   /* High 2 bits of reg in CR55 bits 0-1 (1 is cleared for the TI ramdac) */
   outb(vgaCRIndex, 0x55);
   tmp = inb(vgaCRReg) & 0xFC;
   outb(vgaCRReg, tmp | 0x01);  /* toggle to upper 4 direct registers */
   tmp1 = inb(TI_INDEX_REG);
   outb(TI_INDEX_REG, reg);

   /* Have to map the low two bits to the correct DAC register */
   ret = inb(TI_DATA_REG);

   /* Now clear 2 high-order bits so that other things work */
   outb(TI_INDEX_REG, tmp1);  /* just in case anyone relies on this */
   outb(vgaCRReg, tmp);

   return(ret);
}

#include "../parse_opt.h"   /* for option masks */
typedef int Bool;
#include "common_hw/xf86_HWlib.h"

void xfree_Ti3025_init(int optmask)
  /* code snatched from accel/s3/s3.c. */
{
      int mclk, m, n, p, mcc, cr5c;

      outb(vgaCRIndex, 0x5c);
      cr5c = inb(vgaCRReg);
      outb(vgaCRReg, cr5c & 0xdf);           /* clear RS4 - use 3020 mode */

      s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x00);
      n = s3InTiIndReg(TI_MCLK_PLL_DATA) & 0x7f;
      s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x01);
      m = s3InTiIndReg(TI_MCLK_PLL_DATA) & 0x7f;
      s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x02);
      p = s3InTiIndReg(TI_MCLK_PLL_DATA) & 0x03;
      mcc = s3InTiIndReg(TI_MCLK_DCLK_CONTROL);
      if (mcc & 0x08)
         mcc = (mcc & 0x07) * 2 + 2;
      else
         mcc = 1;
      mclk = ((1431818 * ((m+2) * 8)) / (n+2) / (1 << p) / mcc + 50) / 100;
      if (optmask & OPT_NUMBER_NINE) {
         mclk = 55000;
         /* ErrorF("%s %s: Setting MCLK to %1.3f MHz for #9GXE64 Pro\n",
                 XCONFIG_PROBED, s3InfoRec.name, mclk / 1000.0); */
         Ti3025SetClock(2 * mclk, TI_MCLK_PLL_DATA);
         mcc = s3InTiIndReg(TI_MCLK_DCLK_CONTROL);
         s3OutTiIndReg(TI_MCLK_DCLK_CONTROL,0x00, (mcc & 0xf0) | 0x08);
      }
      outb(vgaCRIndex, 0x5c);
      outb(vgaCRReg, cr5c);
}

  