vgastate.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /*
  2. * linux/drivers/video/vgastate.c -- VGA state save/restore
  3. *
  4. * Copyright 2002 James Simmons
  5. *
  6. * Copyright history from vga16fb.c:
  7. * Copyright 1999 Ben Pfaff and Petr Vandrovec
  8. * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
  9. * Based on VESA framebuffer (c) 1998 Gerd Knorr
  10. *
  11. * This file is subject to the terms and conditions of the GNU General
  12. * Public License. See the file COPYING in the main directory of this
  13. * archive for more details.
  14. *
  15. */
  16. #include <linux/module.h>
  17. #include <linux/slab.h>
  18. #include <linux/fb.h>
  19. #include <linux/vmalloc.h>
  20. #include <video/vga.h>
  21. struct regstate {
  22. __u8 *vga_font0;
  23. __u8 *vga_font1;
  24. __u8 *vga_text;
  25. __u8 *vga_cmap;
  26. __u8 *attr;
  27. __u8 *crtc;
  28. __u8 *gfx;
  29. __u8 *seq;
  30. __u8 misc;
  31. };
  32. static inline unsigned char vga_rcrtcs(void __iomem *regbase, unsigned short iobase,
  33. unsigned char reg)
  34. {
  35. vga_w(regbase, iobase + 0x4, reg);
  36. return vga_r(regbase, iobase + 0x5);
  37. }
  38. static inline void vga_wcrtcs(void __iomem *regbase, unsigned short iobase,
  39. unsigned char reg, unsigned char val)
  40. {
  41. vga_w(regbase, iobase + 0x4, reg);
  42. vga_w(regbase, iobase + 0x5, val);
  43. }
  44. static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
  45. {
  46. struct regstate *saved = (struct regstate *) state->vidstate;
  47. int i;
  48. u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
  49. unsigned short iobase;
  50. /* if in graphics mode, no need to save */
  51. misc = vga_r(state->vgabase, VGA_MIS_R);
  52. iobase = (misc & 1) ? 0x3d0 : 0x3b0;
  53. vga_r(state->vgabase, iobase + 0xa);
  54. vga_w(state->vgabase, VGA_ATT_W, 0x00);
  55. attr10 = vga_rattr(state->vgabase, 0x10);
  56. vga_r(state->vgabase, iobase + 0xa);
  57. vga_w(state->vgabase, VGA_ATT_W, 0x20);
  58. if (attr10 & 1)
  59. return;
  60. /* save regs */
  61. gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
  62. gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
  63. gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
  64. seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
  65. seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
  66. /* blank screen */
  67. seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
  68. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
  69. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
  70. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
  71. /* save font at plane 2 */
  72. if (state->flags & VGA_SAVE_FONT0) {
  73. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
  74. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  75. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
  76. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  77. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  78. for (i = 0; i < 4 * 8192; i++)
  79. saved->vga_font0[i] = vga_r(fbbase, i);
  80. }
  81. /* save font at plane 3 */
  82. if (state->flags & VGA_SAVE_FONT1) {
  83. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
  84. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  85. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
  86. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  87. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  88. for (i = 0; i < state->memsize; i++)
  89. saved->vga_font1[i] = vga_r(fbbase, i);
  90. }
  91. /* save font at plane 0/1 */
  92. if (state->flags & VGA_SAVE_TEXT) {
  93. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
  94. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  95. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
  96. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  97. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  98. for (i = 0; i < 8192; i++)
  99. saved->vga_text[i] = vga_r(fbbase, i);
  100. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
  101. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  102. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
  103. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  104. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  105. for (i = 0; i < 8192; i++)
  106. saved->vga_text[8192+i] = vga_r(fbbase + 2 * 8192, i);
  107. }
  108. /* restore regs */
  109. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
  110. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
  111. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
  112. vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
  113. vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
  114. /* unblank screen */
  115. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
  116. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
  117. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
  118. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
  119. }
  120. static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
  121. {
  122. struct regstate *saved = (struct regstate *) state->vidstate;
  123. int i;
  124. u8 gr1, gr3, gr4, gr5, gr6, gr8;
  125. u8 seq1, seq2, seq4;
  126. /* save regs */
  127. gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE);
  128. gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE);
  129. gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
  130. gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
  131. gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
  132. gr8 = vga_rgfx(state->vgabase, VGA_GFX_BIT_MASK);
  133. seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
  134. seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
  135. /* blank screen */
  136. seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
  137. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
  138. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
  139. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
  140. if (state->depth == 4) {
  141. vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, 0x0);
  142. vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff);
  143. vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00);
  144. }
  145. /* restore font at plane 2 */
  146. if (state->flags & VGA_SAVE_FONT0) {
  147. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
  148. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  149. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
  150. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  151. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  152. for (i = 0; i < 4 * 8192; i++)
  153. vga_w(fbbase, i, saved->vga_font0[i]);
  154. }
  155. /* restore font at plane 3 */
  156. if (state->flags & VGA_SAVE_FONT1) {
  157. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
  158. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  159. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
  160. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  161. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  162. for (i = 0; i < state->memsize; i++)
  163. vga_w(fbbase, i, saved->vga_font1[i]);
  164. }
  165. /* restore font at plane 0/1 */
  166. if (state->flags & VGA_SAVE_TEXT) {
  167. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
  168. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  169. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
  170. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  171. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  172. for (i = 0; i < 8192; i++)
  173. vga_w(fbbase, i, saved->vga_text[i]);
  174. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
  175. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
  176. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
  177. vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
  178. vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
  179. for (i = 0; i < 8192; i++)
  180. vga_w(fbbase, i, saved->vga_text[8192+i]);
  181. }
  182. /* unblank screen */
  183. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
  184. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
  185. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
  186. /* restore regs */
  187. vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1);
  188. vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3);
  189. vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
  190. vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
  191. vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
  192. vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, gr8);
  193. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
  194. vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
  195. vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
  196. }
  197. static void save_vga_mode(struct vgastate *state)
  198. {
  199. struct regstate *saved = (struct regstate *) state->vidstate;
  200. unsigned short iobase;
  201. int i;
  202. saved->misc = vga_r(state->vgabase, VGA_MIS_R);
  203. if (saved->misc & 1)
  204. iobase = 0x3d0;
  205. else
  206. iobase = 0x3b0;
  207. for (i = 0; i < state->num_crtc; i++)
  208. saved->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
  209. vga_r(state->vgabase, iobase + 0xa);
  210. vga_w(state->vgabase, VGA_ATT_W, 0x00);
  211. for (i = 0; i < state->num_attr; i++) {
  212. vga_r(state->vgabase, iobase + 0xa);
  213. saved->attr[i] = vga_rattr(state->vgabase, i);
  214. }
  215. vga_r(state->vgabase, iobase + 0xa);
  216. vga_w(state->vgabase, VGA_ATT_W, 0x20);
  217. for (i = 0; i < state->num_gfx; i++)
  218. saved->gfx[i] = vga_rgfx(state->vgabase, i);
  219. for (i = 0; i < state->num_seq; i++)
  220. saved->seq[i] = vga_rseq(state->vgabase, i);
  221. }
  222. static void restore_vga_mode(struct vgastate *state)
  223. {
  224. struct regstate *saved = (struct regstate *) state->vidstate;
  225. unsigned short iobase;
  226. int i;
  227. vga_w(state->vgabase, VGA_MIS_W, saved->misc);
  228. if (saved->misc & 1)
  229. iobase = 0x3d0;
  230. else
  231. iobase = 0x3b0;
  232. /* turn off display */
  233. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
  234. saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
  235. /* disable sequencer */
  236. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
  237. /* enable palette addressing */
  238. vga_r(state->vgabase, iobase + 0xa);
  239. vga_w(state->vgabase, VGA_ATT_W, 0x00);
  240. for (i = 2; i < state->num_seq; i++)
  241. vga_wseq(state->vgabase, i, saved->seq[i]);
  242. /* unprotect vga regs */
  243. vga_wcrtcs(state->vgabase, iobase, 17, saved->crtc[17] & ~0x80);
  244. for (i = 0; i < state->num_crtc; i++)
  245. vga_wcrtcs(state->vgabase, iobase, i, saved->crtc[i]);
  246. for (i = 0; i < state->num_gfx; i++)
  247. vga_wgfx(state->vgabase, i, saved->gfx[i]);
  248. for (i = 0; i < state->num_attr; i++) {
  249. vga_r(state->vgabase, iobase + 0xa);
  250. vga_wattr(state->vgabase, i, saved->attr[i]);
  251. }
  252. /* reenable sequencer */
  253. vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
  254. /* turn display on */
  255. vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
  256. saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5));
  257. /* disable video/palette source */
  258. vga_r(state->vgabase, iobase + 0xa);
  259. vga_w(state->vgabase, VGA_ATT_W, 0x20);
  260. }
  261. static void save_vga_cmap(struct vgastate *state)
  262. {
  263. struct regstate *saved = (struct regstate *) state->vidstate;
  264. int i;
  265. vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
  266. /* assumes DAC is readable and writable */
  267. vga_w(state->vgabase, VGA_PEL_IR, 0x00);
  268. for (i = 0; i < 768; i++)
  269. saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
  270. }
  271. static void restore_vga_cmap(struct vgastate *state)
  272. {
  273. struct regstate *saved = (struct regstate *) state->vidstate;
  274. int i;
  275. vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
  276. /* assumes DAC is readable and writable */
  277. vga_w(state->vgabase, VGA_PEL_IW, 0x00);
  278. for (i = 0; i < 768; i++)
  279. vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]);
  280. }
  281. static void vga_cleanup(struct vgastate *state)
  282. {
  283. if (state->vidstate != NULL) {
  284. struct regstate *saved = (struct regstate *) state->vidstate;
  285. vfree(saved->vga_font0);
  286. vfree(saved->vga_font1);
  287. vfree(saved->vga_text);
  288. vfree(saved->vga_cmap);
  289. vfree(saved->attr);
  290. kfree(saved);
  291. state->vidstate = NULL;
  292. }
  293. }
  294. int save_vga(struct vgastate *state)
  295. {
  296. struct regstate *saved;
  297. saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
  298. if (saved == NULL)
  299. return 1;
  300. state->vidstate = (void *)saved;
  301. if (state->flags & VGA_SAVE_CMAP) {
  302. saved->vga_cmap = vmalloc(768);
  303. if (!saved->vga_cmap) {
  304. vga_cleanup(state);
  305. return 1;
  306. }
  307. save_vga_cmap(state);
  308. }
  309. if (state->flags & VGA_SAVE_MODE) {
  310. int total;
  311. if (state->num_attr < 21)
  312. state->num_attr = 21;
  313. if (state->num_crtc < 25)
  314. state->num_crtc = 25;
  315. if (state->num_gfx < 9)
  316. state->num_gfx = 9;
  317. if (state->num_seq < 5)
  318. state->num_seq = 5;
  319. total = state->num_attr + state->num_crtc +
  320. state->num_gfx + state->num_seq;
  321. saved->attr = vmalloc(total);
  322. if (!saved->attr) {
  323. vga_cleanup(state);
  324. return 1;
  325. }
  326. saved->crtc = saved->attr + state->num_attr;
  327. saved->gfx = saved->crtc + state->num_crtc;
  328. saved->seq = saved->gfx + state->num_gfx;
  329. save_vga_mode(state);
  330. }
  331. if (state->flags & VGA_SAVE_FONTS) {
  332. void __iomem *fbbase;
  333. /* exit if window is less than 32K */
  334. if (state->memsize && state->memsize < 4 * 8192) {
  335. vga_cleanup(state);
  336. return 1;
  337. }
  338. if (!state->memsize)
  339. state->memsize = 8 * 8192;
  340. if (!state->membase)
  341. state->membase = 0xA0000;
  342. fbbase = ioremap(state->membase, state->memsize);
  343. if (!fbbase) {
  344. vga_cleanup(state);
  345. return 1;
  346. }
  347. /*
  348. * save only first 32K used by vgacon
  349. */
  350. if (state->flags & VGA_SAVE_FONT0) {
  351. saved->vga_font0 = vmalloc(4 * 8192);
  352. if (!saved->vga_font0) {
  353. iounmap(fbbase);
  354. vga_cleanup(state);
  355. return 1;
  356. }
  357. }
  358. /*
  359. * largely unused, but if required by the caller
  360. * we'll just save everything.
  361. */
  362. if (state->flags & VGA_SAVE_FONT1) {
  363. saved->vga_font1 = vmalloc(state->memsize);
  364. if (!saved->vga_font1) {
  365. iounmap(fbbase);
  366. vga_cleanup(state);
  367. return 1;
  368. }
  369. }
  370. /*
  371. * Save 8K at plane0[0], and 8K at plane1[16K]
  372. */
  373. if (state->flags & VGA_SAVE_TEXT) {
  374. saved->vga_text = vmalloc(8192 * 2);
  375. if (!saved->vga_text) {
  376. iounmap(fbbase);
  377. vga_cleanup(state);
  378. return 1;
  379. }
  380. }
  381. save_vga_text(state, fbbase);
  382. iounmap(fbbase);
  383. }
  384. return 0;
  385. }
  386. int restore_vga(struct vgastate *state)
  387. {
  388. if (state->vidstate == NULL)
  389. return 1;
  390. if (state->flags & VGA_SAVE_MODE)
  391. restore_vga_mode(state);
  392. if (state->flags & VGA_SAVE_FONTS) {
  393. void __iomem *fbbase = ioremap(state->membase, state->memsize);
  394. if (!fbbase) {
  395. vga_cleanup(state);
  396. return 1;
  397. }
  398. restore_vga_text(state, fbbase);
  399. iounmap(fbbase);
  400. }
  401. if (state->flags & VGA_SAVE_CMAP)
  402. restore_vga_cmap(state);
  403. vga_cleanup(state);
  404. return 0;
  405. }
  406. EXPORT_SYMBOL(save_vga);
  407. EXPORT_SYMBOL(restore_vga);
  408. MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
  409. MODULE_DESCRIPTION("VGA State Save/Restore");
  410. MODULE_LICENSE("GPL");