more changes on original files
[linux-2.4.git] / drivers / video / fbcon-vga.c
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 MODULE_LICENSE("GPL");
192
193 int init_module(void)
194 {
195     return 0;
196 }
197
198 void cleanup_module(void)
199 {}
200 #endif /* MODULE */
201
202
203     /*
204      *  Visible symbols for modules
205      */
206
207 EXPORT_SYMBOL(fbcon_vga);
208 EXPORT_SYMBOL(fbcon_vga_setup);
209 EXPORT_SYMBOL(fbcon_vga_bmove);
210 EXPORT_SYMBOL(fbcon_vga_clear);
211 EXPORT_SYMBOL(fbcon_vga_putc);
212 EXPORT_SYMBOL(fbcon_vga_putcs);
213 EXPORT_SYMBOL(fbcon_vga_revc);