home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / s3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-22  |  26.0 KB  |  1,010 lines

  1. /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen            */
  2. /*                                   */
  3. /* This library is free software; you can redistribute it and/or   */
  4. /* modify it without any restrictions. This library is distributed */
  5. /* in the hope that it will be useful, but without any warranty.   */
  6.  
  7. /* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer */
  8.  
  9. /*
  10.  * Dec 1994:
  11.  * Partially rewritten using new SVGA-abstracted interface.
  12.  * Based on XFree86 code (accel/s3/s3.c and s3init.c).
  13.  * Goal is to have support for the S3-864 + S3-SDAC (which I can test).
  14.  * 80x with GENDAC might also be supported.
  15.  * Also, 640x480x256 should work on cards that have standard 25 and 28 MHz
  16.  * clocks.
  17.  *
  18.  * Uncertainties:
  19.  * - Is it OK to use outw to use write to all CR registers (outCR()), or
  20.  *   should they be split into two outb's (outbCR())?
  21.  * Remaining problems:
  22.  * - All modes suffer from bad CRT refresh at the right half or so of
  23.  *   scanlines. A chunk of pixels is repeated over the right half.
  24.  *   (This is on a S3-864 + SDAC).
  25.  * - In 640x480x32bpp, something is still wrong with the linewidth.
  26.  * * These problems are now fixed -- XF86_S3 seems to program the linewidth
  27.  *   in bytes doubled for the S3-864 with > 1024K, which caused problems
  28.  *   for this driver. There's still interference though when writing to
  29.  *   video memory in the higher resolutions.
  30.  */
  31.  
  32.  
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include "vga.h"
  37. #include "libvga.h"
  38. #include "driver.h"
  39.  
  40. #include "timing.h"
  41. #include "ramdac.h"
  42. #include "vgaregs.h"
  43. #include "interface.h"
  44.  
  45.  
  46. enum { S3_911, S3_924, S3_801, S3_805, S3_928, S3_864, S3_964, S3_TRIO32,
  47.     S3_TRIO64 };
  48.  
  49. static const char *s3_chipname[] = { "911", "924", "801", "805", "928",
  50.     "864", "Trio32", "Trio64" };
  51.  
  52. /* Extended registers. */
  53.  
  54. #define S3_CR31        VGA_TOTAL_REGS + 0
  55. #define S3_CR32        VGA_TOTAL_REGS + 1
  56. #define S3_CR33        VGA_TOTAL_REGS + 2
  57. #define S3_CR34        VGA_TOTAL_REGS + 3
  58. #define S3_CR35        VGA_TOTAL_REGS + 4
  59. #define S3_CR3A        VGA_TOTAL_REGS + 5
  60. #define S3_CR3B        VGA_TOTAL_REGS + 6
  61. #define S3_CR3C        VGA_TOTAL_REGS + 7
  62. #define S3_CR40        VGA_TOTAL_REGS + 8
  63. #define S3_CR42        VGA_TOTAL_REGS + 9
  64. #define S3_CR43        VGA_TOTAL_REGS + 10
  65. #define S3_CR44        VGA_TOTAL_REGS + 11
  66. #define S3_CR50        VGA_TOTAL_REGS + 12    /* 801+ */
  67. #define S3_CR51        VGA_TOTAL_REGS + 13
  68. #define S3_CR53        VGA_TOTAL_REGS + 14
  69. #define S3_CR54        VGA_TOTAL_REGS + 15
  70. #define S3_CR55        VGA_TOTAL_REGS + 16
  71. #define S3_CR58        VGA_TOTAL_REGS + 17
  72. #define S3_CR59        VGA_TOTAL_REGS + 18
  73. #define S3_CR5A        VGA_TOTAL_REGS + 19
  74. #define S3_CR5D        VGA_TOTAL_REGS + 20
  75. #define S3_CR5E        VGA_TOTAL_REGS + 21
  76. #define S3_CR60        VGA_TOTAL_REGS + 22
  77. #define S3_CR61        VGA_TOTAL_REGS + 23
  78. #define S3_CR62        VGA_TOTAL_REGS + 24
  79. #define S3_CR67        VGA_TOTAL_REGS + 25
  80. #define S3_CR6D        VGA_TOTAL_REGS + 26
  81.  
  82. /* For debugging, these (non-)registers are read also (but never written). */
  83.  
  84. #define S3_CR36        VGA_TOTAL_REGS + 27
  85. #define S3_CR37        VGA_TOTAL_REGS + 28
  86. #define S3_CR38        VGA_TOTAL_REGS + 29
  87. #define S3_CR39        VGA_TOTAL_REGS + 30
  88. #define S3_CR3D        VGA_TOTAL_REGS + 31
  89. #define S3_CR3E        VGA_TOTAL_REGS + 32
  90. #define S3_CR3F        VGA_TOTAL_REGS + 33
  91. #define S3_CR45        VGA_TOTAL_REGS + 34
  92. #define S3_CR46        VGA_TOTAL_REGS + 35
  93. #define S3_CR47        VGA_TOTAL_REGS + 36
  94. #define S3_CR48        VGA_TOTAL_REGS + 37
  95. #define S3_CR49        VGA_TOTAL_REGS + 38
  96. #define S3_CR4A        VGA_TOTAL_REGS + 39
  97. #define S3_CR4B        VGA_TOTAL_REGS + 40
  98. #define S3_CR4C        VGA_TOTAL_REGS + 41
  99. #define S3_CR4D        VGA_TOTAL_REGS + 42
  100. #define S3_CR4E        VGA_TOTAL_REGS + 43
  101. #define S3_CR4F        VGA_TOTAL_REGS + 44
  102. #define S3_CR52        VGA_TOTAL_REGS + 45
  103. #define S3_CR56        VGA_TOTAL_REGS + 46
  104. #define S3_CR57        VGA_TOTAL_REGS + 47
  105. #define S3_CR5B        VGA_TOTAL_REGS + 48
  106. #define S3_CR5C        VGA_TOTAL_REGS + 49
  107. #define S3_CR5F        VGA_TOTAL_REGS + 50
  108. #define S3_CR63        VGA_TOTAL_REGS + 51
  109. #define S3_CR64        VGA_TOTAL_REGS + 52
  110. #define S3_CR65        VGA_TOTAL_REGS + 53
  111. #define S3_CR66        VGA_TOTAL_REGS + 54
  112.  
  113. #define S3_DAC_OFFSET    VGA_TOTAL_REGS + 55
  114.  
  115. #define S3_TOTAL_REGS    VGA_TOTAL_REGS + 55 + 10
  116.  
  117.  
  118. #define CHIP_IS_LOCALBUS() (s3_chiptype == S3_805 || s3_chiptype == S3_864)
  119.  
  120.  
  121. static int s3_chiptype;
  122. static int s3_memory;
  123. static CardSpecs *cardspecs;
  124. static DacMethods *dac_used;
  125.  
  126. static int s3_init(int, int, int);
  127.  
  128.  
  129. static void nothing() { }
  130.  
  131.  
  132. /* Fill in chipset specific mode information */
  133.  
  134. static void s3_unlock() {
  135.     outCR(0x38, 0x48);    /* Unlock special regs. */
  136.     outCR(0x39, 0xA5);    /* Unlock system control regs. */
  137.     if (s3_chiptype >= S3_864)
  138.         /* Unlock enhanced command regs. */
  139.         outCR(0x40, inCR(0x40) | 0x01); 
  140. }
  141.  
  142. static int s3_getmodeinfo( int mode, vga_modeinfo *modeinfo ) {
  143.         switch (modeinfo->colors) {
  144.                 case 16 :       /* 4-plane 16 color mode */
  145.                         modeinfo->maxpixels = 65536 * 8;
  146.                         break;
  147.                 default :
  148.                         modeinfo->maxpixels = s3_memory * 1024 /
  149.                                         modeinfo->bytesperpixel;
  150.                         break;
  151.         }
  152.     modeinfo->maxlogicalwidth = 2040;
  153.     modeinfo->startaddressrange = 0xfffff;
  154.     modeinfo->haveblit = 0;
  155.     modeinfo->flags &= ~HAVE_RWPAGE;
  156.     return 0;
  157. }
  158.  
  159.  
  160. /* Return non-zero if mode is available */
  161.  
  162. static int s3_modeavailable( int mode ) {
  163.     struct info *info;
  164.     ModeInfo *modeinfo;
  165.     ModeTiming *modetiming;
  166.  
  167.     if (mode < G640x480x256 || mode == G720x348x2)
  168.         return vga_driverspecs.modeavailable(mode);
  169.  
  170.     /* Enough memory? */
  171.     info = &__svgalib_infotable[mode];
  172.     if (s3_memory * 1024 < info->ydim * info->xbytes)
  173.         return 0;
  174.  
  175.     modeinfo = createModeInfoStructureForSvgalibMode(mode);
  176.  
  177.     modetiming = malloc(sizeof(ModeTiming));
  178.     if (getmodetiming(modetiming, modeinfo, cardspecs)) {
  179.         free(modetiming);
  180.         free(modeinfo);
  181.         return 0;
  182.     }
  183.     free(modetiming);
  184.     free(modeinfo);
  185.  
  186.     return SVGADRV;
  187. }
  188.  
  189.  
  190. static int s3_saveregs( unsigned char regs[] ) {
  191.         int i;
  192.  
  193.     s3_unlock();
  194.  
  195.      /* Save extended CRTC registers. */
  196.      regs[S3_CR31] = inCR(0x31);
  197.      regs[S3_CR32] = inCR(0x32);
  198.      regs[S3_CR33] = inCR(0x33);
  199.      regs[S3_CR34] = inCR(0x34);
  200.      regs[S3_CR35] = inCR(0x35);
  201.      regs[S3_CR3A] = inCR(0x3A);
  202.      regs[S3_CR3B] = inCR(0x3B);
  203.      regs[S3_CR3C] = inCR(0x3C);
  204.      regs[S3_CR40] = inCR(0x40);
  205.      regs[S3_CR42] = inCR(0x42);
  206.      regs[S3_CR43] = inCR(0x43);
  207.      regs[S3_CR44] = inCR(0x44);
  208.  
  209.     /* Non-registers, for debugging. */
  210.     regs[S3_CR36] = inCR(0x36);
  211.     regs[S3_CR37] = inCR(0x37);
  212.     regs[S3_CR38] = inCR(0x38);
  213.     regs[S3_CR39] = inCR(0x39);
  214.     regs[S3_CR3D] = inCR(0x3D);
  215.     regs[S3_CR3E] = inCR(0x3E);
  216.     regs[S3_CR3F] = inCR(0x3F);
  217.     regs[S3_CR45] = inCR(0x45);
  218.     regs[S3_CR46] = inCR(0x46);
  219.     regs[S3_CR47] = inCR(0x47);
  220.     regs[S3_CR48] = inCR(0x48);
  221.     regs[S3_CR49] = inCR(0x49);
  222.     regs[S3_CR4A] = inCR(0x4A);
  223.     regs[S3_CR4B] = inCR(0x4B);
  224.     regs[S3_CR4C] = inCR(0x4C);
  225.     regs[S3_CR4D] = inCR(0x4D);
  226.     regs[S3_CR4E] = inCR(0x4E);
  227.     regs[S3_CR4F] = inCR(0x4F);
  228.  
  229.      if (s3_chiptype >= S3_801) {
  230.          regs[S3_CR50] = inCR(0x50);
  231.          regs[S3_CR51] = inCR(0x51);
  232.          regs[S3_CR53] = inCR(0x53);
  233.          regs[S3_CR54] = inCR(0x54);
  234.          regs[S3_CR55] = inCR(0x55);
  235.          regs[S3_CR58] = inCR(0x58);
  236.          regs[S3_CR59] = inCR(0x59);
  237.          regs[S3_CR5A] = inCR(0x5A);
  238.          regs[S3_CR5D] = inCR(0x5D);
  239.          regs[S3_CR5E] = inCR(0x5E);
  240.          regs[S3_CR60] = inCR(0x60);
  241.          regs[S3_CR61] = inCR(0x61);
  242.          regs[S3_CR62] = inCR(0x62);
  243.  
  244.         if (dac_used->id == S3_SDAC) {
  245.              regs[S3_CR67] = inCR(0x67);
  246.              regs[S3_CR6D] = inCR(0x6D);
  247.         }
  248.  
  249.         /* Non-registers, for debugging. */
  250.         regs[S3_CR52] = inCR(0x52);
  251.         regs[S3_CR56] = inCR(0x56);
  252.         regs[S3_CR57] = inCR(0x57);
  253.         regs[S3_CR5B] = inCR(0x5B);
  254.         regs[S3_CR5C] = inCR(0x5C);
  255.         regs[S3_CR5F] = inCR(0x5F);
  256.         regs[S3_CR63] = inCR(0x63);
  257.         regs[S3_CR64] = inCR(0x64);
  258.         regs[S3_CR65] = inCR(0x65);
  259.         regs[S3_CR66] = inCR(0x66);
  260.      }
  261.  
  262.     dac_used->saveState(regs + S3_DAC_OFFSET);
  263.     return S3_DAC_OFFSET - VGA_TOTAL_REGS + dac_used->stateSize;
  264. }
  265.  
  266.  
  267. /* Set chipset-specific registers */
  268.  
  269. static void s3_setregs( const unsigned char regs[], int mode )
  270. {
  271.         int i;
  272.         
  273.     s3_unlock(); /* May be locked again by other programs (eg. X) */
  274.  
  275.      /* Write extended CRTC registers. */
  276.     outCR(0x31, regs[S3_CR31]);
  277.     outCR(0x32, regs[S3_CR32]);
  278.      outCR(0x33, regs[S3_CR33]);
  279.      outCR(0x34, regs[S3_CR34]);
  280.      outCR(0x35, regs[S3_CR35]);
  281.      outCR(0x3A, regs[S3_CR3A]);
  282.      outCR(0x3B, regs[S3_CR3B]);
  283.      outCR(0x3C, regs[S3_CR3C]);
  284.      outCR(0x40, regs[S3_CR40]);
  285.      outCR(0x42, regs[S3_CR42]);
  286.      outCR(0x43, regs[S3_CR43]);
  287.      outCR(0x44, regs[S3_CR44]);
  288.      if (s3_chiptype >= S3_801) {
  289.          outCR(0x50, regs[S3_CR50]);
  290.          outCR(0x51, regs[S3_CR51]);
  291.          outCR(0x53, regs[S3_CR53]);
  292.          outCR(0x54, regs[S3_CR54]);
  293.          outCR(0x55, regs[S3_CR55]);
  294.          outCR(0x58, regs[S3_CR58]);
  295.          outCR(0x59, regs[S3_CR59]);
  296.          outCR(0x5A, regs[S3_CR5A]);
  297.          outCR(0x5D, regs[S3_CR5D]);
  298.          outCR(0x5E, regs[S3_CR5E]);
  299.          outCR(0x60, regs[S3_CR60]);
  300.          outCR(0x61, regs[S3_CR61]);
  301.          outCR(0x62, regs[S3_CR62]);
  302.  
  303.         if (dac_used->id == S3_SDAC) {
  304.             unsigned char CR1;
  305.             printf("DAC clock state: 0x%02X 0x%02X\n",
  306.                 regs[S3_DAC_OFFSET + 3],
  307.                 regs[S3_DAC_OFFSET + 4]);
  308.             /* Blank the screen.*/
  309.             CR1 = inCR(0x01);
  310.             outCR(0x01, CR1 | 0x20);
  311.  
  312.             outbCR(0x55, inCR(0x55) | 1);
  313.  
  314.             outCR(0x67, regs[S3_CR67]);    /* S3 pixmux. */
  315.  
  316.             dac_used->restoreState(regs + S3_DAC_OFFSET);
  317.  
  318.             outCR(0x6D, regs[S3_CR6D]);
  319.  
  320.             outbCR(0x55, inCR(0x55) & ~1);
  321.  
  322.             outCR(0x01, CR1);    /* Unblank screen. */
  323.         }
  324.     }
  325. }
  326.  
  327.  
  328. /*
  329.  * Initialize register state for a mode.
  330.  */
  331.  
  332. static void s3_initializemode( unsigned char *moderegs,
  333. ModeTiming *modetiming, ModeInfo *modeinfo) {
  334.  
  335.     /* Get current values. */
  336.     s3_saveregs(moderegs);
  337.  
  338.     /* Set up the standard VGA registers for a generic SVGA. */
  339.     setup_VGA_registers(moderegs, modetiming, modeinfo);
  340.  
  341.     /* Set up the extended register values, including modifications */
  342.     /* of standard VGA registers. */
  343.  
  344.     moderegs[VGA_SR0] = 0x03;
  345.     moderegs[VGA_CR13] = modeinfo->lineWidth >> 3;
  346.     moderegs[VGA_CR17] = 0xE3;
  347.  
  348.     if (modeinfo->lineWidth == 2048)
  349.         moderegs[S3_CR31] = 0x8F;
  350.     else
  351.         moderegs[S3_CR31] = 0x8D;
  352. #ifdef LINEAR_MODE_BANKING_864
  353.     if (s3_chiptype >= S3_864) {
  354.         moderegs[S3_ENHANCEDMODE] |= 0x01;
  355.         /* Enable enhanced memory mode. */
  356.         moderegs[S3_CR31] |= 0x04;
  357.         /* Enable banking via CR6A in linear mode. */
  358.         moderegs[S3_CR31] |= 0x01;
  359.     }
  360. #endif
  361.     moderegs[S3_CR32] = 0;
  362.     moderegs[S3_CR33] = 0x20;
  363.     moderegs[S3_CR34] = 0x10;    /* 1024 */
  364.     moderegs[S3_CR35] = 0;
  365.     /* Call cebank() here when setting registers. */
  366.     moderegs[S3_CR3A] = 0xB5;
  367.  
  368.     moderegs[S3_CR3B] = (moderegs[VGA_CR0] + moderegs[VGA_CR4] + 1) / 2;
  369.     moderegs[S3_CR3C] = moderegs[VGA_CR0] / 2;
  370.     if (s3_chiptype == S3_911) {
  371.         moderegs[S3_CR40] &= 0xF2;
  372.         moderegs[S3_CR40] |= 0x09;
  373.     }
  374.     else if (CHIP_IS_LOCALBUS()) {
  375.         moderegs[S3_CR40] &= 0xF2;
  376.         /* Pegasus wants 0x01 for zero wait states. */
  377.         moderegs[S3_CR40] |= 0x05;
  378.     }
  379.     else {
  380.         moderegs[S3_CR40] &= 0xF6;
  381.         moderegs[S3_CR40] |= 0x01;
  382.     }
  383.     moderegs[S3_CR43] = 0;
  384.     if (modeinfo->bitsPerPixel >= 16 && s3_chiptype == S3_864)
  385.         moderegs[S3_CR43] = 0x08;
  386.     if (modeinfo->bitsPerPixel == 16 && dac_used->id == S3_GENDAC)
  387.         moderegs[S3_CR43] = 0x80;
  388.     /* 0x09 for other DACs at 16bpp. */
  389.  
  390.     moderegs[S3_CR44] = 0;
  391.     /* Skip CR45, 'hi/truecolor cursor color enable'. */
  392.  
  393.     if (s3_chiptype >= S3_801) {
  394.         /* XXXX Not all chips support all widths. */
  395.         int width;
  396.         moderegs[S3_CR50] &= ~0xF1;
  397.         width = modeinfo->lineWidth;
  398.         if (modeinfo->bitsPerPixel == 16)
  399.             moderegs[S3_CR50] |= 0x10;
  400.         if (modeinfo->bitsPerPixel == 32) {
  401.             moderegs[S3_CR50] |= 0x30;
  402.             width /= 4;
  403.         }
  404.         switch (modeinfo->lineWidth) {
  405.         case 640 : moderegs[S3_CR50] |= 0x40; break;
  406.         case 800 : moderegs[S3_CR50] |= 0x80; break;
  407.         case 1152: moderegs[S3_CR50] |= 0x01; break;
  408.         case 1280 : moderegs[S3_CR50] |= 0xC0; break;
  409.         case 1600 : moderegs[S3_CR50] |= 0x81; break;
  410.         /* 1024/2048 no change. */
  411.         }
  412.         moderegs[S3_CR51] &= 0xC0;
  413.         moderegs[S3_CR51] |= (modeinfo->lineWidth >> 7) & 0x30;
  414.         /* moderegs[S3_CR53] |= 0x10; */    /* Enable MMIO. */
  415.         /* For S3_805i with 2MB, OR with 0x20. */
  416.  
  417.         {
  418.         int m, n;
  419.         n = 0xFF;
  420.         if (s3_chiptype == S3_864) {
  421.             /* DRAM CRT FIFO balancing. */
  422.             int clock, mclk;
  423.             clock = modetiming->pixelClock *
  424.                 modeinfo->bytesPerPixel;
  425.             if (s3_memory < 2048)
  426.                 clock *= 2;
  427.             mclk = 60000;    /* Assumption. */
  428.             m = (int)((mclk/1000.0*.72+16.867)*89.736/(clock/1000.0+39)-21.1543);
  429.             if (s3_memory < 2048)
  430.                 m /= 2;
  431.             if (m > 31)
  432.                 m = 31;
  433.             else
  434.             if (m < 0) {
  435.                 m = 0;
  436.                 n = 16;
  437.             }
  438.         }
  439.         else if (s3_memory == 512 || modetiming->HDisplay > 1200)
  440.             m = 0;
  441.         else if (s3_memory == 1024)
  442.             m = 2;
  443.         else
  444.             m = 20;
  445.         moderegs[S3_CR54] = m << 3;
  446.         moderegs[S3_CR60] = n;
  447.         }
  448.  
  449.         moderegs[S3_CR55] &= 0x08;
  450.         moderegs[S3_CR55] |= 0x40;
  451.  
  452.         moderegs[S3_CR58] = 0;        /* s3SAM256 */
  453. #ifdef LINEAR_MODE_BANKING_864
  454.         if (s3_chiptype >= S3_864) {
  455.             /* Enable linear addressing. */
  456.             moderegs[S3_CR58] |= 0x10;
  457.             /* Set window size to 64K. */
  458.             moderegs[S3_CR58] &= ~0x03;
  459.             /* Assume CR59/5A are correctly set up for 0xA0000. */
  460.             /* Set CR6A linear bank to zero. */
  461.             moderegs[S3_CR6A] &= ~0x3F;
  462.         }
  463. #endif
  464.         moderegs[S3_CR59] = 0;
  465.         moderegs[S3_CR5A] = 0x0A;
  466.  
  467.         /* Extended CRTC timing. */
  468.         moderegs[S3_CR5E] =
  469.             (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) |
  470.             (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) |
  471.             (((modetiming->CrtcVSyncStart) & 0x400) >> 8)  |
  472.             (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40;
  473.  
  474.         {
  475.         int i, j;
  476.         i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) |
  477.             ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) |
  478.             ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) |
  479.             ((modetiming->CrtcHSyncStart & 0x800) >> 7);
  480.         j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) +
  481.             moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2);
  482.         moderegs[S3_CR3B] = j & 0xFF;
  483.         i |= (j & 0x100) >> 2;
  484.         /* Interlace mode frame offset. */
  485.         moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2;
  486.         moderegs[S3_CR5D] &= ~0x57;
  487.         moderegs[S3_CR5D] |= i;
  488.         }
  489.  
  490.         {
  491.         int i;
  492. #if 0    /* This seems wrong. Why doesn't XF86_S3 have problems? */
  493.         if (s3_chiptype == S3_864 && s3_memory > 1024)
  494.             i = modetiming->HDisplay *
  495.                 modeinfo->bytesPerPixel / 8 + 1;
  496.         else
  497. #endif
  498.             i = modetiming->HDisplay *
  499.                 modeinfo->bytesPerPixel / 4 + 1;
  500.         moderegs[S3_CR61] = (i >> 8) | 0x80;
  501.         moderegs[S3_CR62] = i & 0xFF;
  502.         }
  503.     } /* 801+ */
  504.  
  505.     if (modetiming->flags & INTERLACED)
  506.         moderegs[S3_CR42] |= 0x20;
  507.  
  508.     /*
  509.      * Clock select works as follows:
  510.      * Clocks 0 and 1 (VGA 25 and 28 MHz) can be selected via the
  511.      * two VGA MiscOutput clock select bits.
  512.      * If 0x3 is written to these bits, the selected clock index
  513.      * is taken from the S3 clock select register at CR43. Clock
  514.      * indices 0 and 1 should correspond to the VGA ones above,
  515.      * and 3 is often 0 MHz, followed by extended clocks for a
  516.      * total of mostly 16.
  517.      */
  518.  
  519.     if (modetiming->flags & USEPROGRCLOCK)
  520.         moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */
  521.     else
  522.     if (modetiming->selectedClockNo < 2) {
  523.         /* Program clock select bits 0 and 1. */
  524.         moderegs[VGA_MISCOUTPUT] &= ~0x0C;
  525.         moderegs[VGA_MISCOUTPUT] |=
  526.             (modetiming->selectedClockNo & 3) << 2;
  527.     }
  528.     else
  529.     if (modetiming->selectedClockNo >= 2) {
  530.         moderegs[VGA_MISCOUTPUT] |= 0x0C;
  531.         /* Program S3 clock select bits. */
  532.         moderegs[S3_CR43] &= ~0x1F;
  533.         moderegs[S3_CR43] |=
  534.             modetiming->selectedClockNo;
  535.     }
  536.  
  537.     if (s3_chiptype == S3_TRIO64) {
  538.         moderegs[S3_CR33] &= ~0x08;
  539.         if (modeinfo->bitsPerPixel == 16)
  540.             moderegs[S3_CR33] |= 0x08;
  541.         /*
  542.          * The rest of the DAC/clocking is setup by the
  543.          * Trio64 code in the RAMDAC interface (ramdac.c).
  544.          */
  545.     }
  546.     else
  547.     if (dac_used->id != NORMAL_DAC) {
  548.         int colormode;
  549.         moderegs[VGA_MISCOUTPUT] |= 0x0C; /* Enable CR42 clock sel. */
  550.         colormode = colorbits_to_colormode(modeinfo->colorBits);
  551.         dac_used->initializeState(&moderegs[S3_DAC_OFFSET],
  552.             modeinfo->bitsPerPixel, colormode,
  553.             modetiming->pixelClock);
  554.  
  555.         if (dac_used->id == S3_SDAC) {
  556.             int pixmux, invert_vclk, blank_delay;
  557.             pixmux = 0;
  558.             invert_vclk = 0;
  559.             blank_delay = 0;
  560.             if (colormode == CLUT8_6
  561.             && modetiming->pixelClock >= 67500) {
  562.                 pixmux = 0x10;
  563.                 invert_vclk = 1;
  564.                 blank_delay = 2;
  565.             }
  566.             else
  567.             if (colormode == RGB16_555) {
  568.                 pixmux = 0x30;
  569.                 blank_delay = 2;
  570.             }
  571.             else
  572.             if (colormode == RGB16_565) {
  573.                 pixmux = 0x50;
  574.                 blank_delay = 2;
  575.             }
  576.             else
  577.             if (colormode == RGB32_888_B) {
  578.                 pixmux = 0x70;
  579.                 blank_delay = 2;
  580.             }
  581.             moderegs[S3_CR67] = pixmux | invert_vclk;
  582.             moderegs[S3_CR6D] = blank_delay;
  583.             /* Clock select. */
  584.             moderegs[S3_CR42] &= ~0x0F;
  585.             moderegs[S3_CR42] |= 0x02;
  586.         }
  587.     }
  588. }
  589.  
  590.  
  591. /* Set a mode */
  592.  
  593. static int s3_setmode( int mode, int prv_mode ) {
  594.     ModeInfo *modeinfo;
  595.     ModeTiming *modetiming;
  596.     unsigned char *moderegs;
  597.  
  598.     if (mode < G640x480x256 || mode == G720x348x2)
  599.         /* Let the standard VGA driver set standard VGA modes. */
  600.         return vga_driverspecs.setmode(mode, prv_mode);
  601.     if (!s3_modeavailable(mode))
  602.         return 1;
  603.  
  604.     modeinfo = createModeInfoStructureForSvgalibMode(mode);
  605.  
  606.     modetiming = malloc(sizeof(ModeTiming));
  607.     if (getmodetiming(modetiming, modeinfo, cardspecs)) {
  608.         free(modetiming);
  609.         free(modeinfo);
  610.         return 1;
  611.     }
  612.  
  613.     /* Adjust the display width. */
  614.     if (s3_chiptype < S3_801)
  615.         modeinfo->lineWidth = 1024;
  616.     else {
  617.         if (modeinfo->lineWidth <= 640)
  618.             modeinfo->lineWidth = 640;
  619.         else
  620.         if (modeinfo->lineWidth <= 800)
  621.             modeinfo->lineWidth = 800;
  622.         else
  623.         if (modeinfo->lineWidth <= 1024)
  624.             modeinfo->lineWidth = 1024;
  625.         else
  626.         if (modeinfo->lineWidth <= 1152)
  627.             modeinfo->lineWidth = 1152;
  628.         else
  629.         if (modeinfo->lineWidth <= 1280)
  630.             modeinfo->lineWidth = 1280;
  631.         else
  632.         if (modeinfo->lineWidth <= 1600)
  633.             modeinfo->lineWidth = 1600;
  634.     }
  635.  
  636.     moderegs = malloc(S3_TOTAL_REGS);
  637.  
  638.     s3_initializemode(moderegs, modetiming, modeinfo);
  639.     free(modeinfo);
  640.     free(modetiming);
  641.  
  642.     __vga_setregs(moderegs);    /* Set standard regs. */
  643.     s3_setregs(moderegs, mode);    /* Set extended regs. */
  644.     free(moderegs);
  645.     return 0;
  646. }
  647.  
  648.  
  649. /* Indentify chipset; return non-zero if detected */
  650.  
  651. /* Some port I/O functions: */
  652. static unsigned char rdinx( int port, unsigned char index )
  653. {
  654.     outb(port, index);
  655.     return inb(port + 1);
  656. }
  657.  
  658. static void wrinx( int port, unsigned char index, unsigned char val )
  659. {
  660.     outb(port, index);
  661.     outb(port + 1, val);
  662. }
  663.  
  664. /*
  665.  * Returns true iff the bits in 'mask' of register 'port', index 'index'
  666.  * are read/write.
  667.  */
  668. static int testinx2( int port, unsigned char index, unsigned char mask)
  669. {
  670.     unsigned char old, new1, new2;
  671.  
  672.     old = rdinx(port, index);
  673.     wrinx(port, index, (old & ~mask));
  674.     new1 = rdinx(port, index) & mask;
  675.     wrinx(port, index, (old | mask));
  676.     new2 = rdinx(port, index) & mask;
  677.     wrinx(port, index, old);
  678.     return (new1 == 0) && (new2 == mask);
  679. }
  680.  
  681. static int s3_test()
  682. {
  683.     int vgaIOBase, vgaCRIndex, vgaCRReg;
  684.  
  685.     vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
  686.     vgaCRIndex = vgaIOBase + 4;
  687.     vgaCRReg = vgaIOBase + 5;
  688.  
  689.     outb(vgaCRIndex, 0x11);    /* for register CR11, (Vertical Retrace End) */
  690.     outb(vgaCRReg, 0x00);    /* set to 0 */
  691.  
  692.     outb(vgaCRIndex, 0x38);    /* check if we have an S3 */
  693.     outb(vgaCRReg, 0x00);
  694.  
  695.     /* Make sure we can't write when locked */
  696.  
  697.     if (testinx2(vgaCRIndex, 0x35, 0x0f))
  698.         return 0;
  699.  
  700.     outb(vgaCRIndex, 0x38);    /* for register CR38, (REG_LOCK1) */
  701.     outb(vgaCRReg, 0x48);    /* unlock S3 register set for read/write */
  702.  
  703.     /* Make sure we can write when unlocked */
  704.  
  705.     if (!testinx2(vgaCRIndex, 0x35, 0x0f))
  706.         return 0;
  707.  
  708.     if (s3_init(0, 0, 0))    /* type not OK */
  709.         return 0;
  710.     return 1;
  711. }
  712.  
  713.  
  714. /* Bank switching function - set 64K bank number */
  715.  
  716. static void s3_setpage( int page ) {
  717. #ifdef LINEAR_MODE_BANKING_864
  718.     if (s3_chiptype >= S3_864) {
  719.         /* "Linear" mode banking. */
  720.         outb(0x3D4, 0x6A);
  721.         outb(0x3D5, (inb(0x3D5) & ~0x3F) | page);
  722.         return;
  723.     }
  724. #endif
  725.     outb(0x3d4, 0x35);
  726.     outb(0x3d5, (inb(0x3d5) & 0xF0) | (page & 0x0F));
  727.     outb(0x3d4, 0x51);
  728.     outb(0x3d5, (inb(0x3d5) & ~0x0C) | ((page & 0x30) >> 2));
  729. }
  730.  
  731.  
  732. /* Set display start address (not for 16 color modes) */
  733.  
  734. /* This works up to 1Mb (should be able to go higher). */
  735. static int s3_setdisplaystart( int address ) {
  736.     outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256);    /* sa2-sa9 */
  737.     outw(0x3d4, 0x0c + ((address >> 2) & 0xff00));        /* sa10-sa17 */
  738.     inb(0x3da);            /* set ATC to addressing mode */
  739.     outb(0x3c0, 0x13 + 0x20);    /* select ATC reg 0x13 */
  740.     outb(0x3c0, (inb(0x3c1) & 0xf0) | ((address & 3) << 1));
  741.         /* write sa0-1 to bits 1-2 */
  742.  
  743.     outb(0x3d4, 0x31);
  744.     /* XXXX This destroys bits for 2048 linewidth. */
  745.     outb(0x3d5, ((address & 0xc0000) >> 14) | 0x8d);
  746.     return 0;
  747. }
  748.  
  749.  
  750. /* Set logical scanline length (usually multiple of 8) */
  751. /* Multiples of 8 to 2040 */
  752.  
  753. static int s3_setlogicalwidth( int width ) { 
  754.     outw(0x3d4, 0x13 + (width >> 3) * 256);    /* lw3-lw11 */
  755.     return 0;
  756. }
  757.  
  758.  
  759. /* Function table (exported) */
  760.  
  761. DriverSpecs s3_driverspecs = {
  762.     s3_saveregs,        /* saveregs */
  763.     s3_setregs,        /* setregs */
  764.     (int (*)()) nothing,    /* unlock */
  765.     (int (*)()) nothing,    /* lock */
  766.     s3_test,
  767.     s3_init,
  768.     (int (*)()) s3_setpage,
  769.     (int (*)()) nothing,
  770.     (int (*)()) nothing,
  771.     s3_setmode,
  772.     s3_modeavailable,
  773.     s3_setdisplaystart,
  774.     s3_setlogicalwidth,
  775.     s3_getmodeinfo,
  776.     0,    /* bitblt */
  777.     0,    /* imageblt */
  778.     0,    /* fillblt */
  779.     0,    /* hlinelistblt */
  780.     0,    /* bltwait */
  781.     0,    /* extset */
  782.     0,
  783.     0,    /* linear */
  784.     NULL    /* accelspecs */
  785. };
  786.  
  787.  
  788. /* S3-specific config file options. */
  789.  
  790. /*
  791.  * Currently this only handles Clocks. It would a good idea to have
  792.  * higher-level code process options like Clocks that are valid for
  793.  * more than one driver driver (with better error detection etc.).
  794.  */
  795.  
  796. static char *s3_config_options[] = {
  797.     "clocks", "ramdac", NULL
  798. };
  799.  
  800. static char *s3_process_option( int option, int mode ) {
  801. /*
  802.  * option is the number of the option string in s3_config_options,
  803.  * mode seems to be a 'hardness' indicator for security.
  804.  */
  805.     if (option == 0) {    /* "Clocks" */
  806.         /* Process at most 16 specified clocks. */
  807.         cardspecs->clocks = malloc(sizeof(int) * 16);
  808.         /* cardspecs->nClocks should be already be 0. */
  809.         for (;;) {
  810.             char *ptr;
  811.             int freq;
  812.             ptr = strtok(NULL, " ");
  813.             if (ptr == NULL)
  814.                 break;
  815.             /*
  816.              * This doesn't protect against bad characters
  817.              * (atof() doesn't detect errors).
  818.              */
  819.             freq = atof(ptr) * 1000;
  820.             cardspecs->clocks[cardspecs->nClocks] = freq;
  821.             cardspecs->nClocks++;
  822.             if (cardspecs->nClocks == 16)
  823.                 break;
  824.         }
  825.     }
  826.     if (option == 1) {    /* "Ramdac" */
  827.         char *ptr;
  828.         ptr = strtok(NULL, " ");
  829.         if (strcasecmp(ptr, "Sierra32K") == 0)
  830.             dac_used = &Sierra_32K_methods;
  831.         if (strcasecmp(ptr, "SDAC") == 0)
  832.             dac_used = &S3_SDAC_methods;
  833.         if (strcasecmp(ptr, "GenDAC") == 0)
  834.             dac_used = &S3_GENDAC_methods;
  835.     }
  836.     return strtok(NULL, " ");
  837. }
  838.  
  839.  
  840. /* Initialize driver (called after detection) */
  841. /* Derived from XFree86 SuperProbe and s3 driver. */
  842.  
  843. static DacMethods *dacs_to_probe[] = { &S3_SDAC_methods, NULL };
  844.  
  845. static int s3_init( int force, int par1, int par2) {
  846.     int id, rev, tmp, config;
  847.  
  848.     s3_unlock();
  849.  
  850.     if (force) {
  851.         s3_chiptype = par1;    /* we already know the type */
  852.         s3_memory = par2;
  853.     }
  854.     else {
  855.         id = inCR(0x30);    /* Get chip id. */
  856.         rev = id & 0x0F;
  857.         if (id >= 0xE0) {
  858.             id |= inCR(0x2E) << 8;
  859.             rev |= inCR(0x2F) << 4;
  860.         }
  861.  
  862.         s3_chiptype = -1;
  863.         switch (id & 0xf0) {
  864.         case 0x80 :
  865.             if (rev == 1) {
  866.                 s3_chiptype = S3_911;
  867.                 break;
  868.             }
  869.             if (rev == 2) {
  870.                 s3_chiptype = S3_924;
  871.                 break;
  872.             }
  873.             break;
  874.         case 0xa0 :
  875.             outb(0x3d4, 0x36);
  876.             tmp = inb(0x3d5);
  877.             switch (tmp & 0x03) {
  878.             case 0x00:
  879.             case 0x01:
  880.                 /* EISA or VLB - 805 */
  881.                 s3_chiptype = S3_805;
  882.                 break;
  883.             case 0x03:
  884.                 /* ISA - 801 */
  885.                 s3_chiptype = S3_801;
  886.                 break;
  887.             }
  888.             break;
  889.         case 0x90:
  890.             s3_chiptype = S3_928;
  891.             break;
  892.         case 0xB0 :
  893.             /* 928P */
  894.             s3_chiptype = S3_928;
  895.             break;
  896.         case 0xC0 :
  897.             s3_chiptype = S3_864; break;
  898.         case 0xD0 :
  899.             s3_chiptype = S3_964; break;
  900.         case 0x10E0 :
  901.             s3_chiptype = S3_TRIO32; break;
  902.         case 0x11E0 :
  903.             s3_chiptype = S3_TRIO64; break;
  904.         }
  905.         if (s3_chiptype == -1) {
  906.             printf("svgalib: S3: Unknown chip id %02x\n",
  907.                 id);
  908.             return -1;
  909.         }
  910.  
  911.         outb(0x3d4, 0x36);    /* for register CR36 (CONFG_REG1), */
  912.         config = inCR(0x36);    /* get amount of ram installed */
  913.  
  914.         if ((config & 0x20) != 0)
  915.             s3_memory = 512;
  916.         else
  917.             if (s3_chiptype == S3_911)
  918.                 s3_memory = 1024;
  919.             else
  920.                 /* look at bits 5, 6 and 7 */
  921.                 switch ((config & 0xE0) >> 5) {
  922.                 case 0 : s3_memory = 4096; break;
  923.                 case 2 : s3_memory = 3072; break;
  924.                 case 3 : s3_memory = 8192; break;
  925.                 case 4 : s3_memory = 2048; break;
  926.                 case 5 : s3_memory = 6144; break;
  927.                 case 6 : s3_memory = 1024; break;
  928.                 }
  929.     }
  930.  
  931. #if 0
  932.     if (s3_chiptype != S3_864) {
  933.         printf("svgalib: s3: Sorry, only S3-864 is currently supported.\n");
  934.         return -1;
  935.     }
  936. #endif
  937.  
  938.  
  939. /* begin: Initialize cardspecs. */
  940.     cardspecs = malloc(sizeof(CardSpecs));
  941.     cardspecs->videoMemory = s3_memory;
  942.     cardspecs->nClocks = 0;
  943.     cardspecs->maxHorizontalCrtc = 4088;
  944.     cardspecs->flags = INTERLACE_DIVIDE_VERT;
  945.  
  946.     /* Process S3-specific config file options. */
  947.     __svgalib_read_options(s3_config_options, s3_process_option);
  948.  
  949.      if (s3_chiptype == S3_TRIO64) {
  950.          dac_used = &Trio64_methods;
  951.          dac_used->initialize();
  952.      }
  953.  
  954.      if (dac_used == NULL)
  955.          dac_used = probeDacs(dacs_to_probe);
  956.  
  957.     if (dac_used == NULL) {
  958.         /* Not supported. */
  959.         printf("svgalib: s3: Assuming normal VGA DAC.\n");
  960.         dac_used = &normal_dac_methods;
  961.     }
  962.  
  963.     dac_used->qualifyCardSpecs(cardspecs);
  964.  
  965.     /* Initialize standard clocks for unknown DAC. */
  966.     if (!(cardspecs->flags & CLOCK_PROGRAMMABLE)
  967.     && cardspecs->nClocks == 0) {
  968.         /*
  969.          * Almost all cards have 25 and 28 MHz on VGA clocks 0 and 1,
  970.          * so use these for an unknown DAC, yielding 640x480x256.
  971.          */
  972.         cardspecs->nClocks = 2;
  973.         cardspecs->clocks = malloc(sizeof(int) * 2);
  974.         cardspecs->clocks[0] = 25175;
  975.         cardspecs->clocks[1] = 28322;
  976.     }
  977.  
  978.     /* Limit pixel clocks according to chip specifications. */
  979.     if (s3_chiptype == S3_864) {
  980.         /* Limit max clocks according to 95 MHz DCLK spec. */
  981.         LIMIT(cardspecs->maxPixelClock4bpp, 95000);
  982.         LIMIT(cardspecs->maxPixelClock8bpp, 95000 * 2);
  983.         LIMIT(cardspecs->maxPixelClock16bpp, 95000);
  984.         /*
  985.          * The official 32bpp limit is 47500, but we allow
  986.          * 50 MHz for VESA 800x600 timing (actually the
  987.          * S3-864 doesn't have the horizontal timing range
  988.          * to run unmodified VESA 800x600 72 Hz timings).
  989.          */
  990.         LIMIT(cardspecs->maxPixelClock32bpp, 50000);
  991.     }
  992.     cardspecs->maxPixelClock4bpp = 0;    /* 16-color doesn't work. */
  993. /* end: Initialize cardspecs. */
  994.  
  995.     if (__svgalib_driver_report) {
  996.         printf("Using S3 driver (%s, %dK).\n", s3_chipname[s3_chiptype],
  997.             s3_memory);
  998.     }
  999. #if 0
  1000.     if (getenv("SVGALIB_TRY_S3") == NULL) {
  1001.         printf("The S3 driver in svgalib probably doesn't work. If you want to try it anyway,\n"
  1002.                "define the environment variable SVGALIB_TRY_S3.\n");
  1003.         return 1;
  1004.     }
  1005. #endif
  1006.     driverspecs = &s3_driverspecs;
  1007.  
  1008.     return 0;
  1009. }
  1010.