patch-2.4.0-test12 linux/drivers/video/fbcon-sti.c

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

diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/fbcon-sti.c linux/drivers/video/fbcon-sti.c
@@ -0,0 +1,330 @@
+/*
+ * linux/drivers/video/fbcon-sti.c -- Low level frame buffer
+ *  	operations for generic HP video boards using STI (standard
+ *  	text interface) firmware
+ *
+ *  Based on linux/drivers/video/fbcon-artist.c
+ *	Created 5 Apr 1997 by Geert Uytterhoeven
+ *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * 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/delay.h>
+#include <asm/types.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+
+#include "sti.h"
+
+/* Translate an address as it would be found in a 2048x2048x1 bit frame
+ * buffer into a logical address Artist actually expects.  Addresses fed
+ * into Artist look like this:
+ *  fixed          Y               X
+ * FFFF FFFF LLLL LLLL LLLC CCCC CCCC CC00
+ *
+ * our "RAM" addresses look like this:
+ * 
+ * FFFF FFFF 0000 0LLL LLLL LLLL CCCC CCCC [CCC]
+ *
+ * */
+
+static inline u32
+ram2log(void * addr)
+{
+	u32 a = (unsigned long) addr;
+	u32 r;
+
+#if 0
+	r  =   a & 0xff000000;		/* fixed part */
+	r += ((a & 0x000000ff) << 5);
+	r += ((a & 0x00ffff00) << 3);
+#else
+	r  =   a & 0xff000000;		/* fixed part */
+	r += ((a & 0x000000ff) << 5);
+	r += ((a & 0x0007ff00) << 5);
+#endif
+
+	return r;
+}
+
+/* All those functions need better names. */
+
+static void
+memcpy_fromhp_tohp(void *dest, void *src, int count)
+{
+	unsigned long d = ram2log(dest);
+	unsigned long s = ram2log(src);
+
+	count += 3;
+	count &= ~3; /* XXX */
+
+	while(count) {
+		count --;
+		gsc_writel(~gsc_readl(s), d);
+		d += 32*4;
+		s += 32*4;
+	}
+}
+
+static void
+memcpy_tohp(void *dest, void *src, int count)
+{
+	unsigned long d = (unsigned long) dest;
+	u32 *s = (u32 *)src;
+
+	count += 3;
+	count &= ~3; /* XXX */
+
+	d = ram2log(dest);
+
+	while(count) {
+		count--;
+		gsc_writel(*s++, d);
+		d += 32*4;
+	}
+}
+
+static void
+memcopy_fromhp(void *dest, void *src, int count)
+{
+	/* FIXME */
+	printk("uhm ...\n");
+}
+
+static void
+memset_tohp(void *dest, u32 word, int count)
+{
+	unsigned long d = ram2log(dest);
+
+	count += 3;
+	count &= ~3;
+
+	while(count) {
+		count--;
+		gsc_writel(word, d);
+		d += 32;
+	}
+}
+
+static u8
+readb_hp(void *src)
+{
+	unsigned long s = ram2log(src);
+
+	return ~gsc_readb(s);
+}
+
+static void
+writeb_hp(u8 b, void *dst)
+{
+	unsigned long d = ram2log(dst);
+
+	if((d&0xf0000000) != 0xf0000000) {
+		printk("writeb_hp %02x %p (%08lx) (%p)\n",
+			b, dst, d, __builtin_return_address(0));
+		return;
+	}
+
+	gsc_writeb(b, d);
+}
+
+static void
+fbcon_sti_setup(struct display *p)
+{
+	if (p->line_length)
+		p->next_line = p->line_length;
+	else
+		p->next_line = p->var.xres_virtual>>3;
+	p->next_plane = 0;
+}
+
+static void
+fbcon_sti_bmove(struct display *p, int sy, int sx,
+		int dy, int dx,
+		int height, int width)
+{
+#if 0 /* Unfortunately, still broken */
+	sti_bmove(&default_sti /* FIXME */, sy, sx, dy, dx, height, width);
+#else
+	u8 *src, *dest;
+	u_int rows;
+
+	if (sx == 0 && dx == 0 && width == p->next_line) {
+		src = p->screen_base+sy*fontheight(p)*width;
+		dest = p->screen_base+dy*fontheight(p)*width;
+		memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
+	} else if (dy <= sy) {
+		src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+		dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
+		for (rows = height*fontheight(p); rows--;) {
+			memcpy_fromhp_tohp(dest, src, width);
+			src += p->next_line;
+			dest += p->next_line;
+		}
+	} else {
+		src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
+		dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
+		for (rows = height*fontheight(p); rows--;) {
+			memcpy_fromhp_tohp(dest, src, width);
+			src -= p->next_line;
+			dest -= p->next_line;
+		}
+	}
+#endif
+}
+
+static void
+fbcon_sti_clear(struct vc_data *conp,
+		struct display *p, int sy, int sx,
+		int height, int width)
+{
+	u8 *dest;
+	u_int rows;
+	int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+	dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+
+	if (sx == 0 && width == p->next_line) {
+		if (inverse)
+			memset_tohp(dest, ~0, height*fontheight(p)*width);
+		else
+			memset_tohp(dest,  0, height*fontheight(p)*width);
+	} else
+		for (rows = height*fontheight(p); rows--; dest += p->next_line)
+			if (inverse)
+				memset_tohp(dest, 0xffffffff, width);
+			else
+				memset_tohp(dest, 0x00000000, width);
+}
+
+static void fbcon_sti_putc(struct vc_data *conp,
+			   struct display *p, int c,
+			   int yy, int xx)
+{
+	u8 *dest, *cdat;
+	u_int rows, bold, revs, underl;
+	u8 d;
+
+	dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+	cdat = p->fontdata+(c&p->charmask)*fontheight(p);
+	bold = attr_bold(p,c);
+	revs = attr_reverse(p,c);
+	underl = attr_underline(p,c);
+
+	for (rows = fontheight(p); rows--; dest += p->next_line) {
+		d = *cdat++;
+		if (underl && !rows)
+			d = 0xff;
+		else if (bold)
+			d |= d>>1;
+		if (revs)
+			d = ~d;
+		writeb_hp (d, dest);
+	}
+}
+
+static void fbcon_sti_putcs(struct vc_data *conp,
+			    struct display *p, 
+			    const unsigned short *s,
+			    int count, int yy, int xx)
+{
+	u8 *dest, *dest0, *cdat;
+	u_int rows, bold, revs, underl;
+	u8 d;
+	u16 c;
+
+	if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
+		printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
+			conp, p, s, count, yy, xx, __builtin_return_address(0));
+		return;
+	}	
+
+
+	dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+	if(((u32)dest0&0xf0000000)!=0xf0000000) {
+		printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
+			conp, p, s, count, yy, xx, __builtin_return_address(0),
+			dest0, p->screen_base, yy, fontheight(p), p->next_line,
+			xx);
+		return;
+	}	
+
+	bold = attr_bold(p,scr_readw(s));
+	revs = attr_reverse(p,scr_readw(s));
+	underl = attr_underline(p,scr_readw(s));
+
+	while (count--) {
+		c = scr_readw(s++) & p->charmask;
+		dest = dest0++;
+		cdat = p->fontdata+c*fontheight(p);
+		for (rows = fontheight(p); rows--; dest += p->next_line) {
+			d = *cdat++;
+			if (0 && underl && !rows)
+				d = 0xff;
+			else if (0 && bold)
+				d |= d>>1;
+			if (revs)
+				d = ~d;
+			writeb_hp (d, dest);
+		}
+	}
+}
+
+static void fbcon_sti_revc(struct display *p,
+			   int xx, int yy)
+{
+	u8 *dest, d;
+	u_int rows;
+
+
+	dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+	for (rows = fontheight(p); rows--; dest += p->next_line) {
+		d = readb_hp(dest);
+		writeb_hp (~d, dest);
+	}
+}
+
+static void
+fbcon_sti_clear_margins(struct vc_data *conp,
+			struct display *p,
+			int bottom_only)
+{
+	u8 *dest;
+	int height, bottom;
+	int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+
+	/* XXX Need to handle right margin? */
+
+	height = p->var.yres - conp->vc_rows * fontheight(p);
+	if (!height)
+		return;
+	bottom = conp->vc_rows + p->yscroll;
+	if (bottom >= p->vrows)
+		bottom -= p->vrows;
+	dest = p->screen_base + bottom * fontheight(p) * p->next_line;
+	if (inverse)
+		memset_tohp(dest, 0xffffffff, height * p->next_line);
+	else
+		memset_tohp(dest, 0x00000000, height * p->next_line);
+}
+
+
+    /*
+     *  `switch' for the low level operations
+     */
+
+struct display_switch fbcon_sti = {
+	fbcon_sti_setup, fbcon_sti_bmove, fbcon_sti_clear,
+	fbcon_sti_putc, fbcon_sti_putcs, fbcon_sti_revc,
+	NULL, NULL, fbcon_sti_clear_margins,
+	FONTWIDTH(8)
+};

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