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