~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/fbcon-vga-planes.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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         int fg = attr_fgcol(p,scr_readw(s));
240         int bg = attr_bgcol(p,scr_readw(s));
241 
242         char *where;
243         int n;
244 
245         setmode(2);
246         setop(0);
247         selectmask();
248 
249         setmask(0xff);
250         where = p->screen_base + xx + yy * p->line_length * fontheight(p);
251         writeb(bg, where);
252         rmb();
253         readb(where); /* fill latches */
254         wmb();
255         selectmask();
256         for (n = 0; n < count; n++) {
257                 int c = scr_readw(s++) & p->charmask;
258                 u8 *cdat = p->fontdata + c * fontheight(p);
259                 u8 *end = cdat + fontheight(p);
260 
261                 while (cdat < end) {
262                         outb(*cdat++, GRAPHICS_DATA_REG);       
263                         wmb();
264                         writeb(fg, where);
265                         where += p->line_length;
266                 }
267                 where += 1 - p->line_length * fontheight(p);
268         }
269         
270         wmb();
271 }
272 
273 /* 6.96 in my test */
274 void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
275                    int count, int yy, int xx)
276 {
277         int fg = attr_fgcol(p,*s);
278         int bg = attr_bgcol(p,*s);
279 
280         char *where;
281         int n;
282 
283         setmode(2);
284         setop(0);
285         setsr(0xf);
286         setcolor(fg);
287         selectmask();
288 
289         setmask(0xff);
290         where = p->screen_base + xx + yy * p->line_length * fontheight(p);
291         writeb(bg, where);
292         rmb();
293         readb(where); /* fill latches */
294         setmode(3);     
295         wmb();
296         for (n = 0; n < count; n++) {
297                 int y;
298                 int c = *s++ & p->charmask;
299                 u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
300 
301                 for (y = 0; y < fontheight(p); y++, cdat++) {
302                         writeb (*cdat, where);
303                         where += p->line_length;
304                 }
305                 where += 1 - p->line_length * fontheight(p);
306         }
307         
308         wmb();
309 }
310 
311 void fbcon_vga_planes_revc(struct display *p, int xx, int yy)
312 {
313         char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
314         int y;
315         
316         setmode(0);
317         setop(0x18);
318         setsr(0xf);
319         setcolor(0xf);
320         selectmask();
321 
322         setmask(0xff);
323         for (y = 0; y < fontheight(p); y++) {
324                 rmw(where);
325                 where += p->line_length;
326         }
327 }
328 
329 struct display_switch fbcon_vga_planes = {
330     setup:              fbcon_vga_planes_setup,
331     bmove:              fbcon_vga_planes_bmove,
332     clear:              fbcon_vga_planes_clear,
333     putc:               fbcon_vga_planes_putc,
334     putcs:              fbcon_vga_planes_putcs,
335     revc:               fbcon_vga_planes_revc,
336     fontwidthmask:      FONTWIDTH(8)
337 };
338 
339 struct display_switch fbcon_ega_planes = {
340     setup:              fbcon_vga_planes_setup,
341     bmove:              fbcon_vga_planes_bmove,
342     clear:              fbcon_vga_planes_clear,
343     putc:               fbcon_ega_planes_putc,
344     putcs:              fbcon_ega_planes_putcs,
345     revc:               fbcon_vga_planes_revc,
346     fontwidthmask:      FONTWIDTH(8)
347 };
348 
349 #ifdef MODULE
350 int init_module(void)
351 {
352     return 0;
353 }
354 
355 void cleanup_module(void)
356 {}
357 #endif /* MODULE */
358 
359 
360     /*
361      *  Visible symbols for modules
362      */
363 
364 EXPORT_SYMBOL(fbcon_vga_planes);
365 EXPORT_SYMBOL(fbcon_vga_planes_setup);
366 EXPORT_SYMBOL(fbcon_vga_planes_bmove);
367 EXPORT_SYMBOL(fbcon_vga_planes_clear);
368 EXPORT_SYMBOL(fbcon_vga_planes_putc);
369 EXPORT_SYMBOL(fbcon_vga_planes_putcs);
370 EXPORT_SYMBOL(fbcon_vga_planes_revc);
371 
372 EXPORT_SYMBOL(fbcon_ega_planes);
373 EXPORT_SYMBOL(fbcon_ega_planes_putc);
374 EXPORT_SYMBOL(fbcon_ega_planes_putcs);
375 
376 /*
377  * Overrides for Emacs so that we follow Linus's tabbing style.
378  * ---------------------------------------------------------------------------
379  * Local variables:
380  * c-basic-offset: 8
381  * End:
382  */
383 
384 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.