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
- Lines: 331
- Date:
Tue Dec 5 12:29:39 2000
- Orig file:
v2.4.0-test11/linux/drivers/video/fbcon-sti.c
- Orig date:
Wed Dec 31 16:00:00 1969
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)