summaryrefslogtreecommitdiffstats
path: root/drivers/video/fbcon-vga.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /drivers/video/fbcon-vga.c
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (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.c206
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);