home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / et4000.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-11  |  27.0 KB  |  1,137 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. /* partially copyrighted (C) 1993 by Hartmut Schirmer */
  9.  
  10. /* ET4000 code taken from VGAlib
  11.  * ET4000 code modified to handle HiColor modes better by David Monro
  12.  * Dynamic register loading by Hartmut Schirmer
  13.  * HH: ET4000/W32 detection added and support for more than 1Mb (based on
  14.  *     vgadoc3) (untested).
  15.  * HH: Detect newer ET4000/W32p.
  16.  */
  17.  
  18.  
  19. /* Note that the clock detection stuff is currently not used. */
  20.  
  21. /* ET4000 registers description (from vgadoc2)
  22. **
  23. **
  24. **
  25. ** 102h: Microchannel Setup Control
  26. ** bit 0  Disable Card if set
  27. **
  28. ** 3BFh (R/W): Hercules Compatability register
  29. ** 
  30. ** 3C0h index 16h: ATC Miscellaneous
  31. **    (Write data to 3C0h, Read from 3C1h  (May not be needed))
  32. ** bit 4,5  High resolution timings.
  33. **       7  Bypass the internal palette if set
  34. **
  35. ** 3C3h (R/W): Microchannel Video Subsystem Enable Register:
  36. ** bit 0  Enable Microchannel VGA if set
  37. **
  38. ** 3C4h index  6  (R/W): TS State Control
  39. ** bit 1-2  dots per characters in text mode 
  40. **        (bit 0: 3c4 index 1, bit 0)
  41. **        bit <2:0>    ! dots/char
  42. **        111    !    16
  43. **        100    !    12
  44. **        011    !    11
  45. **        010    !    10
  46. **        001    !     8
  47. **        000    !     9
  48. **
  49. ** 3C4h index  7  (R/W): TS Auxiliary Mode
  50. ** bit 0  If set select MCLK/4 (if bit 6 is also set to 1)
  51. **     1  If set select SCLK input from MCLK
  52. **   3,5  Rom Bios Enable/Disable:
  53. **      0 0  C000-C3FF Enabled
  54. **      0 1  Rom disabled
  55. **      1 0  C000-C5FF,C680-C7FF Enabled
  56. **      1 1  C000-C7FF Enabled
  57. **     6  MCLK/2 if set
  58. **     7  VGA compatible if set EGA else.
  59. **
  60. ** 3CBh (R/W): PEL Address/Data Wd
  61. **  
  62. ** 3CDh (R/W): Segment Select
  63. **     0-3  64k Write bank nr (0..15)
  64. **     4-7  64k Read bank nr (0..15)
  65. **
  66. ** 3CEh index  Dh (R/W): Microsequencer Mode
  67. **
  68. ** 3CEh index  Eh (R/W): Microsequencer Reset 
  69. **
  70. ** 3d4h index 24h (R/W): Compatibility Control
  71. ** bit 0  Enable Clock Translate
  72. **     1  Additional Master Clock Select
  73. **     2  Enable tri-state for all output pins
  74. **     3  Enable input A8 of 1MB DRAMs
  75. **     4  Reserved
  76. **     5  Enable external ROM CRTC translation
  77. **     6  Enable Double Scan and Underline Attribute
  78. **     7  CGA/MDA/Hercules
  79. **
  80. ** 3d4h index 32h (R/W): RAS/CAS Video Config
  81. **       Ram timing, System clock and Ram type. Sample values:
  82. **       00h  VRAM  80nsec
  83. **       09h  VRAM 100nsec
  84. **       00h  VRAM  28MHz
  85. **       08h  VRAM  36MHz
  86. **       70h  DRAM  40MHz
  87. **
  88. ** 3d4h index 33h (R/W): Extended start ET4000 
  89. ** bit 0-1  Display start address bits 16-17
  90. **     2-3  Cursor start address bits 16-17
  91. **      Can be used to ID ET4000
  92. **
  93. ** 3d4h index 34h (R/W): Compatibility Control Register
  94. ** bit 2  bit 3 of clock select (bit 1-0 in misc output)
  95. **     3  if set Video Subsystem Enable Register at 46E8h
  96. **          else at 3C3h.
  97. **
  98. ** 3d4h index 35h (R/W): Overflow High ET4000
  99. ** bit 0  Vertical Blank Start Bit 10
  100. **     1  Vertical Total Bit 10
  101. **     2  Vertical Display End Bit 10
  102. **     3  Vertical Sync Start Bit 10
  103. **     4  Line Compare Bit 10
  104. **     5  Gen-Lock Enabled if set (External sync)
  105. **     6  Read/Modify/Write Enabled if set. Currently not implemented.
  106. **     7  Vertical interlace if set
  107. **
  108. ** 3d4h index 36h (R/W): Video System Configuration 1
  109. ** bit 0-2 Refresh count per line - 1
  110. **     3   16 bit wide fonts if set, else 8 bit wide
  111. **     4   Linear addressing if set. Video Memory is 
  112. **         mapped as a 1 Meg block above 1MB. (set
  113. **       GDC index 6 bits 3,2 to zero (128k))
  114. **     5   TLI addressing mode if set
  115. **     6   16 bit data path (video memory) if set
  116. **     7   16 bit data (I/O operations) if set
  117. **
  118. ** 3d4h index 37h (R/W): Video System Configuration 2
  119. ** bit 0-1  Display memory data bus width
  120. **          0,1=8bit, 2=16bit, 3=32bit; may be
  121. **        read as number of memory banks (1,2,4)
  122. **     2  Bus read data latch control. If set latches
  123. **        databus at end of CAS cycle else one clock delay
  124. **       3  Clear if 64kx4 RAMs                   ???
  125. **      if set RAM size = (bit 0-1)*256k
  126. **        else RAM size = (bit 0-1)* 64k
  127. **       4  16 bit ROM access if set
  128. **       5  Memory bandwidth (0 better than 1) ???
  129. **       6  TLI internal test mode if set 
  130. **       7  VRAM installed if set DRAM else.
  131. **
  132. ** 3d4h index 3Fh (R/W):
  133. ** bit   7  This bit seems to be bit 8 of the CRTC offset register (3d4h index 13h).
  134. **
  135. ** 3d8h (R/W): Display Mode Control
  136. **
  137. ** 46E8h (R):  Video Subsystem Enable Register
  138. ** bit   3  Enable VGA if set
  139. **
  140. **
  141. **       3C4h index 05 used.
  142. ** 
  143. **
  144. **  Bank Switching:
  145. **
  146. **     64k banks are selected by the Segment Select Register at 3CDh.
  147. **     Both a Read and a Write segment can be selected.
  148. **
  149. **  The sequence: 
  150. **
  151. **      port[$3BF]:=3;
  152. **      port[$3D8]:=$A0;
  153. **
  154. **  is apparently needed to enable the extensions in the Tseng 4000.
  155. **
  156. **
  157. **  Used extended ET4000 registers (EXT+xx) :
  158. **
  159. **    00 : CRT (3d4) index 30
  160. **    01 : CRT (3d4) index 31
  161. **    02 : CRT (3d4) index 32
  162. **    03 : CRT (3d4) index 33
  163. **    04 : CRT (3d4) index 34
  164. **    05 : CRT (3d4) index 35
  165. **    06 : CRT (3d4) index 36
  166. **    07 : CRT (3d4) index 37
  167. **    08 : CRT (3d4) index 3f
  168. **    09 : SEQ (3c4) index 07
  169. **    0A : Microchannel register (3c3)
  170. **    0B : Segment select (3cd)
  171. **    0C : ATT (3c0) index 16
  172. **
  173. */
  174.  
  175. #include <stdlib.h>
  176. #include <stdio.h>
  177. #include <unistd.h>
  178. #include <stdarg.h>
  179. #include "vga.h"
  180. #include "libvga.h"
  181. #include "driver.h"
  182. #include "config.h"
  183.  
  184. #define SEG_SELECT 0x3CD
  185.  
  186. #define CHIP_ET4000    0    /* Chip types. */
  187. #define CHIP_ET4000W32    1
  188. #define CHIP_ET4000W32i    2
  189. #define CHIP_ET4000W32p    3
  190.  
  191. static char *chipname[] = {
  192.     "ET4000",
  193.     "ET4000/W32",
  194.     "ET4000/W32i",
  195.     "ET4000/W32p"
  196. };
  197.  
  198. static int et4000_memory;
  199. static int et4000_chiptype;
  200.  
  201. static int et4000_init( int, int );
  202. static int et4000_interlaced( int mode );
  203. static int et4000_unlock();
  204.  
  205. static int et4000_extdac;
  206. static int pos_ext_settings, ext_settings;
  207.  
  208. /* Mode table */
  209. #if defined(DYNAMIC)
  210.  
  211. static ModeTable *et4000_modes = NULL;
  212. static ModeTable No_Modes = END_OF_MODE_TABLE;
  213.  
  214. #else /* !defined(DYNAMIC) */
  215.  
  216. #include "et4000.regs" 
  217.  
  218. #ifdef DAC_TYPE
  219. static int et4000_dac = DAC_TYPE;
  220. #endif
  221.  
  222. static ModeTable et4000_modes[] = {
  223.     OneModeEntry(320x200x32K),
  224.     OneModeEntry(320x200x64K),
  225.     OneModeEntry(320x200x16M),
  226.     OneModeEntry(640x480x256),
  227.     OneModeEntry(640x480x32K),
  228.     OneModeEntry(640x480x64K),
  229.     OneModeEntry(640x480x16M),
  230.     OneModeEntry(800x600x16),
  231.     OneModeEntry(800x600x256),
  232.     OneModeEntry(800x600x32K),
  233.     OneModeEntry(800x600x64K),
  234.     OneModeEntry(1024x768x16),
  235.     OneModeEntry(1024x768x256),
  236.     OneModeEntry(1280x1024x16),
  237.     END_OF_MODE_TABLE  
  238. };
  239.  
  240. #endif /* !defined(DYNAMIC) */
  241.  
  242. #ifndef DAC_TYPE
  243. static int et4000_dac = -1;
  244. #endif
  245.  
  246. static void dactocomm() {
  247.     inb(0x3c8);    /* set PEL mode */
  248.     inb(0x3c6);    /* read four times */
  249.     inb(0x3c6);
  250.     inb(0x3c6);
  251.     inb(0x3c6);    
  252. }
  253.  
  254. static void dactopel() {
  255.     inb(0x3c8);
  256. }
  257.  
  258. /* Fill in chipset specific mode information */
  259.  
  260. static int et4000_getmodeinfo( int mode, vga_modeinfo *modeinfo ) {
  261.     switch (modeinfo->colors) {
  262.         case 16 :    /* 4-plane 16 color mode */
  263.             modeinfo->maxpixels = 65536 * 8;
  264.             break;
  265.         default :
  266.             if (modeinfo->bytesperpixel > 0)
  267.                 modeinfo->maxpixels = et4000_memory * 1024 / 
  268.                     modeinfo->bytesperpixel;
  269.             else
  270.                 modeinfo->maxpixels = et4000_memory * 1024;
  271.             break;
  272.     }
  273.     modeinfo->maxlogicalwidth = 4088;
  274.     modeinfo->startaddressrange = 0xfffff;
  275.     if (mode == G320x200x256)
  276.         modeinfo->startaddressrange = 0;
  277.     modeinfo->haveblit = 0;
  278.     modeinfo->memory = et4000_memory * 1024;
  279.     modeinfo->flags |= HAVE_RWPAGE | HAVE_EXT_SET;
  280.     if (et4000_interlaced(mode))
  281.       modeinfo->flags |= IS_INTERLACED;
  282.       if (et4000_chiptype != CHIP_ET4000)
  283.         modeinfo->flags |= EXT_INFO_AVAILABLE | CAPABLE_LINEAR;
  284.     return 0;
  285. }
  286.  
  287.  
  288. /* ----------------------------------------------------------------- */
  289. /* Set/get the actual clock frequency */
  290.  
  291. #ifndef CLOCKS
  292. #  define CLOCKS 24
  293. #endif
  294. #ifndef CLOCK_VALUES
  295. #  define CLOCK_VALUES { 0 }
  296. #endif
  297.  
  298. static unsigned clocks[CLOCKS] = CLOCK_VALUES;
  299.  
  300.  
  301. #ifdef USE_CLOCKS
  302.  
  303. /* Only include the rest of the clock stuff if USE_CLOCKS is defined. */
  304.  
  305. static int et4000_clocks(int clk) {
  306.     unsigned char temp;
  307.     int res;
  308.  
  309.     /* get actual clock */
  310.     res = (inb(MIS_R)>>2) & 3;    /* bit 0..1 */
  311.     outb(CRT_I, 0x34); 
  312.     res |= (inb(CRT_D) & 2) << 1; /* bit 2 */
  313.     outb(SEQ_I, 0x07);
  314.     temp = inb(SEQ_D);
  315.     if (temp & 0x41 == 0x41) 
  316.         res |= 0x10;        /* bit 3..4 */
  317.     else  
  318.         res |= (temp&0x40) >> 3;    /* bit 3 */
  319.  
  320.     if (clk >= CLOCKS)
  321.       clk = CLOCKS-1;
  322.     if (clk>=0) {
  323.       /* Set clock */
  324.       temp = inb(MIS_R) & 0xF3;
  325.       outb(MIS_W, temp | ((clk&3)<<2)); 
  326.       outb(CRT_I, 0x34);
  327.       temp = inb(CRT_D) & 0xFD;
  328.       outb(CRT_D, temp | ((clk&4)>>1));
  329.       outb(SEQ_I, 0x07);
  330.       temp = inb(SEQ_D) & 0xBE;
  331.       temp |= (clk&0x10 ? 0x41 : 0x00);
  332.       temp |= (clk&0x08) << 3;
  333.       outb(SEQ_D, temp);
  334.       usleep(5000);
  335.     }
  336.     return res;
  337. }
  338.  
  339. #define FRAMES 2
  340.  
  341. /* I think the Xfree86 uses a similar BAD HACK ... */
  342. static int measure(int frames) {
  343.     unsigned counter;                    
  344.     __asm__ volatile (
  345.     "    xorl    %0,%0        \n"
  346.     "__W1:    inb    %1,%%al        \n"
  347.     "    testb    $8,%%al        \n"
  348.     "    jne    __W1        \n"
  349.     "__W2:    inb    %1,%%al        \n"
  350.     "    testb    $8,%%al        \n"
  351.     "    je    __W2        \n"
  352.     "__L1:    inb    %1,%%al        \n"
  353.     "    incl    %0        \n"
  354.     "    testb    $8,%%al        \n"
  355.     "    jne    __L1        \n"
  356.     "__L2:    inb    %1,%%al        \n"
  357.     "    incl    %0        \n"
  358.     "    testb    $8,%%al        \n"
  359.     "    je    __L2        \n"
  360.     "__L3:    decl    %2        \n"
  361.     "    jns    __L1        \n"
  362.     : "=b" (counter)
  363.     : "d" ((unsigned short)(0x3da)), "c" (frames)
  364.     : "ax", "cx"
  365.     );
  366.     return counter;
  367. }
  368.  
  369. #define BASIS_FREQUENCY 28322
  370.  
  371. static int measure_clk(int clk) {
  372.   unsigned new;
  373.   int  old_clk, state;
  374.   static unsigned act = 0;
  375.  
  376.   old_clk = et4000_clocks(-1);
  377.   if ((state=SCREENON))
  378.     vga_screenoff();
  379.   if (act == 0) {
  380.     unsigned char save = inb( MIS_R);
  381.     outb(MIS_W, (save&0xF3) | 0x04);
  382.     act = measure(FRAMES);
  383.     outb(MIS_W, save);
  384.   }
  385.   et4000_clocks(clk);
  386.   new = measure(FRAMES);
  387.   et4000_clocks(old_clk);
  388.   if (state)
  389.     vga_screenon();
  390.  
  391.   return (((long long)BASIS_FREQUENCY) * act) / new;
  392. }
  393.  
  394. #define set1(f,v) ({ if ((f)==0) (f)=(v); })
  395.  
  396. static void set3(unsigned *f, int clk, unsigned base) {
  397.     if (clk-16 >= 0) set1(f[clk-16], 4*base);
  398.     if (clk- 8 >= 0) set1(f[clk -8], 2*base);
  399.     set1(f[clk], base);
  400.     if (clk+ 8 < CLOCKS) set1(f[clk+ 8], base / 2);
  401.     if (clk+16 < CLOCKS) set1(f[clk+16], base / 4);
  402. }
  403.  
  404. static int get_clock(int clk) {
  405.   static int first = 1;
  406.  
  407.   if (clk < 0 || clk >= CLOCKS)
  408.     return 0;
  409.   if (first) {
  410.     int act_clk;
  411.     first = 0;
  412.     act_clk = et4000_clocks(-1);
  413.     act_clk &= 0xFC;
  414.     set3(clocks, act_clk, 25175);   /* act_clk  : 25175 KHz */
  415.     set3(clocks, act_clk+1, 28322); /* act_clk+1: 28322 KHz */
  416.     for (act_clk = 0; act_clk < CLOCKS; ++act_clk) 
  417.       if (clocks[act_clk] != 0)
  418.     set3(clocks, act_clk, clocks[act_clk]);
  419.   }
  420.   if (clocks[clk] == 0) {
  421.     int c = clk&7;
  422.     clocks[16+c] = measure_clk(16+c);
  423.     clocks[ 8+c] = 2 * clocks[16+c];
  424.     clocks[   c] = 2 * clocks[ 8+c];
  425.   }
  426.   return clocks[clk];
  427. }
  428.  
  429. #endif    /* defined(USE_CLOCKS) */
  430.  
  431. /* ----------------------------------------------------------------- */
  432.  
  433.  
  434. /* Read and store chipset-specific registers */
  435.  
  436. static int et4000_saveregs(unsigned char regs[])
  437. {
  438.     int i;
  439.  
  440.     et4000_unlock();
  441.     /* save extended CRT registers */
  442.     for (i = 0; i < 8; i++) {
  443.      port_out(0x30+i, CRT_I); 
  444.      regs[EXT+i] = port_in(CRT_D); 
  445.     }
  446.     port_out(0x3f, CRT_I);
  447.     regs[EXT+8] = port_in(CRT_D);
  448.  
  449.     /* save extended sequencer register */
  450.     port_out(7, SEQ_I); 
  451.     regs[EXT+9] = port_in(SEQ_D); 
  452.  
  453.     /* save some other ET4000 specific registers */
  454.     regs[EXT+10] = port_in(0x3c3); 
  455.     regs[EXT+11] = port_in(0x3cd); 
  456.  
  457.     /* save extended attribute register */
  458.     port_in(IS1_R);    /* reset flip flop */
  459.     port_out(0x16, ATT_IW);
  460.     regs[EXT+12] = port_in(ATT_R);
  461.  
  462.     if (et4000_extdac) {
  463.             dactocomm();
  464.         regs[EXT+13] = inb(0x3c6);
  465.         dactocomm();
  466.         outb(0x3c6, regs[EXT+13] | 0x10);
  467.         dactocomm();
  468.         inb(0x3c6);
  469.         outb(0x3c6,3);    /* write index low */
  470.         outb(0x3c6,0);    /* write index high */
  471.         regs[EXT+14] = inb(0x3c6);    /* primary ext. pixel select */
  472.         regs[EXT+15] = inb(0x3c6);    /* secondary ext. pixel select */
  473.         regs[EXT+16] = inb(0x3c6);    /* PLL control register */
  474.         dactocomm();
  475.         outb(0x3c6, regs[EXT+13]);
  476.         return 17;
  477.     }
  478.     return 13;  /* ET4000 requires 13 additional registers */
  479. }
  480.  
  481.  
  482. /* Set chipset-specific registers */
  483.  
  484. static int et4000_setregs( const unsigned char regs[], int mode )
  485. {
  486.     int i;
  487.     unsigned char save;
  488.  
  489.     /* make sure linear mode is forced off */
  490.     et4000_setlinear(0);
  491.  
  492.     et4000_unlock();
  493.     /* write some ET4000 specific registers */
  494.     port_out(regs[EXT+10], 0x3c3);
  495.     port_out(regs[EXT+11], 0x3cd);
  496.  
  497.     /* write extended sequencer register */
  498.     port_out(7, SEQ_I); 
  499.     port_out(regs[EXT+9], SEQ_D); 
  500.  
  501. #if 0    /* This writes to registers we shouldn't write to. */
  502.     /* write extended CRT registers */
  503.     for (i = 0; i < 6; i++) {
  504.      port_out(0x32+i, CRT_I); 
  505.      port_out(regs[EXT+i], CRT_D); 
  506.     }
  507.     port_out(0x3f, CRT_I);
  508.     port_out(regs[EXT+6], CRT_D);
  509. #endif
  510.  
  511.     /* deprotect CRT register 0x35 */
  512.     port_out(0x11, CRT_I);
  513.     save = port_in(CRT_D);
  514.     port_out(save&0x7F, CRT_D);
  515.  
  516.     /* write extended CRT registers */
  517.     for (i = 0; i < 6; i++) {
  518.          port_out(0x30+i, CRT_I); 
  519.          port_out(regs[EXT+i], CRT_D); 
  520.     }
  521.     port_out(0x36, CRT_I);
  522.     port_out( (port_in(CRT_D) & 0x40)  | (regs[EXT+6] & 0xbf), CRT_D);
  523.     port_out(0x37, CRT_I);
  524.     port_out( (port_in(CRT_D) & 0xbb)  | (regs[EXT+7] & 0x44), CRT_D);
  525.     port_out(0x3f, CRT_I);
  526.     port_out(regs[EXT+8], CRT_D);
  527.  
  528.     /* set original CRTC 0x11 */
  529.     port_out(0x11, CRT_I);
  530.     port_out(save, CRT_D);
  531.  
  532.     /* write extended attribute register */
  533.     port_in(IS1_R);    /* reset flip flop */
  534.     port_out(0x16, ATT_IW);
  535.     port_out(regs[EXT+12], ATT_IW);
  536.     
  537.     if (et4000_extdac) {
  538.             dactocomm();
  539.             outb(0x3c6,regs[EXT+13] | 0x10);
  540.         dactocomm();
  541.         inb(0x3c6);
  542.         outb(0x3c6,3);    /* write index low */
  543.         outb(0x3c6,0);    /* write index high */
  544.         outb(0x3c6,regs[EXT+14]);    /* primary ext. pixel select */
  545.         outb(0x3c6,regs[EXT+15]);    /* secondary ext. pixel select */
  546.         outb(0x3c6,regs[EXT+16]);    /* PLL control register */
  547.         dactocomm();
  548.         outb(0x3c6, regs[EXT+13]);
  549.     }
  550.     return 0;
  551. }
  552.  
  553.  
  554. /* Return non-zero if mode is available */
  555.  
  556. static int et4000_modeavailable( int mode ) {
  557.     const unsigned char *regs;
  558.     struct info *info;
  559.  
  560.     regs = LOOKUPMODE(et4000_modes, mode);
  561.     if (regs == NULL || mode == GPLANE16)
  562.           return vga_driverspecs.modeavailable(mode);
  563.     if (regs==DISABLE_MODE || mode<=TEXT || mode>GLASTMODE)
  564.       return 0;
  565.  
  566.     info = &__svgalib_infotable[mode];
  567.     if (et4000_memory*1024 < info->ydim * info->xbytes)
  568.       return 0;
  569.  
  570.     switch (info->colors) {
  571.       case 1<<15 : 
  572.         /* All HiColor dacs handle 15 bit */
  573.         if ((et4000_dac & 1) == 0)
  574.             return 0;
  575.         break;
  576.       case 1<<16 : 
  577.         /* Unfortunately, we can't tell the difference between a Sierra Mark 2 */
  578.         /* and a Mark 3, and the mark 2 is only 15 bit. If this gives you trouble */
  579.         /* change it to (8|16) rather than (2|8|16) */
  580.         /* Currently allow Sierra Mark2/3, AT&T, STG-170x and AcuMos */
  581.         if ((et4000_dac & (2|8|16|32|64)) == 0 )
  582.             return 0; 
  583.         break;
  584.       case 1<<24 :
  585.         /* Don't know how to set dac command register for Diamond SS2410 Dac */
  586.         /* Only allow AT&T, STG-170x and AcuMos */
  587.         if ((et4000_dac & (8|16|32|64)) == 0)
  588.             return 0;
  589.         break;
  590.     }
  591.     return SVGADRV;
  592. }
  593.  
  594.  
  595. /* Check if mode is interlaced */
  596.  
  597. static int et4000_interlaced( int mode ) { 
  598.     const unsigned char *regs;
  599.  
  600.     if (et4000_modeavailable(mode) != SVGADRV)
  601.       return 0;
  602.     regs = LOOKUPMODE(et4000_modes, mode);
  603.     if (regs == NULL || regs == DISABLE_MODE)
  604.       return 0;
  605.     return (regs[EXT+5]&0x80) != 0;  /* CRTC 35H */
  606. }
  607.  
  608.  
  609. /* Set a mode */
  610.  
  611. static int et4000_setmode( int mode, int prv_mode ) {
  612.     const unsigned char *regs;
  613.  
  614.     if (et4000_dac)
  615.         /* Standard dac behaviour */
  616.         __vga_hicolor(et4000_dac, STD_DAC);
  617.     switch (et4000_modeavailable(mode)) {
  618.       case STDVGADRV: 
  619.           /* Reset extended register that is set to non-VGA */
  620.           /* compatible value for 132-column textmodes (at */
  621.           /* least on some cards). */
  622.           outb(CRT_I, 0x34);
  623.           if (inb(CRT_D) == 0xca)
  624.               outb(CRT_D, 0xc8);
  625.         return vga_driverspecs.setmode(mode, prv_mode);
  626.       case SVGADRV:
  627.         regs = LOOKUPMODE(et4000_modes, mode);
  628.         if (regs != NULL) break;
  629.       default:
  630.         return 1;    /* mode not available */
  631.     }
  632.  
  633.     if (et4000_dac && !et4000_extdac)
  634.         switch (vga_getmodeinfo(mode)->colors) {
  635.         case 1<<15:
  636.             __vga_hicolor(et4000_dac, HI15_DAC);
  637.             break;
  638.         case 1<<16:
  639.             __vga_hicolor(et4000_dac, HI16_DAC);
  640.             break;
  641.         case 1<<24:
  642.             __vga_hicolor(et4000_dac, TC24_DAC);
  643.             break;
  644.         }
  645.  
  646.     __vga_setregs(regs);
  647.     et4000_setregs(regs, mode);
  648.         return 0;
  649. }
  650.  
  651. /* Unlock chipset-specific registers */
  652.  
  653. static int et4000_unlock() {
  654.     /* get access to extended registers */
  655.     port_out(3, 0x3bf);
  656.     if (port_in( 0x3cc ) & 1) 
  657.         port_out(0xa0, 0x3d8);
  658.     else
  659.         port_out(0xa0, 0x3b8);
  660.     return 0;
  661. }
  662.  
  663.  
  664. /* Relock chipset-specific registers */
  665.  
  666. static int et4000_lock() {
  667.         return 0;
  668. }
  669.  
  670. /* Enable linear mode at a particular 4M page (0 to turn off) */
  671.  
  672. static int et4000_setlinear(int addr) {
  673.     et4000_unlock();
  674.     outb(0x3D4,0x36);
  675.     if (addr)
  676.               outb(0x3D5,inb(0x3D5) | 16);    /* enable linear mode */
  677.     else
  678.         outb(0x3D5,inb(0x3D5) & ~16);   /* disable linear mode */
  679.     outb(0x3D4,0x30);
  680.     outb(0x3D5,addr);
  681.     et4000_lock();
  682. }
  683.  
  684.  
  685. /* Indentify chipset; return non-zero if detected */
  686.  
  687. static int et4000_test()
  688. {
  689.     unsigned char new, old, val;
  690.     int  base;
  691.  
  692.     et4000_unlock();
  693.  
  694.     /* test for Tseng clues */
  695.     old = port_in(0x3cd);              
  696.     port_out(0x55, 0x3cd);
  697.     new = port_in(0x3cd);              
  698.     port_out(old, 0x3cd);
  699.  
  700.     /* return false if not Tseng */
  701.     if (new != 0x55)
  702.     return 0;
  703.  
  704.     /* test for ET4000 clues */
  705.     if (port_in(0x3cc) & 1) 
  706.     base = 0x3d4;
  707.     else 
  708.     base = 0x3b4;
  709.     port_out(0x33, base);
  710.     old = port_in(base+1);
  711.     new = old ^ 0xf;
  712.     port_out(new, base+1);
  713.     val = port_in(base+1);
  714.     port_out(old, base+1);
  715.  
  716.     /* return true if ET4000 */    
  717.     if (val == new) {
  718.         /* Test for ET4000/W32. */
  719.         old = inb(0x3cb);
  720.         outb(0x3cb, 0x33);
  721.         new = inb(0x3cb);
  722.         outb(0x3cb, old);
  723.         if (new != 0x33)
  724.             et4000_chiptype = CHIP_ET4000;
  725.         else {
  726.             /* ET4000/W32. */
  727.             if (getenv("IOPERM") == NULL && iopl(3) < 0)
  728.                 /* Can't get further I/O permissions -- */
  729.                 /* assume ET4000/W32. */
  730.                 et4000_chiptype = CHIP_ET4000W32;
  731.             else {
  732.                 outb(0x217a, 0xec);
  733.                 val = inb(0x217b) >> 4;
  734.                 switch (val) {
  735.                 case 0 :
  736.                     et4000_chiptype = CHIP_ET4000W32; break;
  737.                 case 1 :
  738.                 case 3 :
  739.                     et4000_chiptype = CHIP_ET4000W32i; break;
  740.                 case 2 :
  741.                 case 5 :
  742.                 default :
  743.                     et4000_chiptype = CHIP_ET4000W32p;
  744.                 }
  745.                 iopl(0);
  746.             }
  747.         }
  748.         et4000_init(0, 0);
  749.         return 1;
  750.     }
  751.     return 0;
  752. }
  753.  
  754.  
  755.  
  756. static unsigned char last_page = 0;
  757.  
  758. /* Bank switching function - set 64K bank number */
  759. static void et4000_setpage( int page ) {
  760.     /* Set both read and write bank. */
  761.     port_out(last_page = (page | ((page & 15) << 4)), SEG_SELECT);
  762.     if (et4000_chiptype >= CHIP_ET4000W32i) {
  763.         /* Write page4-5 to bits 0-1 of ext. bank register, */
  764.         /* and to bits 4-5. */
  765.         outb(0x3cb, (inb(0x3cb) & ~0x33) | (page >> 4) | (page & 0x30));
  766.     }
  767. }
  768.  
  769.  
  770. /* Bank switching function - set 64K read bank number */
  771. static void et4000_setrdpage( int page ) {
  772.     last_page &= 0x0F;
  773.     last_page |= (page << 4);
  774.     port_out(last_page, SEG_SELECT);
  775.     if (et4000_chiptype >= CHIP_ET4000W32i) {
  776.         /* Write page4-5 to bits 4-5 of ext. bank register. */
  777.         outb(0x3cb, (inb(0x3cb) & ~0x30) | (page & 0x30));
  778.     }
  779. }
  780.  
  781. /* Bank switching function - set 64K write bank number */
  782. static void et4000_setwrpage( int page ) {
  783.     last_page &= 0xF0;
  784.     last_page |= page;
  785.     port_out(last_page, SEG_SELECT);
  786.     if (et4000_chiptype >= CHIP_ET4000W32i) {
  787.         /* Write page4-5 to bits 0-1 of ext. bank register. */
  788.         outb(0x3cb, (inb(0x3cb) & ~0x03) | (page >> 4));
  789.     }
  790. }
  791.  
  792.  
  793. /* Set display start address (not for 16 color modes) */
  794. /* ET4000 supports any address in video memory (up to 1Mb) */
  795. /* ET4000/W32i/p supports up to 4Mb */
  796.  
  797. static int et4000_setdisplaystart( int address ) {
  798.     outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256);    /* sa2-sa9 */
  799.     outw(0x3d4, 0x0c + ((address >> 2) & 0xff00));        /* sa10-sa17 */
  800.     inb(0x3da);            /* set ATC to addressing mode */
  801.     outb(0x3c0, 0x13 + 0x20);    /* select ATC reg 0x13 */
  802.     outb(0x3c0, (inb(0x3c1) & 0xf0) | ((address & 3) << 1));
  803.         /* write sa0-1 to bits 1-2 */
  804.     outb(0x3d4, 0x33);
  805.     if (et4000_chiptype >= CHIP_ET4000W32i)
  806.         /* write sa18-21 to bit 0-3 */
  807.         outb(0x3d5, (inb(0x3d5) & 0xf0) | ((address & 0x3c0000) >> 18));
  808.     else
  809.         /* write sa18-19 to bit 0-3 */
  810.         outb(0x3d5, (inb(0x3d5) & 0xfc) | ((address & 0xc0000) >> 18));
  811.     return 0;
  812. }
  813.  
  814.  
  815. /* Set logical scanline length (usually multiple of 8) */
  816. /* ET4000 supports multiples of 8 to 4088 */
  817.  
  818. static int et4000_setlogicalwidth( int width ) { 
  819.     outw(0x3d4, 0x13 + (width >> 3) * 256);    /* lw3-lw11 */
  820.     outb(0x3d4, 0x3f);
  821.     outb(0x3d5, (inb(0x3d5) & 0x7f)
  822.         | ((width & 0x800) >> 5));    /* write lw12 to bit 7 */
  823.     return 0;
  824. }
  825.  
  826. static int et4000_ext_set(unsigned what,va_list params)
  827. {
  828. int param2, old_values;
  829.  
  830. switch(what)
  831.     {
  832.     case VGA_EXT_AVAILABLE:
  833.         param2=va_arg(params, int);
  834.         switch(param2)
  835.             {
  836.             case VGA_AVAIL_SET:
  837.                 return VGA_EXT_AVAILABLE|VGA_EXT_SET|VGA_EXT_CLEAR|VGA_EXT_RESET;
  838.             case VGA_AVAIL_ACCEL:
  839.                 return 0;
  840.             case VGA_AVAIL_FLAGS:
  841.                 return pos_ext_settings;
  842.             }
  843.         return 0;
  844.     case VGA_EXT_SET:
  845.         old_values=ext_settings;
  846.         ext_settings|=(va_arg(params, int))&pos_ext_settings;
  847.         params_changed:
  848.         if( ((old_values^ext_settings)&pos_ext_settings))
  849.             {
  850.             int cmd;
  851.             CRITICAL=1;
  852.             vga_lockvc();
  853.             dactocomm();
  854.             cmd = inb(0x3c6);
  855.             dactocomm();
  856.             if(ext_settings&VGA_CLUT8)
  857.                 cmd |= 2;
  858.             else
  859.                 cmd &= ~2;
  860.             outb(0x3c6,cmd);
  861.             vga_unlockvc();
  862.             CRITICAL=0;
  863.             }
  864.         return old_values;
  865.     case VGA_EXT_CLEAR:
  866.         old_values=ext_settings;
  867.         ext_settings&= ~((va_arg(params, int))&pos_ext_settings);
  868.         goto params_changed;
  869.     case VGA_EXT_RESET:
  870.         old_values=ext_settings;
  871.         ext_settings=(va_arg(params, int))&pos_ext_settings;
  872.         goto params_changed;
  873.     default:
  874.         return 0;
  875.     }
  876. }
  877.  
  878. static int et4000_linear(int op,int param)
  879. {
  880.     /* linear mode not supported on original chipset */
  881.     if (et4000_chiptype == CHIP_ET4000)
  882.         return -1;
  883.     else if (op == LINEAR_QUERY_GRANULARITY)
  884.         return 4 * 1024 * 1024;
  885.     else if (op == LINEAR_QUERY_RANGE)
  886.         return 256;
  887.     else if (op == LINEAR_ENABLE) {
  888.         et4000_setlinear(param / (4 * 1024 * 1024));
  889.         return 0;
  890.     }
  891.     else if (op == LINEAR_DISABLE) {
  892.         et4000_setlinear(0);
  893.         return 0;
  894.     }
  895.     else
  896.         return -1;
  897. }
  898.  
  899. /* Function table (exported) */
  900.  
  901. DriverSpecs et4000_driverspecs = {
  902.     et4000_saveregs,
  903.     et4000_setregs,
  904.     et4000_unlock,
  905.     et4000_lock,
  906.     et4000_test,
  907.     et4000_init,
  908.     (int (*)()) et4000_setpage,
  909.     (int (*)()) et4000_setrdpage,
  910.     (int (*)()) et4000_setwrpage,
  911.     et4000_setmode,
  912.     et4000_modeavailable,
  913.     et4000_setdisplaystart,
  914.     et4000_setlogicalwidth,
  915.     et4000_getmodeinfo,
  916.     0, /* bitblt */
  917.     0, /* imageblt */
  918.     0, /* fillblt */
  919.     0, /* hlinelistblt */
  920.     0, /* bltwait */
  921.     et4000_ext_set,
  922.     0,
  923.     et4000_linear,
  924.     NULL    /* accelspecs */
  925. };
  926.  
  927.  
  928. /* Hicolor DAC detection derived from vgadoc (looks tricky) */
  929.  
  930.  
  931. #ifndef DAC_TYPE
  932. static int testdac()
  933. {
  934.     int x, y, z, v, oldcommreg, oldpelreg, retval;
  935.  
  936.     /* Use the following return values:
  937.      *     0: Ordinary DAC
  938.      *    1: Sierra SC11486 (32k)
  939.      *    3: Sierra 32k/64k
  940.      *    5: SS2410 15/24bit DAC
  941.      *    9: AT&T 20c491/2
  942.      *     10: STG-170x
  943.      */
  944.  
  945.     retval = 0;    /* default to no fancy dac */
  946.     dactopel();
  947.     x=inb(0x3c6);
  948.     do {        /* wait for repeat of value */
  949.         y = x;
  950.         x = inb(0x3c6);
  951.     } while (x != y);
  952.     z=x;
  953.     inb(0x3c8);
  954.     inb(0x3c6);
  955.     inb(0x3c6);
  956.     inb(0x3c6);
  957.     x=inb(0x3c6);
  958.     y=8;
  959.     while ( (x!=0x8e) && (y>0) )
  960.     {
  961.         x=inb(0x3c6);
  962.         y--;
  963.     }
  964.     if (x==0x8e)
  965.     {
  966.         /* We have an SS2410 */
  967.         retval = 1 | 4;
  968.         dactopel();
  969.     }
  970.     else
  971.     {
  972.         dactocomm();
  973.         oldcommreg = inb(0x3c6);
  974.         dactopel();
  975.         oldpelreg = inb(0x3c6);
  976.         x = oldcommreg ^ 0xFF;
  977.         outb(0x3c6, x);
  978.         dactocomm();
  979.         v=inb(0x3c6);
  980.         if (v != x)
  981.         {
  982.             dactocomm();
  983.             x = oldcommreg ^ 0x60;
  984.             outb(0x3c6, x);
  985.             dactocomm();
  986.             v = inb(0x3c6);
  987.             /* We have a Sierra SC11486 */
  988.             retval = 1;
  989.  
  990.             if ( (x & 0xe0) == (v & 0xe0) )
  991.             {
  992.                 /* We have a Sierra 32k/64k */
  993.                 x = inb(0x3c6);
  994.                 dactopel();
  995.                 retval = 1 | 2;
  996.  
  997.                 if ( x == inb(0x3c6) )
  998.                 {
  999.                     /* We have an ATT 20c491 or 20c492 */
  1000.                     retval = 1 | 8;
  1001.                     dactocomm();
  1002.                     outb(0x3c6, 0xFF);
  1003.                     dactocomm();
  1004.                     if (inb(0x3c6) != 0xFF)
  1005.                     {
  1006.                         /* We have a weird dac, AcuMos ADAC1 */
  1007.                         retval = 1 | 16;
  1008.                     }
  1009.                     else {     /* maybe an STG-170x */
  1010.                         dactocomm();
  1011.                         /* try to enable ext. registers */
  1012.                         outb(0x3c6, 0x10 | oldcommreg);
  1013.                         dactocomm();
  1014.                         inb(0x3c6);
  1015.                         outb(0x3c6,0);
  1016.                         outb(0x3c6,0);
  1017.                         if (inb(0x3c6) == 0x44) {
  1018.                             /* it's a 170x */
  1019.                             /* Another read from 0x3c6 gets the chiptype, 0x02 == 1702. */
  1020.                             retval = 1 | 64;
  1021.                             et4000_extdac = 1;
  1022.                         }
  1023.                     }
  1024.                 }
  1025.             }
  1026.             dactocomm();
  1027.             outb(0x3c6, oldcommreg);
  1028.         }
  1029.         dactopel();
  1030.         outb(0x3c6, oldpelreg);
  1031.     }
  1032.     return retval;
  1033. }
  1034. #endif /* !defined(DAC_TYPE) */
  1035.  
  1036.  
  1037. /* Initialize chipset (called after detection) */
  1038.  
  1039. static int et4000_init( int force, int par1 ) {
  1040.     int value, i;
  1041.  
  1042. #if defined(DYNAMIC)
  1043.     if (et4000_modes == NULL) {
  1044.       FILE *regs;
  1045.  
  1046.       regs = fopen(ET4000_REGS,"r");
  1047.       if (regs != 0) {
  1048.         et4000_modes = NULL;
  1049.         __vga_readmodes(regs, &et4000_modes, &et4000_dac, &clocks[0]);
  1050.         fclose(regs);
  1051.       } else
  1052.         et4000_modes = &No_Modes;
  1053.     }
  1054. #endif
  1055.  
  1056.     if (force)
  1057.         et4000_memory = par1;
  1058.     else {
  1059.         outb(0x3d4,0x37);
  1060.         value = inb(0x3d5);
  1061.         et4000_memory = (value&0x08) ? 256 : 64;
  1062.         switch (value & 3) {
  1063.           case 2: et4000_memory *= 2;
  1064.               break;
  1065.           case 3: et4000_memory *= 4;
  1066.               break;
  1067.         }
  1068.         if (value&0x80)
  1069.           et4000_memory *= 2;
  1070.         outb(0x3d4, 0x32);
  1071.         if (inb(0x3d5) & 0x80) {
  1072.             /* Interleaved memory on ET4000/W32i/p: */
  1073.             /* Multiply by 2. */
  1074.             et4000_memory *= 2;
  1075.         }
  1076.     }
  1077. #ifndef DAC_TYPE
  1078.     if (et4000_dac < 0)
  1079.       et4000_dac = testdac();
  1080. #endif
  1081.  
  1082. #ifdef USE_CLOCKS
  1083.     /* Measure clock frequencies */
  1084.     for (i=0; i < CLOCKS; ++i)
  1085.       get_clock(i);
  1086. #endif
  1087.  
  1088.     if (__svgalib_driver_report) {
  1089.         char dacname[60];
  1090.         switch (et4000_dac & ~1)
  1091.         {
  1092.         case 0:
  1093.             strcpy(dacname, ", Hicolor Dac: Sierra SC11486");
  1094.             break;
  1095.         case 2:
  1096.             strcpy(dacname, ", Hicolor Dac: Sierra 32k/64k");
  1097.             break;
  1098.         case 4:
  1099.             strcpy(dacname, ", Hicolor Dac: SS2410");
  1100.             break;
  1101.         case 8:
  1102.             strcpy(dacname, ", Hicolor Dac: ATT20c491/2");
  1103.             break;
  1104.         case 16:
  1105.             strcpy(dacname, ", Hicolor Dac: ACUMOS ADAC1");
  1106.             break;
  1107.         case 32:
  1108.             strcpy(dacname, ", Hicolor Dac: Sierra 15025/6 (24-bit)");
  1109.             break;
  1110.         case 64:
  1111.             strcpy(dacname, ", Hicolor Dac: STG-170x (24-bit)");
  1112.             break;
  1113.         default:
  1114.             strcpy(dacname, ", Hicolor Dac: Unknown");
  1115.             break;
  1116.         }
  1117.  
  1118.         printf("Using Tseng ET4000 driver (%s %d%s).",
  1119.             chipname[et4000_chiptype], et4000_memory,
  1120.             et4000_dac & 1 ? dacname : "");
  1121. #ifdef USE_CLOCKS
  1122.         printf(" Clocks:");
  1123.         for (i=0; i < 8; ++i) 
  1124.           printf(" %d", (clocks[i]+500)/1000);
  1125. #endif
  1126.         printf("\n");
  1127.     }
  1128.     driverspecs = &et4000_driverspecs;
  1129.  
  1130.     pos_ext_settings = 0;
  1131.     if (et4000_dac & (8|16|32|64))
  1132.       pos_ext_settings = VGA_CLUT8;
  1133.  
  1134.     return 0;
  1135. }
  1136.  
  1137.