/*DDK*************************************************************************/
/*                                                                           */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDQESC                                        */
/*                                                                    */
/*   Description     = Display Device Driver Escape functions:        */
/*                     Escape,                                        */
/*                     QueryEscSupport,                               */
/*                     QueryVIOCellSizes.                             */
/*                                                                    */
/*   Function        = Escape routes a call to an Escape Subfunction  */
/*                     using the given Escape Code.                   */
/*                     QueryEscSupport indicates which Escape         */
/*                     Subfunctions are supported.                    */
/*                     QueryVIOCellSizes returns the AVIO cell        */
/*                     sizes supported.                               */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/

#define INCL_GRE_DEVICE
#define INCL_NLS                                                        /*YOJN*/
#include <eddinclt.h>

#include <eddvcone.h>
#include <edddtypt.h>
#include <eddqextf.h>
#include <eddgextf.h>
#include <eddmextf.h>
#include <cursor.h>

#ifdef DBCS                                                             /*YOJN*/
#include <os2nlsfd.h>                                                   /*YOJN*/
                                                                        /*YOJN*/
#include <eddjdef.h>                                                    /*YOJN*/
#include <eddjfm.h>                                                     /*YOJN*/
#include <eddjfont.h>                                                   /*YOJN*/
#include <fontdrvr.h>                                                   /*YOJN*/
                                                                        /*YOJN*/
#endif                                                                  /*YOJN*/
extern DDTType             DDT;
extern AvioFontTableType   AvioBaseFont[NO_OF_AVIO_FONTS];
extern SHORT               softDrawInUse;
extern CURSORDATA          cursor_data;

#ifdef DBCS                                                             /*YOJN*/
/*====================================================================*//*YOJN*/
/* internal functions                                                 *//*YOJN*/
/*====================================================================*//*YOJN*/
ULONG pascal near eddq_DbcsFontManagement( ULONG ulInCount,             /*YOJN*/
                                                PFONTMGRPARM pInData,   /*YOJN*/
                                                PFATTRS pOutData );     /*YOJN*/
ULONG QueryVioFontAttrib( PVIOFONTATTRIBUTE pvfattr, PFATTRS pfattr );  /*YOJN*/
VOID pascal CopyAttr( PFOCAFONT pFont, PFATTRS pAttr );                 /*YOJN*/
#endif                                                                  /*YOJN*/

#ifndef S3

/**********************************************************************/
/* Function prototype needed because of forward reference             */
/**********************************************************************/
ULONG SwitchBank(ULONG, PULONG);

#define APERTURE_SAVED 0x01

#ifndef   _8514
extern XGAINSTANCE  InstanceData;
extern ADAPTERINFO  aiXGAAdapter;
#else
extern ADAPTER8514  ai8514Adapter;
#endif
extern FSRSEM       FSRDriverSem;

typedef struct
{
  USHORT control;
  USHORT index;
  ULONG  flags;
} SAVEDAPERTURE;

/* Globals */
APERTURE best_aperture = { 0, 0, 0 };
SAVEDAPERTURE saved_aperture = { 0, 0, 0 };

/**********************************************************************/
/* Defect 66836 - We must set the PEL order field of the Memery       */
/* Access Mode Register to Intel format for the multi-media folks.    */
/* The         display driver is setting this field to Motorola       */
/* format when blitting in a seamless window.                         */
/*                                                                    */
/* Save a local copy of the Memory Access Mode Register               */
/**********************************************************************/
USHORT usMAMR;

/**********************************************************************/
/*                                                                    */
/*   4 SMV (software motion video) DevEscapes added for DCR 96:       */
/*                                                                    */
/*   - GETAPERTURE returns the size and physical address of the       */
/*     largest available aperture.                                    */
/*                                                                    */
/*   - ACQUIREFB allows the caller exclusive access to the adapter    */
/*                                                                    */
/*   - DEACQUIREFB releases the adapter for use by other components   */
/*                                                                    */
/*   - SWITCHBANK allows the caller to select which bank of VRAM is   */
/*     mapped into the aperture (64K only).                           */
/*                                                                    */
/**********************************************************************/

/***EP  GetAperture() - Get the video aperture
 *
 *  This DevEsc will be called be an application in order to get
 *  the aperture information.
 *
 *  ENTRY
 *      PULONG pcOutCount -> Pointer to a ULONG that contains
 *                           the number of bytes being requested.
 *
 *      PAPERTURE pAperture -> Pointer to the APERTURE structure
 *                                shown below. We will fill this in.
 *
 *      typedef struct
 *      {
 *        ULONG ulPhysAddr;      // Physical address of the VRAM
 *        ULONG ulApertureSize;  // Aperture size in bytes
 *        ULONG ulScanLineSize;  // Scan line size in bytes
 *        RECTL rctlScreen;      // Screen dimensions
 *      } APERTURE;
 *
 *      typedef APERTURE *PAPERTURE;
 *
 *
 *  EXIT
 *      SUCCESS - Structure is updated
 *
 *  Defects 62446 and 68657 - On some 386 SX machines, the VE bit of POS
 *  register base+4 is ON indicating that the 4M aperture is enabled.
 *  The 4M aperture should never be ON on an SX system because these
 *  systems have a 16 bit data bus.  This is a HW error probably located
 *  in the POST code. This problem is also carried over to systems with
 *  an XGA/2 adapter when DMQS is used.  The DMQS information is also
 *  incorrect under this circumstance.
 *
 *  As a workaround we check the 1M aperture first.  If the 1M aperture
 *  is not enabled we must check the system interface bus size via
 *  the Auto-config register.
 *
 *  BTW: This problem was first noticed on a model 57 SX machine.
 *
 */

