summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
commitc9c06167e7933d93a6e396174c68abf242294abb (patch)
treed9a8bb30663e9a3405a1ef37ffb62bc14b9f019f /drivers/video
parentf79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff)
Merge with Linux 2.4.0-test12.
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c90
-rw-r--r--drivers/video/atafb.c17
-rw-r--r--drivers/video/aty128fb.c21
-rw-r--r--drivers/video/atyfb.c19
-rw-r--r--drivers/video/dummycon.c3
-rw-r--r--drivers/video/fbcon-sti.c330
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--drivers/video/macmodes.c2
-rw-r--r--drivers/video/mdacon.c18
-rw-r--r--drivers/video/platinumfb.c24
-rw-r--r--drivers/video/sti-bmode.h287
-rw-r--r--drivers/video/sti.h289
-rw-r--r--drivers/video/sticon-bmode.c906
-rw-r--r--drivers/video/sticon.c229
-rw-r--r--drivers/video/sticore.c598
-rw-r--r--drivers/video/stifb.c230
-rw-r--r--drivers/video/tdfxfb.c42
-rw-r--r--drivers/video/vgacon.c2
19 files changed, 2973 insertions, 141 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 96de87f86..54dd6eca1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -68,7 +68,7 @@ obj-$(CONFIG_FB_CYBER) += cyberfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
-obj-$(CONFIG_FB_MAC) += macfb.o
+obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o
obj-$(CONFIG_FB_HP300) += hpfb.o
obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index e6ad28fcf..44f6fc8c5 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -750,13 +750,6 @@ static struct fb_info fb_info;
/*
- * The minimum period for audio depends on htotal (for OCS/ECS/AGA)
- * (Imported from arch/m68k/amiga/amisound.c)
- */
-
-extern volatile u_short amiga_audio_min_period;
-
- /*
* Since we can't read the palette on OCS/ECS, and since reading one
* single color palette entry requires 5 expensive custom chip bus accesses
* on AGA, we keep a copy of the current palette.
@@ -1206,6 +1199,8 @@ int __init amifb_setup(char *options)
if (!strcmp(this_opt, "inverse")) {
amifb_inverse = 1;
fb_invert_cmaps();
+ } else if (!strcmp(this_opt, "off")) {
+ amifb_video_off();
} else if (!strcmp(this_opt, "ilbm"))
amifb_ilbm = 1;
else if (!strncmp(this_opt, "monitorcap:", 11))
@@ -1771,7 +1766,7 @@ default_chipset:
* access the videomem with writethrough cache
*/
videomemory_phys = (u_long)ZTWO_PADDR(videomemory);
- videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
+ //videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
if (!videomemory) {
printk("amifb: WARNING! unable to map videomem cached writethrough\n");
videomemory = ZTWO_VADDR(videomemory_phys);
@@ -1792,15 +1787,11 @@ default_chipset:
ami_init_copper();
- if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0,
- "fb vertb handler", NULL)) {
+ if (request_irq(IRQ_AMIGA_VERTB, amifb_interrupt, 0,
+ "fb vertb handler", &currentpar)) {
err = -EBUSY;
goto amifb_error;
}
- amiga_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
- amiga_intena_vals[IRQ_AMIGA_COPPER] = 0;
- custom.intena = IF_VERTB;
- custom.intena = IF_SETCLR | IF_COPER;
amifb_set_var(&var, -1, &fb_info);
@@ -1895,57 +1886,33 @@ static int flash_cursor(void)
static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
{
- u_short ints = custom.intreqr & custom.intenar;
- static struct irq_server server = {0, 0};
- unsigned long flags;
-
- if (ints & IF_BLIT) {
- custom.intreq = IF_BLIT;
- amiga_do_irq(IRQ_AMIGA_BLIT, fp);
- }
-
- if (ints & IF_COPER) {
- custom.intreq = IF_COPER;
- if (do_vmode_pan || do_vmode_full)
- ami_update_display();
-
- if (do_vmode_full)
- ami_init_display();
-
- if (do_vmode_pan) {
- flash_cursor();
- ami_rebuild_copper();
- do_cursor = do_vmode_pan = 0;
- } else if (do_cursor) {
- flash_cursor();
+ if (do_vmode_pan || do_vmode_full)
+ ami_update_display();
+
+ if (do_vmode_full)
+ ami_init_display();
+
+ if (do_vmode_pan) {
+ flash_cursor();
+ ami_rebuild_copper();
+ do_cursor = do_vmode_pan = 0;
+ } else if (do_cursor) {
+ flash_cursor();
+ ami_set_sprite();
+ do_cursor = 0;
+ } else {
+ if (flash_cursor())
ami_set_sprite();
- do_cursor = 0;
- } else {
- if (flash_cursor())
- ami_set_sprite();
- }
-
- save_flags(flags);
- cli();
- if (get_vbpos() < down2(currentpar.diwstrt_v - 6))
- custom.copjmp2 = 0;
- restore_flags(flags);
-
- if (do_blank) {
- ami_do_blank();
- do_blank = 0;
- }
+ }
- if (do_vmode_full) {
- ami_reinit_copper();
- do_vmode_full = 0;
- }
- amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+ if (do_blank) {
+ ami_do_blank();
+ do_blank = 0;
}
- if (ints & IF_VERTB) {
- printk("%s: Warning: IF_VERTB was enabled\n", __FUNCTION__);
- custom.intena = IF_VERTB;
+ if (do_vmode_full) {
+ ami_reinit_copper();
+ do_vmode_full = 0;
}
}
@@ -3379,5 +3346,6 @@ void cleanup_module(void)
{
unregister_framebuffer(&fb_info);
amifb_deinit();
+ amifb_video_off();
}
#endif /* MODULE */
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index c09a691a8..e305027a7 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2425,6 +2425,21 @@ do_install_cmap(int con, struct fb_info *info)
}
static int
+atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct atafb_par par;
+ if (con == -1)
+ atafb_get_par(&par);
+ else {
+ int err;
+ if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
+ return err;
+ }
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ return fbhw->encode_fix(fix, &par);
+}
+
+static int
atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct atafb_par par;
@@ -2776,7 +2791,7 @@ int __init atafb_init(void)
#endif /* ATAFB_EXT */
mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
- screen_base = atari_stram_alloc(mem_req, NULL, "atafb");
+ screen_base = atari_stram_alloc(mem_req, "atafb");
if (!screen_base)
panic("Cannot allocate screen memory");
memset(screen_base, 0, mem_req);
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index 05fcfcbe1..626bf3cad 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -283,7 +283,6 @@ struct fb_info_aty128 {
const struct aty128_meminfo *mem; /* onboard mem info */
struct aty128fb_par default_par, current_par;
struct display disp;
- struct display_switch dispsw; /* for cursor and font */
struct { u8 red, green, blue, pad; } palette[256];
union {
#ifdef FBCON_HAS_CFB16
@@ -347,7 +346,7 @@ static void aty128fbcon_blank(int blank, struct fb_info *fb);
static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
struct aty128fb_par *par,
const struct fb_info_aty128 *info);
-static void aty128_set_disp(struct display *disp,
+static void aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel);
static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
@@ -1392,7 +1391,7 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
display->inverse = 0;
accel = var->accel_flags & FB_ACCELF_TEXT;
- aty128_set_disp(display, info, par.crtc.bpp, accel);
+ aty128_set_dispsw(display, info, par.crtc.bpp, accel);
if (accel)
display->scrollmode = SCROLL_YNOMOVE;
@@ -1417,35 +1416,31 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
static void
-aty128_set_disp(struct display *disp,
+aty128_set_dispsw(struct display *disp,
struct fb_info_aty128 *info, int bpp, int accel)
{
switch (bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
- info->dispsw = accel ? fbcon_aty128_8 : fbcon_cfb8;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
- info->dispsw = accel ? fbcon_aty128_16 : fbcon_cfb16;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
- info->dispsw = accel ? fbcon_aty128_24 : fbcon_cfb24;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;
disp->dispsw_data = info->fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
- info->dispsw = accel ? fbcon_aty128_32 : fbcon_cfb32;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
break;
#endif
@@ -2135,7 +2130,7 @@ aty128fbcon_switch(int con, struct fb_info *fb)
aty128_decode_var(&fb_display[con].var, &par, info);
aty128_set_par(&par, info);
- aty128_set_disp(&fb_display[con], info, par.crtc.bpp,
+ aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp,
par.accel_flags & FB_ACCELF_TEXT);
do_install_cmap(con, fb);
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index 48b3b4ca2..fb3b09bc9 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -466,8 +466,8 @@ static void set_off_pitch(struct atyfb_par *par,
static int encode_fix(struct fb_fix_screeninfo *fix,
const struct atyfb_par *par,
const struct fb_info_aty *info);
-static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
- int bpp, int accel);
+static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel);
static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *fb);
static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2826,8 +2826,8 @@ static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
}
-static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
- int bpp, int accel)
+static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel)
{
switch (bpp) {
#ifdef FBCON_HAS_CFB8
@@ -2898,6 +2898,7 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
oldbpp = display->var.bits_per_pixel;
oldaccel = display->var.accel_flags;
display->var = *var;
+ accel = var->accel_flags & FB_ACCELF_TEXT;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
@@ -2913,8 +2914,6 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
display->line_length = fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
- accel = var->accel_flags & FB_ACCELF_TEXT;
- atyfb_set_disp(display, info, par.crtc.bpp, accel);
if (accel)
display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
else
@@ -2923,8 +2922,10 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
(*info->fb_info.changevar)(con);
}
if (!info->fb_info.display_fg ||
- info->fb_info.display_fg->vc_num == con)
+ info->fb_info.display_fg->vc_num == con) {
atyfb_set_par(&par, info);
+ atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
+ }
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
@@ -4241,8 +4242,8 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
atyfb_decode_var(&fb_display[con].var, &par, info);
atyfb_set_par(&par, info);
- atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
- par.accel_flags & FB_ACCELF_TEXT);
+ atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
/* Install new colormap */
do_install_cmap(con, fb);
diff --git a/drivers/video/dummycon.c b/drivers/video/dummycon.c
index 3e08ebcb2..f7a09a5d0 100644
--- a/drivers/video/dummycon.c
+++ b/drivers/video/dummycon.c
@@ -20,6 +20,9 @@
#if defined(__arm__)
#define DUMMY_COLUMNS ORIG_VIDEO_COLS
#define DUMMY_ROWS ORIG_VIDEO_LINES
+#elif defined(__hppa__)
+#define DUMMY_COLUMNS 80 /* fixme ! (mine uses 160x64 at 1280x1024) */
+#define DUMMY_ROWS 25
#else
#define DUMMY_COLUMNS 80
#define DUMMY_ROWS 25
diff --git a/drivers/video/fbcon-sti.c b/drivers/video/fbcon-sti.c
new file mode 100644
index 000000000..174ad05c4
--- /dev/null
+++ b/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)
+};
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ba6d70289..60b76a447 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -113,6 +113,8 @@ extern int tdfxfb_init(void);
extern int tdfxfb_setup(char*);
extern int sisfb_init(void);
extern int sisfb_setup(char*);
+extern int stifb_init(void);
+extern int stifb_setup(char*);
extern int pmagbafb_init(void);
extern int pmagbafb_setup(char *);
@@ -200,6 +202,9 @@ static struct {
* management!
*/
+#ifdef CONFIG_FB_STI
+ { "stifb", stifb_init, stifb_setup },
+#endif
#ifdef CONFIG_FB_OF
{ "offb", offb_init, NULL },
#endif
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 8f984ae12..d1ff9c8cc 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -17,7 +17,9 @@
#include <linux/fb.h>
#include <linux/string.h>
+#ifdef CONFIG_FB_COMPAT_XPMAC
#include <asm/vc_ioctl.h>
+#endif
#include <video/fbcon.h>
#include <video/macmodes.h>
diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c
index d988d9e39..98e58b46c 100644
--- a/drivers/video/mdacon.c
+++ b/drivers/video/mdacon.c
@@ -77,10 +77,8 @@ static int mda_last_vc = 16;
static struct vc_data *mda_display_fg = NULL;
-#ifdef MODULE_PARM
MODULE_PARM(mda_first_vc, "1-255i");
MODULE_PARM(mda_last_vc, "1-255i");
-#endif
/* MDA register values
*/
@@ -200,11 +198,7 @@ void __init mdacon_setup(char *str, int *ints)
}
#endif
-#ifdef MODULE
-static int mda_detect(void)
-#else
static int __init mda_detect(void)
-#endif
{
int count=0;
u16 *p, p_save;
@@ -287,11 +281,7 @@ static int __init mda_detect(void)
return 1;
}
-#ifdef MODULE
-static void mda_initialize(void)
-#else
static void __init mda_initialize(void)
-#endif
{
write_mda_b(97, 0x00); /* horizontal total */
write_mda_b(80, 0x01); /* horizontal displayed */
@@ -316,11 +306,7 @@ static void __init mda_initialize(void)
outb_p(0x00, mda_gfx_port);
}
-#ifdef MODULE
-static const char *mdacon_startup(void)
-#else
static const char __init *mdacon_startup(void)
-#endif
{
mda_num_columns = 80;
mda_num_lines = 25;
@@ -605,11 +591,7 @@ const struct consw mda_con = {
con_invert_region: mdacon_invert_region,
};
-#ifdef MODULE
-void mda_console_init(void)
-#else
void __init mda_console_init(void)
-#endif
{
if (mda_first_vc > mda_last_vc)
return;
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 558b6f44e..20ab5c4e5 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -65,7 +65,6 @@ struct fb_par_platinum {
struct fb_info_platinum {
struct fb_info fb_info;
struct display disp;
- struct display_switch dispsw;
struct fb_par_platinum default_par;
struct fb_par_platinum current_par;
@@ -140,8 +139,9 @@ static int platinum_var_to_par(const struct fb_var_screeninfo *var,
static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
const struct fb_par_platinum *par,
const struct fb_info_platinum *info);
-static void platinum_set_disp(struct display *disp, struct fb_info_platinum *info,
- int cmode, int accel);
+static void platinum_set_dispsw(struct display *disp,
+ struct fb_info_platinum *info, int cmode,
+ int accel);
static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *fb);
static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -193,27 +193,25 @@ static int platinum_get_var(struct fb_var_screeninfo *var, int con,
return 0;
}
-static void platinum_set_disp(struct display *disp, struct fb_info_platinum *info,
- int cmode, int accel)
+static void platinum_set_dispsw(struct display *disp,
+ struct fb_info_platinum *info, int cmode,
+ int accel)
{
switch(cmode) {
#ifdef FBCON_HAS_CFB8
case CMODE_8:
- info->dispsw = fbcon_cfb8;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case CMODE_16:
- info->dispsw = fbcon_cfb16;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_cfb16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB32
case CMODE_32:
- info->dispsw = fbcon_cfb32;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_cfb32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
break;
#endif
@@ -271,7 +269,7 @@ static int platinum_set_var(struct fb_var_screeninfo *var, int con,
display->line_length = fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
- platinum_set_disp(display, info, par.cmode, 0);
+ platinum_set_dispsw(display, info, par.cmode, 0);
display->scrollmode = SCROLL_YREDRAW;
if (info->fb_info.changevar)
(*info->fb_info.changevar)(con);
@@ -341,7 +339,7 @@ static int platinum_switch(int con, struct fb_info *fb)
platinum_var_to_par(&fb_display[con].var, &par, info);
platinum_set_par(&par, info);
- platinum_set_disp(&fb_display[con], info, par.cmode, 0);
+ platinum_set_dispsw(&fb_display[con], info, par.cmode, 0);
do_install_cmap(con, fb);
return 1;
diff --git a/drivers/video/sti-bmode.h b/drivers/video/sti-bmode.h
new file mode 100644
index 000000000..4aa38f6d9
--- /dev/null
+++ b/drivers/video/sti-bmode.h
@@ -0,0 +1,287 @@
+#define STI_REGION_MAX 8
+#define STI_DEV_NAME_LENGTH 32
+
+typedef struct {
+ u8 res[3];
+ u8 data;
+} __attribute__((packed)) sti_u8;
+
+typedef struct {
+ sti_u8 data[2];
+} __attribute__((packed)) sti_u16;
+
+typedef struct {
+ sti_u8 data[4];
+} __attribute__((packed)) sti_u32;
+
+#define STI_U8( u8) ((u8).data)
+#define STI_U16(u16) ((STI_U8((u16).data[0])<<8) | STI_U8((u16).data[1]))
+#define STI_U32(u32) ((STI_U8((u32).data[0])<<24) | \
+ (STI_U8((u32).data[1])<<16) | \
+ (STI_U8((u32).data[2])<< 8) | \
+ (STI_U8((u32).data[3])<< 0))
+
+struct sti_rom_region {
+ sti_u32 region;
+};
+
+struct sti_rom_font {
+ sti_u16 first_char;
+ sti_u16 last_char;
+ sti_u8 width;
+ sti_u8 height;
+ sti_u8 font_type;
+ sti_u8 bytes_per_char;
+ sti_u32 next_font;
+ sti_u8 underline_height;
+ sti_u8 underline_pos;
+ sti_u8 res008[2];
+};
+
+struct sti_rom {
+ sti_u8 type;
+ sti_u8 num_mons;
+ sti_u8 revno[2];
+
+ sti_u8 graphics_id[8]; /* 0x010 */
+
+ sti_u32 font_start; /* 0x030 */
+ sti_u32 statesize;
+ sti_u32 last_addr;
+ sti_u32 region_list;
+
+ sti_u16 reentsize; /* 0x070 */
+ sti_u16 maxtime;
+ sti_u32 mon_tbl_addr;
+ sti_u32 user_data_addr;
+ sti_u32 sti_mem_req;
+
+ sti_u32 user_data_size; /* 0x0b0 */
+ sti_u16 power; /* 0x0c0 */
+ sti_u8 bus_support;
+ sti_u8 ext_bus_support;
+ sti_u8 alt_code_type; /* 0x0d0 */
+ sti_u8 ext_dd_struct[3];
+ sti_u32 cfb_addr; /* 0x0e0 */
+
+ sti_u8 res0f0[4];
+
+ sti_u32 init_graph; /* 0x0e0 */
+ sti_u32 state_mgmt;
+ sti_u32 font_unpmv;
+ sti_u32 block_move;
+ sti_u32 self_test;
+ sti_u32 excep_hdlr;
+ sti_u32 inq_conf;
+ sti_u32 set_cm_entry;
+ sti_u32 dma_ctrl;
+ sti_u32 flow_ctrl;
+ sti_u32 user_timing;
+ sti_u32 process_mgr;
+ sti_u32 sti_util;
+ sti_u32 end_addr;
+ sti_u32 res0b8;
+ sti_u32 res0bc;
+
+ sti_u32 init_graph_m68k; /* 0x0e0 */
+ sti_u32 state_mgmt_m68k;
+ sti_u32 font_unpmv_m68k;
+ sti_u32 block_move_m68k;
+ sti_u32 self_test_m68k;
+ sti_u32 excep_hdlr_m68k;
+ sti_u32 inq_conf_m68k;
+ sti_u32 set_cm_entry_m68k;
+ sti_u32 dma_ctrl_m68k;
+ sti_u32 flow_ctrl_m68k;
+ sti_u32 user_timing_m68k;
+ sti_u32 process_mgr_m68k;
+ sti_u32 sti_util_m68k;
+ sti_u32 end_addr_m68k;
+ sti_u32 res0b8_m68k;
+ sti_u32 res0bc_m68k;
+
+ sti_u8 res040[7 * 4];
+};
+
+struct sti_cooked_font {
+ struct sti_rom_font *raw;
+ struct sti_cooked_font *next_font;
+};
+
+struct sti_cooked_rom {
+ struct sti_rom *raw;
+ struct sti_cooked_font *font_start;
+ u32 *region_list;
+};
+
+struct sti_glob_cfg_ext {
+ u8 curr_mon;
+ u8 friendly_boot;
+ s16 power;
+ s32 freq_ref;
+ s32 *sti_mem_addr;
+ s32 *future_ptr;
+};
+
+struct sti_glob_cfg {
+ s32 text_planes;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ u32 region_ptrs[STI_REGION_MAX];
+ s32 reent_lvl;
+ s32 *save_addr;
+ struct sti_glob_cfg_ext *ext_ptr;
+};
+
+struct sti_init_flags {
+ u32 wait : 1;
+ u32 reset : 1;
+ u32 text : 1;
+ u32 nontext : 1;
+ u32 clear : 1;
+ u32 cmap_blk : 1;
+ u32 enable_be_timer : 1;
+ u32 enable_be_int : 1;
+ u32 no_chg_tx : 1;
+ u32 no_chg_ntx : 1;
+ u32 no_chg_bet : 1;
+ u32 no_chg_bei : 1;
+ u32 init_cmap_tx : 1;
+ u32 cmt_chg : 1;
+ u32 retain_ie : 1;
+ u32 pad : 17;
+
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr_ext {
+ u8 config_mon_type;
+ u8 pad[1];
+ u16 inflight_data;
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr {
+ s32 text_planes;
+ struct sti_init_inptr_ext *ext_ptr;
+};
+
+struct sti_init_outptr {
+ s32 errno;
+ s32 text_planes;
+ s32 *future_ptr;
+};
+
+struct sti_conf_flags {
+ u32 wait : 1;
+ u32 pad : 31;
+ s32 *future_ptr;
+};
+
+struct sti_conf_inptr {
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr_ext {
+ u32 crt_config[3];
+ u32 crt_hdw[3];
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr {
+ s32 errno;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ s32 bits_per_pixel;
+ s32 bits_used;
+ s32 planes;
+ u8 dev_name[STI_DEV_NAME_LENGTH];
+ u32 attributes;
+ struct sti_conf_outptr_ext *ext_ptr;
+};
+
+
+struct sti_font_inptr {
+ u32 font_start_addr;
+ s16 index;
+ u8 fg_color;
+ u8 bg_color;
+ s16 dest_x;
+ s16 dest_y;
+ s32 *future_ptr;
+};
+
+struct sti_font_flags {
+ u32 wait : 1;
+ u32 non_text : 1;
+ u32 pad : 30;
+
+ s32 *future_ptr;
+};
+
+struct sti_font_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_flags {
+ u32 wait : 1;
+ u32 color : 1;
+ u32 clear : 1;
+ u32 non_text : 1;
+ u32 pad : 28;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_inptr {
+ u8 fg_color;
+ u8 bg_color;
+ s16 src_x;
+ s16 src_y;
+ s16 dest_x;
+ s16 dest_y;
+ s16 width;
+ s16 height;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_struct {
+ spinlock_t lock;
+
+ struct sti_cooked_rom *rom;
+
+ unsigned long font_unpmv;
+ unsigned long block_move;
+ unsigned long init_graph;
+ unsigned long inq_conf;
+
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_rom_font *font;
+
+ s32 text_planes;
+
+ char **mon_strings;
+ u32 *regions;
+ u8 *pci_regions;
+};
+
+#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
+ ({ \
+ real32_call( func, (unsigned long)STI_PTR(flags), \
+ STI_PTR(inptr), STI_PTR(outptr), \
+ glob_cfg); \
+ })
+
diff --git a/drivers/video/sti.h b/drivers/video/sti.h
new file mode 100644
index 000000000..feea4fb92
--- /dev/null
+++ b/drivers/video/sti.h
@@ -0,0 +1,289 @@
+#define STI_REGION_MAX 8
+#define STI_DEV_NAME_LENGTH 32
+
+struct sti_rom_font {
+ u16 first_char;
+ u16 last_char;
+ u8 width;
+ u8 height;
+ u8 font_type;
+ u8 bytes_per_char;
+ u32 next_font;
+ u8 underline_height;
+ u8 underline_pos;
+ u8 res008[2];
+};
+
+struct sti_rom {
+ u8 type[4];
+ u8 res004;
+ u8 num_mons;
+ u8 revno[2];
+ u8 graphics_id[8];
+
+ u32 font_start;
+ u32 statesize;
+ u32 last_addr;
+ u32 region_list;
+
+ u16 reentsize;
+ u16 maxtime;
+ u32 mon_tbl_addr;
+ u32 user_data_addr;
+ u32 sti_mem_req;
+
+ u32 user_data_size;
+ u16 power;
+ u8 bus_support;
+ u8 ext_bus_support;
+ u8 alt_code_type;
+ u8 ext_dd_struct[3];
+ u32 cfb_addr;
+
+ u32 init_graph;
+ u32 state_mgmt;
+ u32 font_unpmv;
+ u32 block_move;
+ u32 self_test;
+ u32 excep_hdlr;
+ u32 inq_conf;
+ u32 set_cm_entry;
+ u32 dma_ctrl;
+ u8 res040[7 * 4];
+
+ u32 init_graph_m68k;
+ u32 flow_ctrl;
+ u32 user_timing;
+ u32 process_mgr;
+ u32 sti_util;
+ u32 end_addr;
+ u32 res0b8;
+ u32 res0bc;
+};
+
+struct sti_cooked_font {
+ struct sti_rom_font *raw;
+ struct sti_cooked_font *next_font;
+};
+
+struct sti_cooked_rom {
+ struct sti_rom *raw;
+ struct sti_cooked_font *font_start;
+ u32 *region_list;
+};
+
+struct sti_glob_cfg_ext {
+ u8 curr_mon;
+ u8 friendly_boot;
+ s16 power;
+ s32 freq_ref;
+ s32 *sti_mem_addr;
+ s32 *future_ptr;
+};
+
+struct sti_glob_cfg {
+ s32 text_planes;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ u32 region_ptrs[STI_REGION_MAX];
+ s32 reent_lvl;
+ s32 *save_addr;
+ struct sti_glob_cfg_ext *ext_ptr;
+};
+
+struct sti_init_flags {
+ u32 wait : 1;
+ u32 reset : 1;
+ u32 text : 1;
+ u32 nontext : 1;
+ u32 clear : 1;
+ u32 cmap_blk : 1;
+ u32 enable_be_timer : 1;
+ u32 enable_be_int : 1;
+ u32 no_chg_tx : 1;
+ u32 no_chg_ntx : 1;
+ u32 no_chg_bet : 1;
+ u32 no_chg_bei : 1;
+ u32 init_cmap_tx : 1;
+ u32 cmt_chg : 1;
+ u32 retain_ie : 1;
+ u32 pad : 17;
+
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr_ext {
+ u8 config_mon_type;
+ u8 pad[1];
+ u16 inflight_data;
+ s32 *future_ptr;
+};
+
+struct sti_init_inptr {
+ s32 text_planes;
+ struct sti_init_inptr_ext *ext_ptr;
+};
+
+struct sti_init_outptr {
+ s32 errno;
+ s32 text_planes;
+ s32 *future_ptr;
+};
+
+struct sti_conf_flags {
+ u32 wait : 1;
+ u32 pad : 31;
+ s32 *future_ptr;
+};
+
+struct sti_conf_inptr {
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr_ext {
+ u32 crt_config[3];
+ u32 crt_hdw[3];
+ s32 *future_ptr;
+};
+
+struct sti_conf_outptr {
+ s32 errno;
+ s16 onscreen_x;
+ s16 onscreen_y;
+ s16 offscreen_x;
+ s16 offscreen_y;
+ s16 total_x;
+ s16 total_y;
+ s32 bits_per_pixel;
+ s32 bits_used;
+ s32 planes;
+ u8 dev_name[STI_DEV_NAME_LENGTH];
+ u32 attributes;
+ struct sti_conf_outptr_ext *ext_ptr;
+};
+
+
+struct sti_font_inptr {
+ u32 font_start_addr;
+ s16 index;
+ u8 fg_color;
+ u8 bg_color;
+ s16 dest_x;
+ s16 dest_y;
+ s32 *future_ptr;
+};
+
+struct sti_font_flags {
+ u32 wait : 1;
+ u32 non_text : 1;
+ u32 pad : 30;
+
+ s32 *future_ptr;
+};
+
+struct sti_font_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_flags {
+ u32 wait : 1;
+ u32 color : 1;
+ u32 clear : 1;
+ u32 non_text : 1;
+ u32 pad : 28;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_inptr {
+ u8 fg_color;
+ u8 bg_color;
+ s16 src_x;
+ s16 src_y;
+ s16 dest_x;
+ s16 dest_y;
+ s16 width;
+ s16 height;
+ s32 *future_ptr;
+};
+
+struct sti_blkmv_outptr {
+ s32 errno;
+ s32 *future_ptr;
+};
+
+struct sti_struct {
+ spinlock_t lock;
+
+ struct sti_cooked_rom *rom;
+
+ unsigned long font_unpmv;
+ unsigned long block_move;
+ unsigned long init_graph;
+ unsigned long inq_conf;
+
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_rom_font *font;
+
+ s32 text_planes;
+
+ char **mon_strings;
+ u32 *regions;
+ u8 *pci_regions;
+};
+
+#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
+ ({ \
+ real32_call( func, (unsigned long)STI_PTR(flags), \
+ STI_PTR(inptr), STI_PTR(outptr), \
+ glob_cfg); \
+ })
+
+/* The latency of the STI functions cannot really be reduced by setting
+ * this to 0; STI doesn't seem to be designed to allow calling a different
+ * function (or the same function with different arguments) after a
+ * function exited with 1 as return value.
+ *
+ * As all of the functions below could be called from interrupt context,
+ * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
+ * block. Really bad latency there.
+ *
+ * Probably the best solution to all this is have the generic code manage
+ * the screen buffer and a kernel thread to call STI occasionally.
+ *
+ * Luckily, the frame buffer guys have the same problem so we can just wait
+ * for them to fix it and steal their solution. prumpf
+ *
+ * Actually, another long-term viable solution is to completely do STI
+ * support in userspace - that way we avoid the potential license issues
+ * of using proprietary fonts, too. */
+
+#define STI_WAIT 1
+#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
+#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
+
+#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
+#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
+#define sti_font_x(sti) (PTR_STI(sti->font)->width)
+#define sti_font_y(sti) (PTR_STI(sti->font)->height)
+
+extern struct sti_struct * sti_init_roms(void);
+
+void sti_init_graph(struct sti_struct *sti);
+void sti_inq_conf(struct sti_struct *sti);
+void sti_putc(struct sti_struct *sti, int c, int y, int x);
+void sti_set(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width, u8 color);
+void sti_clear(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width);
+void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+ int dst_y, int dst_x, int height, int width);
+
+/* XXX: this probably should not be here, but we rely on STI being
+ initialized early and independently of stifb at the moment, so
+ there's no other way for stifb to find it. */
+extern struct sti_struct default_sti;
diff --git a/drivers/video/sticon-bmode.c b/drivers/video/sticon-bmode.c
new file mode 100644
index 000000000..e401cbfcd
--- /dev/null
+++ b/drivers/video/sticon-bmode.c
@@ -0,0 +1,906 @@
+/*
+TPG CVS users: please don't commit changes to this file directly, send
+them to prumpf@tux.org and wait for a new version instead. Otherwise,
+your changes will get lost when prumpf releases the next version, as
+this file *will* be replaced with it. You have been warned.
+
+2000-05-30, <deller@gmx.de>
+*/
+#if 1
+#define DPRINTK(x) printk x
+#else
+#define DPRINTK(x)
+#endif
+
+/*
+ * linux/drivers/video/sticon.c - console driver using HP's STI firmware
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
+ * which were
+ *
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ * Copyright (C) 1995 Geert Uytterhoeven
+ * Copyright (C) 1993 Bjoern Brauel
+ * Roman Hodek
+ * Copyright (C) 1993 Hamish Macdonald
+ * Greg Harp
+ * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
+ *
+ * with work by William Rucklidge (wjr@cs.cornell.edu)
+ * Geert Uytterhoeven
+ * Jes Sorensen (jds@kom.auc.dk)
+ * Martin Apel
+ * with work by Guenther Kelleter
+ * Martin Schaller
+ * Andreas Schwab
+ * Emmanuel Marty (core@ggi-project.org)
+ * Jakub Jelinek (jj@ultra.linux.cz)
+ * Martin Mares <mj@ucw.cz>
+ *
+ * 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.
+ */
+/*
+ * TODO:
+ * - call STI in virtual mode rather than in real mode
+ * - support for PCI-only STI ROMs (which don't have a traditional region
+ * list)
+ * - safe detection (i.e. verify there is a graphics device at a given
+ * address first, not just read a random device's io space)
+ * - support for multiple STI devices in one machine
+ * - support for byte-mode STI ROMs
+ * - support for just using STI to switch to a colour fb (stifb ?)
+ * - try to make it work on m68k hp workstations ;)
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/real.h>
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/smp.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/font.h>
+
+#include "sti-bmode.h"
+
+/* The latency of the STI functions cannot really be reduced by setting
+ * this to 0; STI doesn't seem to be designed to allow calling a different
+ * function (or the same function with different arguments) after a
+ * function exited with 1 as return value.
+ *
+ * As all of the functions below could be called from interrupt context,
+ * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
+ * block. Really bad latency there.
+ *
+ * Probably the best solution to all this is have the generic code manage
+ * the screen buffer and a kernel thread to call STI occasionally.
+ *
+ * Luckily, the frame buffer guys have the same problem so we can just wait
+ * for them to fix it and steal their solution. prumpf
+ *
+ * Actually, another long-term viable solution is to completely do STI
+ * support in userspace - that way we avoid the potential license issues
+ * of using proprietary fonts, too. */
+
+#define STI_WAIT 1
+#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
+#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
+
+static struct sti_struct default_sti = {
+ SPIN_LOCK_UNLOCKED,
+};
+
+static struct sti_font_flags default_font_flags = {
+ STI_WAIT, 0, 0, NULL
+};
+
+/* The colour indices used by STI are
+ * 0 - Black
+ * 1 - White
+ * 2 - Red
+ * 3 - Yellow/Brown
+ * 4 - Green
+ * 5 - Cyan
+ * 6 - Blue
+ * 7 - Magenta
+ *
+ * So we have the same colours as VGA (basically one bit each for R, G, B),
+ * but have to translate them, anyway. */
+
+static u8 col_trans[8] = {
+ 0, 6, 4, 5,
+ 2, 7, 3, 1
+};
+
+#define c_fg(sti, c) col_trans[((c>> 8) & 7)]
+#define c_bg(sti, c) col_trans[((c>>11) & 7)]
+#define c_index(sti, c) (c&0xff)
+
+#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
+#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
+#define sti_font_x(sti) (STI_U8(PTR_STI(sti->font)->width))
+#define sti_font_y(sti) (STI_U8(PTR_STI(sti->font)->height))
+
+static struct sti_init_flags default_init_flags = {
+ STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
+};
+
+static void sti_init_graph(struct sti_struct *sti)
+{
+ struct sti_init_inptr_ext inptr_ext = {
+ 0, { 0 }, 0, NULL
+ };
+ struct sti_init_inptr inptr = {
+ 3, STI_PTR(&inptr_ext)
+ };
+ struct sti_init_outptr outptr = { 0 };
+ unsigned long flags;
+ s32 ret;
+
+ spin_lock_irqsave(&sti->lock, flags);
+
+ ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
+ &outptr, sti->glob_cfg);
+
+ spin_unlock_irqrestore(&sti->lock, flags);
+
+ sti->text_planes = outptr.text_planes;
+}
+
+#if 0
+static struct sti_conf_flags default_conf_flags = {
+ STI_WAIT, 0, NULL
+};
+
+static void sti_inq_conf(struct sti_struct *sti)
+{
+ struct sti_conf_inptr inptr = { NULL };
+ struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };
+ struct sti_conf_outptr outptr = {
+ ext_ptr: STI_PTR(&outptr_ext)
+ };
+ unsigned long flags;
+ s32 ret;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->inq_conf, &default_conf_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+#endif
+
+static void sti_putc(struct sti_struct *sti, int c, int y, int x)
+{
+ struct sti_font_inptr inptr = {
+ (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
+ x * sti_font_x(sti), y * sti_font_y(sti), NULL
+ };
+ struct sti_font_outptr outptr = {
+ 0, NULL
+ };
+ s32 ret;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->font_unpmv, &default_font_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags clear_blkmv_flags = {
+ STI_WAIT, 1, 1, 0, 0, NULL
+};
+
+static void sti_set(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width, u8 color)
+{
+ struct sti_blkmv_inptr inptr = {
+ color, color,
+ src_x, src_y ,
+ src_x, src_y ,
+ width, height,
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static void sti_clear(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags default_blkmv_flags = {
+ STI_WAIT, 0, 0, 0, 0, NULL
+};
+
+static void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+ int dst_y, int dst_x, int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &default_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+
+/* STICON */
+
+static const char __init *sticon_startup(void)
+{
+ return "STI console";
+}
+
+static int sticon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ return -EINVAL;
+}
+static int sticon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
+}
+
+static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
+{
+ sti_putc(&default_sti, c, ypos, xpos);
+}
+
+static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
+ int count, int ypos, int xpos)
+{
+ while(count--) {
+ sti_putc(&default_sti, *s++, ypos, xpos++);
+ }
+}
+
+static void sticon_cursor(struct vc_data *conp, int mode)
+{
+}
+
+static int sticon_scroll(struct vc_data *conp, int t, int b, int dir,
+ int count)
+{
+ struct sti_struct *sti = &default_sti;
+
+ if(console_blanked)
+ return 0;
+
+ sticon_cursor(conp, CM_ERASE);
+
+ switch(dir) {
+ case SM_UP:
+ sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, b-count, 0, count, conp->vc_cols);
+
+ break;
+
+ case SM_DOWN:
+ sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, t, 0, count, conp->vc_cols);
+
+ break;
+ }
+
+ return 0;
+}
+
+static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ sti_bmove(&default_sti, sy, sx, dy, dx, height, width);
+}
+
+static void sticon_init(struct vc_data *c, int init)
+{
+ struct sti_struct *sti = &default_sti;
+ int vc_cols, vc_rows;
+
+ sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
+ c->vc_can_do_color = 1;
+ vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti);
+ vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti);
+
+ vc_resize_con(vc_rows, vc_cols, c->vc_num);
+}
+
+static void sticon_deinit(struct vc_data *c)
+{
+}
+
+static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
+ int width)
+{
+ sti_clear(&default_sti, sy, sx, height, width);
+}
+
+static int sticon_switch(struct vc_data *conp)
+{
+ return 0;
+}
+
+static int sticon_blank(struct vc_data *conp, int blank)
+{
+ return 0;
+}
+
+static int sticon_scrolldelta(struct vc_data *conp, int lines)
+{
+ return 0;
+}
+
+static int sticon_set_origin(struct vc_data *conp)
+{
+ return 0;
+}
+
+static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
+{
+ return NULL;
+}
+
+static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py)
+{
+ return 0;
+}
+
+static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+
+ if(reverse) {
+ color = ((color>>3)&0x7) | ((color &0x7)<<3);
+ }
+
+
+ return attr;
+}
+
+static struct consw sti_con = {
+ con_startup: sticon_startup,
+ con_init: sticon_init,
+ con_deinit: sticon_deinit,
+ con_clear: sticon_clear,
+ con_putc: sticon_putc,
+ con_putcs: sticon_putcs,
+ con_cursor: sticon_cursor,
+ con_scroll: sticon_scroll,
+ con_bmove: sticon_bmove,
+ con_switch: sticon_switch,
+ con_blank: sticon_blank,
+ con_font_op: sticon_font_op,
+ con_set_palette: sticon_set_palette,
+ con_scrolldelta: sticon_scrolldelta,
+ con_set_origin: sticon_set_origin,
+ con_save_screen: NULL,
+ con_build_attr: sticon_build_attr,
+ con_invert_region: NULL,
+ con_screen_pos: sticon_screen_pos,
+ con_getxy: sticon_getxy,
+};
+
+#include <asm/pgalloc.h> /* need cache flush routines */
+static void __init sti_rom_copy(unsigned long base, unsigned long offset,
+ unsigned long count, void *dest)
+{
+ void *savedest = dest;
+ int savecount = count;
+
+ while(count >= 4) {
+ count -= 4;
+ *(u32 *)dest = gsc_readl(base + offset);
+#if 0
+ DPRINTK(("%08x\n", *(u32 *)dest));
+ if(*(u32 *)dest == 0x64646464) {
+ DPRINTK(("!!!!\n"));
+ { u32 foo = 0; while(foo += 0x100); }
+ }
+#endif
+ offset += 4;
+ dest += 4;
+ }
+ while(count) {
+ count--;
+ *(u8 *)dest = gsc_readb(base + offset);
+ offset++;
+ dest++;
+ }
+ __flush_dcache_range(dest, count);
+ __flush_icache_range(dest, count);
+}
+
+static void dump_sti_rom(struct sti_rom *rom)
+{
+ printk("STI byte mode ROM type %d\n", STI_U8(rom->type));
+ printk(" supports %d monitors\n", STI_U8(rom->num_mons));
+ printk(" conforms to STI ROM spec revision %d.%02x\n",
+ STI_U8(rom->revno[0]) >> 4, STI_U8(rom->revno[0]) & 0x0f);
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ (unsigned int) STI_U8(rom->graphics_id[0]),
+ (unsigned int) STI_U8(rom->graphics_id[1]),
+ (unsigned int) STI_U8(rom->graphics_id[2]),
+ (unsigned int) STI_U8(rom->graphics_id[3]),
+ (unsigned int) STI_U8(rom->graphics_id[4]),
+ (unsigned int) STI_U8(rom->graphics_id[5]),
+ (unsigned int) STI_U8(rom->graphics_id[6]),
+ (unsigned int) STI_U8(rom->graphics_id[7]));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" font start %08x\n", STI_U32(rom->font_start));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" region list %08x\n", STI_U32(rom->region_list));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" init_graph %08x\n", STI_U32(rom->init_graph));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+ printk(" alternate code type %d\n", STI_U8(rom->alt_code_type));
+ printk(__FUNCTION__ ": %d\n", __LINE__);
+}
+
+static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
+ struct sti_rom *raw_rom)
+{
+ struct sti_rom_font *raw_font;
+ struct sti_cooked_font *cooked_font;
+ struct sti_rom_font *font_start;
+
+ cooked_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font)
+ return;
+
+ cooked_rom->font_start = cooked_font;
+
+#if 0
+ DPRINTK(("%p = %p + %08x\n",
+ ((void *)raw_rom) + (STI_U32(raw_rom->font_start)),
+ ((void *)raw_rom), (STI_U32(raw_rom->font_start))));
+#endif
+ raw_font = ((void *)raw_rom) + STI_U32(raw_rom->font_start) - 3;
+
+ font_start = raw_font;
+ cooked_font->raw = raw_font;
+
+ DPRINTK(("next font %08x\n", STI_U32(raw_font->next_font)));
+
+ while(0 && STI_U32(raw_font->next_font)) {
+ raw_font = ((void *)font_start) + STI_U32(raw_font->next_font);
+
+ cooked_font->next_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font->next_font)
+ return;
+
+ cooked_font = cooked_font->next_font;
+
+// cooked_font->raw = raw_font;
+
+ DPRINTK(("raw_font %p\n",
+ raw_font));
+ DPRINTK(("next_font %08x %p\n",
+ STI_U32(raw_font->next_font),
+ ((void *)font_start) + STI_U32(raw_font->next_font)));
+ }
+
+ cooked_font->next_font = NULL;
+}
+
+static unsigned long __init sti_cook_function(void *function,
+ u32 size)
+{
+ sti_u32 *func = (sti_u32 *)function;
+ u32 *ret;
+ int i;
+
+ ret = kmalloc(size, GFP_KERNEL);
+ if(!ret) {
+ printk(KERN_ERR __FILE__ ": could not get memory.\n");
+ return 0;
+ }
+
+ for(i=0; i<(size/4); i++)
+ ret[i] = STI_U32(func[i]);
+
+ flush_all_caches();
+
+ return virt_to_phys(ret);
+}
+
+static int font_index, font_height, font_width;
+
+static int __init sti_search_font(struct sti_cooked_rom *rom,
+ int height, int width)
+{
+ struct sti_cooked_font *font;
+ int i = 0;
+
+ for(font = rom->font_start; font; font = font->next_font, i++) {
+ if((STI_U8(font->raw->width) == width) &&
+ (STI_U8(font->raw->height) == height))
+ return i;
+ }
+
+ return 0;
+}
+
+static struct sti_cooked_font * __init
+sti_select_font(struct sti_cooked_rom *rom)
+{
+ struct sti_cooked_font *font;
+ int i;
+
+ if(font_width && font_height)
+ font_index = sti_search_font(rom, font_height, font_width);
+
+ for(font = rom->font_start, i = font_index;
+ font && (i > 0);
+ font = font->next_font, i--);
+
+ if(font)
+ return font;
+ else
+ return rom->font_start;
+}
+
+/* address is a pointer to a word mode or pci rom */
+static struct sti_struct * __init sti_read_rom(unsigned long address)
+{
+ struct sti_struct *ret = NULL;
+ struct sti_cooked_rom *cooked = NULL;
+ struct sti_rom *raw = NULL;
+ unsigned long size;
+
+ ret = &default_sti;
+
+ if(!ret)
+ goto out_err;
+
+ cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
+ raw = kmalloc(sizeof *raw, GFP_KERNEL);
+
+ if(!(raw && cooked))
+ goto out_err;
+
+ /* reallocate raw */
+ sti_rom_copy(address, 0, sizeof *raw, raw);
+
+ dump_sti_rom(raw);
+
+ size = STI_U32(raw->last_addr) + 1;
+ size = 128*1024;
+// DPRINTK(("size %08lx\n", size));
+// DPRINTK(("font_start %08x\n", STI_U32(raw->font_start)));
+// kfree(raw);
+ raw = kmalloc(size, GFP_KERNEL);
+ if(!raw)
+ goto out_err;
+ sti_rom_copy(address, 0, size-1, raw);
+
+ sti_cook_fonts(cooked, raw);
+// sti_cook_regions(cooked, raw);
+// sti_cook_functions(cooked, raw);
+
+ if(STI_U32(raw->region_list)) {
+ struct sti_rom_region *region =
+ ((void *)raw) + STI_U32(raw->region_list) - 3;
+
+// DPRINTK(("region_list %08x\n", STI_U32(raw->region_list)));
+
+ ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME!! */
+
+ ret->regions[0] = STI_U32(region[0].region);
+ ret->regions[1] = STI_U32(region[1].region);
+ ret->regions[2] = STI_U32(region[2].region);
+ ret->regions[3] = STI_U32(region[3].region);
+ ret->regions[4] = STI_U32(region[4].region);
+ ret->regions[5] = STI_U32(region[5].region);
+ ret->regions[6] = STI_U32(region[6].region);
+ ret->regions[7] = STI_U32(region[7].region);
+ }
+
+ address = virt_to_phys(raw);
+
+#if 0
+ DPRINTK(("init_graph %08x %08x\n"
+ "state_mgmt %08x %08x\n"
+ "font_unpmv %08x %08x\n"
+ "block_move %08x %08x\n"
+ "self_test %08x %08x\n"
+ "excep_hdlr %08x %08x\n"
+ "irq_conf %08x %08x\n"
+ "set_cm_e %08x %08x\n"
+ "dma_ctrl %08x %08x\n"
+ "flow_ctrl %08x %08x\n"
+ "user_timin %08x %08x\n"
+ "process_m %08x %08x\n"
+ "sti_util %08x %08x\n"
+ "end_addr %08x %08x\n",
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->state_mgmt), STI_U32(raw->state_mgmt_m68k),
+ STI_U32(raw->font_unpmv), STI_U32(raw->font_unpmv_m68k),
+ STI_U32(raw->block_move), STI_U32(raw->block_move_m68k),
+ STI_U32(raw->self_test), STI_U32(raw->self_test_m68k),
+ STI_U32(raw->excep_hdlr), STI_U32(raw->excep_hdlr_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
+ STI_U32(raw->end_addr), STI_U32(raw->end_addr_m68k) ) );
+#endif
+
+ ret->init_graph = sti_cook_function(((void *)raw)+STI_U32(raw->init_graph)-3,
+ (STI_U32(raw->state_mgmt) -
+ STI_U32(raw->init_graph))/4);
+
+
+ ret->font_unpmv = sti_cook_function(((void *)raw)+STI_U32(raw->font_unpmv)-3,
+ (STI_U32(raw->block_move) -
+ STI_U32(raw->font_unpmv))/4);
+
+ ret->block_move = sti_cook_function(((void *)raw)+STI_U32(raw->block_move)-3,
+ (STI_U32(raw->self_test) -
+ STI_U32(raw->block_move))/4);
+
+ ret->inq_conf = sti_cook_function(((void *)raw)+STI_U32(raw->inq_conf),
+ STI_U32(raw->set_cm_entry) -
+ STI_U32(raw->inq_conf));
+
+ ret->rom = cooked;
+ ret->rom->raw = raw;
+
+ ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
+
+ return ret;
+
+out_err:
+ if(raw)
+ kfree(raw);
+ if(cooked)
+ kfree(cooked);
+
+ return NULL;
+}
+
+#if 0
+static void dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
+{
+ DPRINTK(("monitor %d\n"
+ "in friendly mode: %d\n"
+ "power consumption %d watts\n"
+ "freq ref %d\n"
+ "sti_mem_addr %p\n",
+ cfg->curr_mon,
+ cfg->friendly_boot,
+ cfg->power,
+ cfg->freq_ref,
+ cfg->sti_mem_addr));
+}
+
+static void dump_globcfg(struct sti_glob_cfg *glob_cfg)
+{
+ DPRINTK(("%d text planes\n"
+ "%4d x %4d screen resolution\n"
+ "%4d x %4d offscreen\n"
+ "%4d x %4d layout\n"
+ "regions at %08x %08x %08x %08x\n"
+ "regions at %08x %08x %08x %08x\n"
+ "reent_lvl %d\n"
+ "save_addr %p\n",
+ glob_cfg->text_planes,
+ glob_cfg->onscreen_x, glob_cfg->onscreen_y,
+ glob_cfg->offscreen_x, glob_cfg->offscreen_y,
+ glob_cfg->total_x, glob_cfg->total_y,
+ glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
+ glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
+ glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
+ glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
+ glob_cfg->reent_lvl,
+ glob_cfg->save_addr));
+ dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
+}
+#endif
+
+static void __init sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
+ unsigned long rom_address)
+{
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_glob_cfg_ext *glob_cfg_ext;
+ void *save_addr;
+ void *sti_mem_addr;
+
+ glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
+ glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
+ save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
+ sti_mem_addr = kmalloc(1024, GFP_KERNEL);
+
+ if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
+ return;
+
+ memset(glob_cfg, 0, sizeof *glob_cfg);
+ memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
+ memset(save_addr, 0, 1024);
+ memset(sti_mem_addr, 0, 1024);
+
+ glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
+ glob_cfg->save_addr = STI_PTR(save_addr);
+ glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
+ glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
+
+ glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
+
+ sti->glob_cfg = STI_PTR(glob_cfg);
+}
+
+static void __init sti_try_rom(unsigned long address, unsigned long hpa)
+{
+ struct sti_struct *sti = NULL;
+ u16 sig;
+
+ /* if we can't read the ROM, bail out early. Not being able
+ * to read the hpa is okay, for romless sti */
+ if(pdc_add_valid((void*)address))
+ return;
+
+ printk("found potential STI ROM at %08lx\n", address);
+
+ sig = le16_to_cpu(gsc_readw(address));
+
+ if((sig&0xff) == 0x01) {
+ sti = sti_read_rom(address);
+ }
+
+ if(sig == 0x0303) {
+ printk("STI word mode ROM at %08lx, ignored\n",
+ address);
+
+ sti = NULL;
+ }
+
+ if(!sti)
+ return;
+
+ /* this is hacked. We need a better way to find out the HPA for
+ * romless STI (eg search for the graphics devices we know about
+ * by sversion) */
+ if (!pdc_add_valid((void *)0xf5000000)) DPRINTK(("f4000000 b\n"));
+ if (!pdc_add_valid((void *)0xf7000000)) DPRINTK(("f6000000 b\n"));
+ if (!pdc_add_valid((void *)0xf9000000)) DPRINTK(("f8000000 b\n"));
+ if (!pdc_add_valid((void *)0xfb000000)) DPRINTK(("fa000000 b\n"));
+ sti_init_glob_cfg(sti, hpa, address);
+
+ sti_init_graph(sti);
+
+ //sti_inq_conf(sti);
+#if !defined(SERIAL_CONSOLE)
+ {
+ extern void pdc_console_die(void);
+ pdc_console_die();
+ }
+#endif
+
+ take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1);
+
+ /* sti_inq_conf(sti); */
+}
+
+static unsigned long sti_address;
+static unsigned long sti_hpa;
+
+static void __init sti_init_roms(void)
+{
+ /* handle the command line */
+ if(sti_address && sti_hpa) {
+ sti_try_rom(sti_address, sti_hpa);
+
+ return;
+ }
+
+ /* 712, 715, some other boxes don't have a separate STI ROM,
+ * but use part of the regular flash */
+ if(PAGE0->proc_sti) {
+ printk("STI ROM from PDC at %08x\n", PAGE0->proc_sti);
+ if(!pdc_add_valid((void *)0xf9000000))
+ sti_try_rom(PAGE0->proc_sti, 0xf8000000);
+ else if(!pdc_add_valid((void *)0xf5000000))
+ sti_try_rom(PAGE0->proc_sti, 0xf4000000);
+ else if(!pdc_add_valid((void *)0xf7000000))
+ sti_try_rom(PAGE0->proc_sti, 0xf6000000);
+ else if(!pdc_add_valid((void *)0xfb000000))
+ sti_try_rom(PAGE0->proc_sti, 0xfa000000);
+ }
+
+ /* standard locations for GSC graphic devices */
+ if(!pdc_add_valid((void *)0xf4000000))
+ sti_try_rom(0xf4000000, 0xf4000000);
+ if(!pdc_add_valid((void *)0xf6000000))
+ sti_try_rom(0xf6000000, 0xf6000000);
+ if(!pdc_add_valid((void *)0xf8000000))
+ sti_try_rom(0xf8000000, 0xf8000000);
+ if(!pdc_add_valid((void *)0xfa000000))
+ sti_try_rom(0xfa000000, 0xfa000000);
+}
+
+static int __init sti_init(void)
+{
+ printk("searching for byte mode STI ROMs\n");
+ sti_init_roms();
+ return 0;
+}
+
+module_init(sti_init)
diff --git a/drivers/video/sticon.c b/drivers/video/sticon.c
new file mode 100644
index 000000000..ba3f1167d
--- /dev/null
+++ b/drivers/video/sticon.c
@@ -0,0 +1,229 @@
+/*
+ * linux/drivers/video/sticon.c - console driver using HP's STI firmware
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
+ * which were
+ *
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ * Copyright (C) 1995 Geert Uytterhoeven
+ * Copyright (C) 1993 Bjoern Brauel
+ * Roman Hodek
+ * Copyright (C) 1993 Hamish Macdonald
+ * Greg Harp
+ * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
+ *
+ * with work by William Rucklidge (wjr@cs.cornell.edu)
+ * Geert Uytterhoeven
+ * Jes Sorensen (jds@kom.auc.dk)
+ * Martin Apel
+ * with work by Guenther Kelleter
+ * Martin Schaller
+ * Andreas Schwab
+ * Emmanuel Marty (core@ggi-project.org)
+ * Jakub Jelinek (jj@ultra.linux.cz)
+ * Martin Mares <mj@ucw.cz>
+ *
+ * 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.
+ */
+/*
+ * TODO:
+ * - call STI in virtual mode rather than in real mode
+ * - support for PCI-only STI ROMs (which don't have a traditional region
+ * list)
+ * - safe detection (i.e. verify there is a graphics device at a given
+ * address first, not just read a random device's io space)
+ * - support for multiple STI devices in one machine
+ * - support for byte-mode STI ROMs
+ * - support for just using STI to switch to a colour fb (stifb ?)
+ * - try to make it work on m68k hp workstations ;)
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/errno.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+
+#include <asm/io.h>
+
+#include "sti.h"
+
+/* STICON */
+
+static const char * __init
+sticon_startup(void)
+{
+ return "STI console";
+}
+
+static int
+sticon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ return -EINVAL;
+}
+static int
+sticon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
+}
+
+static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
+{
+ sti_putc(&default_sti, c, ypos, xpos);
+}
+
+static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
+ int count, int ypos, int xpos)
+{
+ while(count--) {
+ sti_putc(&default_sti, *s++, ypos, xpos++);
+ }
+}
+
+static void sticon_cursor(struct vc_data *conp, int mode)
+{
+}
+
+static int sticon_scroll(struct vc_data *conp, int t, int b, int dir,
+ int count)
+{
+ struct sti_struct *sti = &default_sti;
+
+ if(console_blanked)
+ return 0;
+
+ sticon_cursor(conp, CM_ERASE);
+
+ switch(dir) {
+ case SM_UP:
+ sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, b-count, 0, count, conp->vc_cols);
+
+ break;
+
+ case SM_DOWN:
+ sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+ sti_clear(sti, t, 0, count, conp->vc_cols);
+
+ break;
+ }
+
+ return 0;
+}
+
+static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ sti_bmove(&default_sti, sy, sx, dy, dx, height, width);
+}
+
+static void sticon_init(struct vc_data *c, int init)
+{
+ struct sti_struct *sti = &default_sti;
+ int vc_cols, vc_rows;
+
+ sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
+ c->vc_can_do_color = 1;
+ vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti);
+ vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti);
+
+ vc_resize_con(vc_rows, vc_cols, c->vc_num);
+}
+
+static void sticon_deinit(struct vc_data *c)
+{
+}
+
+static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
+ int width)
+{
+ sti_clear(&default_sti, sy, sx, height, width);
+}
+
+static int sticon_switch(struct vc_data *conp)
+{
+ return 0;
+}
+
+static int sticon_blank(struct vc_data *conp, int blank)
+{
+ return 0;
+}
+
+static int sticon_scrolldelta(struct vc_data *conp, int lines)
+{
+ return 0;
+}
+
+static int sticon_set_origin(struct vc_data *conp)
+{
+ return 0;
+}
+
+static u16 *sticon_screen_pos(struct vc_data *conp, int offset)
+{
+ return NULL;
+}
+
+static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py)
+{
+ return 0;
+}
+
+static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse)
+{
+ u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+
+ if(reverse) {
+ color = ((color>>3)&0x7) | ((color &0x7)<<3);
+ }
+
+
+ return attr;
+}
+
+struct consw sti_con = {
+ con_startup: sticon_startup,
+ con_init: sticon_init,
+ con_deinit: sticon_deinit,
+ con_clear: sticon_clear,
+ con_putc: sticon_putc,
+ con_putcs: sticon_putcs,
+ con_cursor: sticon_cursor,
+ con_scroll: sticon_scroll,
+ con_bmove: sticon_bmove,
+ con_switch: sticon_switch,
+ con_blank: sticon_blank,
+ con_font_op: sticon_font_op,
+ con_set_palette: sticon_set_palette,
+ con_scrolldelta: sticon_scrolldelta,
+ con_set_origin: sticon_set_origin,
+ con_save_screen: NULL,
+ con_build_attr: sticon_build_attr,
+ con_invert_region: NULL,
+ con_screen_pos: sticon_screen_pos,
+ con_getxy: sticon_getxy,
+};
+
+static int __init sti_init(void)
+{
+ printk("searching for word mode STI ROMs\n");
+ if (sti_init_roms()) {
+ pdc_console_die();
+ take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1);
+ return 0;
+ } else
+ return -ENODEV;
+}
+
+module_init(sti_init)
diff --git a/drivers/video/sticore.c b/drivers/video/sticore.c
new file mode 100644
index 000000000..56e7f43ce
--- /dev/null
+++ b/drivers/video/sticore.c
@@ -0,0 +1,598 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+
+#include "sti.h"
+
+struct sti_struct default_sti = {
+ SPIN_LOCK_UNLOCKED,
+};
+
+static struct sti_font_flags default_font_flags = {
+ STI_WAIT, 0, 0, NULL
+};
+
+/* The colour indices used by STI are
+ * 0 - Black
+ * 1 - White
+ * 2 - Red
+ * 3 - Yellow/Brown
+ * 4 - Green
+ * 5 - Cyan
+ * 6 - Blue
+ * 7 - Magenta
+ *
+ * So we have the same colours as VGA (basically one bit each for R, G, B),
+ * but have to translate them, anyway. */
+
+static u8 col_trans[8] = {
+ 0, 6, 4, 5,
+ 2, 7, 3, 1
+};
+
+#define c_fg(sti, c) col_trans[((c>> 8) & 7)]
+#define c_bg(sti, c) col_trans[((c>>11) & 7)]
+#define c_index(sti, c) (c&0xff)
+
+static struct sti_init_flags default_init_flags = {
+ STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
+};
+
+void
+sti_init_graph(struct sti_struct *sti)
+{
+ struct sti_init_inptr_ext inptr_ext = {
+ 0, { 0 }, 0, NULL
+ };
+ struct sti_init_inptr inptr = {
+ 3, STI_PTR(&inptr_ext)
+ };
+ struct sti_init_outptr outptr = { 0 };
+ unsigned long flags;
+ s32 ret;
+
+ spin_lock_irqsave(&sti->lock, flags);
+
+ ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
+ &outptr, sti->glob_cfg);
+
+ spin_unlock_irqrestore(&sti->lock, flags);
+
+ sti->text_planes = outptr.text_planes;
+}
+
+static struct sti_conf_flags default_conf_flags = {
+ STI_WAIT, 0, NULL
+};
+
+void
+sti_inq_conf(struct sti_struct *sti)
+{
+ struct sti_conf_inptr inptr = { NULL };
+ struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };
+ struct sti_conf_outptr outptr = {
+ ext_ptr: STI_PTR(&outptr_ext)
+ };
+ unsigned long flags;
+ s32 ret;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->inq_conf, &default_conf_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+void
+sti_putc(struct sti_struct *sti, int c, int y, int x)
+{
+ struct sti_font_inptr inptr = {
+ (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
+ x * sti_font_x(sti), y * sti_font_y(sti), NULL
+ };
+ struct sti_font_outptr outptr = {
+ 0, NULL
+ };
+ s32 ret;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->font_unpmv, &default_font_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags clear_blkmv_flags = {
+ STI_WAIT, 1, 1, 0, 0, NULL
+};
+
+void
+sti_set(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width, u8 color)
+{
+ struct sti_blkmv_inptr inptr = {
+ color, color,
+ src_x, src_y ,
+ src_x, src_y ,
+ width, height,
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+void
+sti_clear(struct sti_struct *sti, int src_y, int src_x,
+ int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+static struct sti_blkmv_flags default_blkmv_flags = {
+ STI_WAIT, 0, 0, 0, 0, NULL
+};
+
+void
+sti_bmove(struct sti_struct *sti, int src_y, int src_x,
+ int dst_y, int dst_x, int height, int width)
+{
+ struct sti_blkmv_inptr inptr = {
+ 0, 0,
+ src_x * sti_font_x(sti), src_y * sti_font_y(sti),
+ dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
+ width * sti_font_x(sti), height* sti_font_y(sti),
+ NULL
+ };
+ struct sti_blkmv_outptr outptr = { 0, NULL };
+ s32 ret = 0;
+ unsigned long flags;
+
+ do {
+ spin_lock_irqsave(&sti->lock, flags);
+ ret = STI_CALL(sti->block_move, &default_blkmv_flags,
+ &inptr, &outptr, sti->glob_cfg);
+ spin_unlock_irqrestore(&sti->lock, flags);
+ } while(ret == 1);
+}
+
+
+static void __init
+sti_rom_copy(unsigned long base, unsigned long offset,
+ unsigned long count, void *dest)
+{
+ void *savedest = dest;
+ int savecount = count;
+
+ while(count >= 4) {
+ count -= 4;
+ *(u32 *)dest = gsc_readl(base + offset);
+ offset += 4;
+ dest += 4;
+ }
+ while(count) {
+ count--;
+ *(u8 *)dest = gsc_readb(base + offset);
+ offset++;
+ dest++;
+ }
+ __flush_dcache_range((unsigned long) dest, count);
+ __flush_icache_range((unsigned long) dest, count);
+}
+
+static void dump_sti_rom(struct sti_rom *rom)
+{
+ printk("STI word mode ROM type %d\n", rom->type[3]);
+ printk(" supports %d monitors\n", rom->num_mons);
+ printk(" conforms to STI ROM spec revision %d.%02x\n",
+ rom->revno[0] >> 4, rom->revno[0] & 0x0f);
+ printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ rom->graphics_id[0],
+ rom->graphics_id[1],
+ rom->graphics_id[2],
+ rom->graphics_id[3],
+ rom->graphics_id[4],
+ rom->graphics_id[5],
+ rom->graphics_id[6],
+ rom->graphics_id[7]);
+ printk(" font start %08x\n", rom->font_start);
+ printk(" region list %08x\n", rom->region_list);
+ printk(" init_graph %08x\n", rom->init_graph);
+ printk(" alternate code type %d\n", rom->alt_code_type);
+}
+
+static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
+ struct sti_rom *raw_rom)
+{
+ struct sti_rom_font *raw_font;
+ struct sti_cooked_font *cooked_font;
+ struct sti_rom_font *font_start;
+
+ cooked_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font)
+ return;
+
+ cooked_rom->font_start = cooked_font;
+
+ raw_font = ((void *)raw_rom) + (raw_rom->font_start);
+
+ font_start = raw_font;
+ cooked_font->raw = raw_font;
+
+ while(raw_font->next_font) {
+ raw_font = ((void *)font_start) + (raw_font->next_font);
+
+ cooked_font->next_font =
+ kmalloc(sizeof *cooked_font, GFP_KERNEL);
+ if(!cooked_font->next_font)
+ return;
+
+ cooked_font = cooked_font->next_font;
+
+ cooked_font->raw = raw_font;
+ }
+
+ cooked_font->next_font = NULL;
+}
+
+static int font_index, font_height, font_width;
+
+static int __init sti_font_setup(char *str)
+{
+ char *x;
+
+ /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
+ * command lines. */
+
+ if((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
+ font_height = simple_strtoul(str, NULL, 0);
+ font_width = simple_strtoul(x+1, NULL, 0);
+ } else {
+ font_index = simple_strtoul(str, NULL, 0);
+ }
+
+ return 0;
+}
+
+__setup("sti_font=", sti_font_setup);
+
+static int __init sti_search_font(struct sti_cooked_rom *rom,
+ int height, int width)
+{
+ struct sti_cooked_font *font;
+ int i = 0;
+
+ for(font = rom->font_start; font; font = font->next_font, i++) {
+ if((font->raw->width == width) && (font->raw->height == height))
+ return i;
+ }
+
+ return 0;
+}
+
+static struct sti_cooked_font * __init
+sti_select_font(struct sti_cooked_rom *rom)
+{
+ struct sti_cooked_font *font;
+ int i;
+
+ if(font_width && font_height)
+ font_index = sti_search_font(rom, font_height, font_width);
+
+ for(font = rom->font_start, i = font_index;
+ font && (i > 0);
+ font = font->next_font, i--);
+
+ if(font)
+ return font;
+ else
+ return rom->font_start;
+}
+
+static void __init
+sti_dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
+{
+ printk( "monitor %d\n"
+ "in friendly mode: %d\n"
+ "power consumption %d watts\n"
+ "freq ref %d\n"
+ "sti_mem_addr %p\n",
+ cfg->curr_mon,
+ cfg->friendly_boot,
+ cfg->power,
+ cfg->freq_ref,
+ cfg->sti_mem_addr);
+}
+
+void __init
+sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
+{
+ printk( "%d text planes\n"
+ "%4d x %4d screen resolution\n"
+ "%4d x %4d offscreen\n"
+ "%4d x %4d layout\n"
+ "regions at %08x %08x %08x %08x\n"
+ "regions at %08x %08x %08x %08x\n"
+ "reent_lvl %d\n"
+ "save_addr %p\n",
+ glob_cfg->text_planes,
+ glob_cfg->onscreen_x, glob_cfg->onscreen_y,
+ glob_cfg->offscreen_x, glob_cfg->offscreen_y,
+ glob_cfg->total_x, glob_cfg->total_y,
+ glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
+ glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
+ glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
+ glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
+ glob_cfg->reent_lvl,
+ glob_cfg->save_addr);
+ sti_dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
+}
+
+static void __init
+sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
+ unsigned long rom_address)
+{
+ struct sti_glob_cfg *glob_cfg;
+ struct sti_glob_cfg_ext *glob_cfg_ext;
+ void *save_addr;
+ void *sti_mem_addr;
+
+ glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
+ glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
+ save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
+ sti_mem_addr = kmalloc(1024, GFP_KERNEL);
+
+ if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
+ return;
+
+ memset(glob_cfg, 0, sizeof *glob_cfg);
+ memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
+ memset(save_addr, 0, 1024);
+ memset(sti_mem_addr, 0, 1024);
+
+ glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
+ glob_cfg->save_addr = STI_PTR(save_addr);
+ glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
+ glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
+ glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
+
+ glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
+
+ sti->glob_cfg = STI_PTR(glob_cfg);
+}
+
+/* address is a pointer to a word mode or pci rom */
+static struct sti_struct * __init
+sti_read_rom(unsigned long address)
+{
+ struct sti_struct *ret = NULL;
+ struct sti_cooked_rom *cooked = NULL;
+ struct sti_rom *raw = NULL;
+ unsigned long size;
+
+ ret = &default_sti;
+
+ if(!ret)
+ goto out_err;
+
+ cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
+ raw = kmalloc(sizeof *raw, GFP_KERNEL);
+
+ if(!(raw && cooked))
+ goto out_err;
+
+ /* reallocate raw */
+ sti_rom_copy(address, 0, sizeof *raw, raw);
+
+ dump_sti_rom(raw);
+
+ size = raw->last_addr;
+ /* kfree(raw); */
+ raw = kmalloc(size, GFP_KERNEL);
+ if(!raw)
+ goto out_err;
+ sti_rom_copy(address, 0, size, raw);
+
+ sti_cook_fonts(cooked, raw);
+#if 0
+ sti_cook_regions(cooked, raw);
+ sti_cook_functions(cooked, raw);
+#endif
+
+ if(raw->region_list) {
+ ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME */
+
+ memcpy(ret->regions, ((void *)raw)+raw->region_list, 32);
+ }
+
+ address = virt_to_phys(raw);
+
+ ret->font_unpmv = address+(raw->font_unpmv & 0x03ffffff);
+ ret->block_move = address+(raw->block_move & 0x03ffffff);
+ ret->init_graph = address+(raw->init_graph & 0x03ffffff);
+ ret->inq_conf = address+(raw->inq_conf & 0x03ffffff);
+
+ ret->rom = cooked;
+ ret->rom->raw = raw;
+
+ ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
+
+ return ret;
+
+out_err:
+ if(raw)
+ kfree(raw);
+ if(cooked)
+ kfree(cooked);
+
+ return NULL;
+}
+
+static struct sti_struct * __init
+sti_try_rom(unsigned long address, unsigned long hpa)
+{
+ struct sti_struct *sti = NULL;
+ u16 sig;
+
+test_rom:
+ /* if we can't read the ROM, bail out early. Not being able
+ * to read the hpa is okay, for romless sti */
+ if(pdc_add_valid((void*)address))
+ return NULL;
+
+ printk("found potential STI ROM at %08lx\n", address);
+
+ sig = le16_to_cpu(gsc_readw(address));
+
+ if((sig==0x55aa) || (sig==0xaa55)) {
+ address += le32_to_cpu(gsc_readl(address+8));
+ printk("sig %04x, PCI STI ROM at %08lx\n",
+ sig, address);
+
+ goto test_rom;
+ }
+
+ if((sig&0xff) == 0x01) {
+ printk("STI byte mode ROM at %08lx, ignored\n",
+ address);
+
+ sti = NULL;
+ }
+
+ if(sig == 0x0303) {
+ printk("STI word mode ROM at %08lx\n",
+ address);
+
+ sti = sti_read_rom(address);
+ }
+
+ if (!sti)
+ return NULL;
+
+ /* this is hacked. We need a better way to find out the HPA for
+ * romless STI (eg search for the graphics devices we know about
+ * by sversion) */
+ if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 g\n");
+ if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 g\n");
+ if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 g\n");
+ if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 g\n");
+ sti_init_glob_cfg(sti, hpa, address);
+
+ sti_init_graph(sti);
+
+ sti_inq_conf(sti);
+ sti_dump_globcfg(PTR_STI(sti->glob_cfg));
+
+ return sti;
+}
+
+static unsigned long sti_address;
+static unsigned long sti_hpa;
+
+/* XXX: should build a list of STI ROMs */
+struct sti_struct * __init
+sti_init_roms(void)
+{
+ struct sti_struct *tmp = NULL, *sti = NULL;
+
+ /* handle the command line */
+ if (sti_address && sti_hpa) {
+ return sti_try_rom(sti_address, sti_hpa);
+ }
+
+ /* 712, 715, some other boxes don't have a separate STI ROM,
+ * but use part of the regular flash */
+ if (PAGE0->proc_sti) {
+ printk("STI ROM from PDC at %08x\n", PAGE0->proc_sti);
+ if (!pdc_add_valid((void *)0xf9000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xf8000000);
+ else if (!pdc_add_valid((void *)0xf5000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xf4000000);
+ else if (!pdc_add_valid((void *)0xf7000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xf6000000);
+ else if (!pdc_add_valid((void *)0xfb000000))
+ sti = sti_try_rom(PAGE0->proc_sti, 0xfa000000);
+
+ }
+
+ /* standard locations for GSC graphic devices */
+ if (!pdc_add_valid((void *)0xf4000000))
+ tmp = sti_try_rom(0xf4000000, 0xf4000000);
+ sti = tmp ? tmp : sti;
+ if (!pdc_add_valid((void *)0xf6000000))
+ tmp = sti_try_rom(0xf6000000, 0xf6000000);
+ sti = tmp ? tmp : sti;
+ if (!pdc_add_valid((void *)0xf8000000))
+ tmp = sti_try_rom(0xf8000000, 0xf8000000);
+ sti = tmp ? tmp : sti;
+ if (!pdc_add_valid((void *)0xfa000000))
+ tmp = sti_try_rom(0xfa000000, 0xfa000000);
+ sti = tmp ? tmp : sti;
+
+ return sti;
+}
+
+static int __init
+sti_setup(char *str)
+{
+ char *end;
+
+ if(strcmp(str, "pdc") == 0) {
+ sti_address = PAGE0->proc_sti;
+
+ return 1;
+ } else {
+ sti_address = simple_strtoul(str, &end, 16);
+
+ if((end == str) || (sti_address < 0xf0000000)) {
+ sti_address = 0;
+ return 0;
+ }
+
+ sti_hpa = sti_address;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+__setup("sti=", sti_setup);
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
new file mode 100644
index 000000000..661ff29c5
--- /dev/null
+++ b/drivers/video/stifb.c
@@ -0,0 +1,230 @@
+/*
+ * linux/drivers/video/stifb.c - Generic frame buffer driver for HP
+ * workstations with STI (standard text interface) video firmware.
+ *
+ * Based on:
+ * linux/drivers/video/artistfb.c -- Artist frame buffer driver
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * based on skeletonfb, which was
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * 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. */
+
+/*
+ * Notes:
+ *
+ * This driver assumes that the video has been set up in 1bpp mode by
+ * the firmware. Since HP video tends to be planar rather than
+ * packed-pixel this will probably work anyway even if it isn't.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include <video/fbcon.h>
+
+#include "sti.h"
+
+static struct fb_ops stifb_ops;
+
+struct stifb_info {
+ struct fb_info_gen gen;
+ struct sti_struct *sti;
+};
+
+struct stifb_par {
+};
+
+static struct stifb_info fb_info;
+static struct display disp;
+
+int stifb_init(void);
+int stifb_setup(char*);
+
+extern struct display_switch fbcon_sti;
+
+/* ------------------- chipset specific functions -------------------------- */
+
+static int
+sti_encode_fix(struct fb_fix_screeninfo *fix,
+ const void *par, struct fb_info_gen *info)
+{
+ /* XXX: what about smem_len? */
+ fix->smem_start = PTR_STI(fb_info.sti->glob_cfg)->region_ptrs[1];
+ fix->type = FB_TYPE_PLANES; /* well, sort of */
+
+ return 0;
+}
+
+static int
+sti_decode_var(const struct fb_var_screeninfo *var,
+ void *par, struct fb_info_gen *info)
+{
+ return 0;
+}
+
+static int
+sti_encode_var(struct fb_var_screeninfo *var,
+ const void *par, struct fb_info_gen *info)
+{
+ var->xres = PTR_STI(fb_info.sti->glob_cfg)->onscreen_x;
+ var->yres = PTR_STI(fb_info.sti->glob_cfg)->onscreen_y;
+ var->xres_virtual = PTR_STI(fb_info.sti->glob_cfg)->total_x;
+ var->yres_virtual = PTR_STI(fb_info.sti->glob_cfg)->total_y;
+ var->xoffset = var->yoffset = 0;
+
+ var->bits_per_pixel = 1;
+ var->grayscale = 0;
+
+ return 0;
+}
+
+static void
+sti_get_par(void *par, struct fb_info_gen *info)
+{
+}
+
+static void
+sti_set_par(const void *par, struct fb_info_gen *info)
+{
+}
+
+static int
+sti_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp, struct fb_info *info)
+{
+ return 0;
+}
+
+static int
+sti_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ return 0;
+}
+
+static void
+sti_set_disp(const void *par, struct display *disp,
+ struct fb_info_gen *info)
+{
+ disp->screen_base =
+ (void *) PTR_STI(fb_info.sti->glob_cfg)->region_ptrs[1];
+ disp->dispsw = &fbcon_sti;
+}
+
+static void
+sti_detect(void)
+{
+}
+
+static int
+sti_blank(int blank_mode, const struct fb_info *info)
+{
+ return 0;
+}
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+struct fbgen_hwswitch sti_switch = {
+ detect: sti_detect,
+ encode_fix: sti_encode_fix,
+ decode_var: sti_decode_var,
+ encode_var: sti_encode_var,
+ get_par: sti_get_par,
+ set_par: sti_set_par,
+ getcolreg: sti_getcolreg,
+ setcolreg: sti_setcolreg,
+ pan_display: NULL,
+ blank: sti_blank,
+ set_disp: sti_set_disp
+};
+
+
+/* ------------ Hardware Independent Functions ------------ */
+
+ /*
+ * Initialization
+ */
+
+int __init
+stifb_init(void)
+{
+ printk("searching for word mode STI ROMs\n");
+ /* XXX: in the future this will return a list of ROMs */
+ if ((fb_info.sti = sti_init_roms()) == NULL)
+ return -ENXIO;
+
+ fb_info.gen.info.node = -1;
+ fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+ fb_info.gen.info.fbops = &stifb_ops;
+ fb_info.gen.info.disp = &disp;
+ fb_info.gen.info.changevar = NULL;
+ fb_info.gen.info.switch_con = &fbgen_switch;
+ fb_info.gen.info.updatevar = &fbgen_update_var;
+ fb_info.gen.info.blank = &fbgen_blank;
+ strcpy(fb_info.gen.info.modename, "STI Generic");
+ fb_info.gen.fbhw = &sti_switch;
+ fb_info.gen.fbhw->detect();
+
+ /* This should give a reasonable default video mode */
+ fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+ fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+ pdc_console_die();
+ if (register_framebuffer(&fb_info.gen.info) < 0)
+ return -EINVAL;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
+
+ return 0;
+}
+
+
+ /*
+ * Cleanup
+ */
+
+void
+stifb_cleanup(struct fb_info *info)
+{
+ printk("stifb_cleanup: you're on crack\n");
+}
+
+
+int __init
+stifb_setup(char *options)
+{
+ /* XXX: we should take the resolution, bpp as command line arguments. */
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static struct fb_ops stifb_ops = {
+ owner: THIS_MODULE,
+ fb_open: NULL,
+ fb_release: NULL,
+ fb_get_fix: fbgen_get_fix,
+ fb_get_var: fbgen_get_var,
+ fb_set_var: fbgen_set_var,
+ fb_get_cmap: fbgen_get_cmap,
+ fb_set_cmap: fbgen_set_cmap,
+ fb_pan_display: fbgen_pan_display,
+ fb_ioctl: NULL
+};
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 4128c313e..d954dc02e 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -327,7 +327,6 @@ struct fb_info_tdfx {
struct tdfxfb_par default_par;
struct tdfxfb_par current_par;
struct display disp;
- struct display_switch dispsw;
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
union {
#ifdef FBCON_HAS_CFB16
@@ -412,10 +411,10 @@ static int tdfxfb_encode_var(struct fb_var_screeninfo* var,
static int tdfxfb_encode_fix(struct fb_fix_screeninfo* fix,
const struct tdfxfb_par* par,
const struct fb_info_tdfx* info);
-static void tdfxfb_set_disp(struct display* disp,
- struct fb_info_tdfx* info,
- int bpp,
- int accel);
+static void tdfxfb_set_dispsw(struct display* disp,
+ struct fb_info_tdfx* info,
+ int bpp,
+ int accel);
static int tdfxfb_getcolreg(u_int regno,
u_int* red,
u_int* green,
@@ -1640,48 +1639,43 @@ static int tdfxfb_get_var(struct fb_var_screeninfo *var,
return 0;
}
-static void tdfxfb_set_disp(struct display *disp,
- struct fb_info_tdfx *info,
- int bpp,
- int accel) {
+static void tdfxfb_set_dispsw(struct display *disp,
+ struct fb_info_tdfx *info,
+ int bpp,
+ int accel) {
if (disp->dispsw && disp->conp)
fb_con.con_cursor(disp->conp, CM_ERASE);
switch(bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
- info->dispsw = noaccel ? fbcon_cfb8 : fbcon_banshee8;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb8 : &fbcon_banshee8;
if (nohwcursor) fbcon_banshee8.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
- info->dispsw = noaccel ? fbcon_cfb16 : fbcon_banshee16;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb16 : &fbcon_banshee16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
if (nohwcursor) fbcon_banshee16.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
- info->dispsw = noaccel ? fbcon_cfb24 : fbcon_banshee24;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb24 : &fbcon_banshee24;
disp->dispsw_data = info->fbcon_cmap.cfb24;
if (nohwcursor) fbcon_banshee24.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
- info->dispsw = noaccel ? fbcon_cfb32 : fbcon_banshee32;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = noaccel ? &fbcon_cfb32 : &fbcon_banshee32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
if (nohwcursor) fbcon_banshee32.cursor = NULL;
break;
#endif
default:
- info->dispsw = fbcon_dummy;
- disp->dispsw = &info->dispsw;
+ disp->dispsw = &fbcon_dummy;
}
}
@@ -1735,7 +1729,7 @@ static int tdfxfb_set_var(struct fb_var_screeninfo *var,
display->can_soft_blank = 1;
display->inverse = inverse;
accel = var->accel_flags & FB_ACCELF_TEXT;
- tdfxfb_set_disp(display, info, par.bpp, accel);
+ tdfxfb_set_dispsw(display, info, par.bpp, accel);
if(nopan) display->scrollmode = SCROLL_YREDRAW;
@@ -2083,10 +2077,10 @@ static int tdfxfb_switch_con(int con,
info->cursor.redraw=1;
- tdfxfb_set_disp(&fb_display[con],
- info,
- par.bpp,
- par.accel_flags & FB_ACCELF_TEXT);
+ tdfxfb_set_dispsw(&fb_display[con],
+ info,
+ par.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
tdfxfb_install_cmap(&fb_display[con], fb);
tdfxfb_updatevar(con, fb);
diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c
index e48c0f458..6268b1766 100644
--- a/drivers/video/vgacon.c
+++ b/drivers/video/vgacon.c
@@ -11,7 +11,7 @@
* 1995 Jay Estabrook
*
* User definable mapping table and font loading by Eugene G. Crosser,
- * <crosser@pccross.msk.su>
+ * <crosser@average.org>
*
* Improved loadable font/UTF-8 support by H. Peter Anvin
* Feb-Sep 1995 <peter.anvin@linux.org>