patch-2.2.11 linux/drivers/video/fbcon-vga-planes.c

Next file: linux/drivers/video/fbcon.c
Previous file: linux/drivers/video/controlfb.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/drivers/video/fbcon-vga-planes.c linux/drivers/video/fbcon-vga-planes.c
@@ -0,0 +1,364 @@
+/*
+ *  linux/drivers/video/fbcon-vga-planes.c -- Low level frame buffer operations
+ *				  for VGA 4-plane modes
+ *
+ * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Based on code by Michael Schmitz
+ * Based on the old macfb.c 4bpp code by Alan Cox
+ *
+ * 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 <linux/vt_buffer.h>
+
+#include <asm/io.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-vga-planes.h>
+
+#define GRAPHICS_ADDR_REG 0x3ce		/* Graphics address register. */
+#define GRAPHICS_DATA_REG 0x3cf		/* Graphics data register. */
+
+#define SET_RESET_INDEX 0		/* Set/Reset Register index. */
+#define ENABLE_SET_RESET_INDEX 1	/* Enable Set/Reset Register index. */
+#define DATA_ROTATE_INDEX 3		/* Data Rotate Register index. */
+#define GRAPHICS_MODE_INDEX 5		/* Graphics Mode Register index. */
+#define BIT_MASK_INDEX 8		/* Bit Mask Register index. */
+
+/* The VGA's weird architecture often requires that we read a byte and
+   write a byte to the same location.  It doesn't matter *what* byte
+   we write, however.  This is because all the action goes on behind
+   the scenes in the VGA's 32-bit latch register, and reading and writing
+   video memory just invokes latch behavior.
+
+   To avoid race conditions (is this necessary?), reading and writing
+   the memory byte should be done with a single instruction.  One
+   suitable instruction is the x86 bitwise OR.  The following
+   read-modify-write routine should optimize to one such bitwise
+   OR. */
+static inline void rmw(volatile char *p)
+{
+	*p |= 1;
+}
+
+/* Set the Graphics Mode Register.  Bits 0-1 are write mode, bit 3 is
+   read mode. */
+static inline void setmode(int mode)
+{
+	outb(GRAPHICS_MODE_INDEX, GRAPHICS_ADDR_REG);
+	outb(mode, GRAPHICS_DATA_REG);
+}
+
+/* Select the Bit Mask Register. */
+static inline void selectmask(void)
+{
+	outb(BIT_MASK_INDEX, GRAPHICS_ADDR_REG);
+}
+
+/* Set the value of the Bit Mask Register.  It must already have been
+   selected with selectmask(). */
+static inline void setmask(int mask)
+{
+	outb(mask, GRAPHICS_DATA_REG);
+}
+
+/* Set the Data Rotate Register.  Bits 0-2 are rotate count, bits 3-4
+   are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */
+static inline void setop(int op)
+{
+	outb(DATA_ROTATE_INDEX, GRAPHICS_ADDR_REG);
+	outb(op, GRAPHICS_DATA_REG);
+}
+
+/* Set the Enable Set/Reset Register.  The code here always uses value
+   0xf for this register.  */
+static inline void setsr(int sr)
+{
+	outb(ENABLE_SET_RESET_INDEX, GRAPHICS_ADDR_REG);
+	outb(sr, GRAPHICS_DATA_REG);
+}
+
+/* Set the Set/Reset Register. */
+static inline void setcolor(int color)
+{
+	outb(SET_RESET_INDEX, GRAPHICS_ADDR_REG);
+	outb(color, GRAPHICS_DATA_REG);
+}
+
+/* Set the value in the Graphics Address Register. */
+static inline void setindex(int index)
+{
+	outb(index, GRAPHICS_ADDR_REG);
+}
+
+void fbcon_vga_planes_setup(struct display *p)
+{
+}
+
+void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx,
+		   int height, int width)
+{
+	char *src;
+	char *dest;
+	int line_ofs;
+	int x;
+
+	setmode(1);
+	setop(0);
+	setsr(0xf);
+
+	sy *= fontheight(p);
+	dy *= fontheight(p);
+	height *= fontheight(p);
+
+	if (dy < sy || (dy == sy && dx < sx)) {
+		line_ofs = p->line_length - width;
+		dest = p->screen_base + dx + dy * p->line_length;
+		src = p->screen_base + sx + sy * p->line_length;
+		while (height--) {
+			for (x = 0; x < width; x++) 
+				*dest++ = *src++;
+			src += line_ofs;
+			dest += line_ofs;
+		}
+	} else {
+		line_ofs = p->line_length - width;
+		dest = p->screen_base + dx + width + (dy + height - 1) * p->line_length;
+		src = p->screen_base + sx + width + (sy + height - 1) * p->line_length;
+		while (height--) {
+			for (x = 0; x < width; x++)
+				*--dest = *--src;
+			src -= line_ofs;
+			dest -= line_ofs;
+		}
+	}
+}
+
+void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+		   int height, int width)
+{
+	int line_ofs = p->line_length - width;
+	char *where;
+	int x;
+	
+	setmode(0);
+	setop(0);
+	setsr(0xf);
+	setcolor(attr_bgcol_ec(p, conp));
+	selectmask();
+
+	setmask(0xff);
+
+	sy *= fontheight(p);
+	height *= fontheight(p);
+
+	where = p->screen_base + sx + sy * p->line_length;
+	while (height--) {
+		for (x = 0; x < width; x++)
+			*where++ = 0;
+		where += line_ofs;
+	}
+}
+
+void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+	int fg = attr_fgcol(p,c);
+	int bg = attr_bgcol(p,c);
+
+	int y;
+	u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+
+	setmode(0);
+	setop(0);
+	setsr(0xf);
+	setcolor(bg);
+	selectmask();
+
+	setmask(0xff);
+	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
+		rmw(where);
+
+	where -= p->line_length * y;
+	setcolor(fg);
+	selectmask();
+	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
+		if (cdat[y]) {
+			setmask(cdat[y]);
+			rmw(where);
+		}
+}
+
+void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+	int fg = attr_fgcol(p,c);
+	int bg = attr_bgcol(p,c);
+
+	int y;
+	u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+
+	setmode(2);
+	setop(0);
+	setsr(0xf);
+	setcolor(fg);
+	selectmask();
+
+	setmask(0xff);
+	*where = bg;
+	rmb();
+	*(volatile char*)where; /* fill latches */
+	setmode(3);
+	wmb();
+	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
+		*where = cdat[y];
+	wmb();
+}
+
+/* 28.50 in my test */
+void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
+		   int count, int yy, int xx)
+{
+	int fg = attr_fgcol(p,scr_readw(s));
+	int bg = attr_bgcol(p,scr_readw(s));
+
+	char *where;
+	int n;
+
+	setmode(2);
+	setop(0);
+	selectmask();
+
+	setmask(0xff);
+	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+	*where = bg;
+	rmb();
+	*(volatile char*)where;
+	wmb();
+	selectmask();
+	for (n = 0; n < count; n++) {
+		int c = scr_readw(s++) & p->charmask;
+		u8 *cdat = p->fontdata + c * fontheight(p);
+		u8 *end = cdat + fontheight(p);
+
+		while (cdat < end) {
+			outb(*cdat++, GRAPHICS_DATA_REG);	
+			wmb();
+			*where = fg;
+			where += p->line_length;
+		}
+		where += 1 - p->line_length * fontheight(p);
+	}
+	
+	wmb();
+}
+
+/* 6.96 in my test */
+void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
+		   int count, int yy, int xx)
+{
+	int fg = attr_fgcol(p,*s);
+	int bg = attr_bgcol(p,*s);
+
+	char *where;
+	int n;
+
+	setmode(2);
+	setop(0);
+	setsr(0xf);
+	setcolor(fg);
+	selectmask();
+
+	setmask(0xff);
+	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+	*where = bg;
+	rmb();
+	*(volatile char*)where; /* fill latches with background */
+	setmode(3);	
+	wmb();
+	for (n = 0; n < count; n++) {
+		int y;
+		int c = *s++ & p->charmask;
+		u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+
+		for (y = 0; y < fontheight(p); y++, cdat++) {
+			*where = *cdat;
+			where += p->line_length;
+		}
+		where += 1 - p->line_length * fontheight(p);
+	}
+	
+	wmb();
+}
+
+void fbcon_vga_planes_revc(struct display *p, int xx, int yy)
+{
+	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+	int y;
+	
+	setmode(0);
+	setop(0x18);
+	setsr(0xf);
+	setcolor(0xf);
+	selectmask();
+
+	setmask(0xff);
+	for (y = 0; y < fontheight(p); y++) {
+		rmw(where);
+		where += p->line_length;
+	}
+}
+
+struct display_switch fbcon_vga_planes = {
+    fbcon_vga_planes_setup, fbcon_vga_planes_bmove, fbcon_vga_planes_clear,
+    fbcon_vga_planes_putc, fbcon_vga_planes_putcs, fbcon_vga_planes_revc,
+    NULL, NULL, NULL, FONTWIDTH(8)
+};
+
+struct display_switch fbcon_ega_planes = {
+    fbcon_vga_planes_setup, fbcon_vga_planes_bmove, fbcon_vga_planes_clear,
+    fbcon_ega_planes_putc, fbcon_ega_planes_putcs, fbcon_vga_planes_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_planes);
+EXPORT_SYMBOL(fbcon_vga_planes_setup);
+EXPORT_SYMBOL(fbcon_vga_planes_bmove);
+EXPORT_SYMBOL(fbcon_vga_planes_clear);
+EXPORT_SYMBOL(fbcon_vga_planes_putc);
+EXPORT_SYMBOL(fbcon_vga_planes_putcs);
+EXPORT_SYMBOL(fbcon_vga_planes_revc);
+
+EXPORT_SYMBOL(fbcon_ega_planes);
+EXPORT_SYMBOL(fbcon_ega_planes_putc);
+EXPORT_SYMBOL(fbcon_ega_planes_putcs);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)