ULONG GetAperture(PULONG pcOutCount, PAPERTURE pAperture)
{

  USHORT usACR;                          /* Aperture control register */

  #ifndef   _8514
  if ( InstanceData.XGA_1M_aperture_phys ) {

    pAperture->ulPhysAddr =
    best_aperture.ulPhysAddr = InstanceData.XGA_1M_aperture_phys;

    pAperture->ulApertureSize
    = best_aperture.ulApertureSize = 1 * 1024 * 1024;
    goto FOUND_APERTURE;

  }

  if (InstanceData.XGA_4M_aperture_phys) {

    outp(aiXGAAdapter.usIORegBase + XGA_IO_INDEX, 4);
    usACR = (USHORT)inp(aiXGAAdapter.usIORegBase + XGA_IO_INDEX + 1);
    usACR &= 9;                       /* Remove unwanted bits */

    if(usACR == 1) {                  /* We have a 32 bit system interface */
       pAperture->ulPhysAddr =
       best_aperture.ulPhysAddr = InstanceData.XGA_4M_aperture_phys;

       pAperture->ulApertureSize
       = best_aperture.ulApertureSize = 4 * 1024 * 1024;
       goto FOUND_APERTURE;
    }

  }

  /* Check if the 64K aperture has been enabled */

  usACR = (USHORT)inp(aiXGAAdapter.usIORegBase + XGA_APERTURE_CONTROL);

  usACR &= (A0000_APERTURE+B0000_APERTURE);   /* Remove unwanted bits */

  if(usACR == A0000_APERTURE)
     pAperture->ulPhysAddr = best_aperture.ulPhysAddr = 0xa0000;

  else if (usACR == B0000_APERTURE)
     pAperture->ulPhysAddr = best_aperture.ulPhysAddr = 0xb0000;

  else if (!usACR) {                /* No aperture enabled */
     /***********************************************************/
     /* Defect 59723                                            */
     /* If no apertures are enabled then we will go ahead and   */
     /* enable the 64K aperture using the 0xB0000 address       */
     /***********************************************************/
     outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_CONTROL, B0000_APERTURE);
     pAperture->ulPhysAddr = best_aperture.ulPhysAddr = 0xb0000;
  }
  pAperture->ulApertureSize = best_aperture.ulApertureSize = 64 * 1024;

  #else
  #ifdef S3
  if ( ai8514Adapter.ONE_M_aperture_phys ) {

    pAperture->ulPhysAddr =
    best_aperture.ulPhysAddr = ai8514Adapter.ONE_M_aperture_phys;

    pAperture->ulApertureSize
    = best_aperture.ulApertureSize = 1 * 1024 * 1024;
    goto FOUND_APERTURE;

  }

  if ( ai8514Adapter.FOUR_M_aperture_phys ) {

    pAperture->ulPhysAddr =
    best_aperture.ulPhysAddr = ai8514Adapter.FOUR_M_aperture_phys;

    pAperture->ulApertureSize
    = best_aperture.ulApertureSize = 4 * 1024 * 1024;
    goto FOUND_APERTURE;

  }

  #else
  usACR = (USHORT)inp(ai8514Adapter.usIORegBase + XGA_APERTURE_CONTROL);

  usACR &= 3;                     /* Remove unwanted bits */

  if(usACR == 1)
     pAperture->ulPhysAddr = best_aperture.ulPhysAddr = 0xa0000;

  else if (usACR == 2)
     pAperture->ulPhysAddr = best_aperture.ulPhysAddr = 0xb0000;

  else {
     LogError(PMERR_INSUFFICIENT_MEMORY);
     return(DEVESC_ERROR);
  }

  pAperture->ulApertureSize = best_aperture.ulApertureSize = 64 * 1024;
  #endif
  #endif


FOUND_APERTURE:
  pAperture->ulScanLineSize = DDT.ScreenWidth;
  pAperture->rctlScreen.xLeft = 0;
  pAperture->rctlScreen.xRight = DDT.ScreenWidth-1;
  pAperture->rctlScreen.yBottom = DDT.ScreenHeight-1;
  pAperture->rctlScreen.yTop = 0;

  *pcOutCount = sizeof(APERTURE);

  return(DEV_OK);

} /* GetAperture */



/***EP  AcquireFB() - Acquire the frame buffer
 *
 *  This DevEsc will be called be an application in order to get
 *  exclusive access to the frame buffer.
 *
 *  ENTRY
 *      ULONG cInCount - Bytes count of caller data
 *
 *      PACQUIREFB pAcquireFB - Pointer to the ACQUIREFB structure.
 *                              This structure is shown below and defined
 *                              in PMDEV.H.
 *
 *  typedef struct
 *  {
 *    ULONG fAFBFlags;    // Action flags
 *    ULONG ulBankNumber; // Which bank # is being requested
 *                        //-----------------------------------------------
 *                        // This is needed so they don't have to switch
 *                        // banks before aquireing the frame buffer.
 *                        //-----------------------------------------------
 *    RECTL rctlXRegion;  // Cursor Xclude region.
 *  } ACQUIREFB;       // Aquire frame buffer
 *
 *  typedef ACQUIREFB *PACQUIREFB;
 *
 *  Where fAFBFlags bits are defined as;
 *
 *  Bit 0 - (AFB_SWITCH = 1)  // Switch bank before giving access
 *          OFF               // No bank switching.
 *
 *  EXIT
 *      SUCCESS
 *          return(DEV_OK) - App now has exclusive access to the frame buffer.
 *      FAILURE
 *          LogError(PMERR_INV_ESCAPE_DATA);
 *          return(DEVESC_ERROR);
 *
 */

