diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /drivers/video/fbcon-vga.c | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'drivers/video/fbcon-vga.c')
-rw-r--r-- | drivers/video/fbcon-vga.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/drivers/video/fbcon-vga.c b/drivers/video/fbcon-vga.c new file mode 100644 index 000000000..3ea8a5234 --- /dev/null +++ b/drivers/video/fbcon-vga.c @@ -0,0 +1,206 @@ +/* + * linux/drivers/video/fbcon-vga.c -- Low level frame buffer operations for + * VGA characters/attributes + * + * Created 28 Mar 1998 by Geert Uytterhoeven + * Monochrome attributes added May 1998 by Andrew Apted + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/fb.h> + +#include <asm/io.h> + +#include "fbcon.h" +#include "fbcon-vga.h" + + + /* + * VGA screen access + */ + +static inline void vga_writew(u16 val, u16 *addr) +{ +#ifdef __powerpc__ + st_le16(addr, val); +#else + writew(val, (unsigned long)addr); +#endif /* !__powerpc__ */ +} + +static inline u16 vga_readw(u16 *addr) +{ +#ifdef __powerpc__ + return ld_le16(addr); +#else + return readw((unsigned long)addr); +#endif /* !__powerpc__ */ +} + +static inline void vga_memsetw(void *s, u16 c, unsigned int count) +{ + u16 *addr = (u16 *)s; + + while (count) { + count--; + vga_writew(c, addr++); + } +} + +static inline void vga_memmovew(u16 *to, u16 *from, unsigned int count) +{ + if (to < from) { + while (count) { + count--; + vga_writew(vga_readw(from++), to++); + } + } else { + from += count; + to += count; + while (count) { + count--; + vga_writew(vga_readw(--from), --to); + } + } +} + + + /* + * VGA characters/attributes + */ + +static inline u16 fbcon_vga_attr(struct display *p, + unsigned short s) +{ + /* Underline and reverse-video are mutually exclusive on MDA. + * Since reverse-video is used for cursors and selected areas, + * it takes precedence. + */ + + return (attr_reverse(p, s) ? 0x7000 : + (attr_underline(p, s) ? 0x0100 : 0x0700)) | + (attr_bold(p, s) ? 0x0800 : 0) | + (attr_blink(p, s) ? 0x8000 : 0); +} + +void fbcon_vga_setup(struct display *p) +{ + p->next_line = p->line_length; + p->next_plane = 0; +} + +void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + u16 *src, *dst; + int rows; + + if (sx == 0 && dx == 0 && width == p->next_line/2) { + src = (u16 *)(p->screen_base+sy*p->next_line); + dst = (u16 *)(p->screen_base+dy*p->next_line); + vga_memmovew(dst, src, height*width); + } else if (dy < sy || (dy == sy && dx < sx)) { + src = (u16 *)(p->screen_base+sy*p->next_line+sx*2); + dst = (u16 *)(p->screen_base+dy*p->next_line+dx*2); + for (rows = height; rows-- ;) { + vga_memmovew(dst, src, width); + src += p->next_line/2; + dst += p->next_line/2; + } + } else { + src = (u16 *)(p->screen_base+(sy+height-1)*p->next_line+sx*2); + dst = (u16 *)(p->screen_base+(dy+height-1)*p->next_line+dx*2); + for (rows = height; rows-- ;) { + vga_memmovew(dst, src, width); + src -= p->next_line/2; + dst -= p->next_line/2; + } + } +} + +void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + u16 *dest = (u16 *)(p->screen_base+sy*p->next_line+sx*2); + int rows; + + if (sx == 0 && width*2 == p->next_line) + vga_memsetw(dest, conp->vc_video_erase_char, height*width); + else + for (rows = height; rows-- ; dest += p->next_line/2) + vga_memsetw(dest, conp->vc_video_erase_char, width); +} + +void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c, int y, + int x) +{ + u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); + if (conp->vc_can_do_color) + vga_writew(c, dst); + else + vga_writew(fbcon_vga_attr(p, c) | (c & 0xff), dst); +} + +void fbcon_vga_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int y, int x) +{ + u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); + u16 sattr; + if (conp->vc_can_do_color) + while (count--) + vga_writew(*s++, dst++); + else { + sattr = fbcon_vga_attr(p, *s); + while (count--) + vga_writew(sattr | ((int) (*s++) & 0xff), dst++); + } +} + +void fbcon_vga_revc(struct display *p, int x, int y) +{ + u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); + u16 val = vga_readw(dst); + val = (val & 0x88ff) | ((val<<4) & 0x7000) | ((val>>4) & 0x0700); + vga_writew(val, dst); +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_vga = { + fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc, + fbcon_vga_putcs, fbcon_vga_revc, NULL, NULL, NULL, FONTWIDTH(8) +}; + + +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_vga); +EXPORT_SYMBOL(fbcon_vga_setup); +EXPORT_SYMBOL(fbcon_vga_bmove); +EXPORT_SYMBOL(fbcon_vga_clear); +EXPORT_SYMBOL(fbcon_vga_putc); +EXPORT_SYMBOL(fbcon_vga_putcs); +EXPORT_SYMBOL(fbcon_vga_revc); |