home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / x386 / vga / vgaHW.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-26  |  11.4 KB  |  412 lines

  1. /*
  2.  * $XConsortium: vgaHW.c,v 1.3 91/08/26 15:40:56 gildea Exp $
  3.  *
  4.  * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of Thomas Roell not be used in
  11.  * advertising or publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.  Thomas Roell makes no representations
  13.  * about the suitability of this software for any purpose.  It is provided
  14.  * "as is" without express or implied warranty.
  15.  *
  16.  * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  17.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  18.  * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  19.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  20.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  21.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  22.  * PERFORMANCE OF THIS SOFTWARE.
  23.  *
  24.  * Author:  Thomas Roell, roell@informatik.tu-muenchen.de
  25.  */
  26.  
  27. #define _NEED_SYSI86
  28.  
  29. #include "compiler.h"
  30.  
  31. #include "x386OSD.h"
  32. #include "vga.h"
  33. #include "scrnintstr.h"
  34.  
  35. #define new ((vgaHWPtr)vgaNewVideoState)
  36.  
  37.  
  38. /*
  39.  * vgaSaveScreen -- 
  40.  *      Disable the video on the frame buffer to save the screen.
  41.  */
  42. Bool
  43. vgaSaveScreen (pScreen, on)
  44.      ScreenPtr     pScreen;
  45.      Bool          on;
  46. {
  47.   unsigned char   state;
  48.  
  49.   if (x386VTSema) {
  50.     outb(0x3C4,1);
  51.     state = inb(0x3C5);
  52.   
  53.     if (on) state &= 0xDF;
  54.     else    state |= 0x20;
  55.     
  56.     /*
  57.      * turn off srceen if necessary
  58.      */
  59.     outw(0x3C4, 0x0100);              /* syncronous reset */
  60.     outw(0x3C4, (state << 8) | 0x01); /* change mode */
  61.     outw(0x3C4, 0x0300);              /* syncronous reset */
  62.  
  63.   } else {
  64.     if (on)
  65.       ((vgaHWPtr)vgaNewVideoState)->Sequencer[1] &= 0xDF;
  66.     else
  67.       ((vgaHWPtr)vgaNewVideoState)->Sequencer[1] |= 0x20;
  68.   }
  69.  
  70.   return(TRUE);
  71. }
  72.  
  73.  
  74.  
  75. /*
  76.  * vgaHWRestore --
  77.  *      restore a video mode
  78.  */
  79.  
  80. void
  81. vgaHWRestore(restore)
  82.      vgaHWPtr restore;
  83. {
  84.   int i;
  85.  
  86.   outw(0x3C4, ((restore->Sequencer[0] & 0xFD) << 8) | 0x00);
  87.  
  88.   if (vgaIOBase == 0x3B0)
  89.     restore->MiscOutReg &= 0xFE;
  90.   else
  91.     restore->MiscOutReg |= 0x01;
  92.  
  93.   outb(0x3C2, restore->MiscOutReg);
  94.  
  95.   /*
  96.    * This here is a workaround a bug in the kd-driver. We MUST explicitely
  97.    * restore the font we got, when we entered graphics mode.
  98.    * The bug was seen on ESIX, and ISC 2.0.2 when using a monochrome
  99.    * monitor. 
  100.    *
  101.    * BTW, also GIO_FONT seems to have a bug, so we cannot use it, to get
  102.    * a font.
  103.    */
  104.   
  105.   if(restore->FontInfo) {
  106.     /*
  107.      * here we switch temporary to 16 color-plane-mode, to simply
  108.      * copy the font-info
  109.      *
  110.      * BUGALLERT: The vga's segment-select register MUST be set appropriate !
  111.      */
  112.     i = inb(vgaIOBase + 0x0A); /* reset flip-flop */
  113.     outb(0x3C0,0x30); outb(0x3C0, 0x01); /* graphics mode */
  114.     outw(0x3C4, 0x0402);    /* write to plane 2 */
  115.     outw(0x3C4, 0x0604);    /* enable plane graphics */
  116.     outw(0x3CE, 0x0204);    /* read plane 2 */
  117.     outw(0x3CE, 0x0005);    /* write mode 0, read mode 0 */
  118.     outw(0x3CE, 0x0506);    /* set graphics */
  119.     bcopy(restore->FontInfo, vgaBase, 8192);
  120.  
  121.   }
  122.   
  123.   for (i=0; i<5;  i++) outw(0x3C4, (restore->Sequencer[i] << 8) | i);
  124.   i = inb(vgaIOBase + 0x0A); /* reset flip-flop */
  125.   for (i=0; i<16; i++) { outb(0x3C0,i); outb(0x3C0, restore->Attribute[i]); }
  126.   for (i=16; i<21;i++) { outb(0x3C0,i | 0x20);
  127.              outb(0x3C0, restore->Attribute[i]); }
  128.   for (i=0; i<24; i++) outw(vgaIOBase + 4,(restore->CRTC[i] << 8) | i);
  129.   for (i=0; i<9;  i++) outw(0x3CE, (restore->Graphics[i] << 8) | i);
  130.   
  131.   outb(0x3C6,0xFF);
  132.   outb(0x3C8,0x00);
  133.   for (i=0; i<768; i++) outb(0x3C9, restore->DAC[i]);
  134.  
  135. }
  136.  
  137.  
  138.  
  139. /*
  140.  * vgaHWSave --
  141.  *      save the current video mode
  142.  */
  143.  
  144. void *
  145. vgaHWSave(save, size)
  146.      vgaHWPtr save;
  147.      int          size;
  148. {
  149.   int           i;
  150.  
  151.   if (save == NULL) {
  152.     save = (vgaHWPtr)Xcalloc(size);
  153.     /*
  154.      * Here we are, when we first save the videostate. This means we came here
  155.      * to save the original Text mode. Because some drivers may depend
  156.      * on NoClock we set it here to a resonable value.
  157.      */
  158.     save->NoClock = (inb(0x3CC) >> 2) & 3;
  159.   }
  160.  
  161.   /*
  162.    * now get the fuck'in register
  163.    */
  164.   save->MiscOutReg = inb(0x3CC);
  165.  
  166.   vgaIOBase = (save->MiscOutReg & 0x01) ? 0x3D0 : 0x3B0;
  167.   for (i=0; i<24; i++) { outb(vgaIOBase + 4,i);
  168.              save->CRTC[i] = inb(vgaIOBase + 5); }
  169.   for (i=0; i<5;  i++) { outb(0x3C4,i); save->Sequencer[i]   = inb(0x3C5); }
  170.   for (i=0; i<9;  i++) { outb(0x3CE,i); save->Graphics[i]  = inb(0x3CF); }
  171.   i = inb(vgaIOBase + 0x0A); /* reset flip-flop */
  172.   for (i=0; i<16; i++) { outb(0x3C0,i); save->Attribute[i] = inb(0x3C1);
  173.              outb(0x3C0, save->Attribute[i]); }
  174.   for (i=16; i<21; i++) { outb(0x3C0,i | 0x20); 
  175.               save->Attribute[i] = inb(0x3C1);
  176.               outb(0x3C0, save->Attribute[i]); }
  177.   
  178. #ifdef GOOD_ET4000
  179.   /* Some recent (1991) ET4000 chips have a HW bug that prevents the reading
  180.      of the color lookup table.  Mask rev 9042EAI is known to have this bug.
  181.  
  182.      X386 already keeps track of the contents of the color lookup table so
  183.      reading the HW isn't needed.  Therefore, as a workaround for this HW
  184.      bug, the following (correct) code has been #ifdef'ed out.  This is also
  185.      a valid change for ET4000 chips that don't have the HW bug.  The code
  186.      is really just being retained for reference.  MWS 22-Aug-91
  187.   */
  188.  
  189.   /*             
  190.    * save the colorlookuptable 
  191.    */
  192.   outb(0x3C6,0xFF);
  193.   outb(0x3C7,0x00);
  194.   for (i=0; i<768; i++) save->DAC[i] = inb(0x3C9); 
  195. #endif /* GOOD_ET4000 */
  196.  
  197.   /*
  198.    * get the character set of the first non-graphics application
  199.    */
  200.   if (((save->Attribute[0x10] & 0x01) == 0) &&
  201.       (save->FontInfo == NULL)) {
  202.     /*
  203.      * Here we switch temporary to 16 color-plane-mode, to simply
  204.      * copy the font-info
  205.      *
  206.      * BUGALLERT: The vga's segment-select register MUST be set appropriate !
  207.      */
  208.     i = inb(vgaIOBase + 0x0A); /* reset flip-flop */
  209.     outb(0x3C0,0x30); outb(0x3C0, 0x01); /* graphics mode */
  210.     outw(0x3C4, 0x0402);    /* write to plane 2 */
  211.     outw(0x3C4, 0x0604);    /* enable plane graphics */
  212.     outw(0x3CE, 0x0204);    /* read plane 2 */
  213.     outw(0x3CE, 0x0005);    /* write mode 0, read mode 0 */
  214.     outw(0x3CE, 0x0506);    /* set graphics */
  215.  
  216.     save->FontInfo = (pointer)xalloc(8192);
  217.     bcopy(vgaBase, save->FontInfo, 8192);
  218.  
  219.   }
  220.   
  221.   return ((void *) save);
  222. }
  223.  
  224.  
  225.  
  226. /*
  227.  * vgaHWInit --
  228.  *      Handle the initialization, etc. of a screen.
  229.  */
  230.  
  231. void
  232. vgaHWInit(mode,size)
  233.      int             size;
  234.      DisplayModePtr      mode;
  235. {
  236.   int                i;
  237.  
  238.   if (vgaNewVideoState == NULL) {
  239.     vgaNewVideoState = (void *)Xcalloc(size);
  240.  
  241.     /*
  242.      * initialize default colormap for monochrome
  243.      */
  244.     for (i=0; i<3;   i++) new->DAC[i] = 0x00;
  245.     for (i=3; i<768; i++) new->DAC[i] = 0x3F;
  246.  
  247.   }
  248.  
  249.   /*
  250.    * Get NoClock
  251.    */
  252.   new->NoClock   = mode->Clock;
  253.  
  254.   /*
  255.    * compute correct Hsync & Vsync polarity 
  256.    */
  257.   if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
  258.       && (mode->Flags & (V_PVSYNC | V_NVSYNC)))
  259.       {
  260.     new->MiscOutReg = 0x23;
  261.     if (mode->Flags & V_NHSYNC) new->MiscOutReg |= 0x40;
  262.     if (mode->Flags & V_NVSYNC) new->MiscOutReg |= 0x80;
  263.       }
  264.       else
  265.       {
  266.     if      (mode->VDisplay < 400) new->MiscOutReg = 0xA3;
  267.     else if (mode->VDisplay < 480) new->MiscOutReg = 0x63;
  268.     else if (mode->VDisplay < 768) new->MiscOutReg = 0xE3;
  269.     else                           new->MiscOutReg = 0x23;
  270.       }
  271.   new->MiscOutReg |= (new->NoClock & 0x03) << 2;
  272.   
  273.   /*
  274.    * Time Sequencer
  275.    */
  276.   new->Sequencer[0] = 0x00;
  277.   new->Sequencer[1] = 0x01;
  278.   new->Sequencer[2] = 0x0F;
  279.   new->Sequencer[3] = 0x00;                             /* Font select */
  280.   new->Sequencer[4] = 0x0E;                             /* Misc */
  281.  
  282.   /*
  283.    * CRTC Controller
  284.    */
  285.   new->CRTC[0]  = (mode->HTotal >> 3) - 5;
  286.   new->CRTC[1]  = (mode->HDisplay >> 3) - 1;
  287.   new->CRTC[2]  = (mode->HSyncStart >> 3) -1;
  288.   new->CRTC[3]  = ((mode->HSyncEnd >> 3) & 0x1F) | 0x80;
  289.   new->CRTC[4]  = (mode->HSyncStart >> 3);
  290.   new->CRTC[5]  = (((mode->HSyncEnd >> 3) & 0x20 ) << 2 )
  291.     | (((mode->HSyncEnd >> 3)) & 0x1F);
  292.   new->CRTC[6]  = (mode->VTotal - 2) & 0xFF;
  293.   new->CRTC[7]  = (((mode->VTotal -2) & 0x100) >> 8 )
  294.     | (((mode->VDisplay -1) & 0x100) >> 7 )
  295.       | ((mode->VSyncStart & 0x100) >> 6 )
  296.     | (((mode->VSyncStart) & 0x100) >> 5 )
  297.       | 0x10
  298.         | (((mode->VTotal -2) & 0x200)   >> 4 )
  299.           | (((mode->VDisplay -1) & 0x200) >> 3 )
  300.         | ((mode->VSyncStart & 0x200) >> 2 );
  301.   new->CRTC[8]  = 0x00;
  302.   new->CRTC[9]  = ((mode->VSyncStart & 0x200) >>4) | 0x40;
  303.   new->CRTC[10] = 0x00;
  304.   new->CRTC[11] = 0x00;
  305.   new->CRTC[12] = 0x00;
  306.   new->CRTC[13] = 0x00;
  307.   new->CRTC[14] = 0x00;
  308.   new->CRTC[15] = 0x00;
  309.   new->CRTC[16] = mode->VSyncStart & 0xFF;
  310.   new->CRTC[17] = (mode->VSyncEnd & 0x0F) | 0x20;
  311.   new->CRTC[18] = (mode->VDisplay -1) & 0xFF;
  312.   new->CRTC[19] = vga256InfoRec.virtualX >> 4;  /* just a guess */
  313.   new->CRTC[20] = 0x00;
  314.   new->CRTC[21] = mode->VSyncStart & 0xFF; 
  315.   new->CRTC[22] = (mode->VSyncStart +1) & 0xFF;
  316.   new->CRTC[23] = 0xC3;
  317.   new->CRTC[24] = 0xFF;
  318.  
  319.   /*
  320.    * Graphics Display Controller
  321.    */
  322.   new->Graphics[0] = 0x00;
  323.   new->Graphics[1] = 0x00;
  324.   new->Graphics[2] = 0x00;
  325.   new->Graphics[3] = 0x00;
  326.   new->Graphics[4] = 0x00;
  327.   new->Graphics[5] = 0x40;
  328.   new->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
  329.   new->Graphics[7] = 0x0F;
  330.   new->Graphics[8] = 0xFF;
  331.   
  332.   new->Attribute[0]  = 0x00; /* standart colormap translation */
  333.   new->Attribute[1]  = 0x01;
  334.   new->Attribute[2]  = 0x02;
  335.   new->Attribute[3]  = 0x03;
  336.   new->Attribute[4]  = 0x04;
  337.   new->Attribute[5]  = 0x05;
  338.   new->Attribute[6]  = 0x06;
  339.   new->Attribute[7]  = 0x07;
  340.   new->Attribute[8]  = 0x08;
  341.   new->Attribute[9]  = 0x09;
  342.   new->Attribute[10] = 0x0A;
  343.   new->Attribute[11] = 0x0B;
  344.   new->Attribute[12] = 0x0C;
  345.   new->Attribute[13] = 0x0D;
  346.   new->Attribute[14] = 0x0E;
  347.   new->Attribute[15] = 0x0F;
  348.   new->Attribute[16] = 0x41; /* wrong for the ET4000 */
  349.   new->Attribute[17] = 0x01;
  350.   new->Attribute[18] = 0x0F;
  351.   new->Attribute[19] = 0x00;
  352.   new->Attribute[20] = 0x00;
  353. }
  354.  
  355.  
  356. /*
  357.  * vgaGetClocks --
  358.  *      get the dot-clocks via a BIG BAD hack ...
  359.  */
  360.  
  361. void
  362. vgaGetClocks(num, ClockFunc)
  363.      int num;
  364.      void (*ClockFunc)();
  365. {
  366.   int          norm;
  367.   register int status = vgaIOBase + 0x0A;
  368.   unsigned long       i, j, cnt, rcnt, sync;
  369.  
  370.   sysi86(SI86V86, V86SC_IOPL, PS_IOPL);
  371.  
  372.   for (i = 1; i < num; i++) {
  373.     
  374.     (*ClockFunc)(i);
  375.  
  376.     cnt  = 0;
  377.     sync = 200000;
  378.  
  379.     intr_disable();
  380.     while ((inb(status) & 0x08) == 0x00) if (sync-- == 0) goto finish;
  381.     while ((inb(status) & 0x08) == 0x08) if (sync-- == 0) goto finish;
  382.     while ((inb(status) & 0x08) == 0x00) if (sync-- == 0) goto finish;
  383.     
  384.     for (rcnt = 0; rcnt < 5; rcnt++) {
  385.       while (!(inb(status) & 0x08)) cnt++;
  386.       while ((inb(status) & 0x08)) cnt++;
  387.     }
  388.     
  389.   finish:
  390.     intr_enable();
  391.  
  392.     vga256InfoRec.clock[i] = cnt ? cnt : 1000000;
  393.   }
  394.  
  395.   for (i = 2; i < num; i++)
  396.     vga256InfoRec.clock[i] = (int)(0.5 +
  397.       (28.322 * vga256InfoRec.clock[1]) / (vga256InfoRec.clock[i]));
  398.  
  399.   vga256InfoRec.clock[0] = 25;
  400.   vga256InfoRec.clock[1] = 28;
  401.  
  402.   for (i=0; i < num; i++)
  403.     for (j=i+1; j < num; j++)
  404.       if (vga256InfoRec.clock[i] == vga256InfoRec.clock[j]) 
  405.     vga256InfoRec.clock[j] = 0;
  406.  
  407.   vga256InfoRec.clocks = num;
  408.   (ClockFunc)(0);
  409. }
  410.  
  411.  
  412.