ULONG AcquireFB(ULONG cInCount, PACQUIREFB pAcquireFB)
{
  register USHORT sem_result;

  IgnoreParam(cInCount);

  sem_result = RequestDriverSemaphore();

  if ( sem_result != NULL )
  {
    /**************************************************************/
    /* Failed to get the semaphore.                               */
    /**************************************************************/
    return(DEVESC_ERROR);
  }

  /****************************************************************/
  /* Take a copy of the existing aperture control and index       */
  /* registers so they can be restored in DeacquireFB.            */
  /****************************************************************/
  if ( !(saved_aperture.flags & APERTURE_SAVED))
  {
    #ifndef   _8514
    saved_aperture.control = (USHORT)inp(aiXGAAdapter.usIORegBase +
                                         XGA_APERTURE_CONTROL);
    saved_aperture.index =
         (USHORT)inp(aiXGAAdapter.usIORegBase + XGA_APERTURE_INDEX);
    #else
    saved_aperture.control = (USHORT)inp(ai8514Adapter.usIORegBase +
                                         XGA_APERTURE_CONTROL);
    saved_aperture.index =
         (USHORT)inp(ai8514Adapter.usIORegBase + XGA_APERTURE_INDEX);
    #endif
  }

  switch(best_aperture.ulApertureSize)
  {
        #ifdef   _8514
        // @DMS we are going to need to evaluate this !!!

        #else
        case 4 * 1024 * 1024:

        /************************************************************/
        /* 4M aperture: disable 1M and 64k apertures and write 0 to */
        /* the index register (this makes it unnecessary to call    */
        /* SwitchBank for a 4M aperture).                           */
        /************************************************************/

            outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_CONTROL,
                 NO_64K_APERTURE);
            outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_INDEX, 0);
            break;

        case 1 * 1024 * 1024:

        /************************************************************/
        /* 1M aperture: disable the 64K aperture and write 0 to the */
        /* index register (this makes it unnecessary to call        */
        /* SwitchBank for a 1M aperture).                           */
        /************************************************************/

            outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_CONTROL,
                 NO_64K_APERTURE);
            outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_INDEX, 0);
            break;

        case 64 * 1024:

        /************************************************************/
        /* 64K aperture: select the aperture at 0xb0000. The index  */
        /* register is set on a SwitchBank call, ie the selected    */
        /* bank is undefined after this call.                       */
        /************************************************************/

            outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_CONTROL,
                B0000_APERTURE);
            break;
        #endif

        default:

      /****************************************************************/
      /* Invalid: either something has gone       or GetAperture has  */
      /* not been called.                                             */
      /****************************************************************/

            LogError(PMERR_INV_ESCAPE_DATA);
            return(DEVESC_ERROR);
  }

  saved_aperture.flags |= APERTURE_SAVED;

  /* Defect 64434 - The SwitchBank needs to take place after the aperture
     information has been saved.
  */
  if(pAcquireFB->fAFBFlags & AFB_SWITCH) {
     if( SwitchBank(sizeof(ULONG), &pAcquireFB->ulBankNumber) == DEVESC_ERROR )
        return(DEVESC_ERROR);
  }

  /******************************************************************/
  /* If we are using a software cursor we will update the cursor    */
  /* exclude region. UpdateXcludeRegion will remove the cursor      */
  /* if it is currently in this region.                             */
  /******************************************************************/
  if ( cursor_data.cursor_status & CURSOR_SOFTWARE)
     UpdateXcludeRegion(pAcquireFB->rctlXRegion);

#ifndef _8514
  /******************************************************************/
  /* Defect 66836 - Save the original pel order format, and then    */
  /* reset the adapter into Intel pel order format if it was in     */
  /* Motorola format.                                               */
  /******************************************************************/
  usMAMR = (USHORT)inp(aiXGAAdapter.usIORegBase + XGA_MEMORY_ACCESS_MODE);

  if(usMAMR & PEL_ORDER_MOTOROLA)
     outp(aiXGAAdapter.usIORegBase + XGA_MEMORY_ACCESS_MODE,
          (usMAMR & ~PEL_ORDER_MOTOROLA));
#endif // _8514

  return(DEV_OK);

} /* AcquireFB */



/***EP  DeacquireFB() - Release the frame buffer
 *
 *  This DevEsc will be called by an application when it wants
 *  to release its access to the frame buffer.
 *
 *  ENTRY
 *      No input parms
 *
 *  EXIT
 *      SUCCESS
 *          return(DEV_OK)
 *      FAILURE
 *          LogError(PMERR_INV_ESCAPE_DATA);
 *          return(DEVESC_ERROR);
 *
 */

