fbcon-vga-planes.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/fbcon-vga-planes.c -- Low level frame buffer operations
  3.  *   for VGA 4-plane modes
  4.  *
  5.  * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
  6.  * Based on code by Michael Schmitz
  7.  * Based on the old macfb.c 4bpp code by Alan Cox
  8.  *
  9.  * This file is subject to the terms and conditions of the GNU General
  10.  * Public License.  See the file COPYING in the main directory of this
  11.  * archive for more details.  */
  12. #include <linux/module.h>
  13. #include <linux/tty.h>
  14. #include <linux/console.h>
  15. #include <linux/string.h>
  16. #include <linux/fb.h>
  17. #include <linux/vt_buffer.h>
  18. #include <asm/io.h>
  19. #include <video/fbcon.h>
  20. #include <video/fbcon-vga-planes.h>
  21. #define GRAPHICS_ADDR_REG 0x3ce /* Graphics address register. */
  22. #define GRAPHICS_DATA_REG 0x3cf /* Graphics data register. */
  23. #define SET_RESET_INDEX 0 /* Set/Reset Register index. */
  24. #define ENABLE_SET_RESET_INDEX 1 /* Enable Set/Reset Register index. */
  25. #define DATA_ROTATE_INDEX 3 /* Data Rotate Register index. */
  26. #define GRAPHICS_MODE_INDEX 5 /* Graphics Mode Register index. */
  27. #define BIT_MASK_INDEX 8 /* Bit Mask Register index. */
  28. /* The VGA's weird architecture often requires that we read a byte and
  29.    write a byte to the same location.  It doesn't matter *what* byte
  30.    we write, however.  This is because all the action goes on behind
  31.    the scenes in the VGA's 32-bit latch register, and reading and writing
  32.    video memory just invokes latch behavior.
  33.    To avoid race conditions (is this necessary?), reading and writing
  34.    the memory byte should be done with a single instruction.  One
  35.    suitable instruction is the x86 bitwise OR.  The following
  36.    read-modify-write routine should optimize to one such bitwise
  37.    OR. */
  38. static inline void rmw(volatile char *p)
  39. {
  40. readb(p);
  41. writeb(1, p);
  42. }
  43. /* Set the Graphics Mode Register.  Bits 0-1 are write mode, bit 3 is
  44.    read mode. */
  45. static inline void setmode(int mode)
  46. {
  47. outb(GRAPHICS_MODE_INDEX, GRAPHICS_ADDR_REG);
  48. outb(mode, GRAPHICS_DATA_REG);
  49. }
  50. /* Select the Bit Mask Register. */
  51. static inline void selectmask(void)
  52. {
  53. outb(BIT_MASK_INDEX, GRAPHICS_ADDR_REG);
  54. }
  55. /* Set the value of the Bit Mask Register.  It must already have been
  56.    selected with selectmask(). */
  57. static inline void setmask(int mask)
  58. {
  59. outb(mask, GRAPHICS_DATA_REG);
  60. }
  61. /* Set the Data Rotate Register.  Bits 0-2 are rotate count, bits 3-4
  62.    are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */
  63. static inline void setop(int op)
  64. {
  65. outb(DATA_ROTATE_INDEX, GRAPHICS_ADDR_REG);
  66. outb(op, GRAPHICS_DATA_REG);
  67. }
  68. /* Set the Enable Set/Reset Register.  The code here always uses value
  69.    0xf for this register.  */
  70. static inline void setsr(int sr)
  71. {
  72. outb(ENABLE_SET_RESET_INDEX, GRAPHICS_ADDR_REG);
  73. outb(sr, GRAPHICS_DATA_REG);
  74. }
  75. /* Set the Set/Reset Register. */
  76. static inline void setcolor(int color)
  77. {
  78. outb(SET_RESET_INDEX, GRAPHICS_ADDR_REG);
  79. outb(color, GRAPHICS_DATA_REG);
  80. }
  81. /* Set the value in the Graphics Address Register. */
  82. static inline void setindex(int index)
  83. {
  84. outb(index, GRAPHICS_ADDR_REG);
  85. }
  86. void fbcon_vga_planes_setup(struct display *p)
  87. {
  88. }
  89. void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx,
  90.    int height, int width)
  91. {
  92. char *src;
  93. char *dest;
  94. int line_ofs;
  95. int x;
  96. setmode(1);
  97. setop(0);
  98. setsr(0xf);
  99. sy *= fontheight(p);
  100. dy *= fontheight(p);
  101. height *= fontheight(p);
  102. if (dy < sy || (dy == sy && dx < sx)) {
  103. line_ofs = p->line_length - width;
  104. dest = p->screen_base + dx + dy * p->line_length;
  105. src = p->screen_base + sx + sy * p->line_length;
  106. while (height--) {
  107. for (x = 0; x < width; x++) {
  108. readb(src);
  109. writeb(0, dest);
  110. dest++;
  111. src++;
  112. }
  113. src += line_ofs;
  114. dest += line_ofs;
  115. }
  116. } else {
  117. line_ofs = p->line_length - width;
  118. dest = p->screen_base + dx + width + (dy + height - 1) * p->line_length;
  119. src = p->screen_base + sx + width + (sy + height - 1) * p->line_length;
  120. while (height--) {
  121. for (x = 0; x < width; x++) {
  122. dest--;
  123. src--;
  124. readb(src);
  125. writeb(0, dest);
  126. }
  127. src -= line_ofs;
  128. dest -= line_ofs;
  129. }
  130. }
  131. }
  132. void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, int sx,
  133.    int height, int width)
  134. {
  135. int line_ofs = p->line_length - width;
  136. char *where;
  137. int x;
  138. setmode(0);
  139. setop(0);
  140. setsr(0xf);
  141. setcolor(attr_bgcol_ec(p, conp));
  142. selectmask();
  143. setmask(0xff);
  144. sy *= fontheight(p);
  145. height *= fontheight(p);
  146. where = p->screen_base + sx + sy * p->line_length;
  147. while (height--) {
  148. for (x = 0; x < width; x++) {
  149. writeb(0, where);
  150. where++;
  151. }
  152. where += line_ofs;
  153. }
  154. }
  155. void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
  156. {
  157. int fg = attr_fgcol(p,c);
  158. int bg = attr_bgcol(p,c);
  159. int y;
  160. u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
  161. char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
  162. setmode(0);
  163. setop(0);
  164. setsr(0xf);
  165. setcolor(bg);
  166. selectmask();
  167. setmask(0xff);
  168. for (y = 0; y < fontheight(p); y++, where += p->line_length) 
  169. rmw(where);
  170. where -= p->line_length * y;
  171. setcolor(fg);
  172. selectmask();
  173. for (y = 0; y < fontheight(p); y++, where += p->line_length) 
  174. if (cdat[y]) {
  175. setmask(cdat[y]);
  176. rmw(where);
  177. }
  178. }
  179. void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
  180. {
  181. int fg = attr_fgcol(p,c);
  182. int bg = attr_bgcol(p,c);
  183. int y;
  184. u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
  185. char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
  186. setmode(2);
  187. setop(0);
  188. setsr(0xf);
  189. setcolor(fg);
  190. selectmask();
  191. setmask(0xff);
  192. writeb(bg, where);
  193. rmb();
  194. readb(where); /* fill latches */
  195. setmode(3);
  196. wmb();
  197. for (y = 0; y < fontheight(p); y++, where += p->line_length) 
  198. writeb(cdat[y], where);
  199. wmb();
  200. }
  201. /* 28.50 in my test */
  202. void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
  203.    int count, int yy, int xx)
  204. {
  205. u16 c = scr_readw(s);
  206. int fg = attr_fgcol(p, c);
  207. int bg = attr_bgcol(p, c);
  208. char *where;
  209. int n;
  210. setmode(2);
  211. setop(0);
  212. selectmask();
  213. setmask(0xff);
  214. where = p->screen_base + xx + yy * p->line_length * fontheight(p);
  215. writeb(bg, where);
  216. rmb();
  217. readb(where); /* fill latches */
  218. wmb();
  219. selectmask();
  220. for (n = 0; n < count; n++) {
  221. int c = scr_readw(s++) & p->charmask;
  222. u8 *cdat = p->fontdata + c * fontheight(p);
  223. u8 *end = cdat + fontheight(p);
  224. while (cdat < end) {
  225. outb(*cdat++, GRAPHICS_DATA_REG);
  226. wmb();
  227. writeb(fg, where);
  228. where += p->line_length;
  229. }
  230. where += 1 - p->line_length * fontheight(p);
  231. }
  232. wmb();
  233. }
  234. /* 6.96 in my test */
  235. void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
  236.    int count, int yy, int xx)
  237. {
  238. u16 c = scr_readw(s);
  239. int fg = attr_fgcol(p, c);
  240. int bg = attr_bgcol(p, c);
  241. char *where;
  242. int n;
  243. setmode(2);
  244. setop(0);
  245. setsr(0xf);
  246. setcolor(fg);
  247. selectmask();
  248. setmask(0xff);
  249. where = p->screen_base + xx + yy * p->line_length * fontheight(p);
  250. writeb(bg, where);
  251. rmb();
  252. readb(where); /* fill latches */
  253. setmode(3);
  254. wmb();
  255. for (n = 0; n < count; n++) {
  256. int y;
  257. int c = scr_readw(s++) & p->charmask;
  258. u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
  259. for (y = 0; y < fontheight(p); y++, cdat++) {
  260. writeb (*cdat, where);
  261. where += p->line_length;
  262. }
  263. where += 1 - p->line_length * fontheight(p);
  264. }
  265. wmb();
  266. }
  267. void fbcon_vga_planes_revc(struct display *p, int xx, int yy)
  268. {
  269. char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
  270. int y;
  271. setmode(0);
  272. setop(0x18);
  273. setsr(0xf);
  274. setcolor(0xf);
  275. selectmask();
  276. setmask(0xff);
  277. for (y = 0; y < fontheight(p); y++) {
  278. rmw(where);
  279. where += p->line_length;
  280. }
  281. }
  282. struct display_switch fbcon_vga_planes = {
  283.     setup: fbcon_vga_planes_setup,
  284.     bmove: fbcon_vga_planes_bmove,
  285.     clear: fbcon_vga_planes_clear,
  286.     putc: fbcon_vga_planes_putc,
  287.     putcs: fbcon_vga_planes_putcs,
  288.     revc: fbcon_vga_planes_revc,
  289.     fontwidthmask: FONTWIDTH(8)
  290. };
  291. struct display_switch fbcon_ega_planes = {
  292.     setup: fbcon_vga_planes_setup,
  293.     bmove: fbcon_vga_planes_bmove,
  294.     clear: fbcon_vga_planes_clear,
  295.     putc: fbcon_ega_planes_putc,
  296.     putcs: fbcon_ega_planes_putcs,
  297.     revc: fbcon_vga_planes_revc,
  298.     fontwidthmask: FONTWIDTH(8)
  299. };
  300. #ifdef MODULE
  301. MODULE_LICENSE("GPL");
  302. int init_module(void)
  303. {
  304.     return 0;
  305. }
  306. void cleanup_module(void)
  307. {}
  308. #endif /* MODULE */
  309.     /*
  310.      *  Visible symbols for modules
  311.      */
  312. EXPORT_SYMBOL(fbcon_vga_planes);
  313. EXPORT_SYMBOL(fbcon_vga_planes_setup);
  314. EXPORT_SYMBOL(fbcon_vga_planes_bmove);
  315. EXPORT_SYMBOL(fbcon_vga_planes_clear);
  316. EXPORT_SYMBOL(fbcon_vga_planes_putc);
  317. EXPORT_SYMBOL(fbcon_vga_planes_putcs);
  318. EXPORT_SYMBOL(fbcon_vga_planes_revc);
  319. EXPORT_SYMBOL(fbcon_ega_planes);
  320. EXPORT_SYMBOL(fbcon_ega_planes_putc);
  321. EXPORT_SYMBOL(fbcon_ega_planes_putcs);
  322. /*
  323.  * Overrides for Emacs so that we follow Linus's tabbing style.
  324.  * ---------------------------------------------------------------------------
  325.  * Local variables:
  326.  * c-basic-offset: 8
  327.  * End:
  328.  */