clean
[linux-2.4.21-pre4.git] / drivers / video / fbcon-hga.c
1 /*
2  *  linux/drivers/video/fbcon-hga.c -- Low level frame buffer operations for
3  *                                     the Hercules graphics adaptor
4  *
5  *      Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
6  *      Based on fbcon-mfb.c by Geert Uytterhoeven
7  *
8  * History:
9  *
10  * - Revision 0.1.0 (6 Dec 1999): comment changes
11  * - First release (25 Nov 1999)
12  * 
13  *  This file is subject to the terms and conditions of the GNU General Public
14  *  License.  See the file COPYING in the main directory of this archive for
15  *  more details.
16  */
17
18 #include <linux/module.h>
19 #include <linux/tty.h>
20 #include <linux/console.h>
21 #include <linux/string.h>
22 #include <linux/fb.h>
23
24 #include <video/fbcon.h>
25 #include <video/fbcon-hga.h>
26
27 #if 0
28 #define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args)
29 #else
30 #define DPRINTK(args...)
31 #endif
32
33 #define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90)
34
35     /*
36      *  Hercules monochrome
37      */
38
39 static inline u8* rowaddr(struct display *p, u_int row)
40 {
41         return p->screen_base + HGA_ROWADDR(row);
42 }
43         
44 void fbcon_hga_setup(struct display *p)
45 {
46         DPRINTK("fbcon_hga_setup: ll:%d\n", (int)p->line_length);
47
48         p->next_line = p->line_length;
49         p->next_plane = 0;
50 }
51
52 void fbcon_hga_bmove(struct display *p, int sy, int sx, int dy, int dx,
53                      int height, int width)
54 {
55         u8 *src, *dest;
56         u_int rows, y1, y2;
57         
58 #if 0
59         if (sx == 0 && dx == 0 && width == p->next_line) {
60                 src = p->screen_base+sy*fontheight(p)*width;
61                 dest = p->screen_base+dy*fontheight(p)*width;
62                 fb_memmove(dest, src, height*fontheight(p)*width);
63         } else 
64 #endif
65         if (dy <= sy) {
66                 y1 = sy*fontheight(p);
67                 y2 = dy*fontheight(p);
68                 for (rows = height*fontheight(p); rows--; ) {
69                         src = rowaddr(p, y1)+sx;
70                         dest = rowaddr(p, y2)+dx;
71                         fb_memmove(dest, src, width);
72                         y1++;
73                         y2++;
74                 }
75         } else {
76                 y1 = (sy+height)*fontheight(p)-1;
77                 y2 = (dy+height)*fontheight(p)-1;
78                 for (rows = height*fontheight(p); rows--;) {
79                         src = rowaddr(p, y1)+sx;
80                         dest = rowaddr(p, y2)+dx;
81                         fb_memmove(dest, src, width);
82                         y1--;
83                         y2--;
84                 }
85         }
86 }
87
88 void fbcon_hga_clear(struct vc_data *conp, struct display *p, int sy, int sx,
89                      int height, int width)
90 {
91         u8 *dest;
92         u_int rows, y;
93         int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
94
95         DPRINTK("fbcon_hga_clear: sx:%d, sy:%d, height:%d, width:%d\n", sx, sy, height, width);
96         
97         y = sy*fontheight(p);
98 #if 0
99         if (sx == 0 && width == p->next_line) {
100                 if (inverse) {
101                         fb_memset255(dest, height*fontheight(p)*width);
102                 } else {
103                         fb_memclear(dest, height*fontheight(p)*width);
104                 }
105         } else
106 #endif      
107         for (rows = height*fontheight(p); rows--; y++) {
108                 dest = rowaddr(p, y)+sx;
109                 if (inverse) {
110                         fb_memset255(dest, width);
111                 } else {
112                         fb_memclear(dest, width);
113                 }
114         }
115 }
116
117 void fbcon_hga_putc(struct vc_data *conp, struct display *p, int c, int yy,
118                     int xx)
119 {
120         u8 *dest, *cdat;
121         u_int rows, y, bold, revs, underl;
122         u8 d;
123
124         cdat = p->fontdata+(c&p->charmask)*fontheight(p);
125         bold = attr_bold(p, c);
126         revs = attr_reverse(p, c);
127         underl = attr_underline(p, c);
128         y = yy*fontheight(p);
129
130         for (rows = fontheight(p); rows--; y++) {
131                 d = *cdat++;
132                 if (underl && !rows)
133                         d = 0xff;
134                 else if (bold)
135                         d |= d>>1;
136                 if (revs)
137                         d = ~d;
138                 dest = rowaddr(p, y)+xx;
139                 *dest = d;
140         }
141 }
142
143 void fbcon_hga_putcs(struct vc_data *conp, struct display *p, 
144                      const unsigned short *s, int count, int yy, int xx)
145 {
146         u8 *dest, *cdat;
147         u_int rows, y, y0, bold, revs, underl;
148         u8 d;
149         u16 c;
150         
151         c = scr_readw(s);
152         bold = attr_bold(p, c);
153         revs = attr_reverse(p, c);
154         underl = attr_underline(p, c);
155         y0 = yy*fontheight(p);
156
157         while (count--) {
158                 c = scr_readw(s++) & p->charmask;
159                 cdat = p->fontdata+c*fontheight(p);
160                 y = y0;
161                 for (rows = fontheight(p); rows--; y++) {
162                         d = *cdat++;
163                         if (underl && !rows)
164                                 d = 0xff;
165                         else if (bold)
166                                 d |= d>>1;
167                         if (revs)
168                                 d = ~d;
169                         dest = rowaddr(p, y)+xx;
170                         *dest = d;
171                 }
172                 xx++;
173         }
174 }
175
176 void fbcon_hga_revc(struct display *p, int xx, int yy)
177 {
178         u8 *dest;
179         u_int rows, y;
180
181         y = yy*fontheight(p);
182         for (rows = fontheight(p); rows--; y++) {
183                 dest = rowaddr(p, y)+xx;
184                 *dest = ~*dest;
185         }
186 }
187
188 void fbcon_hga_clear_margins(struct vc_data *conp, struct display *p,
189                              int bottom_only)
190 {
191         u8 *dest;
192         u_int height, y;
193         int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
194
195         DPRINTK("fbcon_hga_clear_margins: enter\n");
196
197         /* No need to handle right margin. */
198
199         y = conp->vc_rows * fontheight(p);
200         for (height = p->var.yres - y; height-- > 0; y++) {
201                 DPRINTK("fbcon_hga_clear_margins: y:%d, height:%d\n", y, height);
202                 dest = rowaddr(p, y);
203                 if (inverse) {
204                         fb_memset255(dest, p->next_line);
205                 } else {
206                         fb_memclear(dest, p->next_line);
207                 }
208         }
209 }
210
211
212         /*
213          *  `switch' for the low level operations
214          */
215
216 struct display_switch fbcon_hga = {
217         setup:          fbcon_hga_setup,
218         bmove:          fbcon_hga_bmove,
219         clear:          fbcon_hga_clear,
220         putc:           fbcon_hga_putc,
221         putcs:          fbcon_hga_putcs,
222         revc:           fbcon_hga_revc,
223         clear_margins:  fbcon_hga_clear_margins,
224         fontwidthmask:  FONTWIDTH(8)
225 };
226
227
228 #ifdef MODULE
229 MODULE_LICENSE("GPL");
230
231 int init_module(void)
232 {
233         return 0;
234 }
235
236 void cleanup_module(void)
237 {
238 }
239 #endif /* MODULE */
240
241
242         /*
243          *  Visible symbols for modules
244          */
245
246 EXPORT_SYMBOL(fbcon_hga);
247 EXPORT_SYMBOL(fbcon_hga_setup);
248 EXPORT_SYMBOL(fbcon_hga_bmove);
249 EXPORT_SYMBOL(fbcon_hga_clear);
250 EXPORT_SYMBOL(fbcon_hga_putc);
251 EXPORT_SYMBOL(fbcon_hga_putcs);
252 EXPORT_SYMBOL(fbcon_hga_revc);
253 EXPORT_SYMBOL(fbcon_hga_clear_margins);