/*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 = VDHPALET.c
 *
 * DESCRIPTIVE NAME = Base video device handlers - Color Lookup/Palette 
 *
 *
 * VERSION      V2.0
 *
 * DATE         
 *
 * DESCRIPTION  This source file contains VDH entry points which             
 *              get/set the color lookup table and palette registers.
 *              and get/set palette registers.
 *
 *  NOTE:       These routines execute as ring 2 conforming           
 *
 * FUNCTIONS    GetColorLookup,  SetColorLookup                       
 *              GetPaletteReg,   SetPaletteReg                        
 *
 * NOTES        NONE
 *
 * STRUCTURES   NONE
 *
 * EXTERNAL REFERENCES
 *              SaveRegs, RestoreRegs          
 *              AccessHardware, AccessCLUT      
 *              PhysToUVirt, FreePhysToUVirt    
 *
 * EXTERNAL FUNCTIONS
 *
 *              NONE
 *
*/

/*
**  Include files                                                            
*/

#define  INCL_BASE                     /* ALL of OS/2 Base                  */
#define  INCL_OS2STD                   /* Needed for NULL definition in     */
                                       /* OS2STD.H                          */
#include <os2.h>
#include "vdhctl.h"                    /* Conditional compilation control   */
#include "vdh.h"                       /* Type definitions                  */

/*
**  Externally defined global variables                                      
*/

extern VIDEOMODE Modes[];              /* Supported modes                   */
extern MEMORYMAPS MemoryMaps[];        /* Memory map info for each mode     */
extern UCHAR LCDGrayLUT[];             /* LCD gray scale lookup table       */
extern USHORT OEMFlags;                /* OEM specific features             */
extern SHORT HugeShift;                /* Huge shift value                  */
extern UCHAR READABLE;
extern ULONG PartialSaveSize;          /* Room required to save entire PVB  */
                                       /* in the popup mode                 */
extern USHORT VGA_PRESENT;             /* TRUE if VGA VDH has been          */
                                       /* installed                         */
extern USHORT(APIENTRY *ChainedCallVectorTable[MaxFn])();/*             @T24*/

/*
**  Parameters to ring 2 routines                                            
*/

extern UCHAR CRTReg1;
extern UCHAR CRTReg2;
extern UCHAR PelHeightFixup;
extern UCHAR ScreenRemainder;
extern CLUTDATA far ColorCLUT;
extern CLUTDATA far MonoCLUT;
extern CLUTDATA far SumCLUT;

#if      VDHVGA        || VDH8514A     /* Start of               @S24CHANGES*/
                                       /* MS00                              */

/*****************************************************************************
 *                                                                          
 *  SUBROUTINE NAME: GetColorLookup                                         
 *                                                                          
 *  DESCRIPTIVE NAME: Get color lookup table                                
 *                                                                          
 *  FUNCTION: GetColorLookup is called by BVS to return a specified         
 *            portion of the current color lookup table settings            
 *                                                                          
 *  ENTRY POINT: GetColorLookup                                             
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 263 )       
 *                                                                          
 *  INPUT: (Passed on stack)                                                
 *             FAR *Environment ( Environment buffer for the session )      
 *             FAR *ParmBlock                                               
 *                     USHORT Length = length of this packet                
 *                     USHORT Flags  = 0 - Environment buffer only          
 *                                     1 - Hardware also                    
 *                     CLUTDATA far *LookupTable ( 0x00 - 0xFF )            
 *                                     UCHAR Red                            
 *                                     UCHAR Green                          
 *                                     UCHAR Blue                           
 *                     USHORT   FirstEntry                                  
 *                     USHORT   NumEntries                                  
 *             ULONG Function ( Call vector table entry = 263 )             
 *                                                                          
 *  EXIT-NORMAL: AX = 0                                                     
 *               Portion of CLUT requested is returned                      
 *                                                                          
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                                
 *                                                                          
 *  EFFECTS: If hardware specified and hardware is readable, the            
 *           environment buffer is updated, if passed.                      
 *                                                                          
 *  INTERNAL REFERENCES:                                                    
 *    ROUTINES: NONE                                                        
 *                                                                          
 *  EXTERNAL REFERENCES:                                                    
 *    ROUTINES: AccessCLUT                                                  
 *                                                                          
 ****************************************************************************/

