]> git.hungrycats.org Git - linux/commitdiff
[FRAMEBUFFER]: Convert creatorfb to new APIs.
authorDavid S. Miller <davem@nuts.ninka.net>
Wed, 26 Feb 2003 20:20:25 +0000 (12:20 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Wed, 26 Feb 2003 20:20:25 +0000 (12:20 -0800)
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/creatorfb.c [deleted file]
drivers/video/fbmem.c
drivers/video/ffb.c [new file with mode: 0644]
drivers/video/sbusfb.c [deleted file]
drivers/video/sbuslib.c [new file with mode: 0644]
drivers/video/sbuslib.h [new file with mode: 0644]
include/video/sbusfb.h [deleted file]

index 4e875ace621b03c81130ffccd0feb9c771c87882..39edc0c2b2e40ef6455281708387c48d0dba8e67 100644 (file)
@@ -809,12 +809,12 @@ config FB_SBUS
        help
          Say Y if you want support for SBUS or UPA based frame buffer device.
 
-config FB_CREATOR
-       bool "Creator/Creator3D support"
+config FB_FFB
+       bool "Creator/Creator3D/Elite3D support"
        depends on FB_SBUS && SPARC64
        help
-         This is the frame buffer device driver for the Creator and Creator3D
-         graphics boards.
+         This is the frame buffer device driver for the Creator, Creator3D,
+         and Elite3D graphics boards.
 
 config FB_TCX
        bool "TCX (SS4/SS5 only) support"
index c7a80836286c3e995d7f3afd731d9b94dce7f834..b5fb29910e69da079c8263b3a13697eb2280a1ab 100644 (file)
@@ -48,14 +48,6 @@ obj-$(CONFIG_FB_VGA16)            += vga16fb.o cfbfillrect.o cfbcopyarea.o \
 obj-$(CONFIG_FB_VIRGE)            += virgefb.o
 obj-$(CONFIG_FB_G364)             += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CREATOR)          += creatorfb.o sbusfb.o
-obj-$(CONFIG_FB_CGSIX)            += cgsixfb.o sbusfb.o
-obj-$(CONFIG_FB_BWTWO)            += bwtwofb.o sbusfb.o
-obj-$(CONFIG_FB_CGTHREE)          += cgthreefb.o sbusfb.o
-obj-$(CONFIG_FB_TCX)              += tcxfb.o sbusfb.o
-obj-$(CONFIG_FB_CGFOURTEEN)       += cgfourteenfb.o sbusfb.o
-obj-$(CONFIG_FB_P9100)            += p9100fb.o sbusfb.o
-obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
 obj-$(CONFIG_FB_STI)              += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PMAG_BA)          += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PMAGB_B)          += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
@@ -78,6 +70,18 @@ obj-$(CONFIG_FB_E1355)            += epson1355fb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
+# One by one these are being converted over to the new APIs
+#obj-$(CONFIG_FB_CREATOR)          += creatorfb.o sbusfb.o
+#obj-$(CONFIG_FB_CGSIX)            += cgsixfb.o sbusfb.o
+#obj-$(CONFIG_FB_BWTWO)            += bwtwofb.o sbusfb.o
+#obj-$(CONFIG_FB_CGTHREE)          += cgthreefb.o sbusfb.o
+#obj-$(CONFIG_FB_TCX)              += tcxfb.o sbusfb.o
+#obj-$(CONFIG_FB_CGFOURTEEN)       += cgfourteenfb.o sbusfb.o
+#obj-$(CONFIG_FB_P9100)            += p9100fb.o sbusfb.o
+#obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
+
+obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+
 # Files generated that shall be removed upon make clean
 clean-files := promcon_tbl.c
 
diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c
deleted file mode 100644 (file)
index 7a72397..0000000
+++ /dev/null
@@ -1,928 +0,0 @@
-/* $Id: creatorfb.c,v 1.37 2001/10/16 05:44:44 davem Exp $
- * creatorfb.c: Creator/Creator3D frame buffer driver
- *
- * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-
-#include <asm/upa.h>
-
-#define        FFB_SFB8R_VOFF          0x00000000
-#define        FFB_SFB8G_VOFF          0x00400000
-#define        FFB_SFB8B_VOFF          0x00800000
-#define        FFB_SFB8X_VOFF          0x00c00000
-#define        FFB_SFB32_VOFF          0x01000000
-#define        FFB_SFB64_VOFF          0x02000000
-#define        FFB_FBC_REGS_VOFF       0x04000000
-#define        FFB_BM_FBC_REGS_VOFF    0x04002000
-#define        FFB_DFB8R_VOFF          0x04004000
-#define        FFB_DFB8G_VOFF          0x04404000
-#define        FFB_DFB8B_VOFF          0x04804000
-#define        FFB_DFB8X_VOFF          0x04c04000
-#define        FFB_DFB24_VOFF          0x05004000
-#define        FFB_DFB32_VOFF          0x06004000
-#define        FFB_DFB422A_VOFF        0x07004000      /* DFB 422 mode write to A */
-#define        FFB_DFB422AD_VOFF       0x07804000      /* DFB 422 mode with line doubling */
-#define        FFB_DFB24B_VOFF         0x08004000      /* DFB 24bit mode write to B */
-#define        FFB_DFB422B_VOFF        0x09004000      /* DFB 422 mode write to B */
-#define        FFB_DFB422BD_VOFF       0x09804000      /* DFB 422 mode with line doubling */
-#define        FFB_SFB16Z_VOFF         0x0a004000      /* 16bit mode Z planes */
-#define        FFB_SFB8Z_VOFF          0x0a404000      /* 8bit mode Z planes */
-#define        FFB_SFB422_VOFF         0x0ac04000      /* SFB 422 mode write to A/B */
-#define        FFB_SFB422D_VOFF        0x0b404000      /* SFB 422 mode with line doubling */
-#define        FFB_FBC_KREGS_VOFF      0x0bc04000
-#define        FFB_DAC_VOFF            0x0bc06000
-#define        FFB_PROM_VOFF           0x0bc08000
-#define        FFB_EXP_VOFF            0x0bc18000
-
-#define        FFB_SFB8R_POFF          0x04000000UL
-#define        FFB_SFB8G_POFF          0x04400000UL
-#define        FFB_SFB8B_POFF          0x04800000UL
-#define        FFB_SFB8X_POFF          0x04c00000UL
-#define        FFB_SFB32_POFF          0x05000000UL
-#define        FFB_SFB64_POFF          0x06000000UL
-#define        FFB_FBC_REGS_POFF       0x00600000UL
-#define        FFB_BM_FBC_REGS_POFF    0x00600000UL
-#define        FFB_DFB8R_POFF          0x01000000UL
-#define        FFB_DFB8G_POFF          0x01400000UL
-#define        FFB_DFB8B_POFF          0x01800000UL
-#define        FFB_DFB8X_POFF          0x01c00000UL
-#define        FFB_DFB24_POFF          0x02000000UL
-#define        FFB_DFB32_POFF          0x03000000UL
-#define        FFB_FBC_KREGS_POFF      0x00610000UL
-#define        FFB_DAC_POFF            0x00400000UL
-#define        FFB_PROM_POFF           0x00000000UL
-#define        FFB_EXP_POFF            0x00200000UL
-#define FFB_DFB422A_POFF       0x09000000UL
-#define FFB_DFB422AD_POFF      0x09800000UL
-#define FFB_DFB24B_POFF                0x0a000000UL
-#define FFB_DFB422B_POFF       0x0b000000UL
-#define FFB_DFB422BD_POFF      0x0b800000UL
-#define FFB_SFB16Z_POFF                0x0c800000UL
-#define FFB_SFB8Z_POFF         0x0c000000UL
-#define FFB_SFB422_POFF                0x0d000000UL
-#define FFB_SFB422D_POFF       0x0d800000UL
-
-/* Draw operations */
-#define FFB_DRAWOP_DOT         0x00
-#define FFB_DRAWOP_AADOT       0x01
-#define FFB_DRAWOP_BRLINECAP   0x02
-#define FFB_DRAWOP_BRLINEOPEN  0x03
-#define FFB_DRAWOP_DDLINE      0x04
-#define FFB_DRAWOP_AALINE      0x05
-#define FFB_DRAWOP_TRIANGLE    0x06
-#define FFB_DRAWOP_POLYGON     0x07
-#define FFB_DRAWOP_RECTANGLE   0x08
-#define FFB_DRAWOP_FASTFILL    0x09
-#define FFB_DRAWOP_BCOPY       0x0a
-#define FFB_DRAWOP_VSCROLL     0x0b
-
-/* Pixel processor control */
-/* Force WID */
-#define FFB_PPC_FW_DISABLE     0x800000
-#define FFB_PPC_FW_ENABLE      0xc00000
-/* Auxiliary clip */
-#define FFB_PPC_ACE_DISABLE    0x040000
-#define FFB_PPC_ACE_AUX_SUB    0x080000
-#define FFB_PPC_ACE_AUX_ADD    0x0c0000
-/* Depth cue */
-#define FFB_PPC_DCE_DISABLE    0x020000
-#define FFB_PPC_DCE_ENABLE     0x030000
-/* Alpha blend */
-#define FFB_PPC_ABE_DISABLE    0x008000
-#define FFB_PPC_ABE_ENABLE     0x00c000
-/* View clip */
-#define FFB_PPC_VCE_DISABLE    0x001000
-#define FFB_PPC_VCE_2D         0x002000
-#define FFB_PPC_VCE_3D         0x003000
-/* Area pattern */
-#define FFB_PPC_APE_DISABLE    0x000800
-#define FFB_PPC_APE_ENABLE     0x000c00
-/* Transparent background */
-#define FFB_PPC_TBE_OPAQUE     0x000200
-#define FFB_PPC_TBE_TRANSPARENT        0x000300
-/* Z source */
-#define FFB_PPC_ZS_VAR         0x000080
-#define FFB_PPC_ZS_CONST       0x0000c0
-/* Y source */
-#define FFB_PPC_YS_VAR         0x000020
-#define FFB_PPC_YS_CONST       0x000030
-/* X source */
-#define FFB_PPC_XS_WID         0x000004
-#define FFB_PPC_XS_VAR         0x000008
-#define FFB_PPC_XS_CONST       0x00000c
-/* Color (BGR) source */
-#define FFB_PPC_CS_VAR         0x000002
-#define FFB_PPC_CS_CONST       0x000003
-
-#define FFB_ROP_NEW                  0x83
-
-#define FFB_UCSR_FIFO_MASK     0x00000fff
-#define FFB_UCSR_FB_BUSY       0x01000000
-#define FFB_UCSR_RP_BUSY       0x02000000
-#define FFB_UCSR_ALL_BUSY      (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
-#define FFB_UCSR_READ_ERR      0x40000000
-#define FFB_UCSR_FIFO_OVFL     0x80000000
-#define FFB_UCSR_ALL_ERRORS    (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
-
-struct ffb_fbc {
-       /* Next vertex registers */
-       u32             xxx1[3];
-       volatile u32    alpha;
-       volatile u32    red;
-       volatile u32    green;
-       volatile u32    blue;
-       volatile u32    depth;
-       volatile u32    y;
-       volatile u32    x;
-       u32             xxx2[2];
-       volatile u32    ryf;
-       volatile u32    rxf;
-       u32             xxx3[2];
-       
-       volatile u32    dmyf;
-       volatile u32    dmxf;
-       u32             xxx4[2];
-       volatile u32    ebyi;
-       volatile u32    ebxi;
-       u32             xxx5[2];
-       volatile u32    by;
-       volatile u32    bx;
-       u32             dy;
-       u32             dx;
-       volatile u32    bh;
-       volatile u32    bw;
-       u32             xxx6[2];
-       
-       u32             xxx7[32];
-       
-       /* Setup unit vertex state register */
-       volatile u32    suvtx;
-       u32             xxx8[63];
-       
-       /* Control registers */
-       volatile u32    ppc;
-       volatile u32    wid;
-       volatile u32    fg;
-       volatile u32    bg;
-       volatile u32    consty;
-       volatile u32    constz;
-       volatile u32    xclip;
-       volatile u32    dcss;
-       volatile u32    vclipmin;
-       volatile u32    vclipmax;
-       volatile u32    vclipzmin;
-       volatile u32    vclipzmax;
-       volatile u32    dcsf;
-       volatile u32    dcsb;
-       volatile u32    dczf;
-       volatile u32    dczb;
-       
-       u32             xxx9;
-       volatile u32    blendc;
-       volatile u32    blendc1;
-       volatile u32    blendc2;
-       volatile u32    fbramitc;
-       volatile u32    fbc;
-       volatile u32    rop;
-       volatile u32    cmp;
-       volatile u32    matchab;
-       volatile u32    matchc;
-       volatile u32    magnab;
-       volatile u32    magnc;
-       volatile u32    fbcfg0;
-       volatile u32    fbcfg1;
-       volatile u32    fbcfg2;
-       volatile u32    fbcfg3;
-       
-       u32             ppcfg;
-       volatile u32    pick;
-       volatile u32    fillmode;
-       volatile u32    fbramwac;
-       volatile u32    pmask;
-       volatile u32    xpmask;
-       volatile u32    ypmask;
-       volatile u32    zpmask;
-       volatile u32    clip0min;
-       volatile u32    clip0max;
-       volatile u32    clip1min;
-       volatile u32    clip1max;
-       volatile u32    clip2min;
-       volatile u32    clip2max;
-       volatile u32    clip3min;
-       volatile u32    clip3max;
-       
-       /* New 3dRAM III support regs */
-       volatile u32    rawblend2;
-       volatile u32    rawpreblend;
-       volatile u32    rawstencil;
-       volatile u32    rawstencilctl;
-       volatile u32    threedram1;
-       volatile u32    threedram2;
-       volatile u32    passin;
-       volatile u32    rawclrdepth;
-       volatile u32    rawpmask;
-       volatile u32    rawcsrc;
-       volatile u32    rawmatch;
-       volatile u32    rawmagn;
-       volatile u32    rawropblend;
-       volatile u32    rawcmp;
-       volatile u32    rawwac;
-       volatile u32    fbramid;
-       
-       volatile u32    drawop;
-       u32             xxx10[2];
-       volatile u32    fontlpat;
-       u32             xxx11;
-       volatile u32    fontxy;
-       volatile u32    fontw;
-       volatile u32    fontinc;
-       volatile u32    font;
-       u32             xxx12[3];
-       volatile u32    blend2;
-       volatile u32    preblend;
-       volatile u32    stencil;
-       volatile u32    stencilctl;
-
-       u32             xxx13[4];       
-       volatile u32    dcss1;
-       volatile u32    dcss2;
-       volatile u32    dcss3;
-       volatile u32    widpmask;
-       volatile u32    dcs2;
-       volatile u32    dcs3;
-       volatile u32    dcs4;
-       u32             xxx14;
-       volatile u32    dcd2;
-       volatile u32    dcd3;
-       volatile u32    dcd4;
-       u32             xxx15;
-       
-       volatile u32    pattern[32];
-       
-       u32             xxx16[256];
-       
-       volatile u32    devid;
-       u32             xxx17[63];
-       
-       volatile u32    ucsr;
-       u32             xxx18[31];
-       
-       volatile u32    mer;
-};
-
-static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n)
-{
-       struct ffb_fbc *fbc;
-       int cache = fb->s.ffb.fifo_cache;
-
-       if (cache - n < 0) {
-               fbc = fb->s.ffb.fbc;
-               do {    cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8;
-               } while (cache - n < 0);
-       }
-       fb->s.ffb.fifo_cache = cache - n;
-}
-
-static __inline__ void FFBWait(struct ffb_fbc *ffb)
-{
-       int limit = 10000;
-
-       do {
-               if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
-                       break;
-               if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
-                       upa_writel(FFB_UCSR_ALL_ERRORS, &ffb->ucsr);
-               }
-       } while(--limit > 0);
-}
-
-struct ffb_dac {
-       volatile u32    type;
-       volatile u32    value;
-       volatile u32    type2;
-       volatile u32    value2;
-};
-
-static struct sbus_mmap_map ffb_mmap_map[] = {
-       { FFB_SFB8R_VOFF,       FFB_SFB8R_POFF,         0x0400000 },
-       { FFB_SFB8G_VOFF,       FFB_SFB8G_POFF,         0x0400000 },
-       { FFB_SFB8B_VOFF,       FFB_SFB8B_POFF,         0x0400000 },
-       { FFB_SFB8X_VOFF,       FFB_SFB8X_POFF,         0x0400000 },
-       { FFB_SFB32_VOFF,       FFB_SFB32_POFF,         0x1000000 },
-       { FFB_SFB64_VOFF,       FFB_SFB64_POFF,         0x2000000 },
-       { FFB_FBC_REGS_VOFF,    FFB_FBC_REGS_POFF,      0x0002000 },
-       { FFB_BM_FBC_REGS_VOFF, FFB_BM_FBC_REGS_POFF,   0x0002000 },
-       { FFB_DFB8R_VOFF,       FFB_DFB8R_POFF,         0x0400000 },
-       { FFB_DFB8G_VOFF,       FFB_DFB8G_POFF,         0x0400000 },
-       { FFB_DFB8B_VOFF,       FFB_DFB8B_POFF,         0x0400000 },
-       { FFB_DFB8X_VOFF,       FFB_DFB8X_POFF,         0x0400000 },
-       { FFB_DFB24_VOFF,       FFB_DFB24_POFF,         0x1000000 },
-       { FFB_DFB32_VOFF,       FFB_DFB32_POFF,         0x1000000 },
-       { FFB_FBC_KREGS_VOFF,   FFB_FBC_KREGS_POFF,     0x0002000 },
-       { FFB_DAC_VOFF,         FFB_DAC_POFF,           0x0002000 },
-       { FFB_PROM_VOFF,        FFB_PROM_POFF,          0x0010000 },
-       { FFB_EXP_VOFF,         FFB_EXP_POFF,           0x0002000 },
-       { FFB_DFB422A_VOFF,     FFB_DFB422A_POFF,       0x0800000 },
-       { FFB_DFB422AD_VOFF,    FFB_DFB422AD_POFF,      0x0800000 },
-       { FFB_DFB24B_VOFF,      FFB_DFB24B_POFF,        0x1000000 },
-       { FFB_DFB422B_VOFF,     FFB_DFB422B_POFF,       0x0800000 },
-       { FFB_DFB422BD_VOFF,    FFB_DFB422BD_POFF,      0x0800000 },
-       { FFB_SFB16Z_VOFF,      FFB_SFB16Z_POFF,        0x0800000 },
-       { FFB_SFB8Z_VOFF,       FFB_SFB8Z_POFF,         0x0800000 },
-       { FFB_SFB422_VOFF,      FFB_SFB422_POFF,        0x0800000 },
-       { FFB_SFB422D_VOFF,     FFB_SFB422D_POFF,       0x0800000 },
-       { 0,                    0,                      0         }
-};
-
-static void ffb_setup(struct display *p)
-{
-       p->next_line = 8192;
-       p->next_plane = 0;
-}
-
-static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-                     int height, int width)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(p->fb_info);
-       register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-       unsigned long flags;
-       u64 yx, hw;
-       int fg;
-       
-       spin_lock_irqsave(&fb->lock, flags);
-       fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
-       if (fg != fb->s.ffb.fg_cache) {
-               FFBFifo(fb, 5);
-               upa_writel(fg, &fbc->fg);
-               fb->s.ffb.fg_cache = fg;
-       } else
-               FFBFifo(fb, 4);
-
-       if (fontheightlog(p)) {
-               yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32);
-       } else {
-               yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32;
-       }
-       if (fontwidthlog(p)) {
-               yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p);
-       } else {
-               yx += sx * fontwidth(p); hw += width * fontwidth(p);
-       }
-       upa_writeq(yx + fb->s.ffb.yx_margin, &fbc->by);
-       upa_writeq(hw, &fbc->bh);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
-                    int count, unsigned short *boxes)
-{
-       register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-       unsigned long flags;
-       int fg;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
-       if (fg != fb->s.ffb.fg_cache) {
-               FFBFifo(fb, 1);
-               upa_writel(fg, &fbc->fg);
-               fb->s.ffb.fg_cache = fg;
-       }
-       while (count-- > 0) {
-               FFBFifo(fb, 4);
-               upa_writel(boxes[1], &fbc->by);
-               upa_writel(boxes[0], &fbc->bx);
-               upa_writel(boxes[3] - boxes[1], &fbc->bh);
-               upa_writel(boxes[2] - boxes[0], &fbc->bw);
-               boxes += 4;
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(p->fb_info);
-       register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-       unsigned long flags;
-       int i, xy;
-       u8 *fd;
-       u64 fgbg;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       if (fontheightlog(p)) {
-               xy = (yy << (16 + fontheightlog(p)));
-               i = ((c & p->charmask) << fontheightlog(p));
-       } else {
-               xy = ((yy * fontheight(p)) << 16);
-               i = (c & p->charmask) * fontheight(p);
-       }
-       if (fontwidth(p) <= 8)
-               fd = p->fontdata + i;
-       else
-               fd = p->fontdata + (i << 1);
-       if (fontwidthlog(p))
-               xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
-       else
-               xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
-       fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
-              ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
-       if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
-               FFBFifo(fb, 2);
-               upa_writeq(fgbg, &fbc->fg);
-               *(u64 *)&fb->s.ffb.fg_cache = fgbg;
-       }
-       FFBFifo(fb, 2 + fontheight(p));
-       upa_writel(xy, &fbc->fontxy);
-       upa_writel(fontwidth(p), &fbc->fontw);
-       if (fontwidth(p) <= 8) {
-               for (i = 0; i < fontheight(p); i++) {
-                       u32 val = *fd++ << 24;
-
-                       upa_writel(val, &fbc->font);
-               }
-       } else {
-               for (i = 0; i < fontheight(p); i++) {
-                       u32 val = *(u16 *)fd << 16;
-
-                       upa_writel(val, &fbc->font);
-                       fd += 2;
-               }
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
-                     int count, int yy, int xx)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(p->fb_info);
-       register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-       unsigned long flags;
-       int i, xy;
-       u8 *fd1, *fd2, *fd3, *fd4;
-       u16 c;
-       u64 fgbg;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       c = scr_readw(s);
-       fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p, c)])) << 32) |
-              ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
-       if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
-               FFBFifo(fb, 2);
-               upa_writeq(fgbg, &fbc->fg);
-               *(u64 *)&fb->s.ffb.fg_cache = fgbg;
-       }
-       xy = fb->s.ffb.xy_margin;
-       if (fontwidthlog(p))
-               xy += (xx << fontwidthlog(p));
-       else
-               xy += xx * fontwidth(p);
-       if (fontheightlog(p))
-               xy += (yy << (16 + fontheightlog(p)));
-       else
-               xy += ((yy * fontheight(p)) << 16);
-       if (fontwidth(p) <= 8) {
-               while (count >= 4) {
-                       count -= 4;
-                       FFBFifo(fb, 2 + fontheight(p));
-                       upa_writel(4 * fontwidth(p), &fbc->fontw);
-                       upa_writel(xy, &fbc->fontxy);
-                       if (fontheightlog(p)) {
-                               fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                               fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                               fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                               fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-                       } else {
-                               fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                               fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                               fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                               fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-                       }
-                       if (fontwidth(p) == 8) {
-                               for (i = 0; i < fontheight(p); i++) {
-                                       u32 val;
-
-                                       val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-                                               << 8)) << 8)) << 8);
-                                       upa_writel(val, &fbc->font);
-                               }
-                               xy += 32;
-                       } else {
-                               for (i = 0; i < fontheight(p); i++) {
-                                       u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-                                               << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
-                                       upa_writel(val, &fbc->font);
-                               }
-                               xy += 4 * fontwidth(p);
-                       }
-               }
-       } else {
-               while (count >= 2) {
-                       count -= 2;
-                       FFBFifo(fb, 2 + fontheight(p));
-                       upa_writel(2 * fontwidth(p), &fbc->fontw);
-                       upa_writel(xy, &fbc->fontxy);
-                       if (fontheightlog(p)) {
-                               fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-                               fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-                       } else {
-                               fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-                               fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-                       }
-                       for (i = 0; i < fontheight(p); i++) {
-                               u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
-
-                               upa_writel(val, &fbc->font);
-                               fd1 += 2; fd2 += 2;
-                       }
-                       xy += 2 * fontwidth(p);
-               }
-       }
-       while (count) {
-               count--;
-               FFBFifo(fb, 2 + fontheight(p));
-               upa_writel(fontwidth(p), &fbc->fontw);
-               upa_writel(xy, &fbc->fontxy);
-               if (fontheightlog(p))
-                       i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-               else
-                       i = ((scr_readw(s++) & p->charmask) * fontheight(p));
-               if (fontwidth(p) <= 8) {
-                       fd1 = p->fontdata + i;
-                       for (i = 0; i < fontheight(p); i++) {
-                               u32 val = *fd1++ << 24;
-
-                               upa_writel(val, &fbc->font);
-                       }
-               } else {
-                       fd1 = p->fontdata + (i << 1);
-                       for (i = 0; i < fontheight(p); i++) {
-                               u32 val = *(u16 *)fd1 << 16;
-
-                               upa_writel(val, &fbc->font);
-                               fd1 += 2;
-                       }
-               }
-               xy += fontwidth(p);
-       }
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void ffb_revc(struct display *p, int xx, int yy)
-{
-       /* Not used if hw cursor */
-}
-
-#if 0
-static int ffb_blank(struct fb_info_sbusfb *fb)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       upa_writel(0x6000, &dac->type);
-       tmp = (upa_readl(&dac->value) & ~0x1);
-       upa_writel(0x6000, &dac->type);
-       upa_writel(tmp, &dac->value);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-#endif
-
-static int ffb_unblank(struct fb_info_sbusfb *fb)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       unsigned long flags;
-       u32 tmp;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       upa_writel(0x6000, &dac->type);
-       tmp = (upa_readl(&dac->value) | 0x1);
-       upa_writel(0x6000, &dac->type);
-       upa_writel(tmp, &dac->value);
-       spin_unlock_irqrestore(&fb->lock, flags);
-       return 0;
-}
-
-static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       unsigned long flags;
-       int i, j = count;
-       
-       spin_lock_irqsave(&fb->lock, flags);
-       upa_writel(0x2000 | index, &dac->type);
-       for (i = index; j--; i++) {
-               u32 val;
-
-               /* Feed the colors in :)) */
-               val = ((fb->color_map CM(i,0))) |
-                       ((fb->color_map CM(i,1)) << 8) |
-                       ((fb->color_map CM(i,2)) << 16);
-               upa_writel(val, &dac->value);
-       }
-       if (!p)
-               goto out;
-       for (i = index, j = count; i < 16 && j--; i++)
-               ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
-                                            ((fb->color_map CM(i,1)) << 8) |
-                                            ((fb->color_map CM(i,2)) << 16);
-out:
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static struct display_switch ffb_dispsw __initdata = {
-       .setup =        ffb_setup,
-       .bmove =        fbcon_redraw_bmove,
-       .clear =        ffb_clear,
-       .putc =         ffb_putc,
-       .putcs =        ffb_putcs,
-       .revc =         ffb_revc, 
-       .fontwidthmask =FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
-};
-
-static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
-{
-       register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
-       fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
-       fb->info.screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
-       FFBWait(fbc);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       u32 val;
-
-       upa_writel(0x100, &dac->type2);
-       if (fb->s.ffb.dac_rev <= 2) {
-               val = enable ? 3 : 0;
-       } else {
-               val = enable ? 0 : 3;
-       }
-       upa_writel(val, &dac->value2);
-}
-
-static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       unsigned long flags;
-       
-       spin_lock_irqsave(&fb->lock, flags);
-       __ffb_curs_enable (fb, 0);
-       upa_writel(0x102, &dac->type2);
-       upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2);
-       upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Set cursor shape */
-static void ffb_setcurshape (struct fb_info_sbusfb *fb)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       unsigned long flags;
-       int i, j;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       __ffb_curs_enable (fb, 0);
-       for (j = 0; j < 2; j++) {
-               u32 val = j ? 0 : 0x80;
-
-               upa_writel(val, &dac->type2);
-               for (i = 0; i < 0x40; i++) {
-                       if (fb->cursor.size.fbx <= 32) {
-                               upa_writel(fb->cursor.bits [j][i], &dac->value2);
-                               upa_writel(0, &dac->value2);
-                       } else {
-                               upa_writel(fb->cursor.bits [j][2*i], &dac->value2);
-                               upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2);
-                       }
-               }
-       }       
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Load cursor information */
-static void ffb_setcursor (struct fb_info_sbusfb *fb)
-{
-       struct ffb_dac *dac = fb->s.ffb.dac;
-       struct cg_cursor *c = &fb->cursor;
-       unsigned long flags;
-       u32 val;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       upa_writel(0x104, &dac->type2);
-       /* Should this be just 0x7ff?? 
-          Should I do some margin handling and setcurshape in that case? */
-       val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
-               |((c->cpos.fbx - c->chot.fbx) & 0xffff);
-       upa_writel(val, &dac->value2);
-       __ffb_curs_enable (fb, fb->cursor.enable);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
-{
-       register struct ffb_fbc *fbc = fb->s.ffb.fbc;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fb->lock, flags);
-       FFBWait(fbc);
-       fb->s.ffb.fifo_cache = 0;
-       FFBFifo(fb, 8);
-       upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|
-                  FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
-                  &fbc->ppc);
-       upa_writel(0x2000707f, &fbc->fbc);
-       upa_writel(FFB_ROP_NEW, &fbc->rop);
-       upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
-       upa_writel(0xffffffff, &fbc->pmask);
-       upa_writel(0x10000, &fbc->fontinc);
-       upa_writel(fb->s.ffb.fg_cache, &fbc->fg);
-       upa_writel(fb->s.ffb.bg_cache, &fbc->bg);
-       FFBWait(fbc);
-       spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int __init ffb_rasterimg (struct fb_info *info, int start)
-{
-       ffb_switch_from_graph (sbusfbinfo(info));
-       return 0;
-}
-
-static char idstring[60] __initdata = { 0 };
-
-static int __init creator_apply_upa_parent_ranges(int parent, struct linux_prom64_registers *regs)
-{
-       struct linux_prom64_ranges ranges[PROMREG_MAX];
-       char name[128];
-       int len, i;
-
-       prom_getproperty(parent, "name", name, sizeof(name));
-       if (strcmp(name, "upa") != 0)
-               return 0;
-
-       len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
-       if (len <= 0)
-               return 1;
-
-       len /= sizeof(struct linux_prom64_ranges);
-       for (i = 0; i < len; i++) {
-               struct linux_prom64_ranges *rng = &ranges[i];
-               u64 phys_addr = regs->phys_addr;
-
-               if (phys_addr >= rng->ot_child_base &&
-                   phys_addr < (rng->ot_child_base + rng->or_size)) {
-                       regs->phys_addr -= rng->ot_child_base;
-                       regs->phys_addr += rng->ot_parent_base;
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-char __init *creatorfb_init(struct fb_info_sbusfb *fb)
-{
-       struct fb_fix_screeninfo *fix = &fb->info.fix;
-       struct fb_var_screeninfo *var = &fb->info.var;
-       struct display *disp = &fb->disp;
-       struct fbtype *type = &fb->type;
-       struct linux_prom64_registers regs[2*PROMREG_MAX];
-       int i, afb = 0;
-       unsigned int btype;
-       char name[64];
-       struct fb_ops *fbops;
-
-       if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
-               return NULL;
-
-       if (creator_apply_upa_parent_ranges(fb->prom_parent, &regs[0]))
-               return NULL;
-               
-       disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
-       if (disp->dispsw_data == NULL)
-               return NULL;
-       memset(disp->dispsw_data, 0, 16 * sizeof(u32));
-
-       fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-       if (fbops == NULL) {
-               kfree(disp->dispsw_data);
-               return NULL;
-       }
-       
-       *fbops = *fb->info.fbops;
-       fbops->fb_rasterimg = ffb_rasterimg;
-       fb->info.fbops = fbops;
-
-       prom_getstring(fb->prom_node, "name", name, sizeof(name));
-       if (!strcmp(name, "SUNW,afb"))
-               afb = 1;
-               
-       btype = prom_getintdefault(fb->prom_node, "board_type", 0);
-               
-       strcpy(fb->info.modename, "Creator");
-       if (!afb) {
-               if ((btype & 7) == 3)
-                   strcpy(fix->id, "Creator 3D");
-               else
-                   strcpy(fix->id, "Creator");
-       } else
-               strcpy(fix->id, "Elite 3D");
-       
-       fix->visual = FB_VISUAL_TRUECOLOR;
-       fix->line_length = 8192;
-       fix->accel = FB_ACCEL_SUN_CREATOR;
-       
-       var->bits_per_pixel = 32;
-       var->green.offset = 8;
-       var->blue.offset = 16;
-       var->accel_flags = FB_ACCELF_TEXT;
-       
-       disp->scrollmode = SCROLL_YREDRAW;
-       fb->info.screen_base = (char *)(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
-       fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
-       fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
-       fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
-       fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
-       fb->dispsw = ffb_dispsw;
-
-       fb->margins = ffb_margins;
-       fb->loadcmap = ffb_loadcmap;
-       fb->setcursor = ffb_setcursor;
-       fb->setcursormap = ffb_setcursormap;
-       fb->setcurshape = ffb_setcurshape;
-       fb->switch_from_graph = ffb_switch_from_graph;
-       fb->fill = ffb_fill;
-#if 0
-       /* XXX Can't enable this for now, I've seen cases
-        * XXX where the VC was blanked, and Xsun24 was started
-        * XXX via a remote login, the sunfb code did not
-        * XXX unblank creator when it was mmap'd for some
-        * XXX reason, investigate later... -DaveM
-        */
-       fb->blank = ffb_blank;
-       fb->unblank = ffb_unblank;
-#endif
-       
-       /* If there are any read errors or fifo overflow conditions,
-        * clear them now.
-        */
-       if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
-               upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr);
-
-       ffb_switch_from_graph(fb);
-       
-       fb->physbase = regs[0].phys_addr;
-       fb->mmap_map = ffb_mmap_map;
-       
-       fb->cursor.hwsize.fbx = 64;
-       fb->cursor.hwsize.fby = 64;
-       
-       type->fb_depth = 24;
-       
-       upa_writel(0x8000, &fb->s.ffb.dac->type);
-       fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c);
-                       
-       i = prom_getintdefault (fb->prom_node, "board_type", 8);
-
-       sprintf(idstring, "%s at %016lx type %d DAC %d",
-               fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
-       
-       /* Elite3D has different DAC revision numbering, and no DAC revisions
-          have the reversed meaning of cursor enable */
-       if (afb)
-               fb->s.ffb.dac_rev = 10;
-       
-       /* Unblank it just to be sure.  When there are multiple
-        * FFB/AFB cards in the system, or it is not the OBP
-        * chosen console, it will have video outputs off in
-        * the DAC.
-        */
-       ffb_unblank(fb);
-
-       return idstring;
-}
-
-MODULE_LICENSE("GPL");
index c6bd28291a3b3d874024c83bcdab3b2ef35be392..1c9c54c3248514b977fd4c3dd3b7f639295be964 100644 (file)
@@ -103,8 +103,6 @@ extern int hgafb_setup(char*);
 extern int matroxfb_init(void);
 extern int matroxfb_setup(char*);
 extern int hpfb_init(void);
-extern int sbusfb_init(void);
-extern int sbusfb_setup(char*);
 extern int control_init(void);
 extern int control_setup(char*);
 extern int platinum_init(void);
@@ -146,6 +144,8 @@ extern int sstfb_init(void);
 extern int sstfb_setup(char*);
 extern int i810fb_init(void);
 extern int i810fb_setup(char*);
+extern int ffb_init(void);
+extern int ffb_setup(char*);
 
 static struct {
        const char *name;
@@ -153,13 +153,6 @@ static struct {
        int (*setup)(char*);
 } fb_drivers[] __initdata = {
 
-#ifdef CONFIG_FB_SBUS
-       /*
-        * Sbusfb must be initialized _before_ other frame buffer devices that
-        * use PCI probing
-        */
-       { "sbus", sbusfb_init, sbusfb_setup },
-#endif
        /*
         * Chipset specific drivers that use resource management
         */
@@ -244,6 +237,9 @@ static struct {
 #ifdef CONFIG_FB_STI
        { "stifb", stifb_init, stifb_setup },
 #endif
+#ifdef CONFIG_FB_FFB
+       { "ffb", ffb_init, ffb_setup },
+#endif
 
        /*
         * Generic drivers that are used as fallbacks
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
new file mode 100644 (file)
index 0000000..e9a8ba3
--- /dev/null
@@ -0,0 +1,1046 @@
+/* ffb.c: Creator/Elite3D frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+
+#include <asm/io.h>
+#include <asm/upa.h>
+#include <asm/oplib.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int ffb_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int ffb_set_par(struct fb_info *);
+static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
+                        unsigned, struct fb_info *);
+static int ffb_blank(int, struct fb_info *);
+static void ffb_init_fix(struct fb_info *);
+
+static void ffb_imageblit(struct fb_info *, struct fb_image *);
+static void ffb_fillrect(struct fb_info *, struct fb_fillrect *);
+static void ffb_copyarea(struct fb_info *, struct fb_copyarea *);
+static int ffb_sync(struct fb_info *);
+static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops ffb_ops = {
+       .owner                  = THIS_MODULE,
+       .fb_check_var           = ffb_check_var,
+       .fb_set_par             = ffb_set_par,
+       .fb_setcolreg           = ffb_setcolreg,
+       .fb_blank               = ffb_blank,
+       .fb_fillrect            = ffb_fillrect,
+       .fb_copyarea            = ffb_copyarea,
+       .fb_imageblit           = ffb_imageblit,
+       .fb_sync                = ffb_sync,
+       .fb_mmap                = ffb_mmap,
+
+       /* XXX Use FFB hw cursor once fb cursor API is better understood... */
+       .fb_cursor              = soft_cursor,
+};
+
+/* Register layout and definitions */
+#define        FFB_SFB8R_VOFF          0x00000000
+#define        FFB_SFB8G_VOFF          0x00400000
+#define        FFB_SFB8B_VOFF          0x00800000
+#define        FFB_SFB8X_VOFF          0x00c00000
+#define        FFB_SFB32_VOFF          0x01000000
+#define        FFB_SFB64_VOFF          0x02000000
+#define        FFB_FBC_REGS_VOFF       0x04000000
+#define        FFB_BM_FBC_REGS_VOFF    0x04002000
+#define        FFB_DFB8R_VOFF          0x04004000
+#define        FFB_DFB8G_VOFF          0x04404000
+#define        FFB_DFB8B_VOFF          0x04804000
+#define        FFB_DFB8X_VOFF          0x04c04000
+#define        FFB_DFB24_VOFF          0x05004000
+#define        FFB_DFB32_VOFF          0x06004000
+#define        FFB_DFB422A_VOFF        0x07004000      /* DFB 422 mode write to A */
+#define        FFB_DFB422AD_VOFF       0x07804000      /* DFB 422 mode with line doubling */
+#define        FFB_DFB24B_VOFF         0x08004000      /* DFB 24bit mode write to B */
+#define        FFB_DFB422B_VOFF        0x09004000      /* DFB 422 mode write to B */
+#define        FFB_DFB422BD_VOFF       0x09804000      /* DFB 422 mode with line doubling */
+#define        FFB_SFB16Z_VOFF         0x0a004000      /* 16bit mode Z planes */
+#define        FFB_SFB8Z_VOFF          0x0a404000      /* 8bit mode Z planes */
+#define        FFB_SFB422_VOFF         0x0ac04000      /* SFB 422 mode write to A/B */
+#define        FFB_SFB422D_VOFF        0x0b404000      /* SFB 422 mode with line doubling */
+#define        FFB_FBC_KREGS_VOFF      0x0bc04000
+#define        FFB_DAC_VOFF            0x0bc06000
+#define        FFB_PROM_VOFF           0x0bc08000
+#define        FFB_EXP_VOFF            0x0bc18000
+
+#define        FFB_SFB8R_POFF          0x04000000UL
+#define        FFB_SFB8G_POFF          0x04400000UL
+#define        FFB_SFB8B_POFF          0x04800000UL
+#define        FFB_SFB8X_POFF          0x04c00000UL
+#define        FFB_SFB32_POFF          0x05000000UL
+#define        FFB_SFB64_POFF          0x06000000UL
+#define        FFB_FBC_REGS_POFF       0x00600000UL
+#define        FFB_BM_FBC_REGS_POFF    0x00600000UL
+#define        FFB_DFB8R_POFF          0x01000000UL
+#define        FFB_DFB8G_POFF          0x01400000UL
+#define        FFB_DFB8B_POFF          0x01800000UL
+#define        FFB_DFB8X_POFF          0x01c00000UL
+#define        FFB_DFB24_POFF          0x02000000UL
+#define        FFB_DFB32_POFF          0x03000000UL
+#define        FFB_FBC_KREGS_POFF      0x00610000UL
+#define        FFB_DAC_POFF            0x00400000UL
+#define        FFB_PROM_POFF           0x00000000UL
+#define        FFB_EXP_POFF            0x00200000UL
+#define FFB_DFB422A_POFF       0x09000000UL
+#define FFB_DFB422AD_POFF      0x09800000UL
+#define FFB_DFB24B_POFF                0x0a000000UL
+#define FFB_DFB422B_POFF       0x0b000000UL
+#define FFB_DFB422BD_POFF      0x0b800000UL
+#define FFB_SFB16Z_POFF                0x0c800000UL
+#define FFB_SFB8Z_POFF         0x0c000000UL
+#define FFB_SFB422_POFF                0x0d000000UL
+#define FFB_SFB422D_POFF       0x0d800000UL
+
+/* Draw operations */
+#define FFB_DRAWOP_DOT         0x00
+#define FFB_DRAWOP_AADOT       0x01
+#define FFB_DRAWOP_BRLINECAP   0x02
+#define FFB_DRAWOP_BRLINEOPEN  0x03
+#define FFB_DRAWOP_DDLINE      0x04
+#define FFB_DRAWOP_AALINE      0x05
+#define FFB_DRAWOP_TRIANGLE    0x06
+#define FFB_DRAWOP_POLYGON     0x07
+#define FFB_DRAWOP_RECTANGLE   0x08
+#define FFB_DRAWOP_FASTFILL    0x09
+#define FFB_DRAWOP_BCOPY       0x0a
+#define FFB_DRAWOP_VSCROLL     0x0b
+
+/* Pixel processor control */
+/* Force WID */
+#define FFB_PPC_FW_DISABLE     0x800000
+#define FFB_PPC_FW_ENABLE      0xc00000
+/* Auxiliary clip */
+#define FFB_PPC_ACE_DISABLE    0x040000
+#define FFB_PPC_ACE_AUX_SUB    0x080000
+#define FFB_PPC_ACE_AUX_ADD    0x0c0000
+/* Depth cue */
+#define FFB_PPC_DCE_DISABLE    0x020000
+#define FFB_PPC_DCE_ENABLE     0x030000
+/* Alpha blend */
+#define FFB_PPC_ABE_DISABLE    0x008000
+#define FFB_PPC_ABE_ENABLE     0x00c000
+/* View clip */
+#define FFB_PPC_VCE_DISABLE    0x001000
+#define FFB_PPC_VCE_2D         0x002000
+#define FFB_PPC_VCE_3D         0x003000
+/* Area pattern */
+#define FFB_PPC_APE_DISABLE    0x000800
+#define FFB_PPC_APE_ENABLE     0x000c00
+/* Transparent background */
+#define FFB_PPC_TBE_OPAQUE     0x000200
+#define FFB_PPC_TBE_TRANSPARENT        0x000300
+/* Z source */
+#define FFB_PPC_ZS_VAR         0x000080
+#define FFB_PPC_ZS_CONST       0x0000c0
+/* Y source */
+#define FFB_PPC_YS_VAR         0x000020
+#define FFB_PPC_YS_CONST       0x000030
+/* X source */
+#define FFB_PPC_XS_WID         0x000004
+#define FFB_PPC_XS_VAR         0x000008
+#define FFB_PPC_XS_CONST       0x00000c
+/* Color (BGR) source */
+#define FFB_PPC_CS_VAR         0x000002
+#define FFB_PPC_CS_CONST       0x000003
+
+#define FFB_ROP_NEW                  0x83
+#define FFB_ROP_OLD                  0x85
+#define FFB_ROP_NEW_XOR_OLD          0x86
+
+#define FFB_UCSR_FIFO_MASK     0x00000fff
+#define FFB_UCSR_FB_BUSY       0x01000000
+#define FFB_UCSR_RP_BUSY       0x02000000
+#define FFB_UCSR_ALL_BUSY      (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
+#define FFB_UCSR_READ_ERR      0x40000000
+#define FFB_UCSR_FIFO_OVFL     0x80000000
+#define FFB_UCSR_ALL_ERRORS    (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
+
+struct ffb_fbc {
+       /* Next vertex registers */
+       u32             xxx1[3];
+       volatile u32    alpha;
+       volatile u32    red;
+       volatile u32    green;
+       volatile u32    blue;
+       volatile u32    depth;
+       volatile u32    y;
+       volatile u32    x;
+       u32             xxx2[2];
+       volatile u32    ryf;
+       volatile u32    rxf;
+       u32             xxx3[2];
+       
+       volatile u32    dmyf;
+       volatile u32    dmxf;
+       u32             xxx4[2];
+       volatile u32    ebyi;
+       volatile u32    ebxi;
+       u32             xxx5[2];
+       volatile u32    by;
+       volatile u32    bx;
+       u32             dy;
+       u32             dx;
+       volatile u32    bh;
+       volatile u32    bw;
+       u32             xxx6[2];
+       
+       u32             xxx7[32];
+       
+       /* Setup unit vertex state register */
+       volatile u32    suvtx;
+       u32             xxx8[63];
+       
+       /* Control registers */
+       volatile u32    ppc;
+       volatile u32    wid;
+       volatile u32    fg;
+       volatile u32    bg;
+       volatile u32    consty;
+       volatile u32    constz;
+       volatile u32    xclip;
+       volatile u32    dcss;
+       volatile u32    vclipmin;
+       volatile u32    vclipmax;
+       volatile u32    vclipzmin;
+       volatile u32    vclipzmax;
+       volatile u32    dcsf;
+       volatile u32    dcsb;
+       volatile u32    dczf;
+       volatile u32    dczb;
+       
+       u32             xxx9;
+       volatile u32    blendc;
+       volatile u32    blendc1;
+       volatile u32    blendc2;
+       volatile u32    fbramitc;
+       volatile u32    fbc;
+       volatile u32    rop;
+       volatile u32    cmp;
+       volatile u32    matchab;
+       volatile u32    matchc;
+       volatile u32    magnab;
+       volatile u32    magnc;
+       volatile u32    fbcfg0;
+       volatile u32    fbcfg1;
+       volatile u32    fbcfg2;
+       volatile u32    fbcfg3;
+       
+       u32             ppcfg;
+       volatile u32    pick;
+       volatile u32    fillmode;
+       volatile u32    fbramwac;
+       volatile u32    pmask;
+       volatile u32    xpmask;
+       volatile u32    ypmask;
+       volatile u32    zpmask;
+       volatile u32    clip0min;
+       volatile u32    clip0max;
+       volatile u32    clip1min;
+       volatile u32    clip1max;
+       volatile u32    clip2min;
+       volatile u32    clip2max;
+       volatile u32    clip3min;
+       volatile u32    clip3max;
+       
+       /* New 3dRAM III support regs */
+       volatile u32    rawblend2;
+       volatile u32    rawpreblend;
+       volatile u32    rawstencil;
+       volatile u32    rawstencilctl;
+       volatile u32    threedram1;
+       volatile u32    threedram2;
+       volatile u32    passin;
+       volatile u32    rawclrdepth;
+       volatile u32    rawpmask;
+       volatile u32    rawcsrc;
+       volatile u32    rawmatch;
+       volatile u32    rawmagn;
+       volatile u32    rawropblend;
+       volatile u32    rawcmp;
+       volatile u32    rawwac;
+       volatile u32    fbramid;
+       
+       volatile u32    drawop;
+       u32             xxx10[2];
+       volatile u32    fontlpat;
+       u32             xxx11;
+       volatile u32    fontxy;
+       volatile u32    fontw;
+       volatile u32    fontinc;
+       volatile u32    font;
+       u32             xxx12[3];
+       volatile u32    blend2;
+       volatile u32    preblend;
+       volatile u32    stencil;
+       volatile u32    stencilctl;
+
+       u32             xxx13[4];       
+       volatile u32    dcss1;
+       volatile u32    dcss2;
+       volatile u32    dcss3;
+       volatile u32    widpmask;
+       volatile u32    dcs2;
+       volatile u32    dcs3;
+       volatile u32    dcs4;
+       u32             xxx14;
+       volatile u32    dcd2;
+       volatile u32    dcd3;
+       volatile u32    dcd4;
+       u32             xxx15;
+       
+       volatile u32    pattern[32];
+       
+       u32             xxx16[256];
+       
+       volatile u32    devid;
+       u32             xxx17[63];
+       
+       volatile u32    ucsr;
+       u32             xxx18[31];
+       
+       volatile u32    mer;
+};
+
+struct ffb_dac {
+       volatile u32    type;
+       volatile u32    value;
+       volatile u32    type2;
+       volatile u32    value2;
+};
+
+struct ffb_par {
+       spinlock_t              lock;
+       struct ffb_fbc          *fbc;
+       struct ffb_dac          *dac;
+
+       u32                     flags;
+#define FFB_FLAG_AFB           0x00000001
+#define FFB_FLAG_BLANKED       0x00000002
+
+       u32                     fg_cache __attribute__((aligned (8)));
+       u32                     bg_cache;
+       u32                     rop_cache;
+
+       int                     fifo_cache;
+
+       unsigned long           physbase;
+       unsigned long           fbsize;
+
+       char                    name[64];
+       int                     prom_node;
+       int                     prom_parent_node;
+       int                     dac_rev;
+       int                     board_type;
+       struct list_head        list;
+};
+
+#undef FFB_DO_DEBUG_LOG
+
+#ifdef FFB_DO_DEBUG_LOG
+#define FFB_DEBUG_LOG_ENTS     32
+static struct ffb_log {
+       int op;
+#define OP_FILLRECT    1
+#define OP_IMAGEBLIT   2
+
+       int depth, x, y, w, h;
+} ffb_debug_log[FFB_DEBUG_LOG_ENTS];
+static int ffb_debug_log_ent;
+
+static void ffb_do_log(unsigned long unused)
+{
+       int i;
+
+       for (i = 0; i < FFB_DEBUG_LOG_ENTS; i++) {
+               struct ffb_log *p = &ffb_debug_log[i];
+
+               printk("FFB_LOG: OP[%s] depth(%d) x(%d) y(%d) w(%d) h(%d)\n",
+                      (p->op == OP_FILLRECT ? "FILLRECT" : "IMAGEBLIT"),
+                      p->depth, p->x, p->y, p->w, p->h);
+       }
+}
+static struct timer_list ffb_log_timer =
+       TIMER_INITIALIZER(ffb_do_log, 0, 0);
+
+static void ffb_log(int op, int depth, int x, int y, int w, int h)
+{
+       if (ffb_debug_log_ent < FFB_DEBUG_LOG_ENTS) {
+               struct ffb_log *p = &ffb_debug_log[ffb_debug_log_ent];
+
+               if (ffb_debug_log_ent != 0 &&
+                   p[-1].op == op && p[-1].depth == depth)
+                       return;
+               p->op = op;
+               p->depth = depth;
+               p->x = x;
+               p->y = y;
+               p->w = w;
+               p->h = h;
+
+               if (++ffb_debug_log_ent == FFB_DEBUG_LOG_ENTS) {
+                       ffb_log_timer.expires = jiffies + 2;
+                       add_timer(&ffb_log_timer);
+               }
+       }
+}
+#else
+#define ffb_log(a,b,c,d,e,f)   do { } while(0)
+#endif
+
+#undef FORCE_WAIT_EVERY_ROP
+
+static void FFBFifo(struct ffb_par *par, int n)
+{
+       struct ffb_fbc *fbc;
+       int cache = par->fifo_cache;
+
+       if (cache - n < 0) {
+               fbc = par->fbc;
+               do {    cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8;
+               } while (cache - n < 0);
+       }
+       par->fifo_cache = cache - n;
+}
+
+static void FFBWait(struct ffb_par *par)
+{
+       struct ffb_fbc *fbc;
+       int limit = 10000;
+
+       fbc = par->fbc;
+       do {
+               if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
+                       break;
+               if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
+                       upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
+               }
+               udelay(10);
+       } while(--limit > 0);
+}
+
+static int ffb_sync(struct fb_info *p)
+{
+       struct ffb_par *par = (struct ffb_par *) p->par;
+
+       FFBWait(par);
+       return 0;
+}
+
+static __inline__ void ffb_rop(struct ffb_par *par, u32 rop)
+{
+       if (par->rop_cache != rop) {
+               FFBFifo(par, 1);
+               upa_writel(rop, &par->fbc->rop);
+               par->rop_cache = rop;
+       }
+}
+
+static void ffb_switch_from_graph(struct ffb_par *par)
+{
+       struct ffb_fbc *fbc = par->fbc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&par->lock, flags);
+       FFBWait(par);
+       par->fifo_cache = 0;
+       FFBFifo(par, 7);
+       upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|
+                  FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
+                  &fbc->ppc);
+       upa_writel(0x2000707f, &fbc->fbc);
+       upa_writel(par->rop_cache, &fbc->rop);
+       upa_writel(0xffffffff, &fbc->pmask);
+       upa_writel((0 << 16) | (32 << 0), &fbc->fontinc);
+       upa_writel(par->fg_cache, &fbc->fg);
+       upa_writel(par->bg_cache, &fbc->bg);
+       FFBWait(par);
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *      ffb_fillrect - REQUIRED function. Can use generic routines if 
+ *                     non acclerated hardware and packed pixel based.
+ *                     Draws a rectangle on the screen.               
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @rect: structure defining the rectagle and operation.
+ */
+static void ffb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
+{
+       struct ffb_par *par = (struct ffb_par *) info->par;
+       struct ffb_fbc *fbc = par->fbc;
+       unsigned long flags;
+       u32 fg;
+
+       if (rect->rop != ROP_COPY && rect->rop != ROP_XOR)
+               BUG();
+
+       ffb_log(OP_FILLRECT, 0, rect->dx, rect->dy, rect->width, rect->height);
+
+       fg = ((u32 *)info->pseudo_palette)[rect->color];
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       if (fg != par->fg_cache) {
+               FFBFifo(par, 1);
+               upa_writel(fg, &fbc->fg);
+               par->fg_cache = fg;
+       }
+
+       ffb_rop(par, (rect->rop == ROP_COPY ?
+                     FFB_ROP_NEW :
+                     FFB_ROP_NEW_XOR_OLD));
+
+       FFBFifo(par, 5);
+       upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
+       upa_writel(rect->dy, &fbc->by);
+       upa_writel(rect->dx, &fbc->bx);
+       upa_writel(rect->height, &fbc->bh);
+       upa_writel(rect->width, &fbc->bw);
+#ifdef FORCE_WAIT_EVERY_ROP
+       FFBWait(par);
+#endif
+
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *      ffb_copyarea - REQUIRED function. Can use generic routines if
+ *                     non acclerated hardware and packed pixel based.
+ *                     Copies on area of the screen to another area.
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @area: structure defining the source and destination.
+ */
+
+static void
+ffb_copyarea(struct fb_info *info, struct fb_copyarea *area) 
+{
+       struct ffb_par *par = (struct ffb_par *) info->par;
+       struct ffb_fbc *fbc = par->fbc;
+       unsigned long flags;
+
+       if (area->dx != area->sx ||
+           area->dy == area->dy) {
+               cfb_copyarea(info, area);
+               return;
+       }
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       ffb_rop(par, FFB_ROP_OLD);
+
+       FFBFifo(par, 7);
+       upa_writel(FFB_DRAWOP_VSCROLL, &fbc->drawop);
+       upa_writel(area->sy, &fbc->by);
+       upa_writel(area->sx, &fbc->bx);
+       upa_writel(area->dy, &fbc->dy);
+       upa_writel(area->dx, &fbc->dx);
+       upa_writel(area->height, &fbc->bh);
+       upa_writel(area->width, &fbc->bw);
+
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+/**
+ *      ffb_imageblit - REQUIRED function. Can use generic routines if
+ *                      non acclerated hardware and packed pixel based.
+ *                      Copies a image from system memory to the screen. 
+ *
+ *      @info: frame buffer structure that represents a single frame buffer
+ *      @image: structure defining the image.
+ */
+static void ffb_imageblit(struct fb_info *info, struct fb_image *image)
+{
+       struct ffb_par *par = (struct ffb_par *) info->par;
+       struct ffb_fbc *fbc = par->fbc;
+       u8 *data = (u8 *) image->data;
+       unsigned long flags;
+       u32 fg, bg, xy;
+       u64 fgbg;
+       int i, width;
+
+       ffb_log(OP_IMAGEBLIT, image->depth,
+               image->dx, image->dy, image->width, image->height);
+
+       if (image->depth > 1) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
+       fg = ((u32 *)info->pseudo_palette)[image->fg_color];
+       bg = ((u32 *)info->pseudo_palette)[image->bg_color];
+       fgbg = ((u64) fg << 32) | (u64) bg;
+       xy = (image->dy << 16) | image->dx;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       if (fgbg != *(u64 *)&par->fg_cache) {
+               FFBFifo(par, 2);
+               upa_writeq(fgbg, &fbc->fg);
+               *(u64 *)&par->fg_cache = fgbg;
+       }
+
+       ffb_rop(par, FFB_ROP_NEW);
+
+       for (i = 0; i < image->height; i++) {
+               width = image->width;
+
+               FFBFifo(par, 1);
+               upa_writel(xy, &fbc->fontxy);
+               xy += (1 << 16);
+
+               while (width >= 32) {
+                       u32 val;
+
+                       FFBFifo(par, 2);
+                       upa_writel(32, &fbc->fontw);
+
+                       val = ((u32)data[0] << 24) |
+                             ((u32)data[1] << 16) |
+                             ((u32)data[2] <<  8) |
+                             ((u32)data[3] <<  0);
+                       upa_writel(val, &fbc->font);
+
+                       data += 4;
+                       width -= 32;
+               }
+
+               if (width) {
+                       u32 val;
+
+                       FFBFifo(par, 2);
+                       upa_writel(width, &fbc->fontw);
+                       if (width <= 8) {
+                               val = (u32) data[0] << 24;
+                               data += 1;
+                       } else if (width <= 16) {
+                               val = ((u32) data[0] << 24) |
+                                     ((u32) data[1] << 16);
+                               data += 2;
+                       } else {
+                               val = ((u32) data[0] << 24) |
+                                     ((u32) data[1] << 16) |
+                                     ((u32) data[2] <<  8);
+                               data += 3;
+                       }
+                       upa_writel(val, &fbc->font);
+               }
+       }
+#ifdef FORCE_WAIT_EVERY_ROP
+       FFBWait(par);
+#endif
+
+       spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var)
+{
+       var->red.offset = 0;
+       var->red.length = 8;
+       var->green.offset = 8;
+       var->green.length = 8;
+       var->blue.offset = 16;
+       var->blue.length = 8;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+}
+
+/**
+ *      ffb_check_var - Optional function.  Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int ffb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       if (var->bits_per_pixel != 32)
+               return -EINVAL;
+
+       if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
+               return -EINVAL;
+       if (var->nonstd)
+               return -EINVAL;
+       if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+       if (var->xres != info->var.xres || var->yres != info->var.yres)
+               return -EINVAL;
+
+       ffb_fixup_var_rgb(var);
+
+       return 0;
+}
+
+/**
+ *      ffb_set_par - Optional function.  Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+ffb_set_par(struct fb_info *info)
+{
+       return 0;
+}
+
+/**
+ *      ffb_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int ffb_setcolreg(unsigned regno,
+                        unsigned red, unsigned green, unsigned blue,
+                        unsigned transp, struct fb_info *info)
+{
+       u32 value;
+
+       if (regno >= 256)
+               return 1;
+
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+
+       value = (blue << 16) | (green << 8) | red;
+       ((u32 *)info->pseudo_palette)[regno] = value;
+
+       return 0;
+}
+
+/**
+ *      ffb_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+ffb_blank(int blank, struct fb_info *info)
+{
+       struct ffb_par *par = (struct ffb_par *) info->par;
+       struct ffb_dac *dac = par->dac;
+       unsigned long flags;
+       u32 tmp;
+
+       spin_lock_irqsave(&par->lock, flags);
+
+       FFBWait(par);
+
+       switch (blank) {
+       case 0: /* Unblanking */
+               upa_writel(0x6000, &dac->type);
+               tmp = (upa_readl(&dac->value) | 0x1);
+               upa_writel(0x6000, &dac->type);
+               upa_writel(tmp, &dac->value);
+               par->flags &= ~FFB_FLAG_BLANKED;
+               break;
+
+       case 1: /* Normal blanking */
+       case 2: /* VESA blank (vsync off) */
+       case 3: /* VESA blank (hsync off) */
+       case 4: /* Poweroff */
+               upa_writel(0x6000, &dac->type);
+               tmp = (upa_readl(&dac->value) & ~0x1);
+               upa_writel(0x6000, &dac->type);
+               upa_writel(tmp, &dac->value);
+               par->flags |= FFB_FLAG_BLANKED;
+               break;
+       }
+
+       spin_unlock_irqrestore(&par->lock, flags);
+
+       return 0;
+}
+
+static struct sbus_mmap_map ffb_mmap_map[] = {
+       { FFB_SFB8R_VOFF,       FFB_SFB8R_POFF,         0x0400000 },
+       { FFB_SFB8G_VOFF,       FFB_SFB8G_POFF,         0x0400000 },
+       { FFB_SFB8B_VOFF,       FFB_SFB8B_POFF,         0x0400000 },
+       { FFB_SFB8X_VOFF,       FFB_SFB8X_POFF,         0x0400000 },
+       { FFB_SFB32_VOFF,       FFB_SFB32_POFF,         0x1000000 },
+       { FFB_SFB64_VOFF,       FFB_SFB64_POFF,         0x2000000 },
+       { FFB_FBC_REGS_VOFF,    FFB_FBC_REGS_POFF,      0x0002000 },
+       { FFB_BM_FBC_REGS_VOFF, FFB_BM_FBC_REGS_POFF,   0x0002000 },
+       { FFB_DFB8R_VOFF,       FFB_DFB8R_POFF,         0x0400000 },
+       { FFB_DFB8G_VOFF,       FFB_DFB8G_POFF,         0x0400000 },
+       { FFB_DFB8B_VOFF,       FFB_DFB8B_POFF,         0x0400000 },
+       { FFB_DFB8X_VOFF,       FFB_DFB8X_POFF,         0x0400000 },
+       { FFB_DFB24_VOFF,       FFB_DFB24_POFF,         0x1000000 },
+       { FFB_DFB32_VOFF,       FFB_DFB32_POFF,         0x1000000 },
+       { FFB_FBC_KREGS_VOFF,   FFB_FBC_KREGS_POFF,     0x0002000 },
+       { FFB_DAC_VOFF,         FFB_DAC_POFF,           0x0002000 },
+       { FFB_PROM_VOFF,        FFB_PROM_POFF,          0x0010000 },
+       { FFB_EXP_VOFF,         FFB_EXP_POFF,           0x0002000 },
+       { FFB_DFB422A_VOFF,     FFB_DFB422A_POFF,       0x0800000 },
+       { FFB_DFB422AD_VOFF,    FFB_DFB422AD_POFF,      0x0800000 },
+       { FFB_DFB24B_VOFF,      FFB_DFB24B_POFF,        0x1000000 },
+       { FFB_DFB422B_VOFF,     FFB_DFB422B_POFF,       0x0800000 },
+       { FFB_DFB422BD_VOFF,    FFB_DFB422BD_POFF,      0x0800000 },
+       { FFB_SFB16Z_VOFF,      FFB_SFB16Z_POFF,        0x0800000 },
+       { FFB_SFB8Z_VOFF,       FFB_SFB8Z_POFF,         0x0800000 },
+       { FFB_SFB422_VOFF,      FFB_SFB422_POFF,        0x0800000 },
+       { FFB_SFB422D_VOFF,     FFB_SFB422D_POFF,       0x0800000 },
+       { 0,                    0,                      0         }
+};
+
+static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+       struct ffb_par *par = (struct ffb_par *)info->par;
+
+       return sbusfb_mmap_helper(ffb_mmap_map,
+                                 par->physbase, par->fbsize,
+                                 0, vma);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+ffb_init_fix(struct fb_info *info)
+{
+       struct ffb_par *par = (struct ffb_par *)info->par;
+       const char *ffb_type_name;
+
+       if (!(par->flags & FFB_FLAG_AFB)) {
+               if ((par->board_type & 0x7) == 0x3)
+                       ffb_type_name = "Creator 3D";
+               else
+                       ffb_type_name = "Creator";
+       } else
+               ffb_type_name = "Elite 3D";
+
+       strncpy(info->fix.id, ffb_type_name, sizeof(info->fix.id) - 1);
+       info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+       /* Framebuffer length is the same regardless of resolution. */
+       info->fix.line_length = 8192;
+
+       info->fix.accel = FB_ACCEL_SUN_CREATOR;
+}
+
+static int ffb_apply_upa_parent_ranges(int parent,
+                                      struct linux_prom64_registers *regs)
+{
+       struct linux_prom64_ranges ranges[PROMREG_MAX];
+       char name[128];
+       int len, i;
+
+       prom_getproperty(parent, "name", name, sizeof(name));
+       if (strcmp(name, "upa") != 0)
+               return 0;
+
+       len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
+       if (len <= 0)
+               return 1;
+
+       len /= sizeof(struct linux_prom64_ranges);
+       for (i = 0; i < len; i++) {
+               struct linux_prom64_ranges *rng = &ranges[i];
+               u64 phys_addr = regs->phys_addr;
+
+               if (phys_addr >= rng->ot_child_base &&
+                   phys_addr < (rng->ot_child_base + rng->or_size)) {
+                       regs->phys_addr -= rng->ot_child_base;
+                       regs->phys_addr += rng->ot_parent_base;
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+struct all_info {
+       struct fb_info info;
+       struct ffb_par par;
+       u32 pseudo_palette[256];
+       struct list_head list;
+};
+static LIST_HEAD(ffb_list);
+
+static void ffb_init_one(int node, int parent)
+{
+       struct linux_prom64_registers regs[2*PROMREG_MAX];
+       struct ffb_fbc *fbc;
+       struct ffb_dac *dac;
+       struct all_info *all;
+
+       if (prom_getproperty(node, "reg", (void *) regs, sizeof(regs)) <= 0) {
+               printk("ffb: Cannot get reg device node property.\n");
+               return;
+       }
+
+       if (ffb_apply_upa_parent_ranges(parent, &regs[0])) {
+               printk("ffb: Cannot apply parent ranges to regs.\n");
+               return;
+       }
+
+       all = kmalloc(sizeof(*all), GFP_KERNEL);
+       if (!all) {
+               printk(KERN_ERR "ffb: Cannot allocate memory.\n");
+               return;
+       }
+       memset(all, 0, sizeof(*all));
+
+       INIT_LIST_HEAD(&all->list);     
+
+       spin_lock_init(&all->par.lock);
+       all->par.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
+       all->par.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
+       all->par.rop_cache = FFB_ROP_NEW;
+       all->par.physbase = regs[0].phys_addr;
+       all->par.prom_node = node;
+       all->par.prom_parent_node = parent;
+
+       all->info.node = NODEV;
+       all->info.flags = FBINFO_FLAG_DEFAULT;
+       all->info.fbops = &ffb_ops;
+       all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
+       all->info.currcon = -1;
+       all->info.par = &all->par;
+       all->info.pseudo_palette = all->pseudo_palette;
+
+       sbusfb_fill_var(&all->info.var, all->par.prom_node, 32);
+       all->par.fbsize = PAGE_ALIGN(all->info.var.xres *
+                                    all->info.var.yres *
+                                    4);
+       ffb_fixup_var_rgb(&all->info.var);
+
+       all->info.var.accel_flags = FB_ACCELF_TEXT;
+
+       prom_getstring(node, "name", all->par.name, sizeof(all->par.name));
+       if (!strcmp(all->par.name, "SUNW,afb"))
+               all->par.flags |= FFB_FLAG_AFB;
+
+       all->par.board_type = prom_getintdefault(node, "board_type", 0);
+
+       fbc = all->par.fbc;
+       if((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
+               upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
+
+       ffb_switch_from_graph(&all->par);
+
+       dac = all->par.dac;
+       upa_writel(0x8000, &dac->type);
+       all->par.dac_rev = upa_readl(&dac->value) >> 0x1c;
+
+       /* Elite3D has different DAC revision numbering, and no DAC revisions
+        * have the reversed meaning of cursor enable.
+        */
+       if (all->par.flags & FFB_FLAG_AFB)
+               all->par.dac_rev = 10;
+
+       /* Unblank it just to be sure.  When there are multiple
+        * FFB/AFB cards in the system, or it is not the OBP
+        * chosen console, it will have video outputs off in
+        * the DAC.
+        */
+       ffb_blank(0, &all->info);
+
+       if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+               printk(KERN_ERR "ffb: Could not allocate color map.\n");
+               kfree(all);
+               return;
+       }
+
+       ffb_set_par(&all->info);
+       ffb_init_fix(&all->info);
+
+       if (register_framebuffer(&all->info) < 0) {
+               printk(KERN_ERR "ffb: Could not register framebuffer.\n");
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+               return;
+       }
+
+       list_add(&all->list, &ffb_list);
+
+       printk("ffb: %s at %016lx type %d DAC %d\n",
+              ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
+              regs[0].phys_addr, all->par.board_type, all->par.dac_rev);
+}
+
+static void ffb_scan_siblings(int root)
+{
+       int node, child;
+
+       child = prom_getchild(root);
+       for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
+            node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
+               ffb_init_one(node, root);
+       for (node = prom_searchsiblings(child, "SUNW,afb"); node;
+            node = prom_searchsiblings(prom_getsibling(node), "SUNW,afb"))
+               ffb_init_one(node, root);
+}
+
+int __init ffb_init(void)
+{
+       int root;
+
+       ffb_scan_siblings(prom_root_node);
+
+       root = prom_getchild(prom_root_node);
+       for (root = prom_searchsiblings(root, "upa"); root;
+            root = prom_searchsiblings(prom_getsibling(root), "upa"))
+               ffb_scan_siblings(root);
+
+       return 0;
+}
+
+void __exit ffb_exit(void)
+{
+       struct list_head *pos, *tmp;
+
+       list_for_each_safe(pos, tmp, &ffb_list) {
+               struct all_info *all = list_entry(pos, typeof(*all), list);
+
+               unregister_framebuffer(&all->info);
+               fb_dealloc_cmap(&all->info.cmap);
+               kfree(all);
+       }
+}
+
+int __init
+ffb_setup(char *arg)
+{
+       /* No cmdline options yet... */
+       return 0;
+}
+
+#ifdef MODULE
+module_init(ffb_init);
+module_exit(ffb_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
deleted file mode 100644 (file)
index dd15273..0000000
+++ /dev/null
@@ -1,1165 +0,0 @@
-/*
- *  linux/drivers/video/sbusfb.c -- SBUS or UPA based frame buffer device
- *
- *     Copyright (C) 1998 Jakub Jelinek
- *
- *  This driver is partly based on the Open Firmware console driver
- *
- *     Copyright (C) 1997 Geert Uytterhoeven
- *
- *  and SPARC console subsystem
- *
- *      Copyright (C) 1995 Peter Zaitcev (zaitcev@yahoo.com)
- *      Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu)
- *      Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- *      Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- *      Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *      Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- *
- *  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/config.h>
-#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/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>       /* io_remap_page_range() */
-
-#include <video/sbusfb.h>
-
-#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)
-
-#define CURSOR_SHAPE                   1
-#define CURSOR_BLINK                   2
-
-    /*
-     *  Interface used by the world
-     */
-
-int sbusfb_init(void);
-int sbusfb_setup(char*);
-
-static int defx_margin = -1, defy_margin = -1;
-static char fontname[40] __initdata = { 0 };
-static int curblink __initdata = 1;
-static struct {
-       int depth;
-       int xres, yres;
-       int x_margin, y_margin;
-} def_margins [] = {
-       { 8, 1280, 1024, 64, 80 },
-       { 8, 1152, 1024, 64, 80 },
-       { 8, 1152, 900,  64, 18 },
-       { 8, 1024, 768,  0,  0 },
-       { 8, 800, 600, 16, 12 },
-       { 8, 640, 480, 0, 0 },
-       { 1, 1152, 900,  8,  18 },
-       { 0 },
-};
-
-static int sbusfb_open(struct fb_info *info, int user);
-static int sbusfb_release(struct fb_info *info, int user);
-static int sbusfb_mmap(struct fb_info *info, struct file *file, 
-                       struct vm_area_struct *vma);
-static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,
-                       struct fb_info *info);
-static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-                       struct fb_info *info);
-static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-                       struct fb_info *info);
-static int sbusfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                           u_int transp, struct fb_info *info);
-static int sbusfb_blank(int blank, struct fb_info *info);
-static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-                           u_long arg, int con, struct fb_info *info);
-static void sbusfb_cursor(struct display *p, int mode, int x, int y);
-static void sbusfb_clear_margin(struct display *p, int s);
-                           
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-static int sbusfbcon_switch(int con, struct fb_info *info);
-static int sbusfbcon_updatevar(int con, struct fb_info *info);
-
-    /*
-     *  Internal routines
-     */
-
-static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                           u_int *transp, struct fb_info *info);
-
-static struct fb_ops sbusfb_ops = {
-       .owner =        THIS_MODULE,
-       .fb_open =      sbusfb_open,
-       .fb_release =   sbusfb_release,
-       .fb_set_var =   sbusfb_set_var,
-       .fb_get_cmap =  sbusfb_get_cmap,
-       .fb_set_cmap =  sbusfb_set_cmap,
-       .fb_setcolreg = sbusfb_setcolreg,
-       .fb_blank =     sbusfb_blank,
-       .fb_ioctl =     sbusfb_ioctl,
-       .fb_mmap =      sbusfb_mmap,
-};
-
-    /*
-     *  Open/Release the frame buffer device
-     */
-
-static int sbusfb_open(struct fb_info *info, int user)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-       
-       if (user) {
-               if (fb->open == 0) {
-                       fb->mmaped = 0;
-                       fb->vtconsole = -1;
-               }
-               fb->open++;
-       } else
-               fb->consolecnt++;
-       return 0;
-}
-
-static int sbusfb_release(struct fb_info *info, int user)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-       if (user) {     
-               fb->open--;
-               if (fb->open == 0) {
-                       if (fb->vtconsole != -1) {
-                               vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
-                               if (fb->mmaped) {
-                                       fb->graphmode--;
-                                       sbusfb_clear_margin(&fb_display[fb->vtconsole], 0);
-                               }
-                       }
-                       if (fb->reset)
-                               fb->reset(fb);
-               }
-       } else
-               fb->consolecnt--;
-       return 0;
-}
-
-static unsigned long sbusfb_mmapsize(struct fb_info_sbusfb *fb, long size)
-{
-       if (size == SBUS_MMAP_EMPTY) return 0;
-       if (size >= 0) return size;
-       return fb->type.fb_size * (-size);
-}
-
-static int sbusfb_mmap(struct fb_info *info, struct file *file, 
-                       struct vm_area_struct *vma)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-       unsigned int size, page, r, map_size;
-       unsigned long map_offset = 0;
-       unsigned long off;
-       int i;
-                                        
-       size = vma->vm_end - vma->vm_start;
-       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-               return -EINVAL;
-
-       off = vma->vm_pgoff << PAGE_SHIFT;
-
-       /* To stop the swapper from even considering these pages */
-       vma->vm_flags |= (VM_SHM| VM_LOCKED);
-       
-
-       /* Each page, see which map applies */
-       for (page = 0; page < size; ){
-               map_size = 0;
-               for (i = 0; fb->mmap_map[i].size; i++)
-                       if (fb->mmap_map[i].voff == off+page) {
-                               map_size = sbusfb_mmapsize(fb,fb->mmap_map[i].size);
-#ifdef __sparc_v9__
-#define POFF_MASK      (PAGE_MASK|0x1UL)
-#else
-#define POFF_MASK      (PAGE_MASK)
-#endif                         
-                               map_offset = (fb->physbase + fb->mmap_map[i].poff) & POFF_MASK;
-                               break;
-                       }
-               if (!map_size){
-                       page += PAGE_SIZE;
-                       continue;
-               }
-               if (page + map_size > size)
-                       map_size = size - page;
-               r = io_remap_page_range(vma, vma->vm_start+page, map_offset, map_size, vma->vm_page_prot, fb->iospace);
-               if (r)
-                       return -EAGAIN;
-               page += map_size;
-       }
-       
-       vma->vm_flags |= VM_IO;
-       if (!fb->mmaped) {
-               int lastconsole = 0;
-               
-               if (info->display_fg)
-                       lastconsole = info->display_fg->vc_num;
-               fb->mmaped = 1;
-               if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
-                       fb->vtconsole = lastconsole;
-                       fb->graphmode++;
-                       vt_cons [lastconsole]->vc_mode = KD_GRAPHICS;
-                       vc_cons[lastconsole].d->vc_sw->con_cursor(vc_cons[lastconsole].d,CM_ERASE);
-               } else if (fb->unblank && !fb->blanked)
-                       (*fb->unblank)(fb);
-       }
-       return 0;
-}
-
-static void sbusfb_clear_margin(struct display *p, int s)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-       if (fb->switch_from_graph)
-               (*fb->switch_from_graph)(fb);
-       if (fb->fill) {
-               unsigned short rects [16];
-
-               rects [0] = 0;
-               rects [1] = 0;
-               rects [2] = fb->info.var.xres_virtual;
-               rects [3] = fb->y_margin;
-               rects [4] = 0;
-               rects [5] = fb->y_margin;
-               rects [6] = fb->x_margin;
-               rects [7] = fb->info.var.yres_virtual;
-               rects [8] = fb->info.var.xres_virtual - fb->x_margin;
-               rects [9] = fb->y_margin;
-               rects [10] = fb->info.var.xres_virtual;
-               rects [11] = fb->info.var.yres_virtual;
-               rects [12] = fb->x_margin;
-               rects [13] = fb->info.var.yres_virtual - fb->y_margin;
-               rects [14] = fb->info.var.xres_virtual - fb->x_margin;
-               rects [15] = fb->info.var.yres_virtual;
-               (*fb->fill)(fb, p, s, 4, rects);
-       } else {
-               unsigned char *fb_base = fb->info.screen_base, *q;
-               int skip_bytes = fb->y_margin * fb->info.var.xres_virtual;
-               int scr_size = fb->info.var.xres_virtual
-                       * fb->info.var.yres_virtual;
-               int h, he, incr, size;
-
-               he = fb->info.var.yres;
-               if (fb->info.var.bits_per_pixel == 1) {
-                       fb_base -= (skip_bytes + fb->x_margin) / 8;
-                       skip_bytes /= 8;
-                       scr_size /= 8;
-                       fb_memset255 (fb_base, skip_bytes - fb->x_margin / 8);
-                       fb_memset255 (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);
-                       incr = fb->info.var.xres_virtual / 8;
-                       size = fb->x_margin / 8 * 2;
-                       for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;
-                            h <= he; q += incr, h++)
-                               fb_memset255 (q, size);
-               } else {
-                       fb_base -= (skip_bytes + fb->x_margin);
-                       fb_memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-                       fb_memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-                       incr = fb->info.var.xres_virtual;
-                       size = fb->x_margin * 2;
-                       for (q = fb_base + skip_bytes - fb->x_margin, h = 0;
-                            h <= he; q += incr, h++)
-                               fb_memset (q, attr_bgcol(p,s), size);
-               }
-       }
-}
-
-static void sbusfb_disp_setup(struct display *p)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-       if (fb->setup)
-               fb->setup(p);   
-       sbusfb_clear_margin(p, 0);
-}
-
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,
-                         struct fb_info *info)
-{
-       struct display *display;
-       int activate = var->activate;
-
-       if(con >= 0)
-               display = &fb_display[con];
-       else
-               display = info->disp;
-
-       /* simple check for equality until fully implemented -E */
-       if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-               if (display->var.xres != var->xres ||
-                       display->var.yres != var->yres ||
-                       display->var.xres_virtual != var->xres_virtual ||
-                       display->var.yres_virtual != var->yres_virtual ||
-                       display->var.bits_per_pixel != var->bits_per_pixel ||
-                       display->var.accel_flags != var->accel_flags) {
-                       return -EINVAL;
-               }
-       }
-       return 0;
-
-}
-
-    /*
-     *  Hardware cursor
-     */
-     
-static int sbus_hw_scursor (struct fbcursor *cursor, struct fb_info_sbusfb *fb)
-{
-       int op;
-       int i, bytes = 0;
-       struct fbcursor f;
-       char red[2], green[2], blue[2];
-       
-       if (copy_from_user (&f, cursor, sizeof(struct fbcursor)))
-               return -EFAULT;
-       op = f.set;
-       if (op & FB_CUR_SETSHAPE){
-               if ((u32) f.size.fbx > fb->cursor.hwsize.fbx)
-                       return -EINVAL;
-               if ((u32) f.size.fby > fb->cursor.hwsize.fby)
-                       return -EINVAL;
-               if (f.size.fbx > 32)
-                       bytes = f.size.fby << 3;
-               else
-                       bytes = f.size.fby << 2;
-       }
-       if (op & FB_CUR_SETCMAP){
-               if (f.cmap.index || f.cmap.count != 2)
-                       return -EINVAL;
-               if (copy_from_user (red, f.cmap.red, 2) ||
-                   copy_from_user (green, f.cmap.green, 2) ||
-                   copy_from_user (blue, f.cmap.blue, 2))
-                       return -EFAULT;
-       }
-       if (op & FB_CUR_SETCMAP)
-               (*fb->setcursormap) (fb, red, green, blue);
-       if (op & FB_CUR_SETSHAPE){
-               u32 u;
-               
-               fb->cursor.size = f.size;
-               memset ((void *)&fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-               if (copy_from_user (fb->cursor.bits [0], f.mask, bytes) ||
-                   copy_from_user (fb->cursor.bits [1], f.image, bytes))
-                       return -EFAULT;
-               if (f.size.fbx <= 32) {
-                       u = 0xffffffff << (32 - f.size.fbx);
-                       for (i = fb->cursor.size.fby - 1; i >= 0; i--) {
-                               fb->cursor.bits [0][i] &= u;
-                               fb->cursor.bits [1][i] &= fb->cursor.bits [0][i];
-                       }
-               } else {
-                       u = 0xffffffff << (64 - f.size.fbx);
-                       for (i = fb->cursor.size.fby - 1; i >= 0; i--) {
-                               fb->cursor.bits [0][2*i+1] &= u;
-                               fb->cursor.bits [1][2*i] &= fb->cursor.bits [0][2*i];
-                               fb->cursor.bits [1][2*i+1] &= fb->cursor.bits [0][2*i+1];
-                       }
-               }
-               (*fb->setcurshape) (fb);
-       }
-       if (op & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)){
-               if (op & FB_CUR_SETCUR)
-                       fb->cursor.enable = f.enable;
-               if (op & FB_CUR_SETPOS)
-                       fb->cursor.cpos = f.pos;
-               if (op & FB_CUR_SETHOT)
-                       fb->cursor.chot = f.hot;
-               (*fb->setcursor) (fb);
-       }
-       return 0;
-}
-
-static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
-
-static void
-sbusfb_cursor_timer_handler(unsigned long dev_addr)
-{
-       struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
-        
-       if (!fb->setcursor) return;
-                                
-       if (fb->cursor.mode & CURSOR_BLINK) {
-               fb->cursor.enable ^= 1;
-               fb->setcursor(fb);
-       }
-       
-       fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-       add_timer(&fb->cursor.timer);
-}
-
-static void sbusfb_cursor(struct display *p, int mode, int x, int y)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfod(p);
-       
-       switch (mode) {
-       case CM_ERASE:
-               fb->cursor.mode &= ~CURSOR_BLINK;
-               fb->cursor.enable = 0;
-               (*fb->setcursor)(fb);
-               break;
-                                 
-       case CM_MOVE:
-       case CM_DRAW:
-               if (fb->cursor.mode & CURSOR_SHAPE) {
-                       fb->cursor.size.fbx = fontwidth(p);
-                       fb->cursor.size.fby = fontheight(p);
-                       fb->cursor.chot.fbx = 0;
-                       fb->cursor.chot.fby = 0;
-                       fb->cursor.enable = 1;
-                       memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-                       fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-                       fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-                       fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-                       fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-                       (*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
-                       (*fb->setcurshape) (fb);
-               }
-               fb->cursor.mode = CURSOR_BLINK;
-               if (fontwidthlog(p))
-                       fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
-               else
-                       fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
-               if (fontheightlog(p))
-                       fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
-               else
-                       fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
-               (*fb->setcursor)(fb);
-               break;
-       }
-}
-
-    /*
-     *  Get the Colormap
-     */
-
-static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-                        struct fb_info *info)
-{
-       if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
-               return fb_get_cmap(cmap, kspc, sbusfb_getcolreg, info);
-       else if (fb_display[con].cmap.len) /* non default colormap? */
-               fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-       else
-               fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
-       return 0;
-}
-
-    /*
-     *  Set the Colormap
-     */
-
-static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-                        struct fb_info *info)
-{
-       int err;
-       struct display *disp;
-
-       if (con >= 0)
-               disp = &fb_display[con];
-       else
-               disp = info->disp;
-       if (!disp->cmap.len) {  /* no colormap allocated? */
-               if ((err = fb_alloc_cmap(&disp->cmap, 1<<disp->var.bits_per_pixel, 0)))
-                       return err;
-       }
-       if (con == info->currcon) {                     /* current console? */
-               err = fb_set_cmap(cmap, kspc, info);
-               if (!err) {
-                       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-                       
-                       if (fb->loadcmap)
-                               (*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
-               }
-               return err;
-       } else
-               fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
-       return 0;
-}
-
-static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-                       u_long arg, int con, struct fb_info *info)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-       int i;
-       int lastconsole;
-       
-       switch (cmd){
-       case FBIOGTYPE:         /* return frame buffer type */
-               if (copy_to_user((struct fbtype *)arg, &fb->type, sizeof(struct fbtype)))
-                       return -EFAULT;
-               break;
-       case FBIOGATTR: {
-               struct fbgattr *fba = (struct fbgattr *) arg;
-               
-               i = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct fbgattr));
-               if (i) return i;
-               if (__put_user(fb->emulations[0], &fba->real_type) ||
-                   __put_user(0, &fba->owner) ||
-                   __copy_to_user(&fba->fbtype, &fb->type,
-                                  sizeof(struct fbtype)) ||
-                   __put_user(0, &fba->sattr.flags) ||
-                   __put_user(fb->type.fb_type, &fba->sattr.emu_type) ||
-                   __put_user(-1, &fba->sattr.dev_specific[0]))
-                       return -EFAULT;
-               for (i = 0; i < 4; i++) {
-                       if (put_user(fb->emulations[i], &fba->emu_types[i]))
-                               return -EFAULT;
-               }
-               break;
-       }
-       case FBIOSATTR:
-               i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbsattr));
-               if (i) return i;
-               return -EINVAL;
-       case FBIOSVIDEO:
-               if (fb->consolecnt) {
-                       lastconsole = info->display_fg->vc_num;
-                       if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
-                               break;
-               }
-               if (get_user(i, (int *)arg))
-                       return -EFAULT;
-               if (i){
-                       if (!fb->blanked || !fb->unblank)
-                               break;
-                       if (fb->consolecnt || (fb->open && fb->mmaped))
-                               (*fb->unblank)(fb);
-                       fb->blanked = 0;
-               } else {
-                       if (fb->blanked || !fb->blank)
-                               break;
-                       (*fb->blank)(fb);
-                       fb->blanked = 1;
-               }
-               break;
-       case FBIOGVIDEO:
-               if (put_user(fb->blanked, (int *) arg))
-                       return -EFAULT;
-               break;
-       case FBIOGETCMAP_SPARC: {
-               char *rp, *gp, *bp;
-               int end, count, index;
-               struct fbcmap *cmap;
-
-               if (!fb->loadcmap)
-                       return -EINVAL;
-               i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap));
-               if (i) return i;
-               cmap = (struct fbcmap *) arg;
-               if (__get_user(count, &cmap->count) ||
-                   __get_user(index, &cmap->index))
-                       return -EFAULT;
-               if ((index < 0) || (index > 255))
-                       return -EINVAL;
-               if (index + count > 256)
-                       count = 256 - index;
-               if (__get_user(rp, &cmap->red) ||
-                   __get_user(gp, &cmap->green) ||
-                   __get_user(bp, &cmap->blue))
-                       return -EFAULT;
-               if (verify_area (VERIFY_WRITE, rp, count))
-                       return -EFAULT;
-               if (verify_area (VERIFY_WRITE, gp, count))
-                       return -EFAULT;
-               if (verify_area (VERIFY_WRITE, bp, count))
-                       return -EFAULT;
-               end = index + count;
-               for (i = index; i < end; i++){
-                       if (__put_user(fb->color_map CM(i,0), rp) ||
-                           __put_user(fb->color_map CM(i,1), gp) ||
-                           __put_user(fb->color_map CM(i,2), bp))
-                               return -EFAULT;
-                       rp++; gp++; bp++;
-               }
-               (*fb->loadcmap)(fb, NULL, index, count);
-               break;                  
-       }
-       case FBIOPUTCMAP_SPARC: {       /* load color map entries */
-               char *rp, *gp, *bp;
-               int end, count, index;
-               struct fbcmap *cmap;
-               
-               if (!fb->loadcmap || !fb->color_map)
-                       return -EINVAL;
-               i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap));
-               if (i) return i;
-               cmap = (struct fbcmap *) arg;
-               if (__get_user(count, &cmap->count) ||
-                   __get_user(index, &cmap->index))
-                       return -EFAULT;
-               if ((index < 0) || (index > 255))
-                       return -EINVAL;
-               if (index + count > 256)
-                       count = 256 - index;
-               if (__get_user(rp, &cmap->red) ||
-                   __get_user(gp, &cmap->green) ||
-                   __get_user(bp, &cmap->blue))
-                       return -EFAULT;
-               if (verify_area (VERIFY_READ, rp, count))
-                       return -EFAULT;
-               if (verify_area (VERIFY_READ, gp, count))
-                       return -EFAULT;
-               if (verify_area (VERIFY_READ, bp, count))
-                       return -EFAULT;
-
-               end = index + count;
-               for (i = index; i < end; i++){
-                       if (__get_user(fb->color_map CM(i,0), rp))
-                               return -EFAULT;
-                       if (__get_user(fb->color_map CM(i,1), gp))
-                               return -EFAULT;
-                       if (__get_user(fb->color_map CM(i,2), bp))
-                               return -EFAULT;
-                       rp++; gp++; bp++;
-               }
-               (*fb->loadcmap)(fb, NULL, index, count);
-               break;                  
-       }
-       case FBIOGCURMAX: {
-               struct fbcurpos *p = (struct fbcurpos *) arg;
-               if (!fb->setcursor) return -EINVAL;
-               if(verify_area (VERIFY_WRITE, p, sizeof (struct fbcurpos)))
-                       return -EFAULT;
-               if (__put_user(fb->cursor.hwsize.fbx, &p->fbx) ||
-                   __put_user(fb->cursor.hwsize.fby, &p->fby))
-                       return -EFAULT;
-               break;
-       }
-       case FBIOSCURSOR:
-               if (!fb->setcursor) return -EINVAL;
-               if (fb->consolecnt) {
-                       lastconsole = info->display_fg->vc_num; 
-                       if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
-                               return -EINVAL; /* Don't let graphics programs hide our nice text cursor */
-                       fb->cursor.mode = CURSOR_SHAPE; /* Forget state of our text cursor */
-               }
-               return sbus_hw_scursor ((struct fbcursor *) arg, fb);
-
-       case FBIOSCURPOS:
-               if (!fb->setcursor) return -EINVAL;
-               /* Don't let graphics programs move our nice text cursor */
-               if (fb->consolecnt) {
-                       lastconsole = info->display_fg->vc_num; 
-                       if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
-                               return -EINVAL; /* Don't let graphics programs move our nice text cursor */
-               }
-               if (copy_from_user(&fb->cursor.cpos, (void *)arg, sizeof(struct fbcurpos)))
-                       return -EFAULT;
-               (*fb->setcursor) (fb);
-               break;
-       default:
-               if (fb->ioctl)
-                       return fb->ioctl(fb, cmd, arg);
-               return -EINVAL;
-       }               
-       return 0;
-}
-
-    /*
-     *  Setup: parse used options
-     */
-
-int __init sbusfb_setup(char *options)
-{
-       char *p;
-       
-       for (p = options;;) {
-               if (!strncmp(p, "nomargins", 9)) {
-                       defx_margin = 0; defy_margin = 0;
-               } else if (!strncmp(p, "margins=", 8)) {
-                       int i, j;
-                       char *q;
-                       
-                       i = simple_strtoul(p+8,&q,10);
-                       if (i >= 0 && *q == 'x') {
-                           j = simple_strtoul(q+1,&q,10);
-                           if (j >= 0 && (*q == ' ' || !*q)) {
-                               defx_margin = i; defy_margin = j;
-                           }
-                       }
-               } else if (!strncmp(p, "font=", 5)) {
-                       int i;
-                       
-                       for (i = 0; i < sizeof(fontname) - 1; i++)
-                               if (p[i+5] == ' ' || !p[i+5])
-                                       break;
-                       memcpy(fontname, p+5, i);
-                       fontname[i] = 0;
-               } else if (!strncmp(p, "noblink", 7))
-                       curblink = 0;
-               while (*p && *p != ' ' && *p != ',') p++;
-               if (*p != ',') break;
-               p++;
-       }
-       return 0;
-}
-
-static int sbusfbcon_switch(int con, struct fb_info *info)
-{
-       int x_margin, y_margin;
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-       int lastconsole;
-    
-       /* Do we have to save the colormap? */
-       if (fb_display[info->currcon].cmap.len)
-               fb_get_cmap(&fb_display[info->currcon].cmap, 1, sbusfb_getcolreg, info);
-
-       if (info->display_fg) {
-               lastconsole = info->display_fg->vc_num;
-               if (lastconsole != con && 
-                   (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
-                    fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
-                       fb->cursor.mode |= CURSOR_SHAPE;
-       }
-       x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
-       y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
-       if (fb->margins)
-               fb->margins(fb, &fb_display[con], x_margin, y_margin);
-       if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) {
-               fb->x_margin = x_margin; fb->y_margin = y_margin;
-               sbusfb_clear_margin(&fb_display[con], 0);
-       }
-       info->currcon = con;
-       /* Install new colormap */
-       do_install_cmap(con, info);
-       return 0;
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int sbusfbcon_updatevar(int con, struct fb_info *info)
-{
-       /* Nothing */
-       return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int sbusfb_blank(int blank, struct fb_info *info)
-{
-    struct fb_info_sbusfb *fb = sbusfbinfo(info);
-    
-    if (blank && fb->blank)
-           return fb->blank(fb);
-    else if (!blank && fb->unblank)
-           return fb->unblank(fb);
-    return 0;
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-       if (!fb->color_map || regno > 255)
-               return 1;
-       *red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
-       *green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
-       *blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
-       *transp = 0;
-       return 0;
-}
-
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int sbusfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                           u_int transp, struct fb_info *info)
-{
-       struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-       if (!fb->color_map || regno > 255)
-               return 1;
-       red >>= 8;
-       green >>= 8;
-       blue >>= 8;
-       fb->color_map CM(regno, 0) = red;
-       fb->color_map CM(regno, 1) = green;
-       fb->color_map CM(regno, 2) = blue;
-       return 0;
-}
-
-static int sbusfb_set_font(struct display *p, int width, int height)
-{
-       int margin;
-       int w = p->var.xres_virtual, h = p->var.yres_virtual;
-       int depth = p->var.bits_per_pixel;
-       struct fb_info_sbusfb *fb = sbusfbinfod(p);
-       int x_margin, y_margin;
-       
-       if (depth > 8) depth = 8;
-       x_margin = 0;
-       y_margin = 0;
-       if (defx_margin < 0 || defy_margin < 0) {
-               for (margin = 0; def_margins[margin].depth; margin++)
-                       if (w == def_margins[margin].xres &&
-                           h == def_margins[margin].yres &&
-                           depth == def_margins[margin].depth) {
-                               x_margin = def_margins[margin].x_margin;
-                               y_margin = def_margins[margin].y_margin;
-                               break;
-                       }
-       } else {
-               x_margin = defx_margin;
-               y_margin = defy_margin;
-       }
-       x_margin += ((w - 2*x_margin) % width) / 2;
-       y_margin += ((h - 2*y_margin) % height) / 2;
-
-       p->var.xres = w - 2*x_margin;
-       p->var.yres = h - 2*y_margin;
-       
-       fb->cursor.mode |= CURSOR_SHAPE;
-       
-       if (fb->margins)
-               fb->margins(fb, p, x_margin, y_margin);
-       if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
-               fb->x_margin = x_margin; fb->y_margin = y_margin;
-               sbusfb_clear_margin(p, 0);
-       }
-
-       return 1;
-}
-
-void sbusfb_palette(int enter)
-{
-       int i;
-       struct display *p;
-       
-       for (i = 0; i < MAX_NR_CONSOLES; i++) {
-               p = &fb_display[i];
-               if (p->dispsw && p->dispsw->setup == sbusfb_disp_setup &&
-                   p->fb_info->display_fg &&
-                   p->fb_info->display_fg->vc_num == i) {
-                       struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-                       if (fb->restore_palette) {
-                               if (enter)
-                                       fb->restore_palette(fb);
-                               else if (vt_cons[i]->vc_mode != KD_GRAPHICS)
-                                        vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
-                       }
-               }
-       }
-}
-
-    /*
-     *  Initialisation
-     */
-     
-extern void (*prom_palette)(int);
-
-static void __init sbusfb_init_fb(int node, int parent, int fbtype,
-                                 struct sbus_dev *sbdp)
-{
-       struct fb_fix_screeninfo *fix;
-       struct fb_var_screeninfo *var;
-       struct display *disp;
-       struct fb_info_sbusfb *fb;
-       struct fbtype *type;
-       int linebytes, w, h, depth;
-       char *p = NULL;
-       int margin;
-
-       fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC);
-       if (!fb) {
-               prom_printf("Could not allocate sbusfb structure\n");
-               return;
-       }
-       
-       if (!prom_palette)
-               prom_palette = sbusfb_palette;
-       
-       memset(fb, 0, sizeof(struct fb_info_sbusfb));
-       fix = &fb->info.fix;
-       var = &fb->info.var;
-       disp = &fb->disp;
-       type = &fb->type;
-       
-       spin_lock_init(&fb->lock);
-       fb->prom_node = node;
-       fb->prom_parent = parent;
-       fb->sbdp = sbdp;
-       if (sbdp)
-               fb->iospace = sbdp->reg_addrs[0].which_io;
-
-       type->fb_type = fbtype;
-       memset(&fb->emulations, 0xff, sizeof(fb->emulations));
-       fb->emulations[0] = fbtype;
-       
-#ifdef CONFIG_SPARC32
-       fb->info.screen_base = (unsigned char *)prom_getintdefault(node, "address", 0);
-#endif
-       
-       type->fb_height = h = prom_getintdefault(node, "height", 900);
-       type->fb_width  = w = prom_getintdefault(node, "width", 1152);
-sizechange:
-       type->fb_depth  = depth = (fbtype == FBTYPE_SUN2BW) ? 1 : 8;
-       linebytes = prom_getintdefault(node, "linebytes", w * depth / 8);
-       type->fb_size   = PAGE_ALIGN((linebytes) * h);
-       
-       if (defx_margin < 0 || defy_margin < 0) {
-               for (margin = 0; def_margins[margin].depth; margin++)
-                       if (w == def_margins[margin].xres &&
-                           h == def_margins[margin].yres &&
-                           depth == def_margins[margin].depth) {
-                               fb->x_margin = def_margins[margin].x_margin;
-                               fb->y_margin = def_margins[margin].y_margin;
-                               break;
-                       }
-       } else {
-               fb->x_margin = defx_margin;
-               fb->y_margin = defy_margin;
-       }
-       fb->x_margin += ((w - 2*fb->x_margin) & 7) / 2;
-       fb->y_margin += ((h - 2*fb->y_margin) & 15) / 2;
-
-       var->xres_virtual = w;
-       var->yres_virtual = h;
-       var->xres = w - 2*fb->x_margin;
-       var->yres = h - 2*fb->y_margin;
-       
-       var->bits_per_pixel = depth;
-       var->height = var->width = -1;
-       var->pixclock = 10000;
-       var->vmode = FB_VMODE_NONINTERLACED;
-       var->red.length = var->green.length = var->blue.length = 8;
-
-       fix->line_length = linebytes;
-       fix->smem_len = type->fb_size;
-       fix->type = FB_TYPE_PACKED_PIXELS;
-       fix->visual = FB_VISUAL_PSEUDOCOLOR;
-       
-       fb->info.node = NODEV;
-       fb->info.fbops = &sbusfb_ops;
-       fb->info.disp = disp;
-       fb->info.currcon = -1;
-       strcpy(fb->info.fontname, fontname);
-       fb->info.changevar = NULL;
-       fb->info.switch_con = &sbusfbcon_switch;
-       fb->info.updatevar = &sbusfbcon_updatevar;
-       fb->info.flags = FBINFO_FLAG_DEFAULT;
-       
-       fb->cursor.hwsize.fbx = 32;
-       fb->cursor.hwsize.fby = 32;
-       
-       if (depth > 1 && !fb->color_map)
-               fb->color_map = kmalloc(256 * 3, GFP_ATOMIC);
-               
-       switch(fbtype) {
-#ifdef CONFIG_FB_CREATOR
-       case FBTYPE_CREATOR:
-               p = creatorfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_CGSIX
-       case FBTYPE_SUNFAST_COLOR:
-               p = cgsixfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_CGTHREE
-       case FBTYPE_SUN3COLOR:
-               p = cgthreefb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_TCX
-       case FBTYPE_TCXCOLOR:
-               p = tcxfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_LEO
-       case FBTYPE_SUNLEO:
-               p = leofb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_BWTWO
-       case FBTYPE_SUN2BW:
-               p = bwtwofb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_CGFOURTEEN
-       case FBTYPE_MDICOLOR:
-               p = cgfourteenfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_P9100
-       case FBTYPE_P9100COLOR:
-               /* Temporary crock. For now we are a cg3 */
-               p = p9100fb_init(fb); type->fb_type = FBTYPE_SUN3COLOR; break;
-#endif
-       }
-       
-       if (!p) {
-               if (fb->color_map)
-                       kfree(fb->color_map);
-               kfree(fb);
-               return;
-       }
-       
-       if (p == SBUSFBINIT_SIZECHANGE)
-               goto sizechange;
-
-       disp->dispsw = &fb->dispsw;
-       if (fb->setcursor) {
-               fb->dispsw.cursor = sbusfb_cursor;
-               if (curblink) {
-                       fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-                       init_timer(&fb->cursor.timer);
-                       fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-                       fb->cursor.timer.data = (unsigned long)fb;
-                       fb->cursor.timer.function = sbusfb_cursor_timer_handler;
-                       add_timer(&fb->cursor.timer);
-               }
-       }
-       fb->cursor.mode = CURSOR_SHAPE;
-       fb->dispsw.set_font = sbusfb_set_font;
-       fb->setup = fb->dispsw.setup;
-       fb->dispsw.setup = sbusfb_disp_setup;
-       fb->dispsw.clear_margins = NULL;
-
-       disp->var = *var;
-       
-       if (fb->blank)
-               disp->can_soft_blank = 1;
-
-       sbusfb_set_var(var, -1, &fb->info);
-
-       if (register_framebuffer(&fb->info) < 0) {
-               if (fb->color_map)
-                       kfree(fb->color_map);
-               kfree(fb);
-               return;
-       }
-       printk(KERN_INFO "fb%d: %s\n", minor(fb->info.node), p);
-}
-
-static inline int known_card(char *name)
-{
-       char *p;
-       for (p = name; *p && *p != ','; p++);
-       if (*p == ',') name = p + 1;
-       if (!strcmp(name, "cgsix") || !strcmp(name, "cgthree+"))
-               return FBTYPE_SUNFAST_COLOR;
-       if (!strcmp(name, "cgthree") || !strcmp(name, "cgRDI"))
-               return FBTYPE_SUN3COLOR;
-       if (!strcmp(name, "cgfourteen"))
-               return FBTYPE_MDICOLOR;
-       if (!strcmp(name, "leo"))
-               return FBTYPE_SUNLEO;
-       if (!strcmp(name, "bwtwo"))
-               return FBTYPE_SUN2BW;
-       if (!strcmp(name, "tcx"))
-               return FBTYPE_TCXCOLOR;
-       if (!strcmp(name, "p9100"))
-               return FBTYPE_P9100COLOR;
-       return FBTYPE_NOTYPE;
-}
-
-#ifdef CONFIG_FB_CREATOR
-static void creator_fb_scan_siblings(int root)
-{
-       int node, child;
-
-       child = prom_getchild(root);
-       for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
-            node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
-               sbusfb_init_fb(node, root, FBTYPE_CREATOR, NULL);
-       for (node = prom_searchsiblings(child, "SUNW,afb"); node;
-            node = prom_searchsiblings(prom_getsibling(node), "SUNW,afb"))
-               sbusfb_init_fb(node, root, FBTYPE_CREATOR, NULL);
-}
-
-static void creator_fb_scan(void)
-{
-       int root;
-
-       creator_fb_scan_siblings(prom_root_node);
-
-       root = prom_getchild(prom_root_node);
-       for (root = prom_searchsiblings(root, "upa"); root;
-            root = prom_searchsiblings(prom_getsibling(root), "upa"))
-               creator_fb_scan_siblings(root);
-}
-#endif
-
-int __init sbusfb_init(void)
-{
-       int type;
-       struct sbus_dev *sbdp;
-       struct sbus_bus *sbus;
-       char prom_name[40];
-       extern int con_is_present(void);
-       
-       if (!con_is_present()) return -ENXIO;
-       
-#ifdef CONFIG_FB_CREATOR
-       creator_fb_scan();
-#endif
-#ifdef CONFIG_SUN4
-       sbusfb_init_fb(0, 0, FBTYPE_SUN2BW, NULL);
-#endif
-#if defined(CONFIG_FB_CGFOURTEEN) && !defined(__sparc_v9__)
-       {
-               int root, node;
-               root = prom_getchild(prom_root_node);
-               root = prom_searchsiblings(root, "obio");
-               if (root && 
-                   (node = prom_searchsiblings(prom_getchild(root), "cgfourteen"))) {
-                       sbusfb_init_fb(node, root, FBTYPE_MDICOLOR, NULL);
-               }
-       }
-#endif
-       if (sbus_root == NULL)
-               return 0;
-       for_all_sbusdev(sbdp, sbus) {
-               type = known_card(sbdp->prom_name);
-               if (type == FBTYPE_NOTYPE)
-                       continue;
-               if (prom_getproperty(sbdp->prom_node, "emulation",
-                                    prom_name, sizeof(prom_name)) > 0) {
-                       type = known_card(prom_name);
-                       if (type == FBTYPE_NOTYPE)
-                               type = known_card(sbdp->prom_name);
-               }
-               sbusfb_init_fb(sbdp->prom_node, sbdp->bus->prom_node, type, sbdp);
-       }
-       return 0;
-}
-
-MODULE_LICENSE("GPL"); 
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
new file mode 100644 (file)
index 0000000..7049a3b
--- /dev/null
@@ -0,0 +1,85 @@
+/* sbuslib.c: Helper library for SBUS framebuffer drivers.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/oplib.h>
+
+#include "sbuslib.h"
+
+void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp)
+{
+       memset(var, 0, sizeof(*var));
+
+       var->xres = prom_getintdefault(prom_node, "width", 1152);
+       var->yres = prom_getintdefault(prom_node, "height", 900);
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+       var->bits_per_pixel = bpp;
+}
+
+EXPORT_SYMBOL(sbusfb_fill_var);
+
+static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)
+{
+       if (size == SBUS_MMAP_EMPTY) return 0;
+       if (size >= 0) return size;
+       return fbsize * (-size);
+}
+
+int sbusfb_mmap_helper(struct sbus_mmap_map *map,
+                      unsigned long physbase,
+                      unsigned long fbsize,
+                      unsigned long iospace,
+                      struct vm_area_struct *vma)
+{
+       unsigned int size, page, r, map_size;
+       unsigned long map_offset = 0;
+       unsigned long off;
+       int i;
+                                        
+       size = vma->vm_end - vma->vm_start;
+       if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+               return -EINVAL;
+
+       off = vma->vm_pgoff << PAGE_SHIFT;
+
+       /* To stop the swapper from even considering these pages */
+       vma->vm_flags |= (VM_SHM | VM_IO | VM_LOCKED);
+       
+       /* Each page, see which map applies */
+       for (page = 0; page < size; ){
+               map_size = 0;
+               for (i = 0; map[i].size; i++)
+                       if (map[i].voff == off+page) {
+                               map_size = sbusfb_mmapsize(map[i].size, fbsize);
+#ifdef __sparc_v9__
+#define POFF_MASK      (PAGE_MASK|0x1UL)
+#else
+#define POFF_MASK      (PAGE_MASK)
+#endif                         
+                               map_offset = (physbase + map[i].poff) & POFF_MASK;
+                               break;
+                       }
+               if (!map_size){
+                       page += PAGE_SIZE;
+                       continue;
+               }
+               if (page + map_size > size)
+                       map_size = size - page;
+               r = io_remap_page_range(vma,
+                                       vma->vm_start + page,
+                                       map_offset, map_size,
+                                       vma->vm_page_prot, iospace);
+               if (r)
+                       return -EAGAIN;
+               page += map_size;
+       }
+
+       return 0;
+}
diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
new file mode 100644 (file)
index 0000000..4761685
--- /dev/null
@@ -0,0 +1,21 @@
+/* sbuslib.h: SBUS fb helper library interfaces */
+#ifndef _SBUSLIB_H
+#define _SBUSLIB_H
+
+struct sbus_mmap_map {
+       unsigned long voff;
+       unsigned long poff;
+       unsigned long size;
+};
+
+#define SBUS_MMAP_FBSIZE(n) (-n)
+#define SBUS_MMAP_EMPTY        0x80000000
+
+extern void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp);
+struct vm_area_struct;
+extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
+                             unsigned long physbase, unsigned long fbsize,
+                             unsigned long iospace,
+                             struct vm_area_struct *vma);
+
+#endif /* _SBUSLIB_H */
diff --git a/include/video/sbusfb.h b/include/video/sbusfb.h
deleted file mode 100644 (file)
index a842a22..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <linux/timer.h>
-#include <asm/sbus.h>
-#include <asm/oplib.h>
-#include <asm/fbio.h>
-
-#include <video/fbcon.h>
-
-struct bt_regs {
-       volatile unsigned int addr;           /* address register */
-       volatile unsigned int color_map;      /* color map */
-       volatile unsigned int control;        /* control register */
-       volatile unsigned int cursor;         /* cursor map register */
-};
-
-struct fb_info_creator {
-       struct ffb_fbc *fbc;
-       struct ffb_dac *dac;
-       int xy_margin;
-       int fifo_cache;
-       u64 yx_margin;
-       int fg_cache;
-       int bg_cache;
-       int dac_rev;
-};
-struct fb_info_cgsix {
-       struct bt_regs *bt;
-       struct cg6_fbc *fbc;
-       struct cg6_thc *thc;
-       struct cg6_tec *tec;
-       volatile u32 *fhc;
-};
-struct fb_info_bwtwo {
-       struct bw2_regs *regs;
-};
-struct fb_info_cgthree {
-       struct cg3_regs *regs;
-};
-struct fb_info_tcx {
-       struct bt_regs *bt;
-       struct tcx_thc *thc;
-       struct tcx_tec *tec;
-       u32 *cplane;
-};
-struct fb_info_leo {
-       struct leo_lx_krn *lx_krn;
-       struct leo_lc_ss0_usr *lc_ss0_usr;
-       struct leo_ld_ss0 *ld_ss0;
-       struct leo_ld_ss1 *ld_ss1;
-       struct leo_cursor *cursor;
-       unsigned int extent;
-};
-struct fb_info_cgfourteen {
-       struct cg14_regs *regs;
-       struct cg14_cursor *cursor;
-       struct cg14_clut *clut;
-       int ramsize;
-       int mode;
-};
-struct fb_info_p9100 {
-       struct p9100_ctrl *ctrl;
-       volatile u32 *fbmem;
-};
-
-struct cg_cursor {
-       char    enable;         /* cursor is enabled */
-       char    mode;           /* cursor mode */
-       struct  fbcurpos cpos;  /* position */
-       struct  fbcurpos chot;  /* hot-spot */
-       struct  fbcurpos size;  /* size of mask & image fields */
-       struct  fbcurpos hwsize; /* hw max size */
-       int     bits[2][128];   /* space for mask & image bits */
-       char    color [6];      /* cursor colors */
-       struct  timer_list timer; /* cursor timer */
-       int     blink_rate;     /* cursor blink rate */
-};
-
-struct sbus_mmap_map {
-       unsigned long voff;
-       unsigned long poff;
-       unsigned long size;
-};
-
-#define SBUS_MMAP_FBSIZE(n) (-n)
-#define SBUS_MMAP_EMPTY        0x80000000
-
-struct fb_info_sbusfb {
-       struct fb_info info;
-       struct display disp;
-       struct display_switch dispsw;
-       struct fbtype type;
-       struct sbus_dev *sbdp;
-       spinlock_t lock;
-       int prom_node, prom_parent;
-       union {
-               struct fb_info_creator ffb;
-               struct fb_info_cgsix cg6;
-               struct fb_info_bwtwo bw2;
-               struct fb_info_cgthree cg3;
-               struct fb_info_tcx tcx;
-               struct fb_info_leo leo;
-               struct fb_info_cgfourteen cg14;
-               struct fb_info_p9100 p9100;
-       } s;
-       unsigned char *color_map;
-       struct cg_cursor cursor;
-       unsigned char open;
-       unsigned char mmaped;
-       unsigned char blanked;
-       int x_margin;
-       int y_margin;
-       int vtconsole;
-       int consolecnt;
-       int graphmode;
-       int emulations[4];
-       struct sbus_mmap_map *mmap_map;
-       unsigned long physbase;
-       int iospace;
-       /* Methods */
-       void (*setup)(struct display *);
-       void (*setcursor)(struct fb_info_sbusfb *);
-       void (*setcurshape)(struct fb_info_sbusfb *);
-       void (*setcursormap)(struct fb_info_sbusfb *, unsigned char *, unsigned char *, unsigned char *);
-       void (*loadcmap)(struct fb_info_sbusfb *, struct display *, int, int);
-       int (*blank)(struct fb_info_sbusfb *);
-       int (*unblank)(struct fb_info_sbusfb *);
-       void (*margins)(struct fb_info_sbusfb *, struct display *, int, int);
-       void (*reset)(struct fb_info_sbusfb *);
-       void (*fill)(struct fb_info_sbusfb *, struct display *, int, int, unsigned short *);
-       void (*switch_from_graph)(struct fb_info_sbusfb *);
-       void (*restore_palette)(struct fb_info_sbusfb *);
-       int (*ioctl)(struct fb_info_sbusfb *, unsigned int, unsigned long);
-};
-
-extern char *creatorfb_init(struct fb_info_sbusfb *);
-extern char *cgsixfb_init(struct fb_info_sbusfb *);
-extern char *cgthreefb_init(struct fb_info_sbusfb *);
-extern char *tcxfb_init(struct fb_info_sbusfb *);
-extern char *leofb_init(struct fb_info_sbusfb *);
-extern char *bwtwofb_init(struct fb_info_sbusfb *);
-extern char *cgfourteenfb_init(struct fb_info_sbusfb *);
-extern char *p9100fb_init(struct fb_info_sbusfb *);
-
-#define sbusfbinfod(disp) ((struct fb_info_sbusfb *)(disp->fb_info))
-#define sbusfbinfo(info) ((struct fb_info_sbusfb *)(info))
-#define CM(i, j) [3*(i)+(j)]
-
-#define SBUSFBINIT_SIZECHANGE ((char *)-1)