ULONG DeacquireFB(VOID)
{
  ULONG rc = DEV_OK;
  USHORT usage=FSRDriverSem.Usage;

  if (saved_aperture.flags & APERTURE_SAVED)
  {
      /****************************************************************/
      /* Restore the aperture control and index registers to their    */
      /* values before the AcquireFB.                                 */
      /****************************************************************/

        #ifndef _8514
        outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_CONTROL,
                                                saved_aperture.control);
        outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_INDEX,
                                                  saved_aperture.index);
        #else
        outp(ai8514Adapter.usIORegBase + XGA_APERTURE_CONTROL,
                                                saved_aperture.control);
        outp(ai8514Adapter.usIORegBase + XGA_APERTURE_INDEX,
                                                  saved_aperture.index);
        #endif

        ReleaseDriverSemaphore();


        /*********************************************************************/
        /* If A has grabbed the semaphore but B tries to clear it then we    */
        /* will end up here - the semaphore will not be cleared, but unless  */
        /* precautions are taken RESET_FB_ACQUIRED will be called, with the  */
        /* result that when A (legitimately) tries to clear the semaphore,   */
        /* the "if" statement at the top of this block won't let him - a     */
        /* complete deadlock with then ensue. Thus the usage count in        */
        /* FSRDriverSem is checked to see if it has changed.                 */
        /*********************************************************************/

        if (FSRDriverSem.Usage == usage)
            rc = DEVESC_ERROR;
        else
            saved_aperture.flags &= ~APERTURE_SAVED;

  }
  else

  /***************************************************************************/
  /* Invalid : either something has gone       or GetAperture has not been   */
  /*           called                                                        */
  /***************************************************************************/

  {
      LogError(PMERR_INV_ESCAPE_DATA);
      return(DEVESC_ERROR);
  }

  /******************************************************************/
  /* No more exclude region                                         */
  /******************************************************************/
  cursor_data.cursor_status &= ~CURSOR_XREGION;

#ifndef _8514
  /******************************************************************/
  /* Defect 66836 - Restore the original pel order format           */
  /******************************************************************/
  outp(aiXGAAdapter.usIORegBase + XGA_MEMORY_ACCESS_MODE, usMAMR );
#endif // _8514

  return(rc);

} /* DeacquireFB */



/***EP  SwitchBank() - Switch to a specific bank number.
 *
 *  This DevEsc will be called be an application when it wants to
 *  switch to a specific bank.
 *
 *  ENTRY
 *      ULONG cInCount - Bytes count of caller data
 *
 *      PULONG pInData - Pointer to a ULONG containing the bank number.
 *
 *  EXIT
 *      SUCCESS
 *          return(DEV_OK) - Bank has been switch successfully.
 *      FAILURE
 *          LogError(PMERR_INV_ESCAPE_DATA);
 *          return(DEVESC_ERROR);
 *
 */

ULONG SwitchBank(ULONG cInCount, PULONG pInData)
{
  #ifndef   _8514
  ULONG MaxBankNo = aiXGAAdapter.lMemorySize/0x10000ul;
  #else
  ULONG MaxBankNo = ai8514Adapter.lMemorySize/0x10000ul;
  #endif

  if (MaxBankNo==0) MaxBankNo=1;

  IgnoreParam(cInCount);
  /********************************************************************/
  /* Frame buffer must be acquired and bank number must be valid...   */
  /********************************************************************/
  if ( !(saved_aperture.flags & APERTURE_SAVED))
  {
    LogError(PMERR_INV_ESCAPE_DATA);
    return(DEVESC_ERROR);
  }

  /********************************************************************/
  /* Only the 64K aperture needs bank switching                       */
  /********************************************************************/
  if ( best_aperture.ulApertureSize == 64 * 1024 )
  {
    if ( *pInData > MaxBankNo)
    {
      LogError(PMERR_INV_ESCAPE_DATA);
      return(DEVESC_ERROR);
    }

    #ifndef   _8514
    outp(aiXGAAdapter.usIORegBase + XGA_APERTURE_INDEX,
         *(PUSHORT)pInData);
    #else
    outp(ai8514Adapter.usIORegBase + XGA_APERTURE_INDEX,
         *(PUSHORT)pInData);
    #endif

  }

  return(DEV_OK);

} /* SwitchBank */


/**********************************************************************/
/*                                                                    */
/*   Escape will (depending on the given Escape Code):                */
/*                                                                    */
/*   - route the call to an Escape Subfunction and return the result  */
/*     (and the altered parameters)                                   */
/*                                                                    */
/*   - return DEVESC_NOTIMPLEMENTED if the requested Escape           */
/*     Subfunction is not supported by the driver                     */
/*                                                                    */
/**********************************************************************/

DDIENTRY eddq_Escape (HDC       hdc,
                      ULONG     ArgEscape,
                      ULONG     ArgInCount,
                      PULONG    ArgInData,
                      PULONG    ArgOutCount,
                      PULONG    ArgOutData,
                      PDC       pdcArg,
                      ULONG     FunN)

