home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / VDH / VDHSUBS.C < prev    next >
C/C++ Source or Header  |  1995-04-14  |  61KB  |  1,814 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
  4. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  5. /*                                                                           */
  6. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  7. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  8. /*    drivers. You may use this code in accordance with the IBM License      */
  9. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  10. /*    Copyright statement may not be removed.                                */
  11. /*                                                                           */
  12. /*****************************************************************************/
  13. /*****************************************************************************
  14.  *
  15.  * SOURCE FILE NAME = VDHSUBS.c
  16.  *
  17.  * DESCRIPTIVE NAME = Base video device handlers - Private routines
  18.  *
  19.  *
  20.  * VERSION      V2.0
  21.  *
  22.  * DATE
  23.  *
  24.  * DESCRIPTION  Base video device handlers - Private routines
  25.  *
  26.  *              This source file contains routines which are not public.
  27.  *              They are called by various VDH routines to perform I/O
  28.  *              functions.
  29.  *
  30.  *              These routines execute as ring 2 conforming
  31.  *
  32.  * FUNCTIONS    PhysToUVirt, FreePhysToUVirt, BitNum
  33.  *              SaveRestorePVB, ExamineConfig, SaveRestoreHW,
  34.  *              getBIOSfonts
  35.  *
  36.  * NOTES        NONE
  37.  *
  38.  * STRUCTURES   NONE
  39.  *
  40.  * EXTERNAL REFERENCES  DosDevIOCtl, DosDevConfig
  41.  *                      AccessHardware, AccessRegister
  42.  *
  43.  * EXTERNAL FUNCTIONS
  44.  *
  45.  *              NONE
  46.  *
  47. */
  48.  
  49. /*
  50. **  Include files
  51. */
  52.  
  53. #define  INCL_BASE                     /* ALL of OS/2 Base                  */
  54. #define  INCL_DOSDEVICES               /* Device specific, ring 2 support   */
  55. #define  INCL_OS2STD                   /* Needed for NULL definition in     */
  56.                                        /* OS2STD.H                          */
  57. #include <os2.h>
  58. #include <memory.h>                    /*                               @T42*/
  59. #include "vdhctl.h"                    /* Conditional compilation control   */
  60. #include "vdh.h"                       /* Type definitions                  */
  61.  
  62. /*
  63. **  Externally defined global variables
  64. */
  65.  
  66. extern VIDEOMODE Modes[];              /* Supported modes                   */
  67. extern FONTBUFFER Fonts[];             /* Supported fonts                   */
  68. extern MEMORYMAPS MemoryMaps[];        /* Memory map info for each mode     */
  69. extern short HugeShift;                /* Huge shift value                  */
  70. extern USHORT ConfigFlag;
  71. extern ULONG PartialSaveSize;          /* Room required to save entire PVB
  72.                                           in the popup mode                 */
  73. extern UCHAR READABLE;                 /* Flag to determine if hardware is  */
  74.                                        /* write-only                        */
  75. extern USHORT VGA_PRESENT;             /* TRUE if VGA VDH has been          */
  76.                                        /* installed                         */
  77. extern VDHCONFIGINFO VGAConfigData;
  78. extern USHORT(APIENTRY *ChainedCallVectorTable[MaxFn])();/*             @T24*/
  79. extern VIDEOHARDWARE VideoHardware;    /* installed video hardware          */
  80. extern ENVIRONMENT Env1;               /* Popup environment address         */
  81.                                        /*                         @T42,@T42F*/
  82. extern ENVIRONMENT Env2;               /* Harderr environment address       */
  83.                                        /*                         @T42,@T42F*/
  84. extern USHORT OEMFlags;                /* @MS27 */
  85. USHORT PASCAL near GetBIOSfonts(void); /* get BIOS character font table     */
  86. extern CLUTDATA far SumCLUT;           /*                               @BB1*/
  87. extern CLUTDATA far *LCLUT;            /*                               @BB1*/
  88.  
  89. /*
  90. **  Parameters to ring 2 routines
  91. */
  92.  
  93.  
  94. #if      !(VDH8514A)                   /* @MS00 */
  95.  
  96. /*
  97. **  Internally defined global variables
  98. */
  99.  
  100. extern USHORT *hScreenDD;              /* Handle to screen device driver    */
  101.                                        /* @SM04398                          */
  102.  
  103. /*****************************************************************************
  104.  *
  105.  *  SUBROUTINE NAME: PhysToUVirt
  106.  *
  107.  *  DESCRIPTIVE NAME: Allocate an LDT sel:off to physical memory
  108.  *
  109.  *  FUNCTION: PhysToUVirt is called by routines who need access to
  110.  *            either the physical display buffer, or the ROM font.
  111.  *            This routine calls the screen device driver (SCREEN$)
  112.  *            via DosDevIOCtl who, in turn, issues a
  113.  *            DevHlp_PhysToUVirt call.
  114.  *
  115.  *  ENTRY POINT: PhysToUVirt
  116.  *    LINKAGE:   CALL FAR
  117.  *
  118.  *  INPUT: (Passed on stack)
  119.  *             FAR *PhysicalAddress ( Physical address )
  120.  *             FAR *LDTAddress      ( Place to return LDT sel:off )
  121.  *             USHORT Length        ( Size of physical memory area )
  122.  *
  123.  *  EXIT-NORMAL: AX = 0
  124.  *               LDT sel:off is returned to caller
  125.  *
  126.  *  EXIT-ERROR: AX = DosDevIOCtl error
  127.  *
  128.  *  EFFECTS: NONE
  129.  *
  130.  *  INTERNAL REFERENCES:
  131.  *    ROUTINES: NONE
  132.  *
  133.  *  EXTERNAL REFERENCES:
  134.  *    ROUTINES: DosDevIOCtl
  135.  *
  136.  ****************************************************************************/
  137.  
  138. USHORT near PhysToUVirt(PhysicalAddress,LDTAddress,Length)    /* @B15, @T30 */
  139.  
  140.   FarAddress PhysicalAddress;
  141.   FarAddress far *LDTAddress;          /*                               @T30*/
  142.   USHORT Length;
  143.  
  144. {
  145.   USHORT rc;                           /*                               @T30*/
  146.   USHORT rc2,ActionTaken;              /* @SM04339 */
  147.   FarAddress ParmBlock;                /*                               @T30*/
  148.   struct
  149.  
  150.   {
  151.     FarAddress PhysicalAddress;
  152.     short Length;
  153.   }
  154.  
  155.   ParmList;
  156.  
  157.   ParmList.PhysicalAddress.FullAddress = PhysicalAddress.FullAddress;
  158.   ParmList.Length = Length;
  159.  
  160.   if (!(rc = DosDevIOCtl((PVOID)&ParmBlock, (PVOID)&ParmList,
  161.              0x75, 0x3, *hScreenDD)))  /*                          @T30,@T52*/
  162.     *LDTAddress = ParmBlock;           /*                               @T30*/
  163.  
  164.  
  165. /*
  166. */
  167.  
  168.  
  169.   if (rc == ERROR_INVALID_HANDLE)
  170. {                                    /* reopen SCREEN$                    */
  171.     rc2 = DosOpen(SCREENDD_NAME,
  172.                   (PHFILE)hScreenDD,   /* @SM04339 */
  173.                   (PUSHORT)&ActionTaken,
  174.                   NO_SIZE,
  175.                   NO_ATTRIBUTES,
  176.                   OPEN_IF_EXISTS,      /* @SM04339 */
  177.                   NO_INHERIT+DENY_NONE+READ_WRITE,
  178.                   RESERVED_LONG);      /* @SM04339 */
  179.  
  180.     if (!rc2)
  181.     {
  182.  
  183.       if (!(rc = DosDevIOCtl((PVOID)&ParmBlock, (PVOID)&ParmList, /*@SM04339*/
  184.            0x75, 0x3, *hScreenDD)))    /* @SM04339 */
  185.  
  186.         *LDTAddress = ParmBlock;       /* @SM04339 */
  187.     }                                  /* endif                             */
  188.  
  189.   }                                    /* endif                             */
  190.   return (rc);
  191.  
  192. }
  193.  
  194. /*****************************************************************************
  195.  *
  196.  *  SUBROUTINE NAME: FreePhysToUVirt
  197.  *
  198.  *  DESCRIPTIVE NAME: Deallocate an LDT selector to physical memory
  199.  *
  200.  *  FUNCTION: FreePhysToUVirt is called by routines who are done
  201.  *            accessing the memory allocated by PhysToUVirt.  This is
  202.  *            done by calling the screen device driver (SCREEN$) via
  203.  *            DosDevIOCtl who, in turn, issues a DevHlp_PhysToUVirt.
  204.  *
  205.  *  ENTRY POINT: FreePhysToUVirt
  206.  *    LINKAGE:   CALL FAR
  207.  *
  208.  *  INPUT: (Passed on stack)
  209.  *             USHORT LDTSelector  ( LDT selector to be deallocated )
  210.  *
  211.  *  EXIT-NORMAL: LDT selector is deallocated
  212.  *
  213.  *  EFFECTS: NONE
  214.  *
  215.  *  INTERNAL REFERENCES:
  216.  *    ROUTINES: NONE
  217.  *
  218.  *  EXTERNAL REFERENCES:
  219.  *    ROUTINES: DosDevIOCtl
  220.  *
  221.  ****************************************************************************/
  222.  
  223. void near FreePhysToUVirt(LDTSelector) /*                               @B15*/
  224.  
  225.   USHORT LDTSelector;
  226.  
  227. {
  228.   DosDevIOCtl((PVOID)NULL,
  229.               (PVOID)&LDTSelector,
  230.               0x71,
  231.               0x3,
  232.               *hScreenDD);             /*                               @T52*/
  233. }
  234.  
  235. /*****************************************************************************
  236.  *
  237.  *  SUBROUTINE NAME: SaveRestorePVB
  238.  *
  239.  *  DESCRIPTIVE NAME: Save or restore display buffer and font
  240.  *
  241.  *  FUNCTION: SaveRestorePVB is called by SaveEnv and RestoreEnv
  242.  *            when either a partial or full display buffer save or
  243.  *            restore is requested.  If graphics mode, buffer is
  244.  *            saved/restored only if it is the 3xBox.
  245.  *
  246.  *  ENTRY POINT: SaveRestorePVB
  247.  *    LINKAGE:   CALL FAR
  248.  *
  249.  *  INPUT: (Passed on stack)
  250.  *             FAR *ParmBlock ( SaveEnv/RestoreEnv parameter block )
  251.  *             USHORT Direction ( Either SAVE or RESTORE mode )
  252.  *         (Referenced)
  253.  *             Modes[] (global data - table of supported video modes )
  254.  *             Fonts[] (global data - table of font areas )
  255.  *             MemoryMaps[] (global data - table of memory map info )
  256.  *
  257.  *  EXIT-NORMAL: AX = 0
  258.  *               Physical buffer and font area is saved or restored
  259.  *               if text mode or if 3xBox save/restore.
  260.  *
  261.  *  EXIT-ERROR: AX = ERROR_VIO_MODE
  262.  *
  263.  *  EFFECTS: NONE
  264.  *
  265.  *  INTERNAL REFERENCES:
  266.  *    ROUTINES: PhysToUVirt, FreePhysToUVirt
  267.  *              BitNum
  268.  *
  269.  *  EXTERNAL REFERENCES:
  270.  *    ROUTINES: Transfer
  271.  *              SetMapMask
  272.  *
  273.  ****************************************************************************/
  274.  
  275. USHORT PASCAL near SaveRestorePVB(ParmBlock,Direction,SeqMapMask,Environment)
  276.                                         /*                              @B15*/
  277.   VDH_SAVEREST far *ParmBlock;
  278.   USHORT Direction;
  279.   UCHAR far *SeqMapMask;
  280.   ENVIRONMENT far *Environment;
  281.  
  282. {
  283.  
  284.   USHORT rc,page,MapMask;              /*                               @T30*/
  285.   UCHAR BitPlanes;
  286.  
  287.   FarAddress Source,Destination,Temp;  /*                               @T30*/
  288.   REGDATA RegData;
  289.   REGADDRESS RegAddress;
  290.   USHORT BufSize;
  291.   UCHAR TwoBufs_OnePlane;              /*                               @C25*/
  292.   UCHAR Mode;
  293.   UCHAR TempMode;                      /*                                @@A*/
  294.   UCHAR MemMapMode;                    /*                               @T42*/
  295.   USHORT Save_EnvFlags;                /*                                   */
  296.   ENVIRONMENT far *TempEnv;            /*                                @@A*/
  297.   ENVIRONMENT far *PopupEnv;           /*                              @T42F*/
  298.   ENVIRONMENT far *HarderrEnv;         /*                              @T42F*/
  299.  
  300.   TwoBufs_OnePlane = MemMapMode = 0;   /*                          @T42,@C25*/
  301.  
  302. /*
  303. **  Always save/restore the physical display buffer, even graphics mode
  304. */
  305.  
  306.   Save_EnvFlags = Environment->EnvFlags;         /*                         */
  307.   Mode = TempMode = Environment->ModeIndex;/*                           @T42*/
  308.   MapMask = 1;                         /* Initialize to Map 0           @T42*/
  309.   BitPlanes = (UCHAR)MemoryMaps[Modes[Mode].MemMap].BitPlanes;/*        @T42*/
  310.   Destination.FullAddress = MakeFarPTR(ParmBlock->PVBHugeSEL, 0);/*     @T42*/
  311.  
  312.   if (ParmBlock->Flags&SAVEREST_PARTPVB)
  313.   {                                    /*                                @S4*/
  314.  
  315.   #if      VDHEGA        || VDHVGA     /* @MS00 */
  316.     BitPlanes = 0;                     /*                               @T42*/
  317.  
  318.     if (((MemMapMode = Modes[Mode].MemMap) >= MemMap_ModeD) && /*       @T42*/
  319.        (MemMapMode <= MemMap_Mode13))
  320.     {                                  /*                               @T42*/
  321.       BitPlanes = 1+2+4;               /*                               @T42*/
  322.     }                                  /*                               @T42*/
  323.  
  324.   #endif
  325.  
  326.     TempMode = VideoHardware.popupMode;  /*                             @T42*/
  327.     BufSize = MemoryMaps[Modes[TempMode].MemMap].PageLength;/*          @T42*/
  328.   }
  329.  
  330.   else
  331.   {                                    /*                                @S4*/
  332.  
  333.     if (Environment->ModeData.fbType&GRAPHICS)
  334.     {                                  /*                           @S4,@T51*/
  335.       BufSize = MemoryMaps[Modes[Mode].MemMap].PageLength;/*        @S4,@C25*/
  336.  
  337.       if (Modes[Mode].MemMap == MemMap_LoRes)/*                         @C25*/
  338.         TwoBufs_OnePlane = 2;          /*                               @C25*/
  339.     }
  340.  
  341.     else
  342.     {                                  /*                                @S4*/
  343.       BufSize = (USHORT)Environment->ModeData.BufferLength;/*            @S4*/
  344.     }                                  /*                                @S4*/
  345.   }                                    /*                                @S4*/
  346.  
  347. /*
  348. **  Set mode for popups using a temporary environment
  349. */
  350.  
  351.   TempEnv = Environment;               /*                                @@A*/
  352.   Source.FullAddress = MemoryMaps[Modes[Mode].MemMap].Start.FullAddress;
  353.  
  354.   if (Mode != TempMode)
  355.  
  356.   {                                    /*                                @@A*/
  357.     PopupEnv = (ENVIRONMENT far *)&Env1;/*                             @T42F*/
  358.     HarderrEnv = (ENVIRONMENT far *)&Env2;/*                           @T42F*/
  359.  
  360.     if (!PopupEnv->ModeDataOFF)
  361.     {                                  /* Popup Env not in use?         @T42*/
  362.  
  363.       if (Direction == RESTORE)
  364.       {                                /* Transparent restore?   @T43,@T42f */
  365.         TempEnv = PopupEnv;            /*                         @T42,@T42F*/
  366.         *TempEnv = *Environment;       /*                               @T43*/
  367.       }                                /*                               @T43*/
  368.  
  369.     }                                  /*                               @T42*/
  370.  
  371.     if (HarderrEnv->ModeDataOFF)
  372.     {                                  /* Use Harderr Env?        @T42,@T42F*/
  373.       TempEnv = HarderrEnv;            /*                              @T42F*/
  374.     }
  375.  
  376.     else
  377.     {                                  /*                               @T42*/
  378.       TempEnv = PopupEnv;              /*                          @@A,@T42F*/
  379.     }                                  /*                               @T42*/
  380.  
  381.     if (Direction == SAVE)
  382.     {                                  /*                               @T42*/
  383.       *TempEnv = *Environment;         /*                                @@A*/
  384.     }
  385.  
  386.     else
  387.     {                                  /*                               @T42*/
  388.       *Environment = *TempEnv;         /*                               @T42*/
  389.     }                                  /*                               @T42*/
  390.  
  391.   #if      VDHEGA        || VDHVGA     /* @MS00 */
  392.  
  393.     if ((BitPlanes)                    /*                               @T42*/
  394.  
  395.     #if      VDHVGA
  396.          || (Mode == ModeIndex_VGC2E)
  397.     #endif
  398.  
  399.        )
  400.  
  401.     {
  402.       BufSize = MemoryMaps[Modes[Mode].MemMap].PageLength;/*            @T42*/
  403.     }                                  /*                               @T42*/
  404.  
  405.   #endif
  406.   }                                    /*                                @@A*/
  407.  
  408. /*
  409. **  Save/restore all bit planes ( if mode has more than one )
  410. */
  411.  
  412.   if (!(rc = PhysToUVirt(Source, &Temp, BufSize)))
  413.   {                                    /*                               @T30*/
  414.     Source = Temp;                     /*                               @T30*/
  415.  
  416.     if ((Environment->ModeData.attrib == WorldAttrCount) && /*           @P1*/
  417.        !(Environment->ModeData.fbType&GRAPHICS))
  418.  
  419.     {                                  /*                                @P1*/
  420.       rc = LVB3PVBTransfer(Environment, ParmBlock, Direction);/*         @P1*/
  421.     }
  422.  
  423.     else
  424.     {                                  /*                                @P1*/
  425.  
  426.   #if      VDHEGA        || VDHVGA     /* @MS00 */
  427.  
  428.     #if      VDHVGA
  429.  
  430.       if (Mode == ModeIndex_VGC2E)
  431.  
  432.       { /* Unlock extended VGA graphics regs */
  433.         RegAddress.AddressPort = GraphAddressPort;
  434.         RegAddress.DataPort = GraphDataPort;
  435.         RegAddress.Flags = NONE;
  436.         RegData.DataArea = (UCHAR far *)&page;
  437.         RegData.FirstEntry = VGA_ENV_REG;
  438.         RegData.NumEntries = 1;
  439.         page = VGA_UNLOCK;
  440.         AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  441.         RegData.FirstEntry = 0x45;
  442.  
  443.         if (Mode == TempMode)
  444.         {
  445.           RegData.NumEntries = 2;
  446.  
  447.           for (page = 0x0800; page <= 0x7870; page += 0x1010)
  448.           {
  449.             AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  450.             Source.part.Offset = (page == 0x7870)?32*1024:0;
  451.  
  452.             do
  453.             {
  454.               Source.part.Offset -= 1024;
  455.               Transfer(&Source, &Destination, 640, Direction);
  456.             }
  457.  
  458.             while (Source.part.Offset);
  459.           }
  460.         }
  461.  
  462.         else
  463.         {
  464.  
  465.           for (page = 0x00; page <= 0x20; page += 0x20)
  466.           {
  467.             AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  468.             Transfer(&Source, &Destination, 8*1024, Direction);
  469.           }
  470.         }
  471.       }
  472.  
  473.       else
  474.     #endif
  475.  
  476. /*
  477. **  Address a bitplane (some modes use same memory for all bitplanes)
  478. */
  479.  
  480.            do
  481.         {
  482.  
  483.           if (BitPlanes)
  484.           {                            /* Modes D, E, F, 10, and 12         */
  485.  
  486.             while (!(BitPlanes&MapMask))
  487.             {                          /* Get next active bit               */
  488.               MapMask <<= 1;
  489.             }
  490.  
  491.             SetMapMask(Direction == RESTORE?WriteFunction:BitNum(MapMask),
  492.                MapMask);
  493.  
  494.             BitPlanes &= ~MapMask;     /* Reset the bit just processed      */
  495.  
  496.             if (Mode != TempMode)
  497.             {                          /*                               @T42*/
  498.               BufSize = 4000;          /*                               @T42*/
  499.  
  500.               if (MapMask == 4)
  501.               {                        /*                               @T42*/
  502.                 BufSize = 8192;        /*                               @T42*/
  503.  
  504.                 if (MemMapMode == MemMap_ModeD)
  505.                 {                      /*                               @T42*/
  506.                   BufSize = 8000;      /*                               @T42*/
  507.                 }                      /*                               @T42*/
  508.               }                        /*                               @T42*/
  509.             }                          /*                               @T42*/
  510.           }
  511.  
  512.           else
  513.  
  514.             if (TwoBufs_OnePlane)
  515.             {                          /*                               @C25*/
  516.               TwoBufs_OnePlane--;      /*                               @C25*/
  517.  
  518.               if (!TwoBufs_OnePlane)   /*                               @C25*/
  519.                 Source.FullAddress = MakeFarPTR(Source.part.Selector, 8192);/*
  520.                                                                         @C25*/
  521.  
  522.               else                     /*                               @C25*/
  523.                 BufSize = 8000;        /*                               @C25*/
  524.             }                          /*                               @C25*/
  525.  
  526.           Transfer(&Source, &Destination, BufSize, Direction);
  527.         }
  528.  
  529.         while (BitPlanes || TwoBufs_OnePlane);/*                        @C25*/
  530.  
  531. /*
  532. **  For graphics modes D, E, F, 10, and 12, that Sequencer Map Mask
  533. **  register was altered in order to save/restore each of the
  534. **  individually address-selected bit planes.  After each save/restore,
  535. **  the Map Mask address-selected bit planes.  On each restore, the
  536. **  Map Mask register is set to its original value.
  537. **
  538. **  Note:  This procedure is not necessary during a save because the
  539. **         hardware state is saved before the display buffer is saved.
  540. */
  541.  
  542.       if ((MapMask != 1)           /* Bit planes were selected individually */
  543.          && (Direction == RESTORE))
  544.       {
  545.         SaveRestoreHW(Environment, SET);/*                              @T47*/
  546.       }
  547.  
  548.   #else
  549.  
  550.       do
  551.       {                                /*                               @C25*/
  552.  
  553.         if (TwoBufs_OnePlane)
  554.         {                              /*                               @C25*/
  555.           TwoBufs_OnePlane--;          /*                               @C25*/
  556.  
  557.           if (!TwoBufs_OnePlane)       /*                               @C25*/
  558.             Source.FullAddress = MakeFarPTR(Source.part.Selector, 8192);/*
  559.                                                                         @C25*/
  560.  
  561.           else                         /*                               @C25*/
  562.             BufSize = 8000;            /*                               @C25*/
  563.         }                              /*                               @C25*/
  564.  
  565.         Transfer(&Source, &Destination, BufSize, Direction);/*          @C25*/
  566.       }
  567.  
  568.       while (TwoBufs_OnePlane);        /*                               @C25*/
  569.  
  570.   #endif
  571.     }                                  /*                                @P1*/
  572.  
  573.     FreePhysToUVirt(Temp.part.Selector);/*                              @T30*/
  574.   }
  575.  
  576.   #if      FONT_SUPPORT                /* @MS00 */
  577.  
  578. /*
  579. **  Save/Restore font buffer if in text mode
  580. */
  581.  
  582.   if (!rc && !(Modes[Mode].fbType&GRAPHICS) && /*                       @T53*/
  583.       (Direction == RESTORE))
  584.  
  585.   {                                    /*                               @T70*/
  586.     TempEnv->EnvFlags = Save_EnvFlags; /*                                   */
  587.     rc = SetHWFont(TempEnv, TempEnv->ActiveFontPTR, /*   @@A @T42,@T53      */
  588.                    (UCHAR far *)PHYSICAL_FONT_BUFFER);
  589.   }
  590.  
  591.   #endif
  592.  
  593. /*
  594. **  Restore mode after popup and deallocate the temporary environment
  595. */
  596.  
  597.   if (!rc && (Mode != TempMode))
  598.   {                                    /* @@A, @T42F                        */
  599.  
  600.     if (Direction == RESTORE)
  601.     {                                  /*                                @@A*/
  602.  
  603.       TempEnv->ModeDataOFF = 0;        /*                         @T42,@T42F*/
  604.     }                                  /*                                @@A*/
  605.   }                                    /*                                @@A*/
  606.   return (rc?ERROR_VIO_MODE:0);
  607. }
  608.  
  609. /***************************************************************************
  610.  *
  611.  * FUNCTION NAME =
  612.  *
  613.  * DESCRIPTION   = Return bit number which is set ( called by SaveRestorePVB )
  614.  *
  615.  * INPUT         = BitMask
  616.  * OUTPUT        = NONE
  617.  *
  618.  * RETURN-NORMAL = NONE
  619.  * RETURN-ERROR  = NONE
  620.  *
  621.  **************************************************************************/
  622.  
  623. USHORT PASCAL near BitNum(BitMask)     /*                               @B15*/
  624.  
  625. USHORT BitMask;
  626.  
  627. {
  628.   USHORT i;
  629.  
  630.  
  631.   for (i = 0; !(BitMask&1); i++)
  632.     BitMask >>= 1;
  633.  
  634.   return (i);
  635. }
  636.  
  637. /*****************************************************************************
  638.  *
  639.  *  SUBROUTINE NAME: SaveRestoreHW
  640.  *
  641.  *  DESCRIPTIVE NAME: Save or restore hardware state
  642.  *
  643.  *  FUNCTION: SaveRestoreHW is called to save or restore the hardware
  644.  *            state.
  645.  *
  646.  *  ENTRY POINT: SaveRestoreHW
  647.  *    LINKAGE:   CALL FAR
  648.  *
  649.  *  INPUT: (Passed on stack)
  650.  *             ENVIRONMENT far *Environment
  651.  *             USHORT Direction  ( GET(for SAVE) or SET(for RESTORE) )
  652.  *
  653.  *  EXIT-NORMAL: Hardware state is saved or restored to or from the
  654.  *               environment buffer.
  655.  *
  656.  *  EFFECTS: NONE
  657.  *
  658.  *  INTERNAL REFERENCES:
  659.  *    ROUTINES: NONE
  660.  *
  661.  *  EXTERNAL REFERENCES:
  662.  *    ROUTINES: AccessHardware, AccessRegister, AccessCLUT
  663.  *
  664.  ****************************************************************************/
  665.  
  666. void PASCAL near SaveRestoreHW(Environment,Direction)/*                 @B15*/
  667.  
  668. ENVIRONMENT far *Environment;
  669. USHORT Direction;
  670.  
  671. {
  672.  
  673.   REGDATA RegData;
  674.   REGADDRESS RegAddress;
  675.   USHORT ColorMode;
  676.   UCHAR One = 0x01;
  677.   USHORT VideoEnable;
  678.   UCHAR TempChar;
  679.   UCHAR TempMiscOut;                   /*                              @TB25*/
  680.   int SumCLUT_found,i,j;               /*                               @BB1*/
  681.  
  682.   #if      VDHVGA                      /* @MS00 */
  683.  
  684.   ColorMode = (Direction == SET) ? (USHORT)(Environment->ModeData.fbType
  685.      & NOT_MONO) : HardwareColor();       /* color/mono mode?                  */
  686.  
  687.   #else
  688.   ColorMode = (USHORT)(Environment->ModeData.fbType & NOT_MONO); /* SET only   */
  689.  
  690.   if (Direction == GET)
  691.     return ;
  692.  
  693.   #endif
  694.  
  695. /*
  696. **  Turn the video signal off to reduce snow
  697. */
  698.  
  699.   VideoEnable = 0;                     /* Turn video off                    */
  700.   AccessVideoEnable(ColorMode, SET, &VideoEnable);/* ring 2 callgate        */
  701.  
  702.   #if      VDHEGA        || VDHVGA     /* @MS00 */
  703.  
  704.     #if      VDHVGA                    /*                          @T56,@MS00*/
  705.  
  706. /*
  707. **  IF RESTORE, SET MISC OUTPUT REG TO 25 MHZ CLOCK
  708. */
  709.  
  710.   if (Direction == SET)
  711.   {
  712.     RegAddress.DataPort = MiscOutputRegWrite;
  713.     TempMiscOut = Environment->Hardware.MiscOutputReg;
  714.     Environment->Hardware.MiscOutputReg &= 0xF3;
  715.     AccessRegister(&RegAddress, Direction, &Environment->Hardware.
  716.                    MiscOutputReg);
  717.   }
  718.  
  719.     #endif
  720.  
  721. /*
  722. **  Save/Restore the sequencer registers
  723. */
  724.  
  725.   RegAddress.AddressPort = SeqAddressPort;
  726.   RegAddress.DataPort = SeqDataPort;
  727.   RegAddress.ColorAdjust = NONE;
  728.   RegAddress.Flags = Sequencers_CMD;
  729.   RegData.DataArea = &Environment->Hardware.Sequencers.All
  730.                                [RegData.FirstEntry = 0x00];
  731.   RegData.NumEntries = 0x04+1;         /* All registers                     */
  732.   AccessHardware(&RegAddress, BYTES, ColorMode, Direction, &RegData);
  733.  
  734.     #if      VDHEGA                    /*                          @T56,@MS00*/
  735.  
  736. /*
  737. **  Save/Restore the miscellaneous output register
  738. */
  739.  
  740.     RegAddress.DataPort = Direction == GET ? MiscOutputRegRead:
  741.     MiscOutputRegWrite;                /*                               @T56*/
  742.     AccessRegister(&RegAddress, Direction,             /*               @T56*/
  743.                    &Environment->Hardware.MiscOutputReg);
  744.     #endif
  745.   #endif
  746.  
  747.   #if      VDHCGA                      /* MS?? - BEGIN */
  748.  
  749.   if (OEMFlags&IDC_CGA)
  750.   {
  751.     RegAddress.DataPort = IDCExtendedModeReg;
  752.     AccessRegister(&RegAddress, GET, &TempChar);
  753.  
  754.     if (Direction == GET)
  755.     {
  756.                 /* Save just extended mode bit */
  757.       Environment->Hardware.IDCExtendedMode = TempChar & 0x01;
  758.     }
  759.  
  760.     else
  761.     {           /* Direction == SET               */
  762.                 /* Restore just extended mode bit */
  763.       TempChar &= ~0x01;
  764.       TempChar |= Environment->Hardware.IDCExtendedMode;
  765.       AccessRegister(&RegAddress, SET, &TempChar);
  766.     }
  767.   }
  768.   #endif
  769.  
  770.   #if      VDHMPA                      /* @MS00 */
  771.  
  772.   RegAddress.DataPort = CRTCtlPort1;
  773.   AccessRegister(&RegAddress, Direction, &One);
  774.  
  775.   #endif
  776.  
  777. /*
  778. **  Save/Restore the CRT registers
  779. */
  780.  
  781.   RegAddress.AddressPort = CRTAddressPort;
  782.   RegAddress.DataPort = CRTDataPort;
  783.   RegAddress.ColorAdjust = ColorAdjustment;
  784.   RegAddress.Flags = NONE;
  785.  
  786.   #if      VDHVGA                      /* @MS00 */
  787.  
  788.   if (Direction == SET)
  789.   {
  790.     RegData.DataArea = &Environment->Hardware.CRTCtlRegs.All
  791.                       [RegData.FirstEntry = 0x11];
  792.     RegData.DataArea[0] &= 0x0F;       /* Clear b4-b7 of vert retrace end   */
  793.     RegData.NumEntries = 1;            /* vert retrace end                  */
  794.     AccessHardware(&RegAddress, BYTES, ColorMode, SET, &RegData);
  795.   }
  796.  
  797.   #endif
  798.  
  799.   RegData.DataArea = &Environment->Hardware.CRTCtlRegs.All[RegData.FirstEntry
  800.      = 0x00];
  801.  
  802.   #if      VDHVGA                      /* @MS00 */
  803.  
  804.   if (Direction == SET)
  805.     RegData.DataArea[0x11] |= 0x80;    /* Set b4-b7 of vert retrace end     */
  806.   #endif
  807.  
  808.   #if      VDHMPA        || VDHCGA     /* @MS00 */
  809.   RegData.NumEntries = 0x10;           /* CGA and MPA only have 16
  810.                                           registers                    @TL10*/
  811.  
  812.   #else                                /*                              @TL10*/
  813.   RegData.NumEntries = 0x18+1;         /* All registers                     */
  814.  
  815.   #endif
  816.  
  817.   AccessHardware(&RegAddress, BYTES, ColorMode, Direction, &RegData);
  818.  
  819.   #if      VDHCGA                      /* @MS00 */
  820.  
  821.   RegAddress.DataPort = CGAModeCtlReg;
  822.   AccessRegister(&RegAddress, Direction,
  823.                  &Environment->Hardware.CGAModeControl );
  824.  
  825.   RegAddress.DataPort = CGAColorSelReg;
  826.   AccessRegister(&RegAddress, Direction,
  827.                  &Environment->Hardware.CGAColorSelect );
  828.   #endif
  829.  
  830.   #if      VDHMPA                      /* @MS00 */
  831.  
  832.   RegAddress.DataPort = CRTCtlPort1;
  833.   AccessRegister(&RegAddress, Direction,
  834.                  &Environment->Hardware.MPAModeControl );
  835.   #endif
  836.  
  837.   #if      VDHEGA        || VDHVGA     /* @MS00 */
  838.  
  839.     #if      VDHVGA                    /*                          @T56,@MS00*/
  840.  
  841. /*
  842. **  SAVE/RESTORE THE MISCELLANEOUS OUTPUT REGISTER
  843. */
  844.  
  845.     RegAddress.DataPort = Direction == GET ? MiscOutputRegRead:
  846.     MiscOutputRegWrite;
  847.  
  848.   if (Direction == SET)                /*                              @TB25*/
  849.     Environment->Hardware.MiscOutputReg = TempMiscOut;/*               @TB25*/
  850.  
  851.     AccessRegister(&RegAddress, Direction,
  852.                    &Environment->Hardware.MiscOutputReg) ;
  853.     #endif
  854.  
  855. /*
  856. **  Save/Restore the attribute registers
  857. */
  858.  
  859.   RegAddress.AddressPort = AttAddressPort;
  860.   RegAddress.DataPort = Direction == GET ? AttDataReadPort:
  861.   AttDataWritePort;
  862.   RegAddress.ColorAdjust = NONE;
  863.   RegAddress.Flags = Attributes_CMD;
  864.   RegData.DataArea = &Environment->Hardware.Attributes.All
  865.                      [RegData.FirstEntry = 0x00];
  866.  
  867.   RegData.NumEntries = NUM_ATT_REGS;   /* All registers                     */
  868.   AccessHardware(&RegAddress, BYTES, ColorMode, Direction, &RegData);
  869.  
  870.     #if      VDHEGA                    /* @MS00 */
  871.  
  872. /*
  873. **  Restore the graphics position registers
  874. */
  875.  
  876.   RegAddress.DataPort = Graphics1PosReg;
  877.   AccessRegister(&RegAddress, SET, &Environment->Hardware.Graphics1Position);
  878.   RegAddress.DataPort = Graphics2PosReg;
  879.   AccessRegister(&RegAddress, SET, &Environment->Hardware.Graphics2Position);
  880.  
  881.     #endif
  882.  
  883. /*
  884. **  Save/Restore the graphics registers
  885. */
  886.  
  887.   RegAddress.AddressPort = GraphAddressPort;
  888.   RegAddress.DataPort = GraphDataPort;
  889.   RegAddress.ColorAdjust = NONE;
  890.   RegAddress.Flags = NONE;
  891.   RegData.DataArea = &Environment->Hardware.GraphicsRegs
  892.                      [RegData.FirstEntry = 0x00];
  893.  
  894.   RegData.NumEntries = 0x08+1;         /* All registers                     */
  895.   AccessHardware(&RegAddress, BYTES, ColorMode, Direction, &RegData);
  896.  
  897.     #if      VDHVGA
  898.  
  899.   if (OEMFlags&STARDUST_VGA)
  900.  
  901.   { /* Unlock extended registers */
  902.     RegData.DataArea = &TempChar;
  903.     RegData.FirstEntry = VGA_ENV_REG;
  904.     RegData.NumEntries = 1;
  905.     TempChar = VGA_UNLOCK;
  906.     AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  907.  
  908.     /*
  909.     ** Save/restore STARDUST extended graphics registers.
  910.     */
  911.     RegData.DataArea = Environment->Hardware.ExtVGARegs;
  912.     RegData.FirstEntry = 0x40;
  913.     RegData.NumEntries = 0x07;
  914.     AccessHardware(&RegAddress, BYTES, ColorMode, Direction, &RegData);
  915.  
  916.     /*
  917.     ** Save/restore state of STARDUST DAC (6 bit or 8 bit
  918.     */
  919.     RegAddress.DataPort = DACCmdReg;
  920.     AccessRegister(&RegAddress, GET, &TempChar);
  921.  
  922.     if (Direction == GET)
  923.     {
  924.       /*
  925.       ** Save just the DAC state b
  926.       */
  927.       Environment->Hardware.DACCmd = TempChar & 0x02;
  928.     }
  929.  
  930.     else
  931.     { /* Direction == SET               */
  932.       /* Restore just the DAC state bit */
  933.       TempChar &= ~0x02;
  934.       TempChar |= Environment->Hardware.DACCmd;
  935.       AccessRegister(&RegAddress, SET, &TempChar);
  936.     }
  937.   }
  938.     #endif
  939.   #endif
  940.  
  941.   #if      VDHVGA                          /* @MS00 */
  942.  
  943. /*
  944. **  Save/Restore the color lookup table
  945. */
  946.  
  947.   RegData.DataArea = (UCHAR far *)&Environment->LookupTable
  948.                      [RegData.FirstEntry = 0x00];
  949.   RegData.NumEntries = 0xFF+1;         /* All registers                     */
  950.   AccessCLUT(Direction, (CLUTDATA far *far *)&RegData);/* ring 2 callgate   */
  951.  
  952. /*
  953. **  If the current CLUT is equivalent to SumCLUT set NO_CLR_BRST in fbtype
  954. */
  955.  
  956.   if ((Direction == SET)               /*                               @BB1*/
  957.      && ((Environment->ModeData.fbType&NOT_MONO) == NOT_MONO))
  958.   {                                    /*                               @BB1*/
  959.     register irow = 0;
  960.  
  961.  
  962.     while ((irow < 0xFF+1) && (Environment->LookupTable[irow].Red ==
  963.             Environment->LookupTable[irow].Green) &&
  964.            (Environment->LookupTable[irow].Red ==
  965.             Environment->LookupTable[irow].Blue))
  966.  
  967.       irow++;
  968.  
  969.     /*
  970.     ** If loop completed, assume black & whi
  971.     */
  972.  
  973.     if (irow == 0xFF+1)
  974.       Environment->ModeData.fbType |= NO_CLR_BRST;
  975.   }                                    /*                               @BB1*/
  976.  
  977.   if (Direction == SET)
  978.   {
  979.     SetTextGrays(Environment);
  980.   }
  981.  
  982. /*
  983. **  Turn the video signal back on if Env flag is set@C21
  984. */
  985.  
  986.   if (Environment->VideoEnable)
  987.   {                                    /*                               @C21*/
  988.     VideoEnable = 1;                   /* Turn video on                     */
  989.     AccessVideoEnable(ColorMode, SET, &VideoEnable);/* ring 2 callgate      */
  990.   }                                    /*                               @C21*/
  991.  
  992.   Environment->Hardware.Sequencers.Regs.ClockingMode &= 0xDF;
  993.  
  994. /*
  995. **  Interpret registers and update the mode data structure in the ENVB
  996. */
  997.  
  998.   #endif
  999. }
  1000.  
  1001. #endif
  1002.  
  1003. /*****************************************************************************
  1004.  *
  1005.  *  SUBROUTINE NAME: ExamineConfig
  1006.  *
  1007.  *  DESCRIPTIVE NAME: Examine display adapter configuration
  1008.  *
  1009.  *  FUNCTION: ExamineConfig is called by DevInit in order to verify
  1010.  *            the presence of the appropriate display adapter.
  1011.  *            In addition, info is obtained for late use by
  1012.  *            RetConfigInfo.  Starting addresses for ROM fonts are
  1013.  *            obtained.
  1014.  *
  1015.  *  ENTRY POINT: ExamineConfig
  1016.  *    LINKAGE:   CALL FAR
  1017.  *
  1018.  *  INPUT: (Passed on stack)
  1019.  *             NONE
  1020.  *         (Referenced)
  1021.  *             Modes[] (global data - table of supported video modes )
  1022.  *             Fonts[] (global data - table of font areas )
  1023.  *
  1024.  *  EXIT-NORMAL: AX = 0
  1025.  *
  1026.  *  EXIT-ERROR: AX = ERROR_VIO_BAD_ADAPTER or
  1027.  *                   DosDevConfig error
  1028.  *
  1029.  *  EFFECTS: NONE
  1030.  *
  1031.  *  INTERNAL REFERENCES:
  1032.  *    ROUTINES: PhysToUVirt, FreePhysToUVirt
  1033.  *
  1034.  *  EXTERNAL REFERENCES:
  1035.  *    ROUTINES: DosDevConfig, CharFontBegin, CharFontEnd
  1036.  *
  1037.  ****************************************************************************/
  1038.  
  1039. short PASCAL near ExamineConfig()      /*                               @B15*/
  1040.  
  1041. {
  1042.   USHORT ROMFontSEL,ROMFontLEN,ROMSrchLEN,rc,i;/*                        @S9*/
  1043.   EGABIOSINFO EGAInfo;                 /* EGA information from 40:86, 40:87 */
  1044.   FarAddress PhysAddress,PVB;
  1045.  
  1046. #if      VDH8514A                      /* @MS00 */
  1047.  
  1048.   union
  1049.   {
  1050.  
  1051.     USHORT Flags;
  1052.  
  1053.     struct
  1054.     {
  1055.       UCHAR Display;
  1056.       UCHAR Memory;
  1057.     }
  1058.     part;
  1059.   }
  1060.  
  1061.   A8514;
  1062.   VDH_CONFIG VGAParmBlock;
  1063.  
  1064. #endif
  1065.  
  1066. #if      VDHVGA                        /* Read/write hardware               */
  1067.                                         /* @MS00 */
  1068.   READABLE = TRUE;
  1069.  
  1070. #else
  1071.   READABLE = FALSE;
  1072. #endif
  1073.   rc = INIT_ERROR;                     /* Initially, assume error           */
  1074.  
  1075.   /*
  1076.   ** getvideoType fails only if something is seriously
  1077.   **       with the video system
  1078.   */
  1079.  
  1080.   if (getVideoType() != VDHERROR_NO_ADAPTER)
  1081.   {
  1082.  
  1083. /*
  1084. **  Display types:
  1085. **                 0 - 5151 mono             5 - IBM Japan 5550 mono
  1086. **                 1 - 5153 color            6 - IBM Japan 5550 color
  1087. **                 2 - 5154 enhanced         7 - IBM Japan 5570 color
  1088. **                 3 - 8503 mono             8 - IBM Japan 5570 full page
  1089. **                 4 - 8512/8513 color       9 - 8514 color
  1090. **                                          10 - PDP (Plasma Display Panel)
  1091. **                                          11 - 8507_8604 mono
  1092. **                                          12 - 8515 color
  1093. */
  1094.  
  1095. #if      VDHVGA                        /* @MS00 */
  1096.  
  1097.     if (VideoHardware.fVideoType & VGA_BITS)
  1098.     {
  1099.       rc = NO_ERROR;                   /* at this point the installation    */
  1100.                                        /* will work                         */
  1101.  
  1102. /*
  1103. **  If the VGA doesn't have a display attatched to it, the VDH should fail
  1104. **  to install UNLESS an 8514/A is present and has a display.
  1105. */
  1106.  
  1107.       if (VideoHardware.display == NoDisplay && !(VideoHardware.fVideoType
  1108.          &A8514_BITS))
  1109.  
  1110.         rc = INIT_ERROR;
  1111.     }
  1112.  
  1113. #endif
  1114.  
  1115. #if      VDHEGA                        /* @MS00 */
  1116.  
  1117.     if (VideoHardware.fVideoType&EGA_BITS)
  1118.       rc = NO_ERROR;                   /* allow installation to continue    */
  1119. #endif
  1120.  
  1121. #if      VDHCGA                        /* @MS00 */
  1122.  
  1123. /*
  1124. ** If this VDH can install on the current hardware set up information
  1125. */
  1126.  
  1127.     if (VideoHardware.fVideoType&CGA_BIT)
  1128.       rc = NO_ERROR;                   /* allow installation                */
  1129.  
  1130. #endif
  1131.  
  1132. #if      VDHMPA                        /* @MS00 */
  1133.  
  1134. /*
  1135. ** if this VDH can install on the current hardware set up information
  1136. */
  1137.  
  1138.     if (VideoHardware.fVideoType&MPA_BIT)
  1139.       rc = NO_ERROR;                   /* allow installation                */
  1140.  
  1141. #endif
  1142.  
  1143. #if      VDH8514A                      /* @MS00 */
  1144.  
  1145. /*
  1146. ** if 8514 present record its configuration
  1147. */
  1148.  
  1149.     if (VideoHardware.fVideoType&A8514_BITS)
  1150.     {
  1151.       rc = NO_ERROR;                   /* allow installation                */
  1152.  
  1153. /*
  1154. **  The presence of the VGA VDH is determined by a successful call to
  1155. **  RetConfigInfo in the call vector table
  1156. */
  1157.  
  1158.       VGAParmBlock.Length = sizeof(VDH_CONFIG);
  1159.       VGAParmBlock.Flags = NONE;
  1160.       VGAParmBlock.ConfigDataPTR = (VDHCONFIGINFO far *)&VGAConfigData;
  1161.       VGAConfigData.cb = MinDLen_Config_PartSaveSz;/* Only need display     */
  1162.                                               /* type and partial save size */
  1163.       VGA_PRESENT = !ChainedVDHRetConfigInfo((ENVIRONMENT far *)NULL,
  1164.          (VDH_INITENV far *)&VGAParmBlock, FnReturnConfigInfo);
  1165.     }
  1166.  
  1167. #endif
  1168.  
  1169.     if (!rc)
  1170.     {                                  /* Error Check #3                    */
  1171.  
  1172. #if      ROMFONT_SUPPORT               /* @MS00 */
  1173.  
  1174. /*
  1175. ** The OS/2 loader calls the BIOS interrupt 10h function 1130h to build
  1176. ** a table of 32 bit values each of which points a corresponding font
  1177. ** address supported by the current video cards.  This is not done on
  1178. ** MPA or CGA systems.
  1179. **
  1180. ** If BIOS interrupt 10 function 1130h is not supported the video ROM
  1181. ** will be scanned to see if the font address can be found.  The scan-
  1182. ** ning looks for various character bit maps and their relative
  1183. ** position to do this.
  1184. **
  1185. ** The MPA and CGA do not support this interrupt so these cards will
  1186. ** always use the pattern search.
  1187. **
  1188. ** The function GetBIOSfonts fetches the table built by the loader and
  1189. ** copies its contents to the Fonts[] data a structure, if the table
  1190. ** is not available NOBIOSFONTS is returned and the pattern search
  1191. ** code is used.
  1192. */
  1193.  
  1194.   #if      VDHEGA        || VDHVGA     /*                          @T36,@MS00*/
  1195.  
  1196.       if (GetBIOSfonts() == NOBIOSFONTS)
  1197.       {                                /*                               @T36*/
  1198.  
  1199.       /*
  1200.       ** BIOS fonts were not returned by BIOS int 10 function 1130h
  1201.       ** so font pattern search must be used.
  1202.       */
  1203.  
  1204. /*
  1205. **  Search through ROM to find 8x8, 8x14, 8x16, 9x14, and 9x16 fonts
  1206. **  ROM fonts are located at physical addresses:
  1207. **            F0000 - CGA and MPA
  1208. **            C0000 - EGA and PS/2 Adapter
  1209. **            E0000 - VGA
  1210. */
  1211.  
  1212.         for (ROMFontSEL = 0x0E, ROMFontLEN = 0xFFFF, ROMSrchLEN = 0xFFF0; /*
  1213.                                                                     @S9,@S12*/
  1214.            ROMFontSEL >= 0x0C;         /*                               @S12*/
  1215.            ROMFontSEL -= 2, ROMFontLEN -= 0x8000, ROMSrchLEN = 0x7FF0)
  1216.  
  1217.         {                              /*                            @S5,@S9*/
  1218.           PVB.FullAddress = MakeFarPTR(ROMFontSEL, 0);
  1219.           PhysToUVirt(PVB, &PVB, ROMFontLEN);/*                         @T30*/
  1220.  
  1221. /*
  1222. **  Locate 8x8 ROM font on CGA, EGA, VGA, and PS/2 adapter
  1223. */
  1224.  
  1225.           for (i = 0; i < ROMSrchLEN; i++)
  1226.           {                            /*                                @S9*/
  1227.  
  1228.             while ((i < ROMSrchLEN) && (PVB.FullAddress[i] != (UCHAR)0x7E))
  1229.               i++;                     /*                                @S9*/
  1230.  
  1231.             if (i < ROMSrchLEN)
  1232.             {                          /*                                @S9*/
  1233.  
  1234.               if ((PVB.FullAddress[i+1] == (UCHAR)0x81) &&
  1235.                   (PVB.FullAddress[i+2] == (UCHAR)0xA5) &&
  1236.                   (PVB.FullAddress[i+3] == (UCHAR)0x81))
  1237.               {
  1238.  
  1239.                 if (!Fonts[FONT_8x8].PVB.part.Selector &&
  1240.                     PVB.FullAddress[i+4] == (UCHAR)0xBD)
  1241.  
  1242.                 {
  1243.                   Fonts[FONT_8x8].PVB.part.Selector = ROMFontSEL;
  1244.                   Fonts[FONT_8x8].PVB.part.Offset = i-8;
  1245.                 }
  1246.  
  1247. /*
  1248. **  Locate 8x14 ROM font on EGA, VGA, and PS/2 adapter only
  1249. */
  1250.  
  1251.                 if ((PVB.FullAddress[i+4] == (UCHAR)0x81) &&
  1252.                     (PVB.FullAddress[i+5] == (UCHAR)0xBD) &&
  1253.                     (PVB.FullAddress[i+6] == (UCHAR)0x99) &&
  1254.                     (PVB.FullAddress[i+7] == (UCHAR)0x81))
  1255.                 {
  1256.  
  1257.                   if (!Fonts[FONT_8x14].PVB.part.Selector &&
  1258.                       PVB.FullAddress[i+8] != (UCHAR)0x81)
  1259.                   {
  1260.                     Fonts[FONT_8x14].PVB.part.Selector = ROMFontSEL;
  1261.                     Fonts[FONT_8x14].PVB.part.Offset = i-16;
  1262.                   }
  1263.  
  1264.     #if      VDHVGA                    /* @MS00 */
  1265.  
  1266.  
  1267. /*
  1268. **  Locate 8x16 ROM font on VGA, and PS/2 adapter only
  1269. */
  1270.  
  1271.                   if (!Fonts[FONT_8x16].PVB.part.Selector &&
  1272.                       PVB.FullAddress[i+8] == (UCHAR)0x81)
  1273.                   {
  1274.                     Fonts[FONT_8x16].PVB.part.Selector = ROMFontSEL;
  1275.                     Fonts[FONT_8x16].PVB.part.Offset = i-18;
  1276.                   }
  1277.     #endif
  1278.                 }
  1279.               }
  1280.             }
  1281.           }                            /* Locate 8x8, 8x14, 8x16            */
  1282.  
  1283. /*
  1284. **  Locate 9x14 ROM font on EGA, VGA, and PS/2 adapter only
  1285. */
  1286.  
  1287.           for (i = 0; i < ROMSrchLEN; i++)
  1288.           {                            /*                                @S9*/
  1289.  
  1290.             while ((i < ROMSrchLEN) && (PVB.FullAddress[i] != (UCHAR)0x1D))
  1291.                   i++;                     /*                            @S9*/
  1292.  
  1293.             if (i < ROMSrchLEN)
  1294.             {                          /*                                @S9*/
  1295.  
  1296.               if ((PVB.FullAddress[i+1] == (UCHAR)0x00) &&
  1297.                   (PVB.FullAddress[i+2] == (UCHAR)0x00) &&
  1298.                   (PVB.FullAddress[i+3] == (UCHAR)0x00) &&
  1299.                   (PVB.FullAddress[i+4] == (UCHAR)0x00))
  1300.               {
  1301.  
  1302.                 if (!Fonts[FONT_9x14].PVB.part.Selector  &&
  1303.                    (PVB.FullAddress[i+5] == (UCHAR)0x24) &&
  1304.                    (PVB.FullAddress[i+6] == (UCHAR)0x66))
  1305.                 {
  1306.                   Fonts[FONT_9x14].PVB.part.Selector = ROMFontSEL;
  1307.                   Fonts[FONT_9x14].PVB.part.Offset = i;
  1308.                 }
  1309.  
  1310.     #if      VDHVGA                    /* @MS00 */
  1311.  
  1312. /*
  1313. **  Locate 9x16 ROM font on VGA, and PS/2 adapter only
  1314. */
  1315.  
  1316.                 if (!Fonts[FONT_9x16].PVB.part.Selector  &&
  1317.                    (PVB.FullAddress[i+5] == (UCHAR)0x00) &&
  1318.                    (PVB.FullAddress[i+6] == (UCHAR)0x24))
  1319.                 {
  1320.                   Fonts[FONT_9x16].PVB.part.Selector = ROMFontSEL;
  1321.                   Fonts[FONT_9x16].PVB.part.Offset = i;
  1322.                 }
  1323.     #endif
  1324.               }
  1325.             }
  1326.           }                            /* Locate 9x14, 9x16                 */
  1327.  
  1328.           FreePhysToUVirt(PVB.part.Selector);/* Deallocate selector to ROM  */
  1329.                                        /* font area                     @T30*/
  1330.         }                              /* Search next ROM segment for       */
  1331.                                        /* fonts,                         @S5*/
  1332.       }                                /* use search code               @T36*/
  1333.  
  1334.   #else
  1335.  
  1336.       Fonts[FONT_8x8].PVB.part.Selector = 0x0F;/* Use BIOS default      @T64*/
  1337.       Fonts[FONT_8x8].PVB.part.Offset = 0x0FA6E;/*                      @T64
  1338.                                                                         @T64*/
  1339.   #endif
  1340.  
  1341. /*
  1342. **  If all fonts were not found, then
  1343. **  initialization fails
  1344. */
  1345.  
  1346.  
  1347.       if ((!Fonts[FONT_8x8].PVB.part.Selector)
  1348.  
  1349.       /*
  1350.       ** if the offset is FA6E, it is probably a system ROM image
  1351.       ** also 8 * 256 bytes starting here crosses a 64k physical
  1352.       ** boundry so it would run off the end of the ROM
  1353.       ** so this is a partial font and can not be used
  1354.       */
  1355.  
  1356.  
  1357.   #if      FONT_SUPPORT
  1358.            || (Fonts[FONT_8x8].PVB.part.Offset == 0xFA6E)
  1359.   #endif
  1360.  
  1361.          )
  1362.         rc = INIT_ERROR;               /* @MS22 - END */
  1363.  
  1364.   #if      VDHEGA        || VDHVGA     /* @MS00 */
  1365.  
  1366.       if (!Fonts[FONT_8x14].PVB.part.Selector || !Fonts[FONT_9x14].
  1367.          PVB.part.Selector)
  1368.         rc = INIT_ERROR;
  1369.  
  1370.   #endif
  1371.  
  1372.   #if      VDHVGA                      /* @MS00 */
  1373.  
  1374.       if (!Fonts[FONT_8x16].PVB.part.Selector || !Fonts[FONT_9x16].
  1375.          PVB.part.Selector)
  1376.         rc = INIT_ERROR;
  1377.  
  1378.   #endif
  1379. #endif
  1380.  
  1381.       if (!rc)
  1382.       {                                /* Error Check #5                    */
  1383.  
  1384. /*
  1385. **  Initialize values used in RetConfigInfo and GetMode
  1386. **--------------------------------------------------------------------------
  1387. **  All devices which support text modes can be powerup displays,
  1388. */
  1389.  
  1390. #if      VDH8514A                      /*                         @S16,@MS00*/
  1391. ConfigFlag |= VGA_PRESENT?POWERUP:0;   /*                               @S16*/
  1392.  
  1393. #else                                  /*                               @S16*/
  1394.  
  1395.  #if      VDHMPA                       /* fix: Only 1 popup device          */
  1396.                                        /* @MS23 - BEGIN */
  1397. /*
  1398. */
  1399.  
  1400.         if (VideoHardware.fVideoType == MPA_BIT)
  1401.   #endif
  1402.              ConfigFlag |= POWERUP;    /*                               @S16*/
  1403. #endif
  1404.  
  1405. /*
  1406. **  If power-up display, partial save size = 80x25x2 + maximum font length
  1407. **  If not power-up display, partial save size = 0 ( never a popup )
  1408. */
  1409.  
  1410. #if      VDH8514A                      /* @MS00 */
  1411.         PartialSaveSize = VGA_PRESENT ? VGAConfigData.PartSaveSize : UNKNOWN;
  1412.  
  1413. #else
  1414.  
  1415.   #if      VDHVGA
  1416.  
  1417.         if (OEMFlags & STARDUST_VGA)
  1418.            PartialSaveSize = 16L * 1024L;
  1419.  
  1420.         else
  1421.   #endif
  1422.            PartialSaveSize = 80L * 25L * 2L    /* 80x25 text PVB               */
  1423.  
  1424.   #if      FONT_SUPPORT                        /* @MS00 */
  1425.             + 256L *                           /* Font length                  */
  1426.  
  1427.             (ULONG)((USHORT)Modes[VideoHardware.popupMode].vres / (USHORT)Modes
  1428.                 [VideoHardware.popupMode].row)
  1429.   #endif
  1430.              ;
  1431. #endif
  1432.       }                                /* Error Check #5                    */
  1433.     }                                  /* Error Check #3                    */
  1434.   }                                    /* Error Check #1                    */
  1435.  
  1436.   return (rc);
  1437. }
  1438.  
  1439. #if      ROMFONT_SUPPORT               /*                          @T36,@MS00*/
  1440.  
  1441.   #if      VDHEGA        || VDHVGA     /*                          @T36,@MS00*/
  1442.  
  1443. /*****************************************************************************
  1444.  *
  1445.  * SUBROUTINE NAME: GetBIOSfonts
  1446.  *
  1447.  * DESCRIPTIVE NAME: Copy the OEMHLP table with BIOS fonts to a
  1448.  *                   local table
  1449.  *
  1450.  * FUNCTION: The OS/2 Loader (OS2LDR) calls the BIOS INT 10h
  1451.  *           function 1130h to build a table of 32 bit values
  1452.  *           boot time.  Each table entry point to a corresponding
  1453.  *           font address supported by the current video card.
  1454.  *           The address are returned as segment:offset pairs which
  1455.  *           this function converts to a 32 bit address.
  1456.  *
  1457.  *  Note:    GetBiosFonts does not apply to MPA/CGA hardware
  1458.  *
  1459.  *  ENTRY POINT: GetBIOSfonts
  1460.  *    LINKAGE:   CALL FAR
  1461.  *
  1462.  *  INPUT: None
  1463.  *
  1464.  *  EXIT: NOBIOSFONTS if not Bios fonts found, else BIOSFONTSFOUND
  1465.  *
  1466.  *  EFFECTS: NONE
  1467.  *
  1468.  *  INTERNAL REFERENCES:
  1469.  *    ROUTINES: None
  1470.  *
  1471.  *  EXTERNAL REFERENCES:
  1472.  *    ROUTINES: DosOpen, DosDevIOCtl, DosClose
  1473.  *              sends a request packet to the OEMHLP$ device driver
  1474.  *
  1475.  ****************************************************************************/
  1476.  
  1477. USHORT PASCAL near GetBIOSfonts(void)
  1478.  
  1479. {
  1480.  
  1481.   /*
  1482.   **  fontTable is filled with ROM font addresses obtained from
  1483.   **  OEMHLP$.  It contains the following information:
  1484.   **
  1485.   **            [0] font8x14    - ROM 8x14 font
  1486.   **            [1] font8x8Low  - ROM 8x8  font, charaters 0-7fh
  1487.   **            [2] font8x8High - ROM 8x8  font, charaters 80h-ffh
  1488.   **            [3] font9x14    - ROM 9x14 font
  1489.   **            [4] font8x16    - ROM 8x16 font
  1490.   **            [5] font9x16    - ROM 9x16 font
  1491.   */
  1492.  
  1493.  
  1494.   static ULONG fontTable[] = { 0L,0L,0L,0L,0L,0L,-1L } ;
  1495.  
  1496.   USHORT ifont;                        /* fontTable index                   */
  1497.  
  1498.  
  1499.   if (videoIoctl((UCHAR *)fontTable, NULL, OEMHLP_FUNCTION_FONTS))/* filled */
  1500.                                        /* font addresses                    */
  1501.     return  NOBIOSFONTS;
  1502.  
  1503.     /*
  1504.     **  Scan though fontTable until either a non-zero font address
  1505.     **  found or the end of fontTable is reached
  1506.     */
  1507.  
  1508.   for (ifont = 0; fontTable[ifont] != -1L; ++ifont)
  1509.  
  1510.     if (fontTable[ifont])
  1511.       break;
  1512.  
  1513.   if (fontTable[ifont] == -1L)         /* unable to find ROM fonts?         */
  1514.     return  NOBIOSFONTS;
  1515.  
  1516.   /*
  1517.   **  Convert the required ROM font segment:offsets into 32 bit
  1518.   **  addresses and copy them to the VDH Fonts array.
  1519.   **  Note:  The 2nd 8x8 font address is not used by OS/2
  1520.   */
  1521.  
  1522.   Fonts[FONT_8x14].PVB.FullAddress = (UCHAR far *)REALTO32BITADDR
  1523.                                      (fontTable[0] );
  1524.  
  1525.   Fonts[FONT_8x8].PVB.FullAddress  = (UCHAR far *)REALTO32BITADDR
  1526.                                      (fontTable[1]) ;
  1527.  
  1528.   Fonts[FONT_9x14].PVB.FullAddress = (UCHAR far *)REALTO32BITADDR
  1529.                                      (fontTable[3] );
  1530.  
  1531.     #if      VDHVGA                    /*                          @T37,@MS00*/
  1532.  
  1533.   Fonts[FONT_8x16].PVB.FullAddress = (UCHAR far *)REALTO32BITADDR
  1534.                                        (fontTable[4]);
  1535.  
  1536.   Fonts[FONT_9x16].PVB.FullAddress = (UCHAR far *)REALTO32BITADDR
  1537.                                      (fontTable[5]);
  1538.  
  1539.     #endif
  1540.   return  BIOSFONTSFOUND;
  1541.  
  1542. }
  1543.  
  1544.   #endif
  1545. #endif
  1546.  
  1547. #if      VDH8514A                      /* @MS00 */
  1548.  
  1549. /*****************************************************************************
  1550.  *
  1551.  *  SUBROUTINE NAME: LeaveNativeMode
  1552.  *
  1553.  *  DESCRIPTIVE NAME: 8514/A is forced out of Native Mode
  1554.  *
  1555.  *  FUNCTION: This routine is called to force the 8514/A out of Native
  1556.  *            Mode to allow VGA passthru.
  1557.  *
  1558.  *  ENTRY POINT: LeaveNativeMode
  1559.  *    LINKAGE:   CALL FAR
  1560.  *
  1561.  *  INPUT: None
  1562.  *
  1563.  *  EXIT-NORMAL: 8514/A is taken out of Native Mode
  1564.  *
  1565.  *  EFFECTS: NONE
  1566.  *
  1567.  *  INTERNAL REFERENCES:
  1568.  *    ROUTINES: None
  1569.  *
  1570.  *  EXTERNAL REFERENCES:
  1571.  *    ROUTINES: AccessRegister
  1572.  *
  1573.  ****************************************************************************/
  1574.  
  1575. void PASCAL near LeaveNativeMode()     /*                               @B15*/
  1576.  
  1577. {
  1578.  
  1579.   UCHAR RegValue;
  1580.   REGADDRESS RegAddress;
  1581.  
  1582.   RegAddress.DataPort = 0x22E8;
  1583.   RegValue = 0x53;
  1584.   AccessRegister(&RegAddress, SET, (UCHAR far *)&RegValue);
  1585.   RegAddress.DataPort = 0x4AE8;
  1586.   RegValue = 0x02;
  1587.   AccessRegister(&RegAddress, SET, (UCHAR far *)&RegValue);
  1588.   RegAddress.DataPort = 0x02E8;
  1589.   RegValue = 0x0A;
  1590.   AccessRegister(&RegAddress, SET, (UCHAR far *)&RegValue);
  1591.   RegAddress.DataPort = 0x22E8;
  1592.   RegValue = 0x33;
  1593.   AccessRegister(&RegAddress, SET, (UCHAR far *)&RegValue);
  1594.   RegAddress.DataPort = 0x02EA;
  1595.   RegValue = 0xFF;
  1596.   AccessRegister(&RegAddress, SET, (UCHAR far *)&RegValue);
  1597. }
  1598.  
  1599. #endif
  1600.  
  1601. #if      !(VDH8514A)                   /*                           @P1,@MS00*/
  1602.  
  1603. /*****************************************************************************
  1604.  *
  1605.  *  SUBROUTINE NAME: LVB3ToPVB
  1606.  *
  1607.  *  DESCRIPTIVE NAME: Restore the PVB from a World format LVB
  1608.  *
  1609.  *  FUNCTION: LVB3ToPVB is called by SaveRestorePVB to restore the PVB
  1610.  *            when the environment indicates the calling process is
  1611.  *            in a text mode using the world format id and attribute
  1612.  *            count.
  1613.  *
  1614.  *  ENTRY POINT: LVB3ToPVB
  1615.  *    LINKAGE:   CALL FAR
  1616.  *
  1617.  *  INPUT: (Passed on stack)
  1618.  *             FAR *ParmBlock ( SaveEnv/RestoreEnv parameter block )
  1619.  *             FAR *Environment
  1620.  *
  1621.  *  EXIT-NORMAL: AX = 0
  1622.  *               Physical buffer restored
  1623.  *
  1624.  *  EXIT-ERROR: AX = ERROR_VIO_MODE
  1625.  *
  1626.  *  EFFECTS: NONE
  1627.  *
  1628.  *  INTERNAL REFERENCES:
  1629.  *    ROUTINES:
  1630.  *
  1631.  *  EXTERNAL REFERENCES:
  1632.  *    ROUTINES:
  1633.  *
  1634.  ****************************************************************************/
  1635.  
  1636. USHORT EXPENTRY LVB3PVBTransfer(Environment,ParmBlock,Direction)/*       @P1*/
  1637.  
  1638.   ENVIRONMENT far *Environment;        /*                                @P1*/
  1639.   VDH_SAVEREST far *ParmBlock;         /*                                @P1*/
  1640.   USHORT Direction;                    /*                                @P1*/
  1641.  
  1642. {                                      /*                                @P1*/
  1643.   VDH_BUFUP BufParms;                  /*                                @P1*/
  1644.   char far *pch;                       /*                                @P1*/
  1645.   USHORT rc;                           /*                                @P1*/
  1646.  
  1647.   BufParms.Length = sizeof(BufParms);  /*                                @P1*/
  1648.   BufParms.Flags = BU_PVB_SEL_BIT;     /*                                @P1*/
  1649.  
  1650.   if (Direction == RESTORE)            /*                                @P1*/
  1651.     BufParms.Index = bu_WriteCellStr;  /*                                @P1*/
  1652.  
  1653.   else                                 /*                                @P1*/
  1654.     BufParms.Index = bu_ReadCellStr;   /*                                @P1*/
  1655.  
  1656.   BufParms.StartRow = 0;               /*                                @P1*/
  1657.   BufParms.StartCol = 0;               /*                                @P1*/
  1658.   BufParms.RepeatFactor = Environment->ModeData.col *             /*     @P1*/
  1659.                           Environment->ModeData.row *             /*     @P1*/
  1660.                          (Environment->ModeData.attrib+1);        /*     @P1*/
  1661.  
  1662.   BufParms.LogicalBufSel = ParmBlock->PVBHugeSEL;/*                      @P1*/
  1663.   pch = NULL;                          /*                                @P1*/
  1664.   *((unsigned *)&pch+1) = ParmBlock->PVBHugeSEL;/*                       @P1*/
  1665.   BufParms.AppDataAddr = pch;          /*                                @P1*/
  1666.   BufParms.AppCellAddr = NULL;         /*                                @P1*/
  1667.   rc = BufferUpdate(Environment, &BufParms, FnTextBufferUpdate);/*       @P1*/
  1668.   return (rc);                         /*                                @P1*/
  1669. }                                      /*                                @P1*/
  1670.  
  1671. #endif
  1672.  
  1673. #if      INTEXT_SUPPORT                /* @MS24 - BEGIN */
  1674.  
  1675. /*****************************************************************************
  1676.  *
  1677.  * FUNCTION NAME  = IntExtState(Op)
  1678.  *
  1679.  * DESCRIPTION    = Used to direct video output to either the internal or
  1680.  *                  external monitor for adapters that support dual monitors,
  1681.  *                  and for inquiring which one is currently selected.
  1682.  *
  1683.  *                  Call with Op == Internal_Monitor or External_Monitor to
  1684.  *                  select the monitor to receive video output.
  1685.  *
  1686.  *                  If Op == VST_EXTFLG, Internal_Monitor or External_Monitor
  1687.  *                  is returned depending on which one is currently active.
  1688.  *
  1689.  * INPUT:       Op
  1690.  *
  1691.  * OUTPUT:      None
  1692.  *
  1693.  * RETURNS:     Monitor status (Internal_Monitor or External_Monitor)
  1694.  *
  1695.  ****************************************************************************/
  1696.  
  1697. USHORT PASCAL near IntExtState(Op)
  1698.  
  1699. USHORT Op;
  1700.  
  1701. {
  1702.   REGADDRESS RegAddress;
  1703.   REGDATA RegData;
  1704.   UCHAR IntExtReg;
  1705.   UCHAR DataArea[2];
  1706.  
  1707.   RegAddress.Flags = NONE;
  1708.   RegData.DataArea = DataArea;
  1709.   RegData.NumEntries = 1;
  1710.  
  1711.   #if      VDHVGA
  1712.  
  1713.   if (OEMFlags & (PRISM_VGA | CRYSTAL_VGA))
  1714.   {
  1715.     RegAddress.AddressPort = GraphAddressPort;
  1716.     RegAddress.DataPort = GraphDataPort;
  1717.  
  1718.     /*
  1719.     ** Open access to extended VGA register
  1720.     */
  1721.     RegData.FirstEntry = VGA_ENV_REG;
  1722.     RegData.DataArea[0] = VGA_UNLOCK;
  1723.     AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  1724.  
  1725.     /*
  1726.     ** Read current monitor setting
  1727.     */
  1728.     RegData.FirstEntry = VGA_CONFIG_REG;
  1729.     AccessHardware(&RegAddress, BYTES, NONE, GET, &RegData);
  1730.     IntExtReg = DataArea[0];
  1731.  
  1732.     switch (Op)
  1733.     {
  1734.       case  External_Monitor :         /* Switch to CRT */
  1735.         IntExtReg |= LCD_EXTERNAL;
  1736.         AccessRegister(&RegAddress, SET, &IntExtReg);
  1737.         break;
  1738.  
  1739.       case  Internal_Monitor :         /* Switch to LCD */
  1740.         IntExtReg &= ~LCD_EXTERNAL;
  1741.         AccessRegister(&RegAddress, SET, &IntExtReg);
  1742.         break;
  1743.  
  1744.       case  VST_EXTINT :               /* Return active monitor */
  1745.  
  1746.         if (IntExtReg&LCD_EXTERNAL)
  1747.           Op = External_Monitor;
  1748.  
  1749.         else
  1750.           Op = Internal_Monitor;
  1751.  
  1752.         break;
  1753.  
  1754.     } /* Close access to extended VGA registers */
  1755.  
  1756.     RegData.FirstEntry = VGA_ENV_REG;
  1757.     RegData.DataArea[0] = VGA_LOCK;
  1758.     AccessHardware(&RegAddress, BYTES, NONE, SET, &RegData);
  1759.   }
  1760.  
  1761.   #endif
  1762.  
  1763.   return (Op);
  1764. }
  1765.  
  1766. #endif
  1767.                                                                /*@MS25 - BEGIN */
  1768.  
  1769. /*****************************************************************************
  1770.  * FUNCTION NAME = ReadCMOS(Index)
  1771.  *
  1772.  * DESCRIPTION   = This function is used to read a byte out of CMOS
  1773.  *                 configuration memory.
  1774.  *
  1775.  * INPUT     =  Index
  1776.  *
  1777.  * OUTPUT:      None
  1778.  *
  1779.  * RETURNS:     Value read from CMOS
  1780.  *
  1781.  ****************************************************************************/
  1782.  
  1783. UCHAR PASCAL near ReadCMOS(Index)
  1784.  
  1785. UCHAR Index;                         /* Index into CMOS */
  1786.  
  1787. {
  1788.   HFILE hDev;
  1789.   USHORT usAction;
  1790.   UCHAR CMOSRqst[2];
  1791.   UCHAR CMOSByte;
  1792.  
  1793.   CMOSRqst[0] = Index;
  1794.   CMOSRqst[1] = 1;                     /* Read 1 byte */
  1795.   CMOSByte = 0;                        /* default to 0 if error occurs */
  1796.  
  1797.   if (!DosOpen("CLOCK$", (PHFILE)&hDev, (PUSHORT)&usAction, NO_SIZE,
  1798.      NO_ATTRIBUTES, FILE_OPEN, OPEN_ACCESS_READONLY|OPEN_SHARE_DENYNONE,
  1799.      RESERVED_LONG))
  1800.  
  1801.   {
  1802.     DosDevIOCtl((PVOID)&CMOSByte,
  1803.                 (PVOID)CMOSRqst,
  1804.                 (USHORT)0x60,          /* function */
  1805.                 (USHORT)13,            /* category */
  1806.                 hDev);
  1807.     DosClose(hDev);
  1808.   }
  1809.  
  1810.   return (CMOSByte);
  1811.  
  1812. }                                      /* @MS25 - END */
  1813.  
  1814.