home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / PROGRAM / VIDEO.ZIP / VIDEOID.C next >
C/C++ Source or Header  |  1992-06-29  |  15KB  |  468 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2.  *                                     .                                     *
  3.  *                                   Video                                   *
  4.  *                                                                           *
  5.  *                    (c) Copyright 1988 Michael K. Heney                    *
  6.  *                                                                           *
  7.  * File:      VideoID.C                                                      *
  8.  * Purpose:   Identify the video subsystem(s) present.                       *
  9.  *                                                                           *
  10.  * Routines:  VideoID    FindPS2    FindEGA    FindCGA     FindMono          *
  11.  *            Find6845   FindActive                                          *
  12.  *                                                                           *
  13.  * Written:   15 Jul 88 - 16 Jul 88 MKH                                      *
  14.  *                                                                           *
  15.  * Notes:     Adapted from the VideoID program written in assembler in       *
  16.  *            "Programmer's Guide to PC & PS/2 Video Systems" by             *
  17.  *            Richard Wilton (Microsoft Press).  Listing C-1, pp. 513-521.   *
  18.  *                                                                           *
  19.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  20.  
  21. #include <stdio.h>
  22. #include <dos.h>
  23. #include "videoid.h"
  24.  
  25. union REGS regs ;
  26.  
  27. enum videocard device0, device1 ;
  28. enum display  display0, display1 ;
  29. int EGAFlag, CGAFlag, MonoFlag ;
  30.  
  31. static const int DCCTable[][2] =
  32. {
  33.     None, NoDisplay,
  34.      MDA, MDADisplay,
  35.      CGA, CGADisplay,
  36.     None, NoDisplay,
  37.      EGA, EGAColorDisplay,
  38.      EGA, MDADisplay,
  39.     None, NoDisplay,
  40.      VGA, PS2MonoDisplay,
  41.      VGA, PS2ColorDisplay,
  42.     None, NoDisplay,
  43.     MCGA, EGAColorDisplay,
  44.     MCGA, PS2MonoDisplay,
  45.     MCGA, PS2ColorDisplay
  46. } ;
  47.  
  48. static const int EGADisplays[] =
  49. {
  50.     CGADisplay,
  51.     EGAColorDisplay,
  52.     MDADisplay,
  53.     CGADisplay,
  54.     EGAColorDisplay,
  55.     MDADisplay
  56. } ;
  57.  
  58.  
  59.  
  60. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  61.  *  VideoID checks for up to 2 video systems present, looking for PS/2,      *
  62.  *  EGA, CGA, and Monochrome.                                                *
  63.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  64.  
  65. long VideoID()
  66. {
  67.     long rc ;
  68.  
  69.     /* ---- initilize - no video subsystems found yet ---- */
  70.  
  71.     device0  = None ;
  72.     display0 = NoDisplay ;
  73.  
  74.     device1  = None ;
  75.     display1 = NoDisplay ;
  76.  
  77.     /* ---- flags - nothing ruled out yet ---- */
  78.  
  79.     EGAFlag  = 1 ;
  80.     CGAFlag  = 1 ;
  81.     MonoFlag = 1 ;
  82.  
  83.     /* ---- check each video subsytem type as appropriate ---- */
  84.  
  85.     FindPS2() ;
  86.     if (EGAFlag)  FindEGA() ;
  87.     if (CGAFlag)  FindCGA() ;
  88.     if (MonoFlag) FindMono() ;
  89.  
  90.     /* ---- determine which video subsystem is active, if 2 present ---- */
  91.  
  92.     FindActive() ;
  93.  
  94.     rc = ( ( ( ( ( ( (long) device0 << 8) | (long) display0) << 8)
  95.                   | (long) device1) << 8) | (long) display1) ;
  96.  
  97.     return (rc) ;
  98. }
  99.  
  100.  
  101. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  102.  *  FindPS2 looks for PS/2 compatable video systems (VGA or MCGA)            *
  103.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  104.  
  105. int FindPS2()
  106. {
  107.     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  108.      * use video service 1A (video display combination) of INT 10h *
  109.      * (video services) to see if (1) this is a PS/2 system, and   *
  110.      * (2) what the displays are.                                  *
  111.      *                                                             *
  112.      * Register assignments for service 1A are:                    *
  113.      *                                                             *
  114.      *    Call:                                                    *
  115.      *        AH = 0x1A     video service 1A                       *
  116.      *        AL = 0x00     subservice 0 - PS/2 return video       *
  117.      *                         display combinations                *
  118.      *                                                             *
  119.      *    Return:                                                  *
  120.      *        AL = 0x1A     if service available!                  *
  121.      *        BL = active display                                  *
  122.      *        BH = inactive display                                *
  123.      *                                                             *
  124.      * Display type codes:                                         *
  125.      *     00 No display                                           *
  126.      *     01 MDA with monochrome display                          *
  127.      *     02 CGA with color display                               *
  128.      *     03 (reserved)                                           *
  129.      *     04 EGA with color display                               *
  130.      *     05 EGA with monochrome display                          *
  131.      *     06 Professional Graphics Controller                     *
  132.      *     07 VGA with analog monochrome display                   *
  133.      *     08 VGA with analog color display                        *
  134.      *     09 (reserved)                                           *
  135.      *     0A MCGA with digital color display                      *
  136.      *     0B MCGA with analog mono display                        *
  137.      *     0C MCGA with analog color display                       *
  138.      *     FF Unrecognized video subsystem                         *
  139.      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  140.  
  141.     regs.x.ax = 0x1a00 ;
  142.     int86(0x10, ®s, ®s) ;
  143.  
  144.     /* ---- if not PS/2, leave ---- */
  145.  
  146.     if (regs.h.al != 0x1a)
  147.         return ;
  148.  
  149.     /* ---- if inactive display (BH) exists, classify it ---- */
  150.  
  151.     if (regs.h.bh)
  152.     {
  153.         device1  = DCCTable[1][regs.h.bh] ;
  154.         display1 = DCCTable[2][regs.h.bh] ;
  155.     }
  156.  
  157.     /* ---- now for the active display ---- */
  158.  
  159.     device0  = DCCTable[1][regs.h.bl] ;
  160.     display0 = DCCTable[2][regs.h.bl] ;
  161.  
  162.     /* ---- we have both systems ...  ---- */
  163.  
  164.     EGAFlag  = 0 ;
  165.     CGAFlag  = 0 ;
  166.     MonoFlag = 0 ;
  167.  
  168.     /* ---- if either device was MDA, we'll need to check for HERCULES ---- */
  169.  
  170.     if (device0 == MDA)
  171.     {
  172.         MonoFlag = 1 ;
  173.         device0  = None ;
  174.         display0 = NoDisplay ;
  175.     }
  176.  
  177.     else if (device1 == MDA)
  178.     {
  179.         MonoFlag = 1 ;
  180.         device1  = None ;
  181.         display1 = NoDisplay ;
  182.     }
  183.  
  184.     return ;
  185.  
  186. }
  187.  
  188.  
  189. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  190.  *  FindEGA looks for an EGA system                                          *
  191.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  192.  
  193. int FindEGA()
  194. {
  195.     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  196.      * use video service 12h (video subsystem configuraton of      *
  197.      * INT 10h (video services) to see if there is an EGA card     *
  198.      * and what kind of monitor is attached.                       *                                  *
  199.      *                                                             *
  200.      * Register assignments for service 12h are:                   *
  201.      *                                                             *
  202.      *    Call:                                                    *
  203.      *        AH = 0x12     video service 12h                      *
  204.      *        BL = 0x10     subservice 10h - EGA return video      *
  205.      *                         configuration information           *
  206.      *                                                             *
  207.      *    Return:                                                  *
  208.      *        BH = default BIOS video mode                         *
  209.      *             0  Color                                        *
  210.      *             1  Monochrome                                   *
  211.      *        BL = amount of EGA vide RAM                          *
  212.      *              0    64 KB                                     *
  213.      *              1   128 KB                                     *
  214.      *              2   192 KB                                     *
  215.      *              3   256 KB                                     *
  216.      *             10h subservice not available - no EGA present   *
  217.      *        CH = feature bits                                    *
  218.      *        CL = configuration switch setting                    *
  219.      *                                                             *
  220.      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  221.  
  222.     regs.h.ah = 0x12 ;
  223.     regs.h.bl = 0x10 ;
  224.  
  225.     int86(0x10, ®s, ®s) ;
  226.  
  227.     /* ---- if not EGA (no change in bl) leave ---- */
  228.  
  229.     if (regs.h.bl == 0x10)
  230.         return ;
  231.  
  232.     /* ---- cl described the display type.  Since we get    ---- */
  233.     /* ---- here iff not PS2, this must be the first found. ---- */
  234.  
  235.     device0 = EGA ;
  236.     display0 = EGADisplays[regs.h.cl > 1]  ; /* trust me, it works */
  237.  
  238.     /* ---- figure out what we can't have for a 2nd monitor ---- */
  239.  
  240.     if (display0 == MDA)
  241.         MonoFlag = 0 ;
  242.     else
  243.         CGAFlag = 0 ;
  244.  
  245.     return ;
  246.  
  247. }
  248.  
  249.  
  250. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  251.  *  FindCGA looks for a CGA system                                           *
  252.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  253.  
  254. int FindCGA()
  255. {
  256.     /* Call Find6845 to see if a video controller is at port 0x03d4 ---- */
  257.  
  258.     if ( Find6845(0x03d4) )
  259.     {
  260.         /* ---- assign to 1st or 2nd device found as appropriate ---- */
  261.  
  262.         if (device0)
  263.         {
  264.             device1  = CGA ;
  265.             display1 = CGADisplay ;
  266.         }
  267.         else
  268.         {
  269.             device0  = CGA ;
  270.             display0 = CGADisplay ;
  271.         }
  272.     }
  273.  
  274.     return ;
  275. }
  276.  
  277.  
  278. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  279.  *  FindMono looks for a Mono system.  This gets to be fun, as we need to    *
  280.  *  determine if the monitor is HERCULES graphics if mono.                   *
  281.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  282.  
  283. int FindMono()
  284. {
  285.     register char bit7, hold7 ;
  286.     int i ;
  287.  
  288.     /* Call Find6845 to see if a video controller is at port 0x03b4 ---- */
  289.  
  290.     if ( Find6845(0x03b4) == 0)
  291.         return ;
  292.  
  293.     /* ---- assign to 1st or 2nd device found as appropriate ---- */
  294.  
  295.     if (device0)
  296.     {
  297.         device1  = MDA ;
  298.         display1 = MDADisplay ;
  299.     }
  300.     else
  301.     {
  302.         device0  = MDA ;
  303.         display0 = MDADisplay ;
  304.     }
  305.  
  306.     /* ---- now check for HERCULES.  Hercs use bit 7 of port 0x03ba ---- */
  307.     /* ---- to signal horizontal resynch, non-graphics cards don't. ---- */
  308.     /* ---- So, if this bit changes, it's a HERC!                   ---- */
  309.  
  310.     hold7 = inp(0x03ba) & 0x80 ;
  311.  
  312.     for (i = 0; i < 32767; i++)
  313.     {
  314.         bit7 = inp(0x03ba) & 0x80 ;
  315.         if (hold7 != bit7)
  316.             break ;
  317.     }
  318.  
  319.     /* ---- if it never changed, we're done! ---- */
  320.  
  321.     if (hold7 == bit7)
  322.         return ;
  323.  
  324.     /* ---- check the status port One More Time to get the Herc Type ---- */
  325.     /* ---- bits 4-6 (as 76543210) denote the type.                  ---- */
  326.     /* ---- x000xxxx  is HGC                                         ---- */
  327.     /* ---- x001xxxx  is HGC Plus                                    ---- */
  328.     /* ---- x101xxxx  is Hercules Incolor                            ---- */
  329.     /* ---- Anything else will be assumed to be a plain HGC card.    ---- */
  330.  
  331.     hold7 = inp(0x03ba) & 0x0070 ;
  332.  
  333.     /* ---- HGC+ has only bit 4 on ---- */
  334.  
  335.     if (hold7 == 0x0010)
  336.     {
  337.         if (device0 == MDA)
  338.             device0 = HGCPlus ;
  339.         else
  340.             device1 = HGCPlus ;
  341.         return ;
  342.     }
  343.  
  344.     /* ---- HGC InColor has bits 4 and 6 on ---- */
  345.  
  346.     if (hold7 == 0x0050)
  347.     {
  348.         if (device0 == MDA)
  349.         {
  350.             device0  = InColor ;
  351.             display0 = EGAColorDisplay ;
  352.         }
  353.         else
  354.         {
  355.             device1  = InColor ;
  356.             display1 = EGAColorDisplay ;
  357.         }
  358.         return ;
  359.     }
  360.  
  361.     /* ---- anything else is just an HGC (to be safe) ---- */
  362.  
  363.     if (device0 == MDA)
  364.         device0 = HGC ;
  365.     else
  366.         device1 = HGC ;
  367.  
  368.     return ;
  369.  
  370. }
  371.  
  372.  
  373. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  374.  *  Find6845 tries to write to a specified video port, reporting its success *
  375.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  376.  
  377. int Find6845(int port)
  378. {
  379.     int oldval, newval ;
  380.     int i, port1 ;
  381.  
  382.     port1 = port+1 ;
  383.  
  384.     /* ---- We try to read/write register 0x0f (Cursor Low) on the ---- */
  385.     /* ---- 6845 CRT controller.  For EGA/CGA, use ports 3d4/3d5;  ---- */
  386.     /* ---- for mono use 3b4/3b5 as the register select port and   ---- */
  387.     /* ---- the data port, repectively.  If the write changes the  ---- */
  388.     /* ---- value, we are there is a contoller on those ports.     ---- */
  389.  
  390.  
  391.     /* ---- save current value ---- */
  392.  
  393.     outp(port,0x000f) ;
  394.     oldval = inp(port1) ;
  395.  
  396.     /* ---- try to put a value out - invert oldval ---- */
  397.  
  398.     outp(port, 0x000f) ;
  399.     outp(port1, ~oldval & 0x00ff) ;
  400.  
  401.     /* ---- short wait ---- */
  402.  
  403.     for (i = 0; i < 256; i++)
  404.         ;
  405.  
  406.     /* ----read the port, and see if our value got written ---- */
  407.  
  408.     outp(port,0x000f) ;
  409.     newval = inp(port1) ;
  410.     outp(port,0x000f) ;
  411.     outp (port1,oldval) ;
  412.  
  413.     return (newval == (~oldval & 0x00ff) ) ;
  414.  
  415. }
  416.  
  417.  
  418. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  419.  *  FindaActive makes sure the active display subsystem is device0/display0  *
  420.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  421.  
  422. int FindActive()
  423. {
  424.     enum videocard devicex ;
  425.     enum display  displayx ;
  426.  
  427.     /* ---- if VGA or MCGA is present, or there is only 1 monitor, ---- */
  428.     /* ---- things are quite easy.                                 ---- */
  429.  
  430.     if ( (device1 == None) || (device0 == VGA) || (device0 == MCGA)
  431.                            || (device1 == VGA) || (device1 == MCGA) )
  432.  
  433.         return ;
  434.  
  435.     /* ---- use the BIOS to get the video mode ---- */
  436.  
  437.     regs.h.ah = 0x0F ;
  438.     int86(0x10, ®s, ®s) ;
  439.  
  440.     /* ---- if mode is 7 (mono), we're OK if display0 is mono. ---- */
  441.  
  442.     if (regs.h.al == 7)
  443.     {
  444.         if (display0 == MDADisplay)
  445.             return ;
  446.     }
  447.  
  448.     /* ---- problems in EGAMono if CGA also present ... ---- */
  449.  
  450.     else
  451.     {
  452.         if (display0 != MDADisplay)
  453.             return ;
  454.     }
  455.  
  456.     /* ---- swap the displays and devices ---- */
  457.  
  458.     devicex  = device0 ;
  459.     device0  = device1 ;
  460.     device1  = devicex ;
  461.     displayx = display0 ;
  462.     display0 = display1 ;
  463.     display1 = displayx ;
  464.  
  465.     return ;
  466.  
  467. }
  468.