{
    ULONG   retval;

    /******************************************************************/
    /* For DCR 96: add the SwitchBank function. This must be at ring  */
    /* 2 in order to do the in and out to the XGA indexed registers.  */
    /* If this is called at ring3 then making a call to pmwin for     */
    /* VisRegionNotify causes pmwin to trap. Avoid this by setting    */
    /* the DONT_CLEAN option on EnterDriver - this is OK as long as a */
    /* DevEscape is never added which does drawing using the clip     */
    /* region.                                */
    /******************************************************************/

    #define FLAGS EDF_STANDARD | EDF_DONT_CLEAN

    IgnoreParam(hdc);

    /******************************************************************/
    /* Select function according to ArgEscape.                        */
    /******************************************************************/
    switch (ArgEscape)
    {

    case DEVESC_QUERYESCSUPPORT:
        EnterDriver(pdcArg, FunN, FLAGS);
        retval = eddq_QueryEscSupport(ArgInData);
        ExitDriver(pdcArg, FunN,  FLAGS);
        break;

    case DEVESC_QUERYVIOCELLSIZES:
        EnterDriver(pdcArg, FunN, FLAGS);
        retval = eddq_QueryVIOCellSizes(ArgOutCount, ArgOutData);
        ExitDriver(pdcArg, FunN,  FLAGS);
        break;

    #ifdef S3
    #undef _8514
    #endif

    #ifndef _8514
    case DEVESC_GETAPERTURE:
        EnterDriver(pdcArg, FunN, FLAGS);
        retval = GetAperture(ArgOutCount, (PVOID)ArgOutData);
        ExitDriver(pdcArg, FunN,  FLAGS);
        break;

    case DEVESC_ACQUIREFB:
        retval = AcquireFB(ArgInCount, (PVOID)ArgInData);
        break;

    case DEVESC_DEACQUIREFB:
        retval = DeacquireFB();
        break;

    case DEVESC_SWITCHBANK:
        retval = SwitchBank(ArgInCount, ArgInData);
        break;
    #endif

    #ifdef S3
    #define _8514
    #endif

#ifdef DBCS                                                             /*YOJN*/
    case DEVESC_DBE_FONTMANAGEMENT:                                     /*YOJN*/
        if (CHECKENV(ENV_DBCS_CAPABLE))                                 /*YOJN*/
          {                            /* only when DBCS is supported *//*YOJN*/
            retval = eddq_DbcsFontManagement( ArgInCount,               /*YOJN*/
                                              (PFONTMGRPARM)ArgInData,  /*YOJN*/
                                              (PFATTRS)ArgOutData );    /*YOJN*/
          }                            /* end of if:                  *//*YOJN*/
        else                                                            /*YOJN*/
          {                                                             /*YOJN*/
            retval = DEVESC_NOTIMPLEMENTED;                             /*YOJN*/
          }                            /* end of else:                *//*YOJN*/
        break;                                                          /*YOJN*/
#endif                                                                  /*YOJN*/

    default:
        retval = DEVESC_NOTIMPLEMENTED;
        break;
    }

    return(retval);
}



/**********************************************************************/
/*                                                                    */
/*   QueryEscSupport returns a value indicating whether a particular  */
/* Escape Subfunction, referred to by InData, is supported or not by  */
/* the display driver.                                                */
/*                                                                    */
/*   OutCount and OutData are not set or used by QueryEscSupport.     */
/*                                                                    */
/**********************************************************************/
ULONG DRIVERCALL eddq_QueryEscSupport (PULONG ArgInData)
{
    /******************************************************************/
    /* The desired escape function is indicated by ArgInData.         */
    /******************************************************************/
    switch (*ArgInData)
    {

    case DEVESC_QUERYESCSUPPORT:
    case DEVESC_QUERYVIOCELLSIZES:
    #ifndef _8514
    case DEVESC_GETAPERTURE:
    case DEVESC_ACQUIREFB:
    case DEVESC_DEACQUIREFB:
    case DEVESC_SWITCHBANK:
    #else
    #ifdef   S3
    case DEVESC_GETAPERTURE:
    case DEVESC_ACQUIREFB:
    case DEVESC_DEACQUIREFB:
    case DEVESC_SWITCHBANK:
    #endif
    #endif
        return(DEV_OK);

#ifdef DBCS                                                             /*YOJN*//*YOJN*/
    case DEVESC_DBE_FONTMANAGEMENT:                                     /*YOJN*//*YOJN*/
        if (CHECKENV(ENV_DBCS_CAPABLE))/* if DBCS-enabled OS/2        *//*YOJN*/
          {                            /*                             *//*YOJN*/
            return DEV_OK;             /* then this is supported      *//*YOJN*/
          }                            /* end of if:                  *//*YOJN*/
        else                           /* or if SBCS OS/2             *//*YOJN*/
          {                            /*                             *//*YOJN*/
            return DEVESC_NOTIMPLEMENTED;                               /*YOJN*/
                                       /* this is not supported       *//*YOJN*/
          }                            /* end of else:                *//*YOJN*/
#endif                                                                  /*YOJN*//*YOJN*/

    default:
        return(DEVESC_NOTIMPLEMENTED);
    }
}

#endif // ~S3

/**********************************************************************/
/*                                                                    */
/*   QueryVIOCellSizes returns data describing the VIO cell sizes     */
/* supported by the driver for the display attached.  The data        */
/* returned depends on OutCount.                                      */
/*                                                                    */
/*   InCount and InData are not set or used by QueryVIOCellSizes.     */
/*                                                                    */
/**********************************************************************/

