home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / v / vgalib12.tar / vgalib / vga.c < prev    next >
C/C++ Source or Header  |  1993-02-09  |  41KB  |  1,553 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. #include "vga.h"
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #include <signal.h>
  11. #include <termios.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <sys/mman.h>
  15. #include <sys/kd.h>
  16. #include <linux/mm.h>
  17. #undef free
  18. #include <stdlib.h>
  19.  
  20. #define char unsigned char
  21.  
  22. #define GRAPH_BASE 0xA0000
  23. #define GRAPH_SIZE 0x10000
  24. #define FONT_BASE  0xA0000
  25. #define FONT_SIZE  0x2000
  26. #define NULL_SIZE  0x1000
  27.  
  28. #define MAX_REGS 100
  29.  
  30. /* VGA index register ports */
  31. #define CRT_IC  0x3D4   /* CRT Controller Index - color emulation */
  32. #define CRT_IM  0x3B4   /* CRT Controller Index - mono emulation */
  33. #define ATT_IW  0x3C0   /* Attribute Controller Index & Data Write Register */
  34. #define GRA_I   0x3CE   /* Graphics Controller Index */
  35. #define SEQ_I   0x3C4   /* Sequencer Index */
  36. #define PEL_IW  0x3C8   /* PEL Write Index */
  37. #define PEL_IR  0x3C7   /* PEL Read Index */
  38.  
  39. /* VGA data register ports */
  40. #define CRT_DC  0x3D5   /* CRT Controller Data Register - color emulation */
  41. #define CRT_DM  0x3B5   /* CRT Controller Data Register - mono emulation */
  42. #define ATT_R   0x3C1   /* Attribute Controller Data Read Register */
  43. #define GRA_D   0x3CF   /* Graphics Controller Data Register */
  44. #define SEQ_D   0x3C5   /* Sequencer Data Register */
  45. #define MIS_R   0x3CC   /* Misc Output Read Register */
  46. #define MIS_W   0x3C2   /* Misc Output Write Register */
  47. #define IS1_RC  0x3DA   /* Input Status Register 1 - color emulation */
  48. #define IS1_RM  0x3BA   /* Input Status Register 1 - mono emulation */
  49. #define PEL_D   0x3C9   /* PEL Data Register */
  50.  
  51. /* VGA indexes max counts */
  52. #define CRT_C   24      /* 24 CRT Controller Registers */
  53. #define ATT_C   21      /* 21 Attribute Controller Registers */
  54. #define GRA_C   9       /* 9  Graphics Controller Registers */
  55. #define SEQ_C   5       /* 5  Sequencer Registers */
  56. #define MIS_C   1       /* 1  Misc Output Register */
  57.  
  58. /* VGA registers saving indexes */
  59. #define CRT     0               /* CRT Controller Registers start */
  60. #define ATT     CRT+CRT_C       /* Attribute Controller Registers start */
  61. #define GRA     ATT+ATT_C       /* Graphics Controller Registers start */
  62. #define SEQ     GRA+GRA_C       /* Sequencer Registers */
  63. #define MIS     SEQ+SEQ_C       /* General Registers */
  64. #define EXT     MIS+MIS_C       /* SVGA Extended Registers */
  65.  
  66. #define SEG_SELECT 0x3CD
  67.  
  68. #define ABS(a) (((a)<0) ? -(a) : (a))
  69.  
  70. /* variables used to shift between monchrome and color emulation */
  71. static int CRT_I;        /* current CRT index register address */
  72. static int CRT_D;        /* current CRT data register address */
  73. static int IS1_R;        /* current input status register address */
  74. static int color_text;        /* true if color text emulation */
  75.  
  76.  
  77. /* graphics mode information */
  78. struct info {
  79.     int xdim;
  80.     int ydim;
  81.     int colors;
  82.     int xbytes;
  83. };
  84.  
  85.  
  86. /* BIOS mode 0Dh - 320x200x16 */
  87. static char g320x200x16_regs[60] = {
  88.   0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,0x00,0xC0,0x00,0x00, 
  89.   0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xE3, 
  90.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  91.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, 
  92.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF, 
  93.   0x03,0x09,0x0F,0x00,0x06, 
  94.   0x63
  95. };
  96. static struct info g320x200x16_info = { 320, 200, 16, 40 };
  97.  
  98.  
  99. /* BIOS mode 0Eh - 640x200x16 */
  100. static char g640x200x16_regs[60] = {
  101.   0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0xC0,0x00,0x00, 
  102.   0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x28,0x00,0x96,0xB9,0xE3, 
  103.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  104.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, 
  105.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF, 
  106.   0x03,0x01,0x0F,0x00,0x06, 
  107.   0x63
  108. };
  109. static struct info g640x200x16_info = { 640, 200, 16, 80 };
  110.  
  111.  
  112. /* BIOS mode 10h - 640x350x16 */
  113. static char g640x350x16_regs[60] = {
  114.   0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, 
  115.   0x00,0x00,0x00,0x00,0x83,0x85,0x5D,0x28,0x0F,0x63,0xBA,0xE3, 
  116.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  117.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00, 
  118.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF, 
  119.   0x03,0x01,0x0F,0x00,0x06, 
  120.   0xA3
  121. };
  122. static struct info g640x350x16_info = { 640, 350, 16, 80 };
  123.  
  124.  
  125. /* BIOS mode 12h - 640x480x16 */
  126. static char g640x480x16_regs[60] = {
  127.   0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,
  128.   0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xE3,
  129.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  130.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  131.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF,
  132.   0x03,0x01,0x0F,0x00,0x06,
  133.   0xE3
  134. };
  135. static struct info g640x480x16_info = { 640, 480, 16, 80 };
  136.  
  137.  
  138. /* BIOS mode 13h - 320x200x256 */
  139. static char g320x200x256_regs[60] = {
  140.   0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x41,0x00,0x00, 
  141.   0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x28,0x40,0x96,0xB9,0xA3, 
  142.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  143.   0x0C,0x0D,0x0E,0x0F,0x41,0x00,0x0F,0x00,0x00, 
  144.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, 
  145.   0x03,0x01,0x0F,0x00,0x0E, 
  146.   0x63
  147. };
  148. static struct info g320x200x256_info = { 320, 200, 256, 320 };
  149.  
  150.  
  151. /* non-BIOS mode - 320x240x256 */
  152. static char g320x240x256_regs[60] = {
  153.   0x5F,0x4F,0x50,0x82,0x54,0x80,0x0D,0x3E,0x00,0x41,0x00,0x00, 
  154.   0x00,0x00,0x00,0x00,0xEA,0xAC,0xDF,0x28,0x00,0xE7,0x06,0xE3, 
  155.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  156.   0x0C,0x0D,0x0E,0x0F,0x41,0x00,0x0F,0x00,0x00, 
  157.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, 
  158.   0x03,0x01,0x0F,0x00,0x06, 
  159.   0xE3
  160. };
  161. static struct info g320x240x256_info = { 320, 240, 256, 80 };
  162.  
  163.  
  164. /* non-BIOS mode - 320x400x256 */
  165. static char g320x400x256_regs[60] = {
  166.   0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,0x00,0x40,0x00,0x00, 
  167.   0x00,0x00,0x00,0x00,0x9C,0x8E,0x8F,0x28,0x00,0x96,0xB9,0xE3, 
  168.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  169.   0x0C,0x0D,0x0E,0x0F,0x41,0x00,0x0F,0x00,0x00, 
  170.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, 
  171.   0x03,0x01,0x0F,0x00,0x06, 
  172.   0x63
  173. };
  174. static struct info g320x400x256_info = { 320, 400, 256, 80 };
  175.  
  176.  
  177. /* non-BIOS mode - 360x480x256 */
  178. static char g360x480x256_regs[60] = {
  179.   0x6B,0x59,0x5A,0x8E,0x5E,0x8A,0x0D,0x3E,0x00,0x40,0x00,0x00, 
  180.   0x00,0x00,0x00,0x00,0xEA,0xAC,0xDF,0x2D,0x00,0xE7,0x06,0xE3, 
  181.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, 
  182.   0x0C,0x0D,0x0E,0x0F,0x41,0x00,0x0F,0x00,0x00, 
  183.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF, 
  184.   0x03,0x01,0x0F,0x00,0x06, 
  185.   0xE7
  186. };
  187. static struct info g360x480x256_info = { 360, 480, 256, 90 };
  188.  
  189.  
  190. /* monochrome mode based on BIOS mode 12h - 640x480x2 */
  191. static char g640x480x2_regs[60] = {
  192.   0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,
  193.   0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xE3,
  194.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  195.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  196.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF,
  197.   0x03,0x01,0x0F,0x00,0x06,
  198.   0xE3
  199. };
  200. static struct info g640x480x2_info = { 640, 480, 2, 80 };
  201.  
  202.  
  203. /* ET4000 BIOS mode 2Eh - 640x480x256 */
  204. static char g640x480x256_regs[70] = {
  205.   0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,
  206.   0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x50,0x60,0xE7,0x04,0xAB,
  207.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  208.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  209.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF,
  210.   0x03,0x01,0x0F,0x00,0x0E,
  211.   0xE3,
  212.   0x70,0x00,0x08,0x00,0x43,0x1F,0xBC,0x00,0x00,0x00
  213. };
  214. static struct info g640x480x256_info = { 640, 480, 256, 640 };
  215.  
  216.  
  217. /* ET4000 BIOS mode 30h - 800x600x256 */
  218. static char g800x600x256_regs[70] = {
  219.   0x7A,0x63,0x64,0x1D,0x68,0x9A,0x78,0xF0,0x00,0x60,0x00,0x00,
  220.   0x00,0x00,0x00,0x00,0x5C,0x8E,0x57,0x64,0x60,0x5B,0x75,0xAB,
  221.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  222.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  223.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF,
  224.   0x03,0x01,0x0F,0x00,0x0E,
  225.   0xEF,
  226.   0x70,0x00,0x08,0x00,0x43,0x1F,0xBC,0x00,0x00,0x00
  227. };
  228. static struct info g800x600x256_info = { 800, 600, 256, 800 };
  229.  
  230.  
  231. /* ET4000 BIOS mode 38h - 1024x768x256 */
  232. static char g1024x768x256_regs[70] = {
  233.   0x99,0x7F,0x7F,0x1D,0x83,0x17,0x2F,0xF5,0x00,0x60,0x00,0x00,
  234.   0x00,0x00,0x00,0x00,0x08,0x80,0xFF,0x80,0x60,0xFF,0x30,0xAB,
  235.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  236.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  237.   0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,0xFF,
  238.   0x03,0x01,0x0F,0x00,0x0E,
  239.   0x27,
  240.   0x70,0x00,0x0A,0x80,0x43,0x1F,0xBC,0x00,0x00,0x00
  241. };
  242. static struct info g1024x768x256_info = { 1024, 768, 256, 1024 };
  243.  
  244.  
  245. /* default palette values */
  246. static char default_red[256]   
  247.              = { 0, 0, 0, 0,42,42,42,42,21,21,21,21,63,63,63,63,
  248.          0, 5, 8,11,14,17,20,24,28,32,36,40,45,50,56,63,
  249.          0,16,31,47,63,63,63,63,63,63,63,63,63,47,31,16,
  250.          0, 0, 0, 0, 0, 0, 0, 0,31,39,47,55,63,63,63,63,
  251.         63,63,63,63,63,55,47,39,31,31,31,31,31,31,31,31,
  252.         45,49,54,58,63,63,63,63,63,63,63,63,63,58,54,49,
  253.         45,45,45,45,45,45,45,45, 0, 7,14,21,28,28,28,28,
  254.         28,28,28,28,28,21,14, 7, 0, 0, 0, 0, 0, 0, 0, 0,
  255.         14,17,21,24,28,28,28,28,28,28,28,28,28,24,21,17,
  256.         14,14,14,14,14,14,14,14,20,22,24,26,28,28,28,28,
  257.         28,28,28,28,28,26,24,22,20,20,20,20,20,20,20,20,
  258.          0, 4, 8,12,16,16,16,16,16,16,16,16,16,12, 8, 4,
  259.          0, 0, 0, 0, 0, 0, 0, 0, 8,10,12,14,16,16,16,16,
  260.         16,16,16,16,16,14,12,10, 8, 8, 8, 8, 8, 8, 8, 8,
  261.         11,12,13,15,16,16,16,16,16,16,16,16,16,15,13,12,
  262.         11,11,11,11,11,11,11,11, 0, 0, 0, 0, 0, 0, 0, 0};
  263. static char default_green[256] 
  264.          = { 0, 0,42,42, 0, 0,21,42,21,21,63,63,21,21,63,63,
  265.          0, 5, 8,11,14,17,20,24,28,32,36,40,45,50,56,63,
  266.          0, 0, 0, 0, 0, 0, 0, 0, 0,16,31,47,63,63,63,63,
  267.         63,63,63,63,63,47,31,16,31,31,31,31,31,31,31,31,
  268.         31,39,47,55,63,63,63,63,63,63,63,63,63,55,47,39,
  269.         45,45,45,45,45,45,45,45,45,49,54,58,63,63,63,63,
  270.         63,63,63,63,63,58,54,49, 0, 0, 0, 0, 0, 0, 0, 0,
  271.          0, 7,14,21,29,28,28,28,28,28,28,28,28,21,14, 7,
  272.         14,14,14,14,14,14,14,14,14,17,21,24,28,28,28,28,
  273.         28,28,28,28,28,24,21,17,20,20,20,20,20,20,20,20,
  274.         20,22,24,26,28,28,28,28,28,28,28,28,28,26,24,22,
  275.          0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8,12,16,16,16,16,
  276.         16,16,16,16,16,12, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8,
  277.          8,10,12,14,16,16,16,16,16,16,16,16,16,14,12,10,
  278.         11,11,11,11,11,11,11,11,11,12,13,15,16,16,16,16,
  279.         16,16,16,16,16,15,13,12, 0, 0, 0, 0, 0, 0, 0, 0};
  280. static char default_blue[256]  
  281.              = { 0,42, 0,42, 0,42, 0,42,21,63,21,63,21,63,21,63,
  282.          0, 5, 8,11,14,17,20,24,28,32,36,40,45,50,56,63,
  283.         63,63,63,63,63,47,31,16, 0, 0, 0, 0, 0, 0, 0, 0,
  284.          0,16,31,47,63,63,63,63,63,63,63,63,63,55,47,39,
  285.         31,31,31,31,31,31,31,31,31,39,47,55,63,63,63,63,
  286.         63,63,63,63,63,58,54,49,45,45,45,45,45,45,45,45,
  287.         45,49,54,58,63,63,63,63,28,28,28,28,28,21,14, 7,
  288.          0, 0, 0, 0, 0, 0, 0, 0, 0, 7,14,21,28,28,28,28,
  289.         28,28,28,28,28,24,21,17,14,14,14,14,14,14,14,14,
  290.         14,17,21,24,28,28,28,28,28,28,28,28,28,26,24,22,
  291.         20,20,20,20,20,20,20,20,20,22,24,26,28,28,28,28,
  292.         16,16,16,16,16,12, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0,
  293.          0, 4, 8,12,16,16,16,16,16,16,16,16,16,14,12,10,
  294.          8, 8, 8, 8, 8, 8, 8, 8, 8,10,12,14,16,16,16,16,
  295.         16,16,16,16,16,15,13,12,11,11,11,11,11,11,11,11,
  296.         11,12,13,15,16,16,16,16, 0, 0, 0, 0, 0, 0, 0, 0};
  297.  
  298.  
  299. /* used to decompose color value into bits (for fast scanline drawing) */
  300. union bits {
  301.     struct {
  302.         char bit3;
  303.         char bit2;
  304.         char bit1;
  305.         char bit0;
  306.     } b;
  307.     unsigned int i;
  308. };
  309.  
  310. /* color decompositions */
  311. static union bits color16[16] = {{0,0,0,0},
  312.                      {0,0,0,1},
  313.                        {0,0,1,0},
  314.                      {0,0,1,1},
  315.                      {0,1,0,0},
  316.                      {0,1,0,1},
  317.                      {0,1,1,0},
  318.                      {0,1,1,1},
  319.                      {1,0,0,0},
  320.                      {1,0,0,1},
  321.                      {1,0,1,0},
  322.                      {1,0,1,1},
  323.                      {1,1,0,0},
  324.                      {1,1,0,1},
  325.                      {1,1,1,0},
  326.                      {1,1,1,1}};
  327.  
  328. /* display plane buffers (for fast scanline drawing) */
  329. static char plane0[256];
  330. static char plane1[256];
  331. static char plane2[256];
  332. static char plane3[256];
  333.  
  334.  
  335. static char text_regs[MAX_REGS];   /* VGA registers for saved text mode */   
  336.  
  337. /* saved text mode palette values */ 
  338. static char text_red[256];  
  339. static char text_green[256];  
  340. static char text_blue[256];  
  341.  
  342. /* saved graphics mode palette values */ 
  343. static char graph_red[256];  
  344. static char graph_green[256];  
  345. static char graph_blue[256];  
  346.  
  347. static int         prv_mode  = TEXT;     /* previous video mode      */
  348. static int         cur_mode  = TEXT;     /* current video mode       */
  349. static int         flip_mode = TEXT;     /* flipped video mode       */
  350. static struct info cur_info;             /* current video parameters */
  351. static int         cur_color;            /* current color            */
  352.  
  353. static int initialized = 0;   /* flag: initialize() called ?  */
  354. static int flip        = 0;   /* flag: executing vga_flip() ? */
  355. static int et4000      = 0;   /* flag: ET4000 or standard VGA */
  356.  
  357. static int   tty0_fd;    /* /dev/tty0 file descriptor              */
  358. static int   mem_fd;     /* /dev/mem file descriptor             */
  359. static FILE* console;    /* console input stream             */
  360. static char* graph_mem;  /* dummy buffer for mmapping grahics memory */
  361.  
  362. static char* graph_buf = NULL;  /* saves graphics data during flip */
  363.  
  364. static char font_buf1[FONT_SIZE];  /* saved font data - plane 2 */
  365. static char font_buf2[FONT_SIZE];  /* saved font data - plane 3 */
  366. static char null_buf[NULL_SIZE];   /* used to speed up clear */
  367.  
  368. static struct termios text_termio;  /* text mode termio parameters     */
  369. static struct termios graph_termio; /* graphics mode termio parameters */
  370.  
  371. int flipchar = '\x1b';   /* flip character - initially  ESCAPE */
  372.  
  373.  
  374. static void inline port_out(char value, unsigned short port)
  375. {
  376. __asm__ volatile ("outb %0,%1"
  377.         ::"a" ((char) value),"d" ((unsigned short) port));
  378. }
  379.  
  380.  
  381. static char inline port_in(unsigned short port)
  382. {
  383.     char _v;
  384. __asm__ volatile ("inb %1,%0"
  385.         :"=a" (_v):"d" ((unsigned short) port));
  386.     return _v;
  387. }
  388.  
  389.  
  390. static void set_graphtermio()
  391. {
  392.         /* set graphics mode termio parameters */
  393.         ioctl(0, TCSETSW, &graph_termio);
  394. }
  395.  
  396.  
  397. static void set_texttermio()
  398. {
  399.     /* restore text mode termio parameters */
  400.     ioctl(0, TCSETSW, &text_termio);
  401. }
  402.  
  403.  
  404. static void disable_interrupt()
  405. {
  406.     struct termios cur_termio;
  407.  
  408.     ioctl(0, TCGETS, &cur_termio);
  409.     cur_termio.c_lflag &= ~ISIG;
  410.     ioctl(0, TCSETSW, &cur_termio);
  411. }
  412.  
  413.  
  414. static void enable_interrupt()
  415. {
  416.     struct termios cur_termio;
  417.  
  418.     ioctl(0, TCGETS, &cur_termio);
  419.     cur_termio.c_lflag |= ISIG;
  420.     ioctl(0, TCSETSW, &cur_termio);
  421. }
  422.  
  423.  
  424. static int get_perm()
  425. {
  426.     /* get I/O permissions for VGA registers */
  427.     if (ioperm(CRT_IC, 1, 1)) {
  428.     printf("VGAlib: can't get I/O permissions \n");
  429.     exit (-1);
  430.     }
  431.     ioperm(CRT_IM,  1, 1);
  432.     ioperm(ATT_IW, 1, 1);
  433.     ioperm(GRA_I,  1, 1);
  434.     ioperm(SEQ_I,  1, 1);
  435.     ioperm(PEL_IW, 1, 1);
  436.     ioperm(PEL_IR, 1, 1);
  437.     ioperm(CRT_DC,  1, 1);
  438.     ioperm(CRT_DM,  1, 1);
  439.     ioperm(ATT_R,  1, 1);
  440.     ioperm(GRA_D,  1, 1);
  441.     ioperm(SEQ_D,  1, 1);
  442.     ioperm(MIS_R,  1, 1);
  443.     ioperm(MIS_W,  1, 1);
  444.     ioperm(IS1_RC,  1, 1);
  445.     ioperm(IS1_RM,  1, 1);
  446.     ioperm(PEL_D,  1, 1);
  447.  
  448.     /* ET4000 registers */
  449.     ioperm(0x3bf,  1, 1);
  450.     ioperm(0x3cc,  1, 1);
  451.     ioperm(0x3d8,  1, 1);
  452.     ioperm(0x3b8,  1, 1);
  453.     ioperm(0x3c3,  1, 1);
  454.     ioperm(0x3cd,  1, 1);
  455.  
  456.     /* color or monochrome text emulation? */
  457.     color_text = port_in(MIS_R)&0x01;
  458.  
  459.     /* chose registers for color/monochrome emulation */
  460.     if (color_text) {
  461.     CRT_I = CRT_IC;
  462.     CRT_D = CRT_DC;
  463.     IS1_R = IS1_RC;
  464.     } else {
  465.     CRT_I = CRT_IM;
  466.     CRT_D = CRT_DM;
  467.     IS1_R = IS1_RM;
  468.     }
  469. }
  470.  
  471.  
  472. static int et4000_test()
  473. {
  474.     char new, old, val;
  475.     int  base;
  476.  
  477.     /* test for Tseng clues */
  478.     old = port_in(0x3cd);              
  479.     port_out(0x55, 0x3cd);
  480.     new = port_in(0x3cd);              
  481.     port_out(old, 0x3cd);
  482.  
  483.     /* return false if not Tseng */
  484.     if (new != 0x55)
  485.     return 0;
  486.  
  487.     /* test for ET4000 clues */
  488.     if (port_in(0x3cc) & 1) 
  489.     base = 0x3d4;
  490.     else 
  491.     base = 0x3b4;
  492.     port_out(0x33, base);
  493.     old = port_in(base+1);
  494.     new = old ^ 0xf;
  495.     port_out(new, base+1);
  496.     val = port_in(base+1);
  497.     port_out(old, base+1);
  498.  
  499.     /* return true if ET4000 */    
  500.     return (val == new);
  501. }
  502.  
  503.  
  504. static int et4000_save_regs(char regs[])
  505. {
  506.     int i;
  507.  
  508.     /* save extended CRT registers */
  509.     for (i = 0; i < 6; i++) {
  510.      port_out(0x32+i, CRT_I); 
  511.      regs[EXT+i] = port_in(CRT_D); 
  512.     }
  513.  
  514.     /* save extended sequencer register */
  515.     port_out(7, SEQ_I); 
  516.     regs[EXT+6] = port_in(SEQ_D); 
  517.  
  518.     /* save some other ET4000 specific registers */
  519.     regs[EXT+7] = port_in(0x3c3); 
  520.     regs[EXT+8] = port_in(0x3cd); 
  521.  
  522.     /* save extended attribute register */
  523.     port_in(IS1_R);    /* reset flip flop */
  524.     port_out(0x16, ATT_IW);
  525.     regs[EXT+9] = port_in(ATT_R);
  526. }
  527.  
  528.  
  529. static int et4000_set_regs(char regs[])
  530. {
  531.     int i;
  532.  
  533.     /* write some ET4000 specific registers */
  534.     port_out(regs[EXT+7], 0x3c3);
  535.     port_out(regs[EXT+8], 0x3cd);
  536.  
  537.     /* write extended sequencer register */
  538.     port_out(7, SEQ_I); 
  539.     port_out(regs[EXT+6], SEQ_D); 
  540.  
  541.     /* write extended CRT registers */
  542.     for (i = 0; i < 6; i++) {
  543.      port_out(0x32+i, CRT_I); 
  544.      port_out(regs[EXT+i], CRT_D); 
  545.     }
  546.  
  547.     /* write extended attribute register */
  548.     port_in(IS1_R);    /* reset flip flop */
  549.     port_out(0x16, ATT_IW);
  550.     port_out(regs[EXT+9], ATT_IW);
  551. }
  552.  
  553.  
  554. static int save_regs(char regs[])
  555. {
  556.     int i;
  557.  
  558.     /* save VGA registers */
  559.     for (i = 0; i < CRT_C; i++) {
  560.      port_out(i, CRT_I); 
  561.      regs[CRT+i] = port_in(CRT_D); 
  562.     }
  563.     for (i = 0; i < ATT_C; i++) {
  564.            port_in(IS1_R);
  565.          port_out(i, ATT_IW); 
  566.          regs[ATT+i] = port_in(ATT_R); 
  567.     }
  568.     for (i = 0; i < GRA_C; i++) {
  569.             port_out(i, GRA_I); 
  570.             regs[GRA+i] = port_in(GRA_D); 
  571.     }
  572.     for (i = 0; i < SEQ_C; i++) {
  573.             port_out(i, SEQ_I); 
  574.             regs[SEQ+i] = port_in(SEQ_D); 
  575.     }
  576.     regs[MIS] = port_in(MIS_R); 
  577.  
  578.     if (et4000)
  579.     et4000_save_regs(regs);
  580. }
  581.  
  582.  
  583. static int set_regs(char regs[], int mode)
  584. {
  585.     int i;
  586.  
  587.     /* disable video */
  588.     port_in(IS1_R);            
  589.     port_out(0x00, ATT_IW);     
  590.   
  591.     /* update misc output register */
  592.     port_out(regs[MIS], MIS_W);         
  593.  
  594.     /* synchronous reset on */
  595.     port_out(0x00,SEQ_I); 
  596.     port_out(0x01,SEQ_D);            
  597.   
  598.     /* write sequencer registers */
  599.     for (i = 1; i < SEQ_C; i++) {       
  600.     port_out(i, SEQ_I); 
  601.     port_out(regs[SEQ+i], SEQ_D); 
  602.     }
  603.  
  604.     /* synchronous reset off */
  605.     port_out(0x00, SEQ_I); 
  606.     port_out(0x03, SEQ_D);            
  607.   
  608.     /* deprotect CRT registers 0-7 */
  609.     port_out(0x11, CRT_I);          
  610.     port_out(port_in(CRT_D)&0x7F, CRT_D);   
  611.   
  612.     /* write CRT registers */
  613.     for (i = 0; i < CRT_C; i++) {       
  614.     port_out(i, CRT_I); 
  615.     port_out(regs[CRT+i], CRT_D); 
  616.     }
  617.  
  618.     /* write graphics controller registers */
  619.     for (i = 0; i < GRA_C; i++) {       
  620.     port_out(i, GRA_I); 
  621.     port_out(regs[GRA+i], GRA_D); 
  622.     }
  623.      
  624.     /* write attribute controller registers */
  625.     for (i = 0; i < ATT_C; i++) {       
  626.     port_in(IS1_R);   /* reset flip-flop */
  627.     port_out(i, ATT_IW);
  628.     port_out(regs[ATT+i],ATT_IW);
  629.     }
  630.  
  631.     if (et4000)
  632.     if (mode == G640x480x256 || mode == G800x600x256 || mode == G1024x768x256)
  633.         et4000_set_regs(regs);
  634. }
  635.  
  636.  
  637. static void interrupt_handler(int value) 
  638. {
  639.     /* handle SIGINT - restore text mode and exit */
  640.     if (cur_mode != TEXT) 
  641.     vga_setmode(TEXT);
  642.     set_texttermio();
  643.     exit(-1);
  644.  
  645. }
  646.  
  647.  
  648. static void initialize()
  649. {
  650.     int  i, j;
  651.  
  652.     /* save text mode termio parameters */
  653.     ioctl(0, TCGETS, &text_termio);
  654.  
  655.     graph_termio = text_termio;
  656.  
  657.     /* change termio parameters to allow our own I/O processing */
  658.     graph_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IUCLC|IXON|IXOFF);
  659.     graph_termio.c_iflag |=  (IGNBRK|IGNPAR);
  660.  
  661.     graph_termio.c_oflag &= ~(ONOCR);
  662.  
  663.     graph_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
  664.     graph_termio.c_lflag |= (ISIG);   /* enable interrupt */
  665.  
  666.     graph_termio.c_cc[VMIN] = 1;
  667.     graph_termio.c_cc[VTIME] = 0;
  668.     graph_termio.c_cc[VSUSP] = 0;   /* disable suspend */
  669.  
  670.     disable_interrupt();
  671.  
  672.     get_perm();
  673.  
  674.     et4000 = et4000_test();
  675.  
  676.     if (et4000) {
  677.     /* get acces to extended registers */
  678.     port_out(3, 0x3bf);
  679.     if (port_in( 0x3cc ) & 1) 
  680.         port_out(0xa0, 0x3d8);
  681.     else
  682.         port_out(0xa0, 0x3b8);
  683.     }
  684.     
  685.     /* open /dev/tty0 - current virtual console */
  686.     if ((tty0_fd = open("/dev/tty0", O_RDONLY) ) < 0) {
  687.     printf("VGAlib: can't open /dev/tty0 \n");
  688.     exit (-1);
  689.     }
  690.     console = fdopen(tty0_fd, "r"); 
  691.  
  692.     /* disable text output to console */
  693.     ioctl(tty0_fd, KDSETMODE, KD_GRAPHICS);
  694.     
  695.     /* open /dev/mem */
  696.     if ((mem_fd = open("/dev/mem", O_RDWR) ) < 0) {
  697.     printf("VGAlib: can't open /dev/mem \n");
  698.     exit (-1);
  699.     }
  700.  
  701.     /* mmap graphics memory */
  702.     if ((graph_mem = malloc(GRAPH_SIZE + (PAGE_SIZE-1))) == NULL) {
  703.     printf("VGAlib: allocation error \n");
  704.     exit (-1);
  705.     }
  706.     if ((unsigned long)graph_mem % PAGE_SIZE)
  707.     graph_mem += PAGE_SIZE - ((unsigned long)graph_mem % PAGE_SIZE);
  708.     graph_mem = (char *)mmap(
  709.     (caddr_t)graph_mem, 
  710.     GRAPH_SIZE,
  711.     PROT_READ|PROT_WRITE,
  712.     MAP_SHARED|MAP_FIXED,
  713.     mem_fd, 
  714.     GRAPH_BASE
  715.     );
  716.     if ((long)graph_mem < 0) {
  717.     printf("VGAlib: mmap error \n");
  718.     exit (-1);
  719.     }
  720.  
  721.     /* disable video */
  722.     port_in(IS1_R);            
  723.     port_out(0x00, ATT_IW);     
  724.   
  725.     save_regs(text_regs);
  726.  
  727.     /* save text mode palette - first select palette index 0 */
  728.     port_out(0, PEL_IR); 
  729.  
  730.     /* read RGB components - index is autoincremented */
  731.     for(i = 0; i < 256; i++) {
  732.     for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */ 
  733.     text_red[i] = port_in(PEL_D);
  734.     for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */ 
  735.     text_green[i] = port_in(PEL_D);
  736.     for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */ 
  737.     text_blue[i] = port_in(PEL_D);
  738.     }
  739.  
  740.     /* shift to color emulation */
  741.     CRT_I = CRT_IC;
  742.     CRT_D = CRT_DC;
  743.     IS1_R = IS1_RC;
  744.     port_out(port_in(MIS_R)|0x01, MIS_W); 
  745.  
  746.     /* save font data - first select a 16 color graphics mode */
  747.     set_regs(g640x480x16_regs, G640x480x16);
  748.  
  749.     /* save font data in plane 2 */
  750.     port_out(0x04, GRA_I); 
  751.     port_out(0x02, GRA_D); 
  752.     memcpy(font_buf1, graph_mem, FONT_SIZE);
  753.  
  754.     /* save font data in plane 3 */
  755.     port_out(0x04, GRA_I); 
  756.     port_out(0x03, GRA_D); 
  757.     memcpy(font_buf2, graph_mem, FONT_SIZE);
  758.  
  759.     /* initialize buffer used when clearing in 256 color modes */
  760.     for(i = 0; i < NULL_SIZE; i++)
  761.         null_buf[i] = 0;
  762.  
  763.     initialized = 1;
  764.  
  765.     /* do our own interrupt handling */
  766.     (void) signal(SIGINT, interrupt_handler);
  767. }
  768.  
  769.  
  770. int vga_dumpregs()
  771. {
  772.     char regs[MAX_REGS];
  773.     int i;
  774.  
  775.     get_perm();
  776.  
  777.     et4000 = et4000_test();
  778.  
  779.     save_regs(regs);
  780.  
  781.     if (et4000)
  782.     printf("static char regs[70] = {\n  ");
  783.     else
  784.     printf("static char regs[60] = {\n  ");
  785.  
  786.     for (i = 0; i < 12; i++) 
  787.         printf("0x%02X,", regs[CRT+i]);
  788.     printf("\n  "); 
  789.     for (i = 12; i < CRT_C; i++) 
  790.         printf("0x%02X,", regs[CRT+i]);
  791.     printf("\n  "); 
  792.     for (i = 0; i < 12; i++) 
  793.         printf("0x%02X,", regs[ATT+i]);
  794.     printf("\n  "); 
  795.     for (i = 12; i < ATT_C; i++) 
  796.         printf("0x%02X,", regs[ATT+i]);
  797.     printf("\n  "); 
  798.     for (i = 0; i < GRA_C; i++) 
  799.         printf("0x%02X,", regs[GRA+i]);
  800.     printf("\n  "); 
  801.     for (i = 0; i < SEQ_C; i++) 
  802.         printf("0x%02X,", regs[SEQ+i]);
  803.     printf("\n  "); 
  804.     printf("0x%02X", regs[MIS]);
  805.  
  806.     if (et4000) {
  807.     printf(",\n  "); 
  808.     for (i = 0; i < 9; i++) 
  809.             printf("0x%02X,", regs[EXT+i]);
  810.     printf("0x%02X", regs[EXT+9]);
  811.     }
  812.  
  813.     printf("\n};\n"); 
  814. }
  815.  
  816.  
  817. int vga_setmode(int mode) 
  818. {
  819.     int i;
  820.  
  821.     if (!initialized)
  822.         initialize();
  823.  
  824.     disable_interrupt();
  825.  
  826.     prv_mode = cur_mode;
  827.     cur_mode = mode;
  828.  
  829.     /* disable video */
  830.     port_in(IS1_R);         
  831.     port_out(0x00, ATT_IW);    
  832.  
  833.     if (et4000 && prv_mode == G1024x768x256)
  834.     set_regs(g640x480x256_regs, G640x480x256);
  835.  
  836.     if (mode == TEXT) {    
  837.         /* restore font data - first select a 16 color graphics mode */
  838.         set_regs(g640x480x16_regs, G640x480x16);
  839.  
  840.     /* disable Set/Reset Register */
  841.         port_out(0x01, GRA_I ); 
  842.         port_out(0x00, GRA_D );   
  843.  
  844.         /* restore font data in plane 2 - necessary for all VGA's */
  845.         port_out(0x02, SEQ_I ); 
  846.         port_out(0x04, SEQ_D );   
  847.     memcpy(graph_mem, font_buf1, FONT_SIZE);
  848.  
  849.         /* restore font data in plane 3 - necessary for Trident VGA's */
  850.         port_out(0x02, SEQ_I ); 
  851.         port_out(0x08, SEQ_D );   
  852.     memcpy(graph_mem, font_buf2, FONT_SIZE);
  853.  
  854.         /* change register adresses if monochrome text mode */
  855.         if (!color_text) {
  856.             CRT_I = CRT_IM;
  857.             CRT_D = CRT_DM;
  858.             IS1_R = IS1_RM;
  859.             port_out(port_in(MIS_R)&0xFE, MIS_W); 
  860.         }
  861.  
  862.         /* restore saved palette */
  863.         for(i = 0; i < 256; i++)
  864.             vga_setpalette(
  865.                 i, text_red[i], text_green[i], text_blue[i]
  866.             );
  867.  
  868.     /* restore text mode VGA registers */
  869.         set_regs(text_regs, TEXT);
  870.  
  871.     /* enable text output - restores the screen contents */ 
  872.         ioctl(tty0_fd, KDSETMODE, KD_TEXT);
  873.  
  874.         /* enable video */
  875.         port_in(IS1_R); 
  876.         port_out(0x20, ATT_IW); 
  877.   
  878.         /* restore text mode termio */
  879.         set_texttermio();
  880.  
  881.     } else {
  882.     /* disable text output */
  883.         ioctl(tty0_fd, KDSETMODE, KD_GRAPHICS);
  884.  
  885.         /* shift to color emulation */
  886.         CRT_I = CRT_IC;
  887.         CRT_D = CRT_DC;
  888.         IS1_R = IS1_RC;
  889.         port_out(port_in(MIS_R)|0x01, MIS_W); 
  890.  
  891.         switch (mode) {
  892.             case G320x200x16:
  893.                 set_regs(g320x200x16_regs, G320x200x16);
  894.                 cur_info = g320x200x16_info;
  895.                 break;
  896.             case G640x200x16:
  897.                 set_regs(g640x200x16_regs, G640x200x16);
  898.                 cur_info = g640x200x16_info;
  899.                 break;
  900.             case G640x350x16:
  901.                 set_regs(g640x350x16_regs, G640x350x16);
  902.                 cur_info = g640x350x16_info;
  903.                 break;
  904.             case G640x480x16:
  905.                 set_regs(g640x480x16_regs, G640x480x16);
  906.                 cur_info = g640x480x16_info;
  907.                 break;
  908.         case G320x200x256:
  909.                 set_regs(g320x200x256_regs, G320x200x256);
  910.                 cur_info = g320x200x256_info;
  911.                 break;
  912.         case G320x240x256:
  913.                 set_regs(g320x240x256_regs, G320x240x256);
  914.                 cur_info = g320x240x256_info;
  915.                 break;
  916.         case G320x400x256:
  917.                 set_regs(g320x400x256_regs, G320x400x256);
  918.                 cur_info = g320x400x256_info;
  919.                 break;
  920.         case G360x480x256:
  921.                 set_regs(g360x480x256_regs, G360x480x256);
  922.                 cur_info = g360x480x256_info;
  923.                 break;
  924.             case G640x480x2:
  925.                 set_regs(g640x480x2_regs, G640x480x2);
  926.                 cur_info = g640x480x2_info;
  927.                 break;
  928.         case G640x480x256:
  929.                 set_regs(g640x480x256_regs, G640x480x256);
  930.                 cur_info = g640x480x256_info;
  931.                 break;
  932.         case G800x600x256:
  933.                 set_regs(g800x600x256_regs, G800x600x256);
  934.                 cur_info = g800x600x256_info;
  935.                 break;
  936.         case G1024x768x256:
  937.                 set_regs(g1024x768x256_regs, G1024x768x256);
  938.                 cur_info = g1024x768x256_info;
  939.                 break;
  940.         }
  941.  
  942.         if (!flip) {
  943.             /* set default palette */
  944.             for(i = 0; i < 256; i++)
  945.                 vga_setpalette(
  946.                     i, default_red[i], default_green[i], default_blue[i]
  947.                 );
  948.  
  949.             /* clear screen (sets current color to 15) */
  950.             vga_clear();
  951.         }    
  952.  
  953.         /* enable video */
  954.         port_in(IS1_R); 
  955.         port_out(0x20, ATT_IW); 
  956.   
  957.         /* set graphics mode termio */
  958.         set_graphtermio();
  959.     }
  960.  
  961.     return 0;  
  962. }
  963.  
  964. int vga_hasmode(int mode)
  965. {
  966.     switch (mode) {
  967.     case TEXT:
  968.         case G320x200x16:
  969.         case G640x200x16:
  970.         case G640x350x16:
  971.         case G640x480x16:
  972.         case G640x480x2:
  973.     case G320x200x256:
  974.     case G320x240x256:
  975.     case G320x400x256:
  976.     case G360x480x256:
  977.         return 1;
  978.     case G640x480x256:
  979.     case G800x600x256:
  980.     case G1024x768x256:
  981.         get_perm();
  982.         return et4000_test();
  983.     default:
  984.         return 0;
  985.     }
  986. }
  987.  
  988. int vga_clear()
  989. {
  990.     int i, j;
  991.  
  992.     vga_screenoff();
  993.  
  994.     switch (cur_mode) {
  995.         case G320x200x16:
  996.         case G640x200x16:
  997.         case G640x350x16:
  998.         case G640x480x16:
  999.         case G640x480x2:
  1000.             vga_setcolor(0);
  1001.  
  1002.         /* write to all bits */
  1003.             port_out(0x08, GRA_I ); 
  1004.             port_out(0xFF, GRA_D );   
  1005.  
  1006.             /* write dummy values to clear video memory */
  1007.             for(i = 0; i < 16; i++)
  1008.         memcpy(graph_mem + i*NULL_SIZE, null_buf, NULL_SIZE);
  1009.  
  1010.             break;
  1011.     case G320x200x256:
  1012.     case G320x240x256:
  1013.     case G320x400x256:
  1014.     case G360x480x256:
  1015.             /* write to all planes */ 
  1016.             port_out(0x02, SEQ_I ); 
  1017.             port_out(0x0F, SEQ_D );
  1018.    
  1019.             /* clear video memory */
  1020.             for(i = 0; i < 16; i++)
  1021.         memcpy(graph_mem + i*NULL_SIZE, null_buf, NULL_SIZE);
  1022.  
  1023.             break;
  1024.     case G640x480x256:
  1025.     case G800x600x256:
  1026.     case G1024x768x256:
  1027.         for(i = 0; i < 16; i++) {
  1028.         /* select segment */
  1029.            port_out(i, SEG_SELECT);
  1030.  
  1031.             /* clear video memory */
  1032.             for(j = 0; j < 16; j++)
  1033.             memcpy(graph_mem + j*NULL_SIZE, null_buf, NULL_SIZE);
  1034.         }
  1035.             break;
  1036.     }
  1037.  
  1038.     vga_setcolor(15);
  1039.         
  1040.     vga_screenon();
  1041.  
  1042.     return 0;
  1043. }
  1044.  
  1045.  
  1046. int vga_setpalette(int index, int red, int green, int blue)
  1047. {
  1048.     int i;
  1049.  
  1050.     /* select palette register */
  1051.     port_out(index, PEL_IW); 
  1052.  
  1053.     /* write RGB components */
  1054.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */ 
  1055.     port_out(red, PEL_D);
  1056.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */ 
  1057.     port_out(green, PEL_D);
  1058.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */ 
  1059.     port_out(blue, PEL_D);
  1060.  
  1061.     return 0;
  1062. }
  1063.  
  1064.  
  1065. int vga_getpalette(int index, int *red, int *green, int *blue)
  1066. {
  1067.     int i;
  1068.  
  1069.     /* select palette register */
  1070.     port_out(index, PEL_IR);
  1071.  
  1072.     /* read RGB components */
  1073.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1074.     *red = (int) port_in(PEL_D);
  1075.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1076.     *green = (int) port_in(PEL_D);
  1077.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1078.     *blue = (int) port_in(PEL_D);
  1079.  
  1080.     return 0;
  1081. }
  1082.  
  1083.  
  1084. int vga_setpalvec(int start, int num, int *pal)
  1085. {
  1086.     int i, j;
  1087.  
  1088.     /* select palette register */
  1089.     port_out(start, PEL_IW);
  1090.  
  1091.     for(j = 0; j < num; j++) {
  1092.         for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1093.         port_out(*(pal++), PEL_D);
  1094.         for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1095.         port_out(*(pal++), PEL_D);
  1096.         for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1097.         port_out(*(pal++), PEL_D);
  1098.     }
  1099.  
  1100.     return j;
  1101. }
  1102.  
  1103.  
  1104. int vga_getpalvec(int start, int num, int *pal)
  1105. {
  1106.     int i, j;
  1107.  
  1108.     /* select palette register */
  1109.     port_out(start, PEL_IR);
  1110.  
  1111.     for(j = 0; j < num; j++) {
  1112.         for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1113.         *(pal++) = (int) port_in(PEL_D);
  1114.         for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1115.         *(pal++) = (int) port_in(PEL_D);
  1116.         for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  1117.         *(pal++) = (int) port_in(PEL_D);
  1118.     }
  1119.  
  1120.     return i;
  1121. }
  1122.  
  1123.  
  1124. int vga_setcolor(int color)
  1125. {
  1126.     switch (cur_mode) {
  1127.         case G320x200x16:
  1128.         case G640x200x16:
  1129.         case G640x350x16:
  1130.         case G640x480x16:
  1131.             /* update set/reset register */
  1132.         port_out(0x00, GRA_I ); 
  1133.         port_out(color, GRA_D );   
  1134.             break;
  1135.         case G640x480x2:
  1136.         if (color != 0)
  1137.         color = 15;
  1138.             /* update set/reset register */
  1139.         port_out(0x00, GRA_I ); 
  1140.         port_out(color, GRA_D );   
  1141.             break;
  1142.     case G320x200x256:
  1143.     case G320x240x256:
  1144.     case G320x400x256:
  1145.     case G360x480x256:
  1146.     case G640x480x256:
  1147.     case G800x600x256:
  1148.     case G1024x768x256:
  1149.         cur_color = color;
  1150.             break;
  1151.     }
  1152.         
  1153.     return 0;
  1154. }
  1155.  
  1156.  
  1157. int vga_drawpixel(int x, int y)
  1158. {
  1159.     unsigned long offset;
  1160.  
  1161.     switch (cur_mode) {
  1162.         case G320x200x16:
  1163.         case G640x200x16:
  1164.         case G640x350x16:
  1165.         case G640x480x16:
  1166.         case G640x480x2:
  1167.         /* select bit */
  1168.         port_out(8, GRA_I);
  1169.         port_out(0x80 >> (x & 7), GRA_D);   
  1170.  
  1171.             /* read into latch and write dummy back */
  1172.         offset = y*cur_info.xbytes + (x>>3);   
  1173.             graph_mem[offset] = graph_mem[offset];   
  1174.             break;
  1175.     case G320x200x256:
  1176.             /* write color to pixel */
  1177.         graph_mem[y*320 + x] = cur_color;  
  1178.             break;
  1179.     case G320x240x256:
  1180.     case G320x400x256:
  1181.     case G360x480x256:
  1182.         /* select plane */ 
  1183.         port_out(0x02, SEQ_I); 
  1184.             port_out(1 << (x & 3), SEQ_D);   
  1185.  
  1186.             /* write color to pixel */
  1187.         graph_mem[y*cur_info.xbytes + (x>>2)] = cur_color;  
  1188.             break;
  1189.     case G640x480x256:
  1190.     case G800x600x256:
  1191.     case G1024x768x256:
  1192.         offset = y*cur_info.xbytes+x; 
  1193.  
  1194.         /* select segment */
  1195.            port_out(offset >> 16, SEG_SELECT);
  1196.  
  1197.             /* write color to pixel */
  1198.         graph_mem[offset & 0xFFFF] = cur_color;  
  1199.             break;
  1200.     }
  1201.         
  1202.     return 0;
  1203. }
  1204.  
  1205.  
  1206. int vga_drawscanline(int line, char* colors)
  1207. {
  1208.     if (cur_mode == G640x480x2)
  1209.     vga_drawscansegment(colors, 0, line, cur_info.xbytes);
  1210.     else
  1211.     vga_drawscansegment(colors, 0, line, cur_info.xdim);
  1212. }
  1213.  
  1214.  
  1215. int vga_drawscansegment(char* colors, int x, int y, int length)
  1216. {
  1217.     /* both length and x must divide with 8 */
  1218.  
  1219.     switch (cur_mode) {
  1220.         case G320x200x16:
  1221.         case G640x200x16:
  1222.         case G640x350x16:
  1223.         case G640x480x16:
  1224.         {
  1225.                int i, j, k, first, last;
  1226.         union bits bytes;
  1227.                 char* address;
  1228.  
  1229.                 k = 0;
  1230.                 for(i = 0; i < length; i += 8) {
  1231.                     bytes.i = 0;
  1232.                     first = i;
  1233.                     last  = i+8;
  1234.                     for(j = first; j < last; j++)
  1235.                        bytes.i = (bytes.i<<1) | color16[colors[j]].i;
  1236.             plane0[k]   = bytes.b.bit0;
  1237.             plane1[k]   = bytes.b.bit1;
  1238.             plane2[k]   = bytes.b.bit2;
  1239.             plane3[k++] = bytes.b.bit3;
  1240.                 }
  1241.  
  1242.                 address = graph_mem + (y*cur_info.xdim+x)/8;
  1243.  
  1244.         /* disable Set/Reset Register */
  1245.             port_out(0x01, GRA_I ); 
  1246.             port_out(0x00, GRA_D ); 
  1247.  
  1248.         /* write to all bits */
  1249.             port_out(0x08, GRA_I ); 
  1250.             port_out(0xFF, GRA_D );   
  1251.  
  1252.         /* select map mask register */
  1253.             port_out(0x02, SEQ_I ); 
  1254.  
  1255.                 /* write plane 0 */
  1256.             port_out(0x01, SEQ_D ); 
  1257.             memcpy(address, plane0, length/8);
  1258.  
  1259.                 /* write plane 1 */
  1260.             port_out(0x02, SEQ_D ); 
  1261.             memcpy(address, plane1, length/8);
  1262.  
  1263.                 /* write plane 2 */
  1264.             port_out(0x04, SEQ_D ); 
  1265.             memcpy(address, plane2, length/8);
  1266.  
  1267.                 /* write plane 3 */
  1268.             port_out(0x08, SEQ_D ); 
  1269.             memcpy(address, plane3, length/8);
  1270.  
  1271.                 /* restore map mask register */
  1272.             port_out(0x0F, SEQ_D ); 
  1273.   
  1274.         /* enable Set/Reset Register */
  1275.             port_out(0x01, GRA_I ); 
  1276.             port_out(0x0F, GRA_D );   
  1277.             }
  1278.             break;
  1279.         case G640x480x2:
  1280.         {
  1281.         /* disable Set/Reset Register */
  1282.             port_out(0x01, GRA_I ); 
  1283.             port_out(0x00, GRA_D ); 
  1284.  
  1285.         /* write to all bits */
  1286.             port_out(0x08, GRA_I ); 
  1287.             port_out(0xFF, GRA_D );   
  1288.  
  1289.         /* write to all planes */
  1290.             port_out(0x02, SEQ_I ); 
  1291.             port_out(0x0F, SEQ_D ); 
  1292.  
  1293.             memcpy(graph_mem + (y*cur_info.xdim+x)/8, colors, length);
  1294.  
  1295.                 /* restore map mask register */
  1296.             port_out(0x0F, SEQ_D ); 
  1297.   
  1298.         /* enable Set/Reset Register */
  1299.             port_out(0x01, GRA_I ); 
  1300.             port_out(0x0F, GRA_D );   
  1301.             }
  1302.             break;
  1303.     case G320x200x256:
  1304.             /* linear addressing - easy and fast */
  1305.         memcpy(graph_mem + y*cur_info.xdim+x, colors, length);
  1306.             break;
  1307.     case G320x240x256:
  1308.     case G320x400x256:
  1309.     case G360x480x256: 
  1310.             {
  1311.                 int first, last, offset, pixel, plane;
  1312.  
  1313.             /* select map mask register */ 
  1314.             port_out(0x02, SEQ_I); 
  1315.  
  1316.                 for(plane = 0; plane < 4; plane++) {
  1317.                     /* select plane */
  1318.                     port_out(1 << plane, SEQ_D);   
  1319.  
  1320.                     pixel = plane;
  1321.                     first = (y*cur_info.xdim+x)/4;
  1322.                     last  = (y*cur_info.xdim+x+length)/4;
  1323.                     for(offset = first; offset < last; offset++) {
  1324.                 graph_mem[offset] = colors[pixel];  
  1325.                         pixel += 4;
  1326.                     }
  1327.             }
  1328.             }
  1329.             break;
  1330.     case G640x480x256:
  1331.     case G800x600x256:
  1332.     case G1024x768x256:
  1333.         {
  1334.         unsigned long offset;
  1335.         int segment, free;
  1336.  
  1337.         offset  = y*cur_info.xbytes+x; 
  1338.         segment = offset >> 16;
  1339.         free    = ((segment+1)<<16)-offset;
  1340.  
  1341.         if (free < length) {
  1342.                port_out(segment, SEG_SELECT);
  1343.             memcpy(graph_mem + (offset & 0xFFFF), colors, free);
  1344.                port_out(segment+1, SEG_SELECT);
  1345.             memcpy(graph_mem, colors+free, length-free);
  1346.         } else {
  1347.                port_out(segment, SEG_SELECT);
  1348.             memcpy(graph_mem + (offset & 0xFFFF), colors, length);
  1349.         }
  1350.  
  1351.         }
  1352.             break;
  1353.     }
  1354.         
  1355.     return 0;
  1356. }
  1357.  
  1358.  
  1359. int vga_drawline(int x1, int y1, int x2, int y2)
  1360. {
  1361.     int dx = x2 - x1;
  1362.     int dy = y2 - y1;
  1363.     int ax = ABS(dx) << 1;
  1364.     int ay = ABS(dy) << 1;
  1365.     int sx = (dx >= 0) ? 1 : -1;
  1366.     int sy = (dy >= 0) ? 1 : -1;
  1367.  
  1368.     int x  = x1;
  1369.     int y  = y1;
  1370.  
  1371.     if (ax > ay) {
  1372.         int d = ay - (ax >> 1);
  1373.         while (x != x2) {
  1374.         vga_drawpixel(x, y);
  1375.  
  1376.             if (d > 0 || d == 0 && sx == 1) {
  1377.                 y += sy;
  1378.                 d -= ax;
  1379.             }
  1380.             x += sx;
  1381.             d += ay;
  1382.         }
  1383.     } else {
  1384.         int d = ax - (ay >> 1);
  1385.         while (y != y2) {
  1386.         vga_drawpixel(x, y);
  1387.  
  1388.             if (d > 0 || d == 0 && sy == 1) {
  1389.                 x += sx;
  1390.                 d -= ay;
  1391.             }
  1392.             y += sy;
  1393.             d += ax;
  1394.         }
  1395.     }
  1396.     vga_drawpixel(x, y);
  1397.      
  1398.     return 0;
  1399. }
  1400.  
  1401.  
  1402. int vga_screenoff()
  1403. {
  1404.     /* turn off screen for faster VGA memory acces */
  1405.     port_out(0x01, SEQ_I);           
  1406.     port_out(port_in(SEQ_D)|0x20, SEQ_D);   
  1407.  
  1408.     return 0;
  1409. }
  1410.  
  1411.  
  1412. int vga_screenon()
  1413. {
  1414.     /* turn screen back on */
  1415.     port_out(0x01, SEQ_I);           
  1416.     port_out(port_in(SEQ_D)&0xDF, SEQ_D);   
  1417.  
  1418.     return 0;
  1419. }
  1420.  
  1421.  
  1422. int vga_getxdim()
  1423. {
  1424.     return cur_info.xdim;
  1425. }
  1426.  
  1427.  
  1428. int vga_getydim()
  1429. {
  1430.     return cur_info.ydim;
  1431. }
  1432.  
  1433.  
  1434. int vga_getcolors()
  1435. {
  1436.     return cur_info.colors;
  1437. }
  1438.  
  1439.  
  1440. int vga_getch()
  1441. {
  1442.     char c;
  1443.  
  1444.     if (cur_mode == TEXT)
  1445.     return -1;
  1446.  
  1447.     read(tty0_fd, &c, 1);
  1448.     while(c == flipchar) {
  1449.     vga_flip();
  1450.  
  1451.     set_graphtermio();
  1452.         read(tty0_fd, &c, 1);
  1453.  
  1454.     vga_flip();
  1455.         read(tty0_fd, &c, 1);
  1456.     }
  1457.  
  1458.     return c;
  1459. }
  1460.  
  1461.  
  1462. int vga_setflipchar(int c)
  1463. {
  1464.     flipchar = c;
  1465.  
  1466.     return 0;
  1467. }
  1468.  
  1469.  
  1470. int vga_flip()
  1471. {
  1472.     int i, j;
  1473.  
  1474.     if (cur_mode == TEXT && flip_mode == TEXT)
  1475.     return -1;
  1476.  
  1477.     flip = 1;
  1478.  
  1479.     disable_interrupt();
  1480.  
  1481.     /* disable video */
  1482.     port_in(IS1_R);         
  1483.     port_out(0x00, ATT_IW);    
  1484.   
  1485.     if (cur_mode == TEXT) {
  1486.     /* disable text output */
  1487.         ioctl(tty0_fd, KDSETMODE, KD_GRAPHICS);
  1488.  
  1489.         /* restore all four planes - first select a 16 color graphics mode */
  1490.         set_regs(g640x480x16_regs, G640x480x16);
  1491.  
  1492.     /* disable Set/Reset Register */
  1493.         port_out(0x01, GRA_I ); 
  1494.         port_out(0x00, GRA_D );   
  1495.  
  1496.         for(i = 0; i < 4; i++) {
  1497.             /* restore plane i */
  1498.             port_out(0x02, SEQ_I ); 
  1499.             port_out(1<<i, SEQ_D );   
  1500.             memcpy(graph_mem, graph_buf + i*GRAPH_SIZE, GRAPH_SIZE);
  1501.     }
  1502.  
  1503.         free(graph_buf);
  1504.  
  1505.         /* restore saved palette */
  1506.         for(i = 0; i < 256; i++)
  1507.             vga_setpalette(
  1508.                 i, graph_red[i], graph_green[i], graph_blue[i]
  1509.             );
  1510.  
  1511.         vga_setmode(flip_mode);
  1512.  
  1513.     flip_mode = TEXT;
  1514.     } else {
  1515.     /* save all four planes - first select a 16 color graphics mode */
  1516.         set_regs(g640x480x16_regs, G640x480x16);
  1517.  
  1518.     /* allocate memory for saved graphics data - only if necessary */
  1519.         if ((graph_buf = malloc(4*GRAPH_SIZE)) == NULL) {
  1520.             printf("vga_flip: allocation error \n");
  1521.             exit (-1);
  1522.         }
  1523.  
  1524.         for(i = 0; i < 4; i++) {
  1525.             /* save plane i */
  1526.             port_out(0x04, GRA_I); 
  1527.             port_out(   i, GRA_D); 
  1528.             memcpy(graph_buf + i*GRAPH_SIZE, graph_mem, GRAPH_SIZE);
  1529.     }
  1530.  
  1531.         /* save graphics mode palette - first select palette index 0 */
  1532.         port_out(0, PEL_IR); 
  1533.  
  1534.         /* read RGB components - index is autoincremented */
  1535.         for(i = 0; i < 256; i++) {
  1536.             for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */ 
  1537.             graph_red[i] = port_in(PEL_D);
  1538.             for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */ 
  1539.             graph_green[i] = port_in(PEL_D);
  1540.             for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */ 
  1541.             graph_blue[i] = port_in(PEL_D);
  1542.         }
  1543.  
  1544.         flip_mode = cur_mode;
  1545.  
  1546.     vga_setmode(TEXT);
  1547.     }
  1548.  
  1549.     flip = 0;
  1550.  
  1551.     return 0;
  1552. }
  1553.