USHORT EXPENTRY GetColorLookup(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_CLUT far *ParmBlock;
  ULONG Function;

{
  USHORT rc,EnvBufferPassed;
  int i,j;

  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */

  #if      VDH8514A                    /*  MS00                             */
 
  if (EnvBufferPassed)
  {
 
    if (!(Environment->ModeData.fbType & NATIVE))
    {                                  /* Passthru VGA modes                */
      rc = (*ChainedCallVectorTable[Function-FnTextBufferUpdate])((char far *)
            &Environment->VGAEnvironment, ParmBlock, Function);
      return (rc);
    } 
  } 
 
  else
  {
    return (rc);
  } 

  #endif        /*          VDH8514A,  MS00                                 */
 
  if ((Function == FnGetColorLookupTable) && /* Valid function request      */
     (ParmBlock->Length >= sizeof(VDH_CLUT)) && /* Valid packet length      */
     (ParmBlock->Flags <= 1) &&        /* Valid flags                       */
     (ParmBlock->NumEntries) &&        /* Non-zero amount                   */
     (ParmBlock->FirstEntry <= 0xFF) && /* Valid first entry                */
     (ParmBlock->FirstEntry + ParmBlock->NumEntries <= 0xFF+1) &&
     (EnvBufferPassed || (ParmBlock->Flags & UPDATE_HARDWARE)))
  {

/*
**  If requesting application is running in foreground,           
**    - Return hardware value                                     
**    - Otherwise return environment buffer value                 
**  If requesting application is running in background,           
**    - Return environment buffer value                           
**     ( report error if environment buffer was not passed )      
*/

    rc = NO_ERROR;                     /* Initialize no error               */

/*
**  Get CLUT values directly from the hardware                              
*/

    if (ParmBlock->Flags & UPDATE_HARDWARE)
    {
      AccessCLUT(GET, &ParmBlock->LookupTable);/* ring 2 callgate           */

  #if      VDHVGA                      /*  MS00                             */

/*
**  Copy CLUT values from caller's parmeter area to the env buffer 
*/

      if (EnvBufferPassed)
      {
 
        for (i = ParmBlock->FirstEntry, j = 0; j < ParmBlock->NumEntries;
             i++, j++)
        {
          Environment->LookupTable[i] = ParmBlock->LookupTable[j]; /*  MS20 */
        } 
      } 
    } 
 
    else
    {                                  /* Caller in background              */

/*
**  Copy CLUT values from env buffer to caller's parameter area   
*/

      for (i = ParmBlock->FirstEntry, j = 0; j < ParmBlock->NumEntries; 
           i++, j ++)
      {
        ParmBlock->LookupTable[j] = Environment->LookupTable[i]; /*  MS20   */
      } 

  #endif        /*        VDH8514A,  MS00                                   */
    } 
  } 

  return (rc);
} 

/*****************************************************************************
 *                                                                        
 *  SUBROUTINE NAME: SetColorLookup                                       
 *                                                                        
 *  DESCRIPTIVE NAME: Set color lookup table                              
 *                                                                        
 *  FUNCTION: SetColorLookup is called by BVS to set a specified          
 *            portion of the color lookup table settings                  
 *                                                                        
 *  ENTRY POINT: SetColorLookup                                           
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 264 )     
 *                                                                        
 *  INPUT: (Passed on stack)                                              
 *             FAR *Environment ( Environment buffer for the session )    
 *             FAR *ParmBlock                                             
 *                     USHORT Length = length of this packet              
 *                     USHORT Flags  = 0 - Environment buffer only        
 *                                     1 - Hardware also                  
 *                     CLUTDATA far *LookupTable ( 0x00 - 0xFF )          
 *                                     UCHAR Red                          
 *                                     UCHAR Green                        
 *                                     UCHAR Blue                         
 *                     USHORT   FirstEntry                                
 *                     USHORT   NumEntries                                
 *             ULONG Function ( Call vector table entry = 264 )           
 *                                                                        
 *  EXIT-NORMAL: AX = 0                                                   
 *               Portion of CLUT requested is set                         
 *                                                                        
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                              
 *                                                                        
 *  INTERNAL REFERENCES:                                                  
 *    ROUTINES: NONE                                                      
 *                                                                        
 *  EXTERNAL REFERENCES:                                                  
 *    ROUTINES: AccessCLUT                                                
 *                                                                        
 ****************************************************************************/

USHORT EXPENTRY SetColorLookup(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_CLUT far *ParmBlock;
  ULONG Function;

{

  USHORT rc,i,j,EnvBufferPassed;
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */

  #if      VDH8514A                    /*  MS00                             */
 
  if (EnvBufferPassed)
  {
 
    if (!(Environment->ModeData.fbType&NATIVE))
    {                                  /* Passthru VGA modes                */
      rc = (*ChainedCallVectorTable[Function-FnTextBufferUpdate])((char far *)
         &Environment->VGAEnvironment, ParmBlock, Function);
      return (rc);
    } 
  } 
 
  else
  {
    return (rc);
  } 
  #endif        /*        VDH8514A,  MS00                                   */
 
  if ((Function == FnSetColorLookupTable) && /* Valid function request      */
     (ParmBlock->Length >= sizeof(VDH_CLUT)) && /* Valid packet length      */
     (ParmBlock->Flags <= 1) &&        /* Valid flags                       */
     (ParmBlock->NumEntries) &&        /* Non-zero amount                   */
     (ParmBlock->FirstEntry <= 0xFF) && /* Valid first entry                */
     (ParmBlock->FirstEntry + ParmBlock->NumEntries <= 0xFF+1) &&
     (EnvBufferPassed || (ParmBlock->Flags & UPDATE_HARDWARE)))
  {

/*
**  Parameters are valid - Update environment buffer if it was passed  
**                       - Update hardware if in foreground            
*/

    rc = NO_ERROR;                     /* Initialize no error               */

  #if      VDHVGA                      /*  MS00                             */

/*
**  Copy CLUT values from caller's parmeter area to the env buffer       
*/

    if (EnvBufferPassed)
    {
 
      for (i = ParmBlock->FirstEntry, j = 0; j < ParmBlock->NumEntries; 
           i++, j++)
      {
        Environment->LookupTable[i] = ParmBlock->LookupTable[j]; /*  MS20   */
      } 

    } 

  #endif        /*        VDHVGA,  MS00                                     */

/*
**  Set CLUT registers directly on the hardware                      
*/

    if (ParmBlock->Flags & UPDATE_HARDWARE)
    {
      AccessCLUT(SET, &ParmBlock->LookupTable);/* ring 2 callgate           */
    } 
  } 
  return (rc);
} 

#endif              /*  VDHVGA || VDH8514A    End of @S24 changes           */

#if      PALETTE_SUPPORT                   /* MS00                          */

/*****************************************************************************
 *                                                                        
 *  SUBROUTINE NAME: GetPaletteReg                                        
 *                                                                        
 *  DESCRIPTIVE NAME: Get palette registers                               
 *                                                                        
 *  FUNCTION: GetPaletteReg is called by BVS to return the specified      
 *            portion of the palette registers.  If the request           
 *            specifies hardware and the hardware is readable, the        
 *            actual hardware setting will be read and returned.          
 *            Otherwise the returned information will be taken from       
 *            the environment buffer, if it has been passed.              
 *                                                                        
 *  ENTRY POINT: GetPaletteReg                                            
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 273 )     
 *                                                                        
 *  INPUT: (Passed on stack)                                              
 *             FAR *Environment ( Environment buffer for the session )    
 *             FAR *ParmBlock                                             
 *                     USHORT Length = length of this packet              
 *                     USHORT Flags  = 0 - Environment buffer only        
 *                                     1 - Hardware also                  
 *                     FAR *PaletteBuffer                                 
 *                     USHORT   FirstEntry                                
 *                     USHORT   NumEntries                                
 *             ULONG Function ( Call vector table entry = 273 )           
 *                                                                        
 *  EXIT-NORMAL: AX = 0                                                   
 *               Requested palette registers are returned                 
 *                                                                        
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                              
 *                                                                        
 *  EFFECTS: If hardware specified and hardware is readable, the          
 *           environment buffer is updated, if passed.                    
 *                                                                        
 *  INTERNAL REFERENCES:                                                  
 *    ROUTINES: NONE                                                      
 *                                                                        
 *  EXTERNAL REFERENCES:                                                  
 *    ROUTINES: AccessHardware                                            
 *                                                                        
 ****************************************************************************/

USHORT EXPENTRY GetPaletteReg(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_PALETTE far *ParmBlock;
  ULONG Function;

{

  USHORT rc,ColorMode,                 /*                               @C21*/
         VideoOn,                      /*                               @C21*/
         EnvBufferPassed;
  int i,j;
  REGADDRESS RegAddress;


  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */
 
  if ((Function == FnGetPaletteRegisters) && /* Valid function request      */
     (ParmBlock->Length >= sizeof(VDH_PALETTE)) && /* Valid packet length   */
     (ParmBlock->Flags <= 1) &&        /* Valid flags                       */
     (EnvBufferPassed || (ParmBlock->Flags & UPDATE_HARDWARE)))
 
    if ((ParmBlock->PaletteBuffer.NumEntries) && /* Non-zero amount         */
       (ParmBlock->PaletteBuffer.FirstEntry <= 0x0F) && /* Valid first      */
                                                        /*  entry           */
       (ParmBlock->PaletteBuffer.FirstEntry +
        ParmBlock->PaletteBuffer.NumEntries <= 0x0F+1))
    {
      rc = NO_ERROR;                   /* Initialize no error               */

/*
**  If requesting application is running in foreground,                  
**    - Return hardware value if hardware can be read                    
**    - Otherwise return environment buffer value                        
**     ( report error if write-only hardware and no env buffer passed )  
**  If requesting application is running in background,                  
**    - Return environment buffer value                                  
**     ( report error if environment buffer was not passed )             
*/

      if ((ParmBlock->Flags&UPDATE_HARDWARE) && READABLE)
      {

 #if      VDHVGA                        /* Read/write hardware              */
                                        /*  MS00                            */

/*
**  Get palette values directly from the hardware                     
**  Accessing the Attribute regs resets the VideoEnable status so have
**  TO RESET IT IF IT WAS ON BEFORE THE CALL                          
*/

        ColorMode = HardwareColor();   /* color/mono mode ( hardware )  @C21*/
 
        if (EnvBufferPassed)           /*                               @C21*/
          VideoOn = Environment->VideoEnable;/*                         @C21*/
 
        else                           /*                               @C21*/
          AccessVideoEnable(ColorMode, GET, &VideoOn);/*                @C21*/
        RegAddress.AddressPort = AttAddressPort;
        RegAddress.DataPort = AttDataReadPort;
        RegAddress.ColorAdjust = NONE;
        RegAddress.Flags = Attributes_CMD;
        AccessHardware(&RegAddress, WORDS, HardwareColor(), GET, 
                      (REGDATA far *)&ParmBlock->PaletteBuffer);
 
        if (VideoOn)                   /*                               @C21*/
          AccessVideoEnable(ColorMode, SET, &VideoOn);/*                @C21*/
 
        if (EnvBufferPassed)

/*
**  Copy palette values from caller's parmeter area to the env buffer        
*/

          for (i = ParmBlock->PaletteBuffer.FirstEntry, j = 0; 
               j < ParmBlock->PaletteBuffer.NumEntries; i++, j++)

            Environment->Hardware.Attributes.Regs.Palettes[i] = 
                    (UCHAR) ParmBlock->PaletteBuffer.DataArea[j];

  #endif        /*        VDHVGA,  MS00                                     */
      } 
 
      else
      {

/*
**  Requesting application is running in the background                      
*/

        if (EnvBufferPassed)

/*
**  Copy palette values from env buffer to caller's parameter area           
*/

          for (i = ParmBlock->PaletteBuffer.FirstEntry, j = 0;
               j < ParmBlock->PaletteBuffer.NumEntries; i++, j++)

            ParmBlock->PaletteBuffer.DataArea[j] = (USHORT)
               Environment->Hardware.Attributes.Regs.Palettes[i];
 
        else
          rc = ERROR_VIO_INVALID_PARMS;/* Not FG OR write-only, no env      */
                                       /* buffer                            */
      } 
    } 


  return (rc);
} 

/*****************************************************************************
 *                                                                         
 *  SUBROUTINE NAME: SetPaletteReg                                         
 *                                                                         
 *  DESCRIPTIVE NAME: Set palette registers                                
 *                                                                         
 *  FUNCTION: SetPaletteReg is called by BVS to set the specified          
 *            portion of the palette registers.  If the request            
 *            specifies hardware the hardware and the environment          
 *            buffer, if passed, will be updated.  Otherwise just the      
 *            environment buffer, if passed, will be updated.              
 *                                                                         
 *  ENTRY POINT: SetPaletteReg                                             
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 274 )      
 *                                                                         
 *  INPUT: (Passed on stack)                                               
 *             FAR *Environment ( Environment buffer for the session )     
 *             FAR *ParmBlock                                              
 *                     USHORT Length = length of this packet               
 *                     USHORT Flags  = 0 - Environment buffer only         
 *                                     1 - Hardware also                   
 *                     FAR *PaletteBuffer                                  
 *                     USHORT   FirstEntry                                 
 *                     USHORT   NumEntries                                 
 *             ULONG Function ( Call vector table entry = 274 )            
 *                                                                         
 *  EXIT-NORMAL: AX = 0                                                    
 *               Requested palette registers are set                       
 *                                                                         
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                               
 *                                                                         
 *  INTERNAL REFERENCES:                                                   
 *    ROUTINES: NONE                                                       
 *                                                                         
 *  EXTERNAL REFERENCES:                                                   
 *    ROUTINES: AccessHardware                                             
 *                                                                         
 ****************************************************************************/

USHORT EXPENTRY SetPaletteReg(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_PALETTE far *ParmBlock;
  ULONG Function;

{

  USHORT rc,i,j,ColorMode,VideoOn,     /*                               @C21*/
         EnvBufferPassed;
  REGADDRESS RegAddress;


  rc = ERROR_VIO_INVALID_PARMS;        /* Init to error                     */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */
 
  if ((Function == FnSetPaletteRegisters) && /* Valid function request      */
     (ParmBlock->Length >= sizeof(VDH_PALETTE)) && /* Valid packet length   */
     (ParmBlock->Flags <= 1) &&        /* Valid flags                       */
     (ParmBlock->PaletteBuffer.FirstEntry <= 0x0F) && /*     @@AVALID1STNTRY*/
     (EnvBufferPassed || (ParmBlock->Flags&UPDATE_HARDWARE)))
 
    if ((ParmBlock->PaletteBuffer.NumEntries) && /* Non-zero amount         */
       (ParmBlock->PaletteBuffer.FirstEntry +
        ParmBlock->PaletteBuffer.NumEntries <= 0x0F+1))
    {
      rc = NO_ERROR;                   /* Initialize no error               */

/*
**  Parameters are valid - Update environment buffer if it was passed       
**                       - Update hardware if in foreground                  
*/

      if (EnvBufferPassed)
      {

/*
**  Copy palette values from caller's parmeter area to the env buffer        
*/

        for (i = ParmBlock->PaletteBuffer.FirstEntry, j = 0; 
             j < ParmBlock->PaletteBuffer.NumEntries; i++, j++)

          Environment->Hardware.Attributes.Regs.Palettes[i] = 
                (UCHAR) ParmBlock->PaletteBuffer.DataArea[j];

      } 
 
      if (ParmBlock->Flags&UPDATE_HARDWARE)
      {

/*
**  Set palette values directly from the hardware                            
**  Accessing the Attribute regs resets the VideoEnable status so have
**  TO RESET IT IF IT WAS ON BEFORE THE CALL                          
*/

        RegAddress.AddressPort = AttAddressPort;
        RegAddress.DataPort = AttDataWritePort;
        RegAddress.ColorAdjust = NONE;
        RegAddress.Flags = Attributes_CMD;

 #if      VDHVGA                       /* Read/write hardware               */
                                       /*  MS00                             */
        ColorMode = HardwareColor();   /* color/mono mode ( hardware )      */

  #else                                /* Write-only hardware               */
        ColorMode = Environment->ModeData.fbType & NOT_MONO;/* color/mono   */
                                       /* mode (env buffer)                 */

  #endif        /*        VDHVGA,  MS00                                     */
 
        if (EnvBufferPassed)           /*                               @C21*/
          VideoOn = Environment->VideoEnable;/*                         @C21*/
 
        else                           /*                               @C21*/

  #if      VDHVGA                      /*                          @C21,MS00*/
  AccessVideoEnable(ColorMode, GET, &VideoOn);/*                        @C21*/

  #else                                /*                          @C21,MS00*/
  VideoOn = 1;                         /*                               @C21*/
  #endif                               /*   VDHVGA,   @C21,MS00             */

        AccessHardware(&RegAddress, WORDS, ColorMode, SET, 
                      (REGDATA far *) &ParmBlock->PaletteBuffer);
 
        if (VideoOn)                   /*                               @C21*/
          AccessVideoEnable(ColorMode, SET, &VideoOn);/*                @C21*/
      } 
    } 

  return (rc);
} 

#endif        /*        PALETTE_SUPPORT,  MS00                              */

#if      VDHVGA                         /*  MS21 - BEGIN                    */

/***************************************************************************
 *
 * FUNCTION NAME = SetTextGrays(Environment)
 *
 * DESCRIPTION   = 
 *                                                                      
 *     When running on an LCD in text mode, this programs the gray scale
 *     so that foreground/background combinations have nearly the same  
 *     contrast as the standard colors do on a color monitor.           
 *                                                                      
 * INPUT         = *Environment;
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

void PASCAL near SetTextGrays(Environment)

  ENVIRONMENT far *Environment;        /*  Session environment buffer       */

{
  REGADDRESS RegAddress;
  REGDATA RegData;
  UCHAR DataArea;
  USHORT i;
 

  if ((OEMFlags&(PRISM_VGA|CRYSTAL_VGA)) /*  LCD adapter                    */
     && (Environment->ModeData.fbType == NOT_MONO))
  {                                    /*  & Color text mode                */
                                       /*  = Set gray scale                 */
    /*
    ** Open access to extended VGA registers
    */
    RegAddress.AddressPort = GraphAddressPort;
    RegAddress.DataPort = GraphDataPort;
    RegAddress.Flags = NONE;
    RegData.DataArea = &DataArea;
    RegData.FirstEntry = VGA_ENV_REG;
    RegData.NumEntries = 1;
    DataArea = VGA_UNLOCK;
    AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);

    /*
    ** Map 16 colors onto gray levels.
    */
    for (i = 0; i < 16; i++)
    {

      /*
      ** Use color's palette value as index into gray scale LUT...
      */
      RegData.FirstEntry = LCD_GRAYSCALE_ADDR;
      DataArea = Environment->Hardware.Attributes.Regs.Palettes[i];
      AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);

      /*
      ** then set that entry to a gray level.
      */
      RegData.FirstEntry = LCD_GRAYSCALE_DATA;
      DataArea = (OEMFlags&CRYSTAL_VGA)?LCDGrayLUT[i] /*  range 0..31       */
         : LCDGrayLUT[i] >> 1;                         /*  range 0..15       */
      AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
    } 

    /*
    ** Close access to extended VGA registers
    */
    RegData.FirstEntry = VGA_ENV_REG;
    DataArea = VGA_LOCK;
    AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  } 
} 

#endif            /*    VDHVGA,  @MS21 - END                                */