ULONG DRIVERCALL eddq_QueryVIOCellSizes (PULONG ArgOutCount,
                                         PULONG ArgOutData)
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    register ULONG   Count;           /* no of cell sizes returned    */
    register ULONG   i;               /* loop control variable        */

    /******************************************************************/
    /* The data returned depends on OutCount                          */
    /******************************************************************/
    if (*ArgOutCount < 4)
    {
        *ArgOutCount = 0;
    }
    else
    {
#ifdef DBCS                                                             /*YOJN*/
      if (CHECKENV(ENV_DBCS_CAPABLE))  /*                             *//*YOJN*/
        {                              /*                             *//*YOJN*/
          *ArgOutData++ = AVIOFonts;   /*                             *//*YOJN*/
        }                              /* end of if:                  *//*YOJN*/
      else                             /*                             *//*YOJN*/
        {                                                               /*YOJN*/
#endif /*DBCS*/                                                         /*YOJN*/
        *ArgOutData++ = MAX_AVIO_FONTS_LOADED;
#ifdef DBCS                                                             /*YOJN*/
        }                              /* end of else:                *//*YOJN*/
#endif /*DBCS*/                                                         /*YOJN*/

        if (*ArgOutCount < 8)
        {
            *ArgOutCount = 4;
        }
        else
        {
#ifndef DBCS                                                            /*YOJN*/
            Count = min( MAX_AVIO_FONTS_LOADED,
                         ((*ArgOutCount - 8) / 8) );
#else /*DBCS*/                                                          /*YOJN*/
            Count = min( *(ArgOutData-1),                               /*YOJN*/
                         ((*ArgOutCount - 8) / 8) );                    /*YOJN*/
#endif /*DBCS*/                                                         /*YOJN*/
            *ArgOutData++ = Count;
            *ArgOutCount  = 8 + 8 * Count;

#ifdef DBCS                                                             /*YOJN*/
         if (CHECKENV(ENV_DBCS_CAPABLE))                                /*YOJN*/
           {                           /*                             *//*YOJN*/
             i = 0;                                                     /*YOJN*/
           }                           /* end of if:                  *//*YOJN*/
         else                          /*                             *//*YOJN*/
           {                                                            /*YOJN*/
#endif /*DBCS*/                                                         /*YOJN*/
            if ( DDT.ScreenWidth < HI_RES_WIDTH )
            {
              i = 0;
            }
            else
            {
              i = NO_OF_AVIO_FONTS - MAX_AVIO_FONTS_LOADED;
              Count = MAX_AVIO_FONTS_LOADED + i;
            }
#ifdef DBCS                                                             /*YOJN*/
           }                           /* end of else:                *//*YOJN*/
#endif /*DBCS*/                                                         /*YOJN*/
            for ( ; i < Count; i++)
            {
                *ArgOutData++ = AvioBaseFont[i].CellWidth;
                *ArgOutData++ = AvioBaseFont[i].CellHeight;
            }
        }
    }

    return( DEV_OK );
}

#ifdef DBCS                                                             /*YOJN*/
/*===================== Private  Routine =============================*//*YOJN*/
/*      eddq_DbcsFontManagement                                       *//*YOJN*/
/*                                                                    *//*YOJN*/
/* GreEscape subfunction handler for DEVESC_DBE_FONTMANAGEMENT        *//*YOJN*/
/* Following sub-subfunctions are supported:                          *//*YOJN*/
/*              LOAD_FD_PRIVATE   : load DBCS font driver as private  *//*YOJN*/
/*              UNLOAD_FD_PRIVATE : unload private DBCS font driver   *//*YOJN*/
/*              LOAD_FD_PUBLIC    : load DBCS font driver as public   *//*YOJN*/
/*              UNLOAD_FD_PUBLIC  : unload public DBCS font driver    *//*YOJN*/
/*              QUERY_VIO_FONT_ATTRIBUTE :                            *//*YOJN*/
/*                                  returns FATTR struct for an AVIO  *//*YOJN*/
/*                                  font having supplied cell size    *//*YOJN*/
/*                                  (See DCR 189 @ JP20)              *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Entry       :        Parameters supplied to GreEscape entry are    *//*YOJN*/
/*                      passed as is.                                 *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Returns     :                                                      *//*YOJN*/
/*            - Returns DEV_OK                                        *//*YOJN*/
/*            - if QUERY_VIO_FONT_ATTRIBUTE is specified, attribute   *//*YOJN*/
/*              of font is returned where specified by caller.        *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Error Returns :      Returns DEVESC_ERROR if error                 *//*YOJN*/
/*                      Returns DEVESC_NOTIMPLEMENTED if unknown      *//*YOJN*/
/*                              function is requested                 *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Note        :                                                      *//*YOJN*/
/*            - To return font attribute, note that out-count parm    *//*YOJN*/
/*              is not used at all.  (And therefore not passed to     *//*YOJN*/
/*              this func.)  This behavior is just as defined in      *//*YOJN*/
/*              DCR 189.                                              *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Calls       :                                                      *//*YOJN*/
/*                                                                    *//*YOJN*/
/*====================================================================*//*YOJN*/
ULONG pascal near eddq_DbcsFontManagement( ULONG ulInCount,             /*YOJN*/
                                           PFONTMGRPARM pInData,        /*YOJN*/
                                           PFATTRS pOutData )           /*YOJN*/
{                                      /* top of func: eddj_DbcsFontMa*//*YOJN*/
#define TFUNC "eddq_DbcsFontManagement"                                 /*YOJN*/


  if (ulInCount < sizeof( FONTMGRPARM ))                                /*YOJN*/
    {                                  /* if too little input parm    *//*YOJN*/
      LOGERR( TFUNC, "Invalid parm block size", FNULL, 0,               /*YOJN*/
              PMERR_INV_LENGTH_OR_COUNT );                              /*YOJN*/
      return DEVESC_ERROR;             /*                             *//*YOJN*/
    }                                  /* end of if:                  *//*YOJN*/
                                                                        /*YOJN*/
  switch (pInData->fdi.fdi_lFunctionID)/* common field for 2 members  *//*YOJN*/
    {                                  /*   of this union             *//*YOJN*/
    /*----------------------------------------------------------------*//*YOJN*/
    /* Font Driver Loading/Unloading                                  *//*YOJN*/
    /*----------------------------------------------------------------*//*YOJN*/
    case LOAD_FD_PRIVATE:                                               /*YOJN*/
    case UNLOAD_FD_PRIVATE:                                             /*YOJN*/
    case LOAD_FD_PUBLIC:                                                /*YOJN*/
    case UNLOAD_FD_PUBLIC:             /*                             *//*YOJN*/
      if (eddj_LoadFontDriver(LOUSHORT(pInData->fdi.fdi_lFunctionID),   /*YOJN*/
                              pInData->fdi.fdi_pFontInfo))              /*YOJN*/
        {                              /* if loading completes        *//*YOJN*/
          return DEV_OK;               /*                             *//*YOJN*/
        }                              /* end of if:                  *//*YOJN*/
      else                             /*                             *//*YOJN*/
        {                              /*                             *//*YOJN*/
          LOGERR( TFUNC, "Font Driver Loading failure", FNULL, 0,       /*YOJN*/
                  PMERR_INV_ESCAPE_DATA );                              /*YOJN*/
          return DEVESC_ERROR;         /*                             *//*YOJN*/
        }                              /* end of else:                *//*YOJN*/
      break;                           /* end of case:                *//*YOJN*/
                                                                        /*YOJN*/
    /*----------------------------------------------------------------*//*YOJN*/
    /* Query VIO Font Attribute                                       *//*YOJN*/
    /*----------------------------------------------------------------*//*YOJN*/
    case QUERY_VIO_FONTATTRIBUTE:      /*                             *//*YOJN*/
      return QueryVioFontAttrib( &pInData->vioa, pOutData );            /*YOJN*/
      break;                           /* end of case:                *//*YOJN*/
                                                                        /*YOJN*/
    /*----------------------------------------------------------------*//*YOJN*/
    /* unknown function ID                                            *//*YOJN*/
    /*----------------------------------------------------------------*//*YOJN*/
    default:                                                            /*YOJN*/
      LOGERR( TFUNC, "Unknown function ID", FNULL, 0,                   /*YOJN*/
              PMERR_INV_ESCAPE_DATA );                                  /*YOJN*/
      return DEVESC_ERROR;         /*                             */    /*YOJN*/
      break;                           /* end of default:             *//*YOJN*/
    }                                  /* end of switch:              *//*YOJN*/
}                                      /* end of func: eddj_DbcsFontMa*//*YOJN*/
#undef TFUNC                                                            /*YOJN*/
                                                                        /*YOJN*/
