vga.c 40 KB

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