1 /*
2 * linux/drivers/video/fbcon-vga.c -- Low level frame buffer operations for
3 * VGA characters/attributes
4 *
5 * Created 28 Mar 1998 by Geert Uytterhoeven
6 * Monochrome attributes added May 1998 by Andrew Apted
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive for
10 * more details.
11 */
12
13 #include <linux/module.h>
14 #include <linux/tty.h>
15 #include <linux/console.h>
16 #include <linux/string.h>
17 #include <linux/fb.h>
18
19 #include <asm/io.h>
20
21 #include <video/fbcon.h>
22 #include <video/fbcon-vga.h>
23
24
25 /*
26 * VGA screen access
27 */
28
29 static inline void vga_writew(u16 val, u16 *addr)
30 {
31 #ifdef __powerpc__
32 st_le16(addr, val);
33 #else
34 writew(val, (unsigned long)addr);
35 #endif /* !__powerpc__ */
36 }
37
38 static inline u16 vga_readw(u16 *addr)
39 {
40 #ifdef __powerpc__
41 return ld_le16(addr);
42 #else
43 return readw((unsigned long)addr);
44 #endif /* !__powerpc__ */
45 }
46
47 static inline void vga_memsetw(void *s, u16 c, unsigned int count)
48 {
49 u16 *addr = (u16 *)s;
50
51 while (count) {
52 count--;
53 vga_writew(c, addr++);
54 }
55 }
56
57 static inline void vga_memmovew(u16 *to, u16 *from, unsigned int count)
58 {
59 if (to < from) {
60 while (count) {
61 count--;
62 vga_writew(vga_readw(from++), to++);
63 }
64 } else {
65 from += count;
66 to += count;
67 while (count) {
68 count--;
69 vga_writew(vga_readw(--from), --to);
70 }
71 }
72 }
73
74
75 /*
76 * VGA characters/attributes
77 */
78
79 static inline u16 fbcon_vga_attr(struct display *p,
80 unsigned short s)
81 {
82 /* Underline and reverse-video are mutually exclusive on MDA.
83 * Since reverse-video is used for cursors and selected areas,
84 * it takes precedence.
85 */
86
87 return (attr_reverse(p, s) ? 0x7000 :
88 (attr_underline(p, s) ? 0x0100 : 0x0700)) |
89 (attr_bold(p, s) ? 0x0800 : 0) |
90 (attr_blink(p, s) ? 0x8000 : 0);
91 }
92
93 void fbcon_vga_setup(struct display *p)
94 {
95 p->next_line = p->line_length;
96 p->next_plane = 0;
97 }
98
99 void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx,
100 int height, int width)
101 {
102 u16 *src, *dst;
103 int rows;
104
105 if (sx == 0 && dx == 0 && width == p->next_line/2) {
106 src = (u16 *)(p->screen_base+sy*p->next_line);
107 dst = (u16 *)(p->screen_base+dy*p->next_line);
108 vga_memmovew(dst, src, height*width);
109 } else if (dy < sy || (dy == sy && dx < sx)) {
110 src = (u16 *)(p->screen_base+sy*p->next_line+sx*2);
111 dst = (u16 *)(p->screen_base+dy*p->next_line+dx*2);
112 for (rows = height; rows-- ;) {
113 vga_memmovew(dst, src, width);
114 src += p->next_line/2;
115 dst += p->next_line/2;
116 }
117 } else {
118 src = (u16 *)(p->screen_base+(sy+height-1)*p->next_line+sx*2);
119 dst = (u16 *)(p->screen_base+(dy+height-1)*p->next_line+dx*2);
120 for (rows = height; rows-- ;) {
121 vga_memmovew(dst, src, width);
122 src -= p->next_line/2;
123 dst -= p->next_line/2;
124 }
125 }
126 }
127
128 void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy, int sx,
129 int height, int width)
130 {
131 u16 *dest = (u16 *)(p->screen_base+sy*p->next_line+sx*2);
132 int rows;
133
134 if (sx == 0 && width*2 == p->next_line)
135 vga_memsetw(dest, conp->vc_video_erase_char, height*width);
136 else
137 for (rows = height; rows-- ; dest += p->next_line/2)
138 vga_memsetw(dest, conp->vc_video_erase_char, width);
139 }
140
141 void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c, int y,
142 int x)
143 {
144 u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2);
145 if (conp->vc_can_do_color)
146 vga_writew(c, dst);
147 else
148 vga_writew(fbcon_vga_attr(p, c) | (c & 0xff), dst);
149 }
150
151 void fbcon_vga_putcs(struct vc_data *conp, struct display *p,
152 const unsigned short *s, int count, int y, int x)
153 {
154 u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2);
155 u16 sattr;
156 if (conp->vc_can_do_color)
157 while (count--)
158 vga_writew(scr_readw(s++), dst++);
159 else {
160 sattr = fbcon_vga_attr(p, scr_readw(s));
161 while (count--)
162 vga_writew(sattr | ((int) (scr_readw(s++)) & 0xff), dst++);
163 }
164 }
165
166 void fbcon_vga_revc(struct display *p, int x, int y)
167 {
168 u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2);
169 u16 val = vga_readw(dst);
170 val = (val & 0x88ff) | ((val<<4) & 0x7000) | ((val>>4) & 0x0700);
171 vga_writew(val, dst);
172 }
173
174
175 /*
176 * `switch' for the low level operations
177 */
178
179 struct display_switch fbcon_vga = {
180 setup: fbcon_vga_setup,
181 bmove: fbcon_vga_bmove,
182 clear: fbcon_vga_clear,
183 putc: fbcon_vga_putc,
184 putcs: fbcon_vga_putcs,
185 revc: fbcon_vga_revc,
186 fontwidthmask: FONTWIDTH(8)
187 };
188
189
190 #ifdef MODULE
191 int init_module(void)
192 {
193 return 0;
194 }
195
196 void cleanup_module(void)
197 {}
198 #endif /* MODULE */
199
200
201 /*
202 * Visible symbols for modules
203 */
204
205 EXPORT_SYMBOL(fbcon_vga);
206 EXPORT_SYMBOL(fbcon_vga_setup);
207 EXPORT_SYMBOL(fbcon_vga_bmove);
208 EXPORT_SYMBOL(fbcon_vga_clear);
209 EXPORT_SYMBOL(fbcon_vga_putc);
210 EXPORT_SYMBOL(fbcon_vga_putcs);
211 EXPORT_SYMBOL(fbcon_vga_revc);
212
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.