/*===================== Private  Routine =============================*//*YOJN*/
/*      QueryVioFontAttrib                                            *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Query font attributes for given AVIO font                          *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Entry      :                                                       *//*YOJN*/
/*            - ptr to VIOFONTATTRIBUTE (input)                       *//*YOJN*/
/*            - ptr to FATTR struct (output)                          *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Returns    :         Returns DEV_OK       if completes             *//*YOJN*/
/*                              DEVESC_ERROR if some error is found   *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Error Returns :      None                                          *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Note       :                                                       *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Calls      :                                                       *//*YOJN*/
/*                                                                    *//*YOJN*/
/*====================================================================*//*YOJN*/
ULONG QueryVioFontAttrib( PVIOFONTATTRIBUTE pvfattr, PFATTRS pfattr )   /*YOJN*/
{                                      /* top of func: QueryVioFontAtt*//*YOJN*/
#define TFUNC "QueryVioFontAttrib"                                      /*YOJN*/
                                                                        /*YOJN*/
  LONG index, index2;                  /*                             *//*YOJN*/
  USHORT usPoint;                      /*                             *//*YOJN*/
                                                                        /*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  /* see if we have that font                                         *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  for (index = 0; index < AVIOFonts; index ++)                          /*YOJN*/
    {                                  /*                             *//*YOJN*/
      if (((ULONG)AvioBaseFont[index].CellWidth                         /*YOJN*/
                    == pvfattr->vioa_cx)                                /*YOJN*/
       && ((ULONG)AvioBaseFont[index].CellHeight                        /*YOJN*/
                    == pvfattr->vioa_cy))                               /*YOJN*/
        {                              /* if width/height is same     *//*YOJN*/
          break;                       /* target found                *//*YOJN*/
        }                              /* end of if:                  *//*YOJN*/
    }                                  /* end of for:                 *//*YOJN*/
                                                                        /*YOJN*/
  if (index == AVIOFonts)              /* if not found                *//*YOJN*/
    {                                  /*                             *//*YOJN*/
      LOGERR( TFUNC, "Unknown cell size", FNULL, 0,                     /*YOJN*/
              PMERR_INV_ESCAPE_DATA );                                  /*YOJN*/
                                       /* specified cell size cannot  *//*YOJN*/
                                       /* be found in our AVIO list   *//*YOJN*/
      return DEVESC_ERROR;             /*                             *//*YOJN*/
    }                                  /* end of if:                  *//*YOJN*/
                                                                        /*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  /* Some app. (for OS/2 J1.x) assume yInternalLeading of AVIO        *//*YOJN*/
  /*        fonts should be 0.  So we have to provide compatibility   *//*YOJN*/
  /*        option for them...                                        *//*YOJN*/
  /* We will do back-search (as VGA-DBCS does) with the criteria:     *//*YOJN*/
  /*        Nominal Point Size  : equal to the font we found          *//*YOJN*/
  /*        Cell Width          : equal or smaller                    *//*YOJN*/
  /*        yInternal Leading   : 0                                   *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  if (flDrvAdjustCellSize)             /* if compat. option required  *//*YOJN*/
    {                                  /*                             *//*YOJN*/
      usPoint = ((PFOCAFONT)AvioBaseFont[index].pResourceData)->        /*YOJN*/
                  fmMetrics.usNominalPointSize;                         /*YOJN*/
                                       /* point size of the font we   *//*YOJN*/
                                       /*   already found             *//*YOJN*/
      for (index2 = index; index2 >= 0; index2 --)                      /*YOJN*/
        {                              /* assumes already sorted by   *//*YOJN*/
                                       /* width/height                *//*YOJN*/
          if ( (((PFOCAFONT)AvioBaseFont[index2].pResourceData)->       /*YOJN*/
                  fmMetrics.yInternalLeading == 0) &&                   /*YOJN*/
               (((PFOCAFONT)AvioBaseFont[index2].pResourceData)->       /*YOJN*/
                  fmMetrics.usNominalPointSize == usPoint) )            /*YOJN*/
            {                          /* if meets to criteria        *//*YOJN*/
              break;                   /*                             *//*YOJN*/
            }                          /* end of if:                  *//*YOJN*/
        }                              /* end of for:                 *//*YOJN*/
                                                                        /*YOJN*/
      if (index2 >= 0)                 /* if some font was found      *//*YOJN*/
        {                              /*                             *//*YOJN*/
          index = index2;              /* use this one instead        *//*YOJN*/
        }                              /* end of if:                  *//*YOJN*/
    }                                  /* end of if:                  *//*YOJN*/
                                                                        /*YOJN*/
  CopyAttr( (PFOCAFONT)AvioBaseFont[index].pResourceData, pfattr );     /*YOJN*/
  return DEV_OK;                       /*                             *//*YOJN*/
}                                      /* end of func: QueryVioFontAtt*//*YOJN*/
#undef TFUNC                                                            /*YOJN*/
/*===================== Private  Routine =============================*//*YOJN*/
/*      CopyAttr                                                      *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Copy font attribute from metrics to FATTR struct                   *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Entry      :                                                       *//*YOJN*/
/*            - ptr to FOCAFONT struct (source)                       *//*YOJN*/
/*            - ptr to FATTR struct (destination)                     *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Returns    :         None                                          *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Error Returns :      None                                          *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Note       :                                                       *//*YOJN*/
/*                                                                    *//*YOJN*/
/* Calls      :                                                       *//*YOJN*/
/*                                                                    *//*YOJN*/
/*====================================================================*//*YOJN*/
VOID pascal CopyAttr( PFOCAFONT pFont, PFATTRS pAttr )                  /*YOJN*/
{                                      /* top of func: CopyAttr       *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  /* copy some attributes                                             *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  pAttr->fsSelection     = pFont->fmMetrics.fsSelectionFlags;           /*YOJN*/
  pAttr->idRegistry      = pFont->fmMetrics.usRegistryId;               /*YOJN*/
  pAttr->fsType          = pFont->fmMetrics.fsTypeFlags;                /*YOJN*/
  pAttr->lMaxBaselineExt = (LONG)(pFont->fmMetrics.yMaxBaselineExt);    /*YOJN*/
  pAttr->lAveCharWidth   = (LONG)(pFont->fmMetrics.xAveCharWidth);      /*YOJN*/
                                                                        /*YOJN*/
  memcpy( pAttr->szFacename, pFont->fmMetrics.szFacename, FACESIZE );   /*YOJN*/
                                       /* we use memcpy() rather than *//*YOJN*/
                                       /* string func here, since     *//*YOJN*/
                                       /* strncpy() isn't inline func *//*YOJN*/
                                       /* and strcpy() has risk of    *//*YOJN*/
                                       /* overrun.                    *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  /* codepage needs consideration                                     *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  if (pFont->fmMetrics.usCodePage == CP_UGL_FONT)                       /*YOJN*/
    {                                  /* if this is UGL font         *//*YOJN*/
      pAttr->usCodePage = 0;           /*   In attrib, 0 means UGL    *//*YOJN*/
    }                                  /* end of if:                  *//*YOJN*/
  else                                 /* if this is not UGL font     *//*YOJN*/
    {                                  /*                             *//*YOJN*/
      pAttr->usCodePage = pFont->fmMetrics.usCodePage;                  /*YOJN*/
                                       /* use the CP as is            *//*YOJN*/
    }                                  /* end of else:                *//*YOJN*/
                                                                        /*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  /* set other values                                                 *//*YOJN*/
  /*------------------------------------------------------------------*//*YOJN*/
  pAttr->usRecordLength  = sizeof( FATTRS );                            /*YOJN*/
  pAttr->lMatch          = eddj_QueryMatchNum( pFont );                 /*YOJN*/
                                       /* we assume this is DBCS FM   *//*YOJN*/
                                       /* font, since when system is  *//*YOJN*/
                                       /* DBCS capable, only FM fonts *//*YOJN*/
                                       /* can be used for AVIO.       *//*YOJN*/
  pAttr->fsFontUse       = 0;                                           /*YOJN*/
                                       /* 0 should be OK for these    *//*YOJN*/
                                       /* since VGA-DBCS does so.     *//*YOJN*/
}                                      /* end of func: CopyAttr       *//*YOJN*/
#endif                                                                  /*YOJN*/
