/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/*****************************************************************************
 *
 * SOURCE FILE NAME = SVGADIAM.C
 *
 * DESCRIPTIVE NAME = Diamond specific functions for SVGADATA.PMI file.
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION
 *
 *   This program determines which SVGA chip set is installed and creates a
 *   file containing chip set specific register information used by the base
 *   video handlers in setting video modes.  This utility creates the OS/2
 *   Version 2.2 SVGADATA.PMI file.
 *
 *        Dependencies: None
 *        Restrictions: Runs in Real Mode
 *        Patch Label: N/A
 *
 *      Entry Points: main()
 *
 * FUNCTIONS
 *
 * NOTES
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

/*
**      Include files
*/

#include "svga.h"
#include "svgagen.h"

extern OEMSVGAINFO sSVGA;
CHAR  viperfile[256];
TOK ViperTokens[] =
{
   "[HARDWARE]",        TOK_HARDWARE,     /*            */
   "MEMSPEED",          TOK_MEMSPEED,     /*            */
   "MEMADDR",           TOK_MMIO_ADDRESS, /*            */
   "[640X480X8]",       TOK_640x480x8,
   "[640X480X16]",      TOK_640x480x16,
   "[640X480X24]",      TOK_640x480x24,
   "[800X600X4]",       TOK_800x600x4,
   "[800X600X8]",       TOK_800x600x8,
   "[800X600X16]",      TOK_800x600x16,
   "[800X600X24]",      TOK_800x600x24,
   "[1024X768X4]",      TOK_1024x768x4,
   "[1024X768X8]",      TOK_1024x768x8,
   "[1024X768X16]",     TOK_1024x768x16,
   "[1280X1024X4]",     TOK_1280x1024x4,
   "[1280X1024X8]",     TOK_1280x1024x8,
   NULL,0,                                   /*            always 0 end it */
};
ULONG WSpeed= 0;
ULONG Vclk[MAX_MODES] =
{
   0x4BD8B500,0x4BD8B500,0x4BD8B500,0x4BD8B500,0x4BD8B500,
   0x4BD8B500,0x4BD8B500,0x4BD8B500,0x4BD8B500,0x4BD8B500,
   0x4BD8B500,0x4BD8B500,0x4BD8B500,0x4BD8B500,0x4BD8B500,
};
BYTE SEQ12_ORMask[MAX_MODES] = {0};
#define VGADISABLE 0x10
/*****************************************************************************
 *
 * FUNCTION NAME = AddVIPERMMIORegAss
 *
 * DESCRIPTION   = Add 32bit MMIO register assignments for VIPER to the
 *                 mode section.
 *
 *
 * INPUT         =
 * OUTPUT        = RegData setup with all command fields.
 *
 * RETURN-NORMAL = 1 if RegData updated, 0 if end
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/
VOID AddVIPERMMIORegAss( PREGDATA pRegData, FILE *fViper )
{
  PMITOKEN tok;
  USHORT usVariableIndex, usRegDataIndex;
  /*
  ** Each mode section has vclk and few other VIPER specific variables.
  ** So read until vclk is reached. For each register name, see if it is
  ** in the declaration section (in case they change their syntax) and if
  ** so, change the PMICMD_WRITEDW's for that register to the mode set data.
  ** There is no table of expected tokens,
  ** so use NextToken to extract one token at the time.
  */
  while ( ((tok = NextToken(fViper, (TOK *) 0)) != TOK_EOF)
          && strcmpi(CurrentToken,"vclk") )
  {
     /* for some        reason, Diamond calls srtctl register srtctc! */
     if(!strcmpi(CurrentToken,"srtctc"))
       strcpy(CurrentToken,"srtctl");
     for( usVariableIndex = 0;          /* See if we need this name: */
          (usVariableIndex<usSizeWeitekDeclaration)
          && !strcmpi(CurrentToken,
                      WeitekDeclarations[usVariableIndex].RegisterName);
          usVariableIndex++ )
     {}
     tok = NextToken(fViper, &ViperTokens[0]); //get the equal sign
     tok = NextToken(fViper, &ViperTokens[0]); //get the value.
     if( usVariableIndex < usSizeWeitekDeclaration )
     {                                  /* If we need this name: */
       for( usRegDataIndex = 0;
            pRegData[usRegDataIndex].Command != PMICMD_NONE;
            usRegDataIndex++)
       {
         if( (pRegData[usRegDataIndex].Command == PMICMD_WRITEDW)
             && (pRegData[usRegDataIndex].R.MMIO.Destination
                 == usVariableIndex)
             && (pRegData[usRegDataIndex].R.MMIO.MemFlags
                 == (MMIO_READCONF_ALL
                     | MMIO_SRC_IMMEDIATE
                     | MMIO_DST_VARIABLE)) )
         {
           pRegData->R.MMIO.Source = GetLongValue(CurrentToken,16);
           if( (usVariableIndex == WEITEK_MMIO_INDEX_MEMCONFIG)
               && (sSVGA.Memory == WINDOW_2MB) )
             pRegData->R.MMIO.Source = 0x2;
         }
       }
     }
  }
}
/*****************************************************************************
 *
 * FUNCTION NAME = processVIPERconf()
 *
 * DESCRIPTION   = Process VIPER.INI file and setup the MMIO structure and
 *                 other global vars as needed.
 *
 * INPUT         = fViper FILE *
 * OUTPUT        = sMMIOSVGA
 *
 * RETURN-NORMAL = 0 if OK
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/
INT  ProcessVIPERConf(FILE *fViper,MMIO_INFO  *sMMIOSVGA)
{
  PMITOKEN tok;
  tok = NextToken(fViper,&ViperTokens[0]);

  while ((tok != TOK_HARDWARE) && (tok != TOK_EOF))
    tok = NextToken(fViper,&ViperTokens[0]);
  if (tok == TOK_EOF)
    return 1;
  while ((tok != TOK_MEMSPEED) && (tok != TOK_EOF))
    tok = NextToken(fViper,&ViperTokens[0]);
  if (tok == TOK_EOF)
    return 1;
  if (NextToken(fViper,&ViperTokens[0]) == TOK_EQUALS)
  {
    NextToken(fViper,&ViperTokens[0]);    //get the value token.
    if (!(CurrValue = GetLongValue(CurrentToken,16)))
      return 1;
    WSpeed = (ULONG) CurrValue;
  }
  while ((tok != TOK_MMIO_ADDRESS) && (tok != TOK_EOF))
    tok = NextToken(fViper,&ViperTokens[0]);
  if (tok == TOK_EOF)
    return 1;
  if (NextToken(fViper,&ViperTokens[0]) == TOK_EQUALS)
  {
    NextToken(fViper,&ViperTokens[0]);    //get the value token.
//    if (!(CurrValue = GetLongValue(CurrentToken,16)))
//      return 1;
//    sMMIOSVGA->ulMMIOBase = (ULONG) CurrValue<<16;      //hardcode to 0x8000000
    sMMIOSVGA->ulMMIOBase = 0x80000000;
    return 0;
  }
  return 1;
}
/*****************************************************************************
 *
 * FUNCTION NAME = OpenVIPERFile()
 *
 * DESCRIPTION   = Process VIPER.INI file and setup the MMIO structure and
 *                 other global vars as needed.
 *
 * INPUT         =
 * OUTPUT        = fViper FILE *
 *
 * RETURN-NORMAL = 0 if OK
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/
FILE * OpenVIPERFile(VOID)
{
   FILE * hFile;
   CHAR *p;

   strcpy(viperfile,"");

   /*
   ** If VIPERPATH env variable exists, look for the file there. If it doesn't
   ** exist there, return an error.
   ** Else, look for it in the root directory of the current drive.
   ** Else, look for it in the x:\viper directory (x=boot drive)
   */
   if ((p = getenv("VIPERPATH")) != NULL)
   {
      strcat(viperfile,p);
      strcat(viperfile,"\\viper.ini");
      if (!(hFile = fopen(viperfile,"r")))
        return NULL;
   }
   else
   {
      strcat(viperfile,"\\viper.ini");
      if (!(hFile = fopen(viperfile,"r")))
      {
        viperfile[0] = GetBootDrive();
        strcpy(&viperfile[1],":\\viper\\viper.ini");
        if (!(hFile = fopen(viperfile,"r")))
          return NULL;
      }
   }
   return hFile;
}
/*****************************************************************************
 *
 * FUNCTION NAME = ProcessSupportedVIPERModes
 *
 * DESCRIPTION   = Process VIPER.INI file and setup all aflicted CHIPINFO
 *                 structures
 *
 * INPUT         =
 * OUTPUT        = fViper FILE *
 *
 * RETURN-NORMAL = 0 if OK
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/
VOID ProcessSupportedVIPERModes(PCHIPINFO ChipInfo, FILE *fViper, MMIO_INFO  *sMMIOSVGA)
{
  USHORT i,hp,vp;
  PCHIPHEADER pChipHdr;
  PMITOKEN ExpectedTok, tok;
  SHORT MemAddrBits=0001;
  SHORT MemAddrBitsTable[16] = {-1,-1,2,2,2,2,-1,-1,3,3,1,1,-1,-1,-1,-1};

  MemAddrBits = MemAddrBitsTable[(sMMIOSVGA->ulMMIOBase>>28) & 0xF];
  if (MemAddrBits == -1)
  {                                     /* error in the configuration */
    sMMIOSVGA->ulMMIOBase = 0x80000000;
    MemAddrBits = MemAddrBitsTable[0x08];
  }
  /*
  ** Find the mode in VIPER.INI. If not found, reset Int10Mode.
  ** We know the layout of the VIPER.INI file, the modes are listed
  ** in ascending order just as ours are.
  */
  for (i = 0; i < usNumModes; i++)
  {
    pChipHdr = ChipInfo[i].pChipHdr;
    if ((pChipHdr->bModeAttributes & GRAPHICS_MODEATTR) &&
        (pChipHdr->bBitsPerPixel > 4))
    {
      switch(pChipHdr->usXResolution)
      {
        case 640:
          switch(pChipHdr->bBitsPerPixel)
          {
            case 8: ExpectedTok =TOK_640x480x8;
            break;
            case 16:ExpectedTok =TOK_640x480x16;
            break;
            case 24:ExpectedTok =TOK_640x480x24;
            break;
          }
          break;
        case 800:
          switch(pChipHdr->bBitsPerPixel)
          {
            case 8: ExpectedTok =TOK_800x600x8;
            break;
            case 16:ExpectedTok =TOK_800x600x16;
            break;
            case 24:ExpectedTok =TOK_800x600x24;
            break;
          }
          break;
        case 1024:
          switch(pChipHdr->bBitsPerPixel)
          {
            case 8: ExpectedTok =TOK_1024x768x8;
            break;
            case 16:ExpectedTok =TOK_1024x768x16;
            break;
          }
          break;
        case 1280:
          switch(pChipHdr->bBitsPerPixel)
          {
            case 8: ExpectedTok =TOK_1280x1024x8;
            break;
          }
          break;
      }
      while (((tok = NextToken(fViper,&ViperTokens[0])) != TOK_EOF) &&
             (tok != ExpectedTok));
      if (tok == TOK_EOF)
      {
        /*
        ** Try again. Their order doesn't necessarely meet our mode order.
        */
        fclose(fViper);
        fViper = fopen(viperfile,"r");
        while (((tok = NextToken(fViper,&ViperTokens[0])) != TOK_EOF) &&
              (tok != ExpectedTok));
        if (tok == TOK_EOF)
          ChipInfo[i].Int10Mode = MODE_NOT_SUPPORTED;
      }
      /*
      ** If mode is supported, see if we need the mode data from the
      ** configuration file. Find PMICMD_WRITEDW's with MMIO_READCONF_ALL
      ** flag and change the REGDATA to use the VIPER.INI values.
      */
      if (ChipInfo[i].Int10Mode != MODE_NOT_SUPPORTED)
      {
        AddVIPERMMIORegAss( ChipInfo[i].pRegData, fViper );
        if(!strcmpi(CurrentToken,"vclk"))
        {
          NextToken(fViper,&ViperTokens[0]);   /* pass = */
          NextToken(fViper,&ViperTokens[0]); /* get value */
          if (CurrValue = GetLongValue(CurrentToken,16))
            Vclk[i] = CurrValue;
        }
      }
    }
    vp = (Vclk[i]&128) ? 0 : 1;
    hp = (Vclk[i]&64) ? 0 : 1;
    /* enable VGA */
    SEQ12_ORMask[i] = 0x80;
    /* setup the video select register for the mode */
    if ((ChipInfo[i].Int10Mode != MODE_NOT_SUPPORTED) &&
        (pChipHdr->bModeAttributes & GRAPHICS_MODEATTR) &&
        (pChipHdr->bBitsPerPixel > 4))
      SEQ12_ORMask[i] = (BYTE) (MemAddrBits | hp<<5 | vp<<6 | VGADISABLE);
  }
}
