PageRenderTime 131ms CodeModel.GetById 18ms RepoModel.GetById 2ms app.codeStats 1ms

/video/svgalib/src/et4000.c

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