Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / drivers / video / cirrusfb.c
index adcb451..1103010 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Contributors (thanks, all!)
  *
- *     David Eger:
- *     Overhaul for Linux 2.6
+ *     David Eger:
+ *     Overhaul for Linux 2.6
  *
  *      Jeff Rugen:
  *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
@@ -60,8 +60,8 @@
 #include <asm/amigahw.h>
 #endif
 #ifdef CONFIG_PPC_PREP
-#include <asm/processor.h>
-#define isPReP (_machine == _MACH_prep)
+#include <asm/machdep.h>
+#define isPReP (machine_is(prep))
 #else
 #define isPReP 0
 #endif
@@ -145,9 +145,6 @@ typedef enum {
  * a run-time table?
  */
 static const struct cirrusfb_board_info_rec {
-       cirrusfb_board_t btype; /* chipset enum, not strictly necessary, as
-                                * cirrusfb_board_info[] is directly indexed
-                                * by this value */
        char *name;             /* ASCII name of chipset */
        long maxclock[5];               /* maximum video clock */
        /* for  1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
@@ -164,123 +161,134 @@ static const struct cirrusfb_board_info_rec {
 
        unsigned char sr1f;     /* SR1F VGA initial register value */
 } cirrusfb_board_info[] = {
-       { BT_NONE, }, /* dummy record */
-       { BT_SD64,
-               "CL SD64",
-               { 140000, 140000, 140000, 140000, 140000, },    /* guess */
-               /* the SD64/P4 have a higher max. videoclock */
-               TRUE,
-               TRUE,
-               TRUE,
-               0xF0,
-               0xF0,
-               0,              /* unused, does not multiplex */
-               0xF1,
-               0,              /* unused, does not multiplex */
-               0x20 },
-       { BT_PICCOLO,
-               "CL Piccolo",
-               { 90000, 90000, 90000, 90000, 90000 },  /* guess */
-               TRUE,
-               TRUE,
-               FALSE,
-               0x80,
-               0x80,
-               0,              /* unused, does not multiplex */
-               0x81,
-               0,              /* unused, does not multiplex */
-               0x22 },
-       { BT_PICASSO,
-               "CL Picasso",
-               { 90000, 90000, 90000, 90000, 90000, }, /* guess */
-               TRUE,
-               TRUE,
-               FALSE,
-               0x20,
-               0x20,
-               0,              /* unused, does not multiplex */
-               0x21,
-               0,              /* unused, does not multiplex */
-               0x22 },
-       { BT_SPECTRUM,
-               "CL Spectrum",
-               { 90000, 90000, 90000, 90000, 90000, }, /* guess */
-               TRUE,
-               TRUE,
-               FALSE,
-               0x80,
-               0x80,
-               0,              /* unused, does not multiplex */
-               0x81,
-               0,              /* unused, does not multiplex */
-               0x22 },
-       { BT_PICASSO4,
-               "CL Picasso4",
-               { 135100, 135100, 85500, 85500, 0 },
-               TRUE,
-               FALSE,
-               TRUE,
-               0x20,
-               0x20,
-               0,              /* unused, does not multiplex */
-               0x21,
-               0,              /* unused, does not multiplex */
-               0 },
-       { BT_ALPINE,
-               "CL Alpine",
-               { 85500, 85500, 50000, 28500, 0}, /* for the GD5430.  GD5446 can do more... */
-               TRUE,
-               TRUE,
-               TRUE,
-               0xA0,
-               0xA1,
-               0xA7,
-               0xA1,
-               0xA7,
-               0x1C },
-       { BT_GD5480,
-               "CL GD5480",
-               { 135100, 200000, 200000, 135100, 135100 },
-               TRUE,
-               TRUE,
-               TRUE,
-               0x10,
-               0x11,
-               0,              /* unused, does not multiplex */
-               0x11,
-               0,              /* unused, does not multiplex */
-               0x1C },
-       { BT_LAGUNA,
-               "CL Laguna",
-               { 135100, 135100, 135100, 135100, 135100, }, /* guess */
-               FALSE,
-               FALSE,
-               TRUE,
-               0,              /* unused */
-               0,              /* unused */
-               0,              /* unused */
-               0,              /* unused */
-               0,              /* unused */
-               0 },            /* unused */
+       [BT_SD64] = {
+               .name                   = "CL SD64",
+               .maxclock               = {
+                       /* guess */
+                       /* the SD64/P4 have a higher max. videoclock */
+                       140000, 140000, 140000, 140000, 140000,
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = TRUE,
+               .scrn_start_bit19       = TRUE,
+               .sr07                   = 0xF0,
+               .sr07_1bpp              = 0xF0,
+               .sr07_8bpp              = 0xF1,
+               .sr1f                   = 0x20
+       },
+       [BT_PICCOLO] = {
+               .name                   = "CL Piccolo",
+               .maxclock               = {
+                       /* guess */
+                       90000, 90000, 90000, 90000, 90000
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = TRUE,
+               .scrn_start_bit19       = FALSE,
+               .sr07                   = 0x80,
+               .sr07_1bpp              = 0x80,
+               .sr07_8bpp              = 0x81,
+               .sr1f                   = 0x22
+       },
+       [BT_PICASSO] = {
+               .name                   = "CL Picasso",
+               .maxclock               = {
+                       /* guess */
+                       90000, 90000, 90000, 90000, 90000
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = TRUE,
+               .scrn_start_bit19       = FALSE,
+               .sr07                   = 0x20,
+               .sr07_1bpp              = 0x20,
+               .sr07_8bpp              = 0x21,
+               .sr1f                   = 0x22
+       },
+       [BT_SPECTRUM] = {
+               .name                   = "CL Spectrum",
+               .maxclock               = {
+                       /* guess */
+                       90000, 90000, 90000, 90000, 90000
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = TRUE,
+               .scrn_start_bit19       = FALSE,
+               .sr07                   = 0x80,
+               .sr07_1bpp              = 0x80,
+               .sr07_8bpp              = 0x81,
+               .sr1f                   = 0x22
+       },
+       [BT_PICASSO4] = {
+               .name                   = "CL Picasso4",
+               .maxclock               = {
+                       135100, 135100, 85500, 85500, 0
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = FALSE,
+               .scrn_start_bit19       = TRUE,
+               .sr07                   = 0x20,
+               .sr07_1bpp              = 0x20,
+               .sr07_8bpp              = 0x21,
+               .sr1f                   = 0
+       },
+       [BT_ALPINE] = {
+               .name                   = "CL Alpine",
+               .maxclock               = {
+                       /* for the GD5430.  GD5446 can do more... */
+                       85500, 85500, 50000, 28500, 0
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = TRUE,
+               .scrn_start_bit19       = TRUE,
+               .sr07                   = 0xA0,
+               .sr07_1bpp              = 0xA1,
+               .sr07_1bpp_mux          = 0xA7,
+               .sr07_8bpp              = 0xA1,
+               .sr07_8bpp_mux          = 0xA7,
+               .sr1f                   = 0x1C
+       },
+       [BT_GD5480] = {
+               .name                   = "CL GD5480",
+               .maxclock               = {
+                       135100, 200000, 200000, 135100, 135100
+               },
+               .init_sr07              = TRUE,
+               .init_sr1f              = TRUE,
+               .scrn_start_bit19       = TRUE,
+               .sr07                   = 0x10,
+               .sr07_1bpp              = 0x11,
+               .sr07_8bpp              = 0x11,
+               .sr1f                   = 0x1C
+       },
+       [BT_LAGUNA] = {
+               .name                   = "CL Laguna",
+               .maxclock               = {
+                       /* guess */
+                       135100, 135100, 135100, 135100, 135100,
+               },
+               .init_sr07              = FALSE,
+               .init_sr1f              = FALSE,
+               .scrn_start_bit19       = TRUE,
+       }
 };
 
 
 #ifdef CONFIG_PCI
 #define CHIP(id, btype) \
-       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
+       { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
 
 static struct pci_device_id cirrusfb_pci_table[] = {
-       CHIP( CIRRUS_5436,      BT_ALPINE ),
-       CHIP( CIRRUS_5434_8,    BT_ALPINE ),
-       CHIP( CIRRUS_5434_4,    BT_ALPINE ),
-       CHIP( CIRRUS_5430,      BT_ALPINE ), /* GD-5440 has identical id */
-       CHIP( CIRRUS_7543,      BT_ALPINE ),
-       CHIP( CIRRUS_7548,      BT_ALPINE ),
-       CHIP( CIRRUS_5480,      BT_GD5480 ), /* MacPicasso probably */
-       CHIP( CIRRUS_5446,      BT_PICASSO4 ), /* Picasso 4 is a GD5446 */
-       CHIP( CIRRUS_5462,      BT_LAGUNA ), /* CL Laguna */
-       CHIP( CIRRUS_5464,      BT_LAGUNA ), /* CL Laguna 3D */
-       CHIP( CIRRUS_5465,      BT_LAGUNA ), /* CL Laguna 3DA*/
+       CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
+       CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
+       CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
+       CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
@@ -289,31 +297,50 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
 
 
 #ifdef CONFIG_ZORRO
+static const struct zorro_device_id cirrusfb_zorro_table[] = {
+       {
+               .id             = ZORRO_PROD_HELFRICH_SD64_RAM,
+               .driver_data    = BT_SD64,
+       }, {
+               .id             = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+               .driver_data    = BT_PICCOLO,
+       }, {
+               .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+               .driver_data    = BT_PICASSO,
+       }, {
+               .id             = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+               .driver_data    = BT_SPECTRUM,
+       }, {
+               .id             = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
+               .driver_data    = BT_PICASSO4,
+       },
+       { 0 }
+};
+
 static const struct {
-       cirrusfb_board_t btype;
-       zorro_id id, id2;
+       zorro_id id2;
        unsigned long size;
-} cirrusfb_zorro_probe_list[] __initdata = {
-       { BT_SD64,
-               ZORRO_PROD_HELFRICH_SD64_RAM,
-               ZORRO_PROD_HELFRICH_SD64_REG,
-               0x400000 },
-       { BT_PICCOLO,
-               ZORRO_PROD_HELFRICH_PICCOLO_RAM,
-               ZORRO_PROD_HELFRICH_PICCOLO_REG,
-               0x200000 },
-       { BT_PICASSO,
-               ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
-               ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
-               0x200000 },
-       { BT_SPECTRUM,
-               ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
-               ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
-               0x200000 },
-       { BT_PICASSO4,
-               ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
-               0,
-               0x400000 },
+} cirrusfb_zorro_table2[] = {
+       [BT_SD64] = {
+               .id2    = ZORRO_PROD_HELFRICH_SD64_REG,
+               .size   = 0x400000
+       },
+       [BT_PICCOLO] = {
+               .id2    = ZORRO_PROD_HELFRICH_PICCOLO_REG,
+               .size   = 0x200000
+       },
+       [BT_PICASSO] = {
+               .id2    = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
+               .size   = 0x200000
+       },
+       [BT_SPECTRUM] = {
+               .id2    = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
+               .size   = 0x200000
+       },
+       [BT_PICASSO4] = {
+               .id2    = 0,
+               .size   = 0x400000
+       }
 };
 #endif /* CONFIG_ZORRO */
 
@@ -364,9 +391,9 @@ typedef enum {
 struct cirrusfb_info {
        struct fb_info *info;
 
-       caddr_t fbmem;
-       caddr_t regbase;
-       caddr_t mem;
+       u8 __iomem *fbmem;
+       u8 __iomem *regbase;
+       u8 __iomem *mem;
        unsigned long size;
        cirrusfb_board_t btype;
        unsigned char SFR;      /* Shadow of special function register */
@@ -377,17 +404,16 @@ struct cirrusfb_info {
        struct cirrusfb_regs currentmode;
        int blank_mode;
 
-       u32     pseudo_palette[17];
+       u32     pseudo_palette[16];
        struct { u8 red, green, blue, pad; } palette[256];
 
 #ifdef CONFIG_ZORRO
-       unsigned long board_addr,
-                     board_size;
+       struct zorro_dev *zdev;
 #endif
-
 #ifdef CONFIG_PCI
        struct pci_dev *pdev;
 #endif
+       void (*unmap)(struct cirrusfb_info *cinfo);
 };
 
 
@@ -401,50 +427,83 @@ static int noaccel = 0;
 static const struct {
        const char *name;
        struct fb_var_screeninfo var;
-} cirrusfb_predefined[] =
-
-{
-       {"Autodetect",          /* autodetect mode */
-        {0}
-       },
-
-       {"640x480",             /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
-        {
-                640, 480, 640, 480, 0, 0, 8, 0,
-                {0, 8, 0},
-                {0, 8, 0},
-                {0, 8, 0},
-                {0, 0, 0},
-              0, 0, -1, -1, FB_ACCEL_NONE, 40000, 48, 16, 32, 8, 96, 4,
-     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-        }
-       },
-
-       {"800x600",             /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
-        {
-                800, 600, 800, 600, 0, 0, 8, 0,
-                {0, 8, 0},
-                {0, 8, 0},
-                {0, 8, 0},
-                {0, 0, 0},
-              0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6,
-     0, FB_VMODE_NONINTERLACED
-        }
-       },
-
-       /*
-          Modeline from XF86Config:
-          Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
-        */
-       {"1024x768",            /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
-               {
-                       1024, 768, 1024, 768, 0, 0, 8, 0,
-                       {0, 8, 0},
-                       {0, 8, 0},
-                       {0, 8, 0},
-                       {0, 0, 0},
-             0, 0, -1, -1, FB_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6,
-     0, FB_VMODE_NONINTERLACED
+} cirrusfb_predefined[] = {
+       {
+               /* autodetect mode */
+               .name   = "Autodetect",
+       }, {
+               /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
+               .name   = "640x480",
+               .var    = {
+                       .xres           = 640,
+                       .yres           = 480,
+                       .xres_virtual   = 640,
+                       .yres_virtual   = 480,
+                       .bits_per_pixel = 8,
+                       .red            = { .length = 8 },
+                       .green          = { .length = 8 },
+                       .blue           = { .length = 8 },
+                       .width          = -1,
+                       .height         = -1,
+                       .pixclock       = 40000,
+                       .left_margin    = 48,
+                       .right_margin   = 16,
+                       .upper_margin   = 32,
+                       .lower_margin   = 8,
+                       .hsync_len      = 96,
+                       .vsync_len      = 4,
+                       .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+                       .vmode          = FB_VMODE_NONINTERLACED
+                }
+       }, {
+               /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
+               .name   = "800x600",
+               .var    = {
+                       .xres           = 800,
+                       .yres           = 600,
+                       .xres_virtual   = 800,
+                       .yres_virtual   = 600,
+                       .bits_per_pixel = 8,
+                       .red            = { .length = 8 },
+                       .green          = { .length = 8 },
+                       .blue           = { .length = 8 },
+                       .width          = -1,
+                       .height         = -1,
+                       .pixclock       = 20000,
+                       .left_margin    = 128,
+                       .right_margin   = 16,
+                       .upper_margin   = 24,
+                       .lower_margin   = 2,
+                       .hsync_len      = 96,
+                       .vsync_len      = 6,
+                       .vmode          = FB_VMODE_NONINTERLACED
+                }
+       }, {
+               /*
+                * Modeline from XF86Config:
+                * Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
+                */
+               /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
+               .name   = "1024x768",
+               .var    = {
+                       .xres           = 1024,
+                       .yres           = 768,
+                       .xres_virtual   = 1024,
+                       .yres_virtual   = 768,
+                       .bits_per_pixel = 8,
+                       .red            = { .length = 8 },
+                       .green          = { .length = 8 },
+                       .blue           = { .length = 8 },
+                       .width          = -1,
+                       .height         = -1,
+                       .pixclock       = 12500,
+                       .left_margin    = 144,
+                       .right_margin   = 32,
+                       .upper_margin   = 30,
+                       .lower_margin   = 2,
+                       .hsync_len      = 192,
+                       .vsync_len      = 6,
+                       .vmode          = FB_VMODE_NONINTERLACED
                }
        }
 };
@@ -456,29 +515,31 @@ static const struct {
 
 
 /*--- Interface used by the world ------------------------------------------*/
-int cirrusfb_init (void);
-int cirrusfb_setup (char *options);
-
-int cirrusfb_open (struct fb_info *info, int user);
-int cirrusfb_release (struct fb_info *info, int user);
-int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
-                       unsigned blue, unsigned transp,
-                       struct fb_info *info);
-int cirrusfb_check_var (struct fb_var_screeninfo *var,
-                       struct fb_info *info);
-int cirrusfb_set_par (struct fb_info *info);
-int cirrusfb_pan_display (struct fb_var_screeninfo *var,
-                         struct fb_info *info);
-int cirrusfb_blank (int blank_mode, struct fb_info *info);
-void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
-void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
+static int cirrusfb_init (void);
+#ifndef MODULE
+static int cirrusfb_setup (char *options);
+#endif
+
+static int cirrusfb_open (struct fb_info *info, int user);
+static int cirrusfb_release (struct fb_info *info, int user);
+static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+                              unsigned blue, unsigned transp,
+                              struct fb_info *info);
+static int cirrusfb_check_var (struct fb_var_screeninfo *var,
+                              struct fb_info *info);
+static int cirrusfb_set_par (struct fb_info *info);
+static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
+                                struct fb_info *info);
+static int cirrusfb_blank (int blank_mode, struct fb_info *info);
+static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
+static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
 
 /* function table of the above functions */
 static struct fb_ops cirrusfb_ops = {
        .owner          = THIS_MODULE,
        .fb_open        = cirrusfb_open,
-       .fb_release     = cirrusfb_release,
+       .fb_release     = cirrusfb_release,
        .fb_setcolreg   = cirrusfb_setcolreg,
        .fb_check_var   = cirrusfb_check_var,
        .fb_set_par     = cirrusfb_set_par,
@@ -487,7 +548,6 @@ static struct fb_ops cirrusfb_ops = {
        .fb_fillrect    = cirrusfb_fillrect,
        .fb_copyarea    = cirrusfb_copyarea,
        .fb_imageblit   = cirrusfb_imageblit,
-       .fb_cursor      = soft_cursor,
 };
 
 /*--- Hardware Specific Routines -------------------------------------------*/
@@ -512,13 +572,13 @@ static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned c
                   unsigned char *green,
                   unsigned char *blue);
 #endif
-static void cirrusfb_WaitBLT (caddr_t regbase);
-static void cirrusfb_BitBLT (caddr_t regbase, int bits_per_pixel,
+static void cirrusfb_WaitBLT (u8 __iomem *regbase);
+static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
                             u_short curx, u_short cury,
                             u_short destx, u_short desty,
                             u_short width, u_short height,
                             u_short line_length);
-static void cirrusfb_RectFill (caddr_t regbase, int bits_per_pixel,
+static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
                               u_short x, u_short y,
                               u_short width, u_short height,
                               u_char color, u_short line_length);
@@ -541,7 +601,7 @@ static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
 static int opencount = 0;
 
 /*--- Open /dev/fbx ---------------------------------------------------------*/
-int cirrusfb_open (struct fb_info *info, int user)
+static int cirrusfb_open (struct fb_info *info, int user)
 {
        if (opencount++ == 0)
                switch_monitor (info->par, 1);
@@ -549,7 +609,7 @@ int cirrusfb_open (struct fb_info *info, int user)
 }
 
 /*--- Close /dev/fbx --------------------------------------------------------*/
-int cirrusfb_release (struct fb_info *info, int user)
+static int cirrusfb_release (struct fb_info *info, int user)
 {
        if (--opencount == 0)
                switch_monitor (info->par, 0);
@@ -601,8 +661,8 @@ static long cirrusfb_get_mclk (long freq, int bpp, long *div)
        return mclk;
 }
 
-int cirrusfb_check_var(struct fb_var_screeninfo *var,
-                      struct fb_info *info)
+static int cirrusfb_check_var(struct fb_var_screeninfo *var,
+                             struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
        int nom, den;           /* translyting from pixels->bytes */
@@ -693,6 +753,12 @@ int cirrusfb_check_var(struct fb_var_screeninfo *var,
 
        switch (var->bits_per_pixel) {
        case 1:
+               var->red.offset = 0;
+               var->red.length = 1;
+               var->green.offset = 0;
+               var->green.length = 1;
+               var->blue.offset = 0;
+               var->blue.length = 1;
                break;
 
        case 8:
@@ -951,7 +1017,7 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
        struct cirrusfb_info *cinfo = info->par;
        struct fb_var_screeninfo *var = &info->var;
        struct cirrusfb_regs regs;
-       caddr_t regbase = cinfo->regbase;
+       u8 __iomem *regbase = cinfo->regbase;
        unsigned char tmp;
        int offset = 0, err;
        const struct cirrusfb_board_info_rec *bi;
@@ -1132,7 +1198,7 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
                        DPRINTK (" (for GD54xx)\n");
                        vga_wseq (regbase, CL_SEQR7,
                                  regs.multiplexing ?
-                                       bi->sr07_1bpp_mux : bi->sr07_1bpp);
+                                       bi->sr07_1bpp_mux : bi->sr07_1bpp);
                        break;
 
                case BT_LAGUNA:
@@ -1216,7 +1282,7 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
                        DPRINTK (" (for GD54xx)\n");
                        vga_wseq (regbase, CL_SEQR7,
                                  regs.multiplexing ?
-                                       bi->sr07_8bpp_mux : bi->sr07_8bpp);
+                                       bi->sr07_8bpp_mux : bi->sr07_8bpp);
                        break;
 
                case BT_LAGUNA:
@@ -1508,15 +1574,15 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
 
 /* for some reason incomprehensible to me, cirrusfb requires that you write
  * the registers twice for the settings to take..grr. -dte */
-int cirrusfb_set_par (struct fb_info *info)
+static int cirrusfb_set_par (struct fb_info *info)
 {
        cirrusfb_set_par_foo (info);
        return cirrusfb_set_par_foo (info);
 }
 
-int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
-                       unsigned blue, unsigned transp,
-                       struct fb_info *info)
+static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+                              unsigned blue, unsigned transp,
+                              struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
 
@@ -1537,14 +1603,14 @@ int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
 
                switch (info->var.bits_per_pixel) {
                        case 8:
-                               ((u8*)(info->pseudo_palette))[regno] = v;
+                               cinfo->pseudo_palette[regno] = v;
                                break;
                        case 16:
-                               ((u16*)(info->pseudo_palette))[regno] = v;
+                               cinfo->pseudo_palette[regno] = v;
                                break;
                        case 24:
                        case 32:
-                               ((u32*)(info->pseudo_palette))[regno] = v;
+                               cinfo->pseudo_palette[regno] = v;
                                break;
                }
                return 0;
@@ -1567,8 +1633,8 @@ int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
 
        performs display panning - provided hardware permits this
 **************************************************************************/
-int cirrusfb_pan_display (struct fb_var_screeninfo *var,
-                         struct fb_info *info)
+static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
+                                struct fb_info *info)
 {
        int xoffset = 0;
        int yoffset = 0;
@@ -1637,7 +1703,7 @@ int cirrusfb_pan_display (struct fb_var_screeninfo *var,
 }
 
 
-int cirrusfb_blank (int blank_mode, struct fb_info *info)
+static int cirrusfb_blank (int blank_mode, struct fb_info *info)
 {
        /*
         *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
@@ -1662,7 +1728,8 @@ int cirrusfb_blank (int blank_mode, struct fb_info *info)
        }
 
        /* Undo current */
-       if (current_mode != VESA_NO_BLANKING) {
+       if (current_mode == FB_BLANK_NORMAL ||
+           current_mode == FB_BLANK_UNBLANK) {
                /* unblank the screen */
                val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
                vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf);      /* clear "FullBandwidth" bit */
@@ -1671,22 +1738,23 @@ int cirrusfb_blank (int blank_mode, struct fb_info *info)
        }
 
        /* set new */
-       if(blank_mode != VESA_NO_BLANKING) {
+       if(blank_mode > FB_BLANK_NORMAL) {
                /* blank the screen */
                val = vga_rseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE);
                vga_wseq (cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20);      /* set "FullBandwidth" bit */
        }
 
        switch (blank_mode) {
-       case VESA_NO_BLANKING:
+       case FB_BLANK_UNBLANK:
+       case FB_BLANK_NORMAL:
                break;
-       case VESA_VSYNC_SUSPEND:
+       case FB_BLANK_VSYNC_SUSPEND:
                vga_wgfx (cinfo->regbase, CL_GRE, 0x04);
                break;
-       case VESA_HSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
                vga_wgfx (cinfo->regbase, CL_GRE, 0x02);
                break;
-       case VESA_POWERDOWN:
+       case FB_BLANK_POWERDOWN:
                vga_wgfx (cinfo->regbase, CL_GRE, 0x06);
                break;
        default:
@@ -1696,7 +1764,9 @@ int cirrusfb_blank (int blank_mode, struct fb_info *info)
 
        cinfo->blank_mode = blank_mode;
        DPRINTK ("EXIT, returning 0\n");
-       return 0;
+
+       /* Let fbcon do a soft blank for us */
+       return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
 }
 /**** END   Hardware specific Routines **************************************/
 /****************************************************************************/
@@ -1950,24 +2020,27 @@ static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
                                   const struct fb_fillrect *region)
 {
        int m; /* bytes per pixel */
+       u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ?
+               cinfo->pseudo_palette[region->color] : region->color;
+
        if(cinfo->info->var.bits_per_pixel == 1) {
                cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
                                  region->dx / 8, region->dy,
                                  region->width / 8, region->height,
-                                 region->color,
+                                 color,
                                  cinfo->currentmode.line_length);
        } else {
                m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8;
                cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel,
                                  region->dx * m, region->dy,
                                  region->width * m, region->height,
-                                 region->color,
+                                 color,
                                  cinfo->currentmode.line_length);
        }
        return;
 }
 
-void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
+static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
 {
        struct cirrusfb_info *cinfo = info->par;
        struct fb_fillrect modded;
@@ -2017,7 +2090,7 @@ static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo,
 }
 
 
-void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
        struct cirrusfb_info *cinfo = info->par;
        struct fb_copyarea modded;
@@ -2052,7 +2125,7 @@ void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        cirrusfb_prim_copyarea(cinfo, &modded);
 }
 
-void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        struct cirrusfb_info *cinfo = info->par;
 
@@ -2084,7 +2157,7 @@ static int release_io_ports = 0;
  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
  * seem to have. */
-static unsigned int cirrusfb_get_memsize (caddr_t regbase)
+static unsigned int cirrusfb_get_memsize (u8 __iomem *regbase)
 {
        unsigned long mem;
        unsigned char SRF;
@@ -2142,7 +2215,7 @@ static void get_pci_addrs (const struct pci_dev *pdev,
 }
 
 
-static void __devexit cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
+static void cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
 {
        struct pci_dev *pdev = cinfo->pdev;
 
@@ -2156,10 +2229,143 @@ static void __devexit cirrusfb_pci_unmap (struct cirrusfb_info *cinfo)
        framebuffer_release(cinfo->info);
        pci_disable_device(pdev);
 }
+#endif /* CONFIG_PCI */
+
+
+#ifdef CONFIG_ZORRO
+static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
+{
+       zorro_release_device(cinfo->zdev);
+
+       if (cinfo->btype == BT_PICASSO4) {
+               cinfo->regbase -= 0x600000;
+               iounmap ((void *)cinfo->regbase);
+               iounmap ((void *)cinfo->fbmem);
+       } else {
+               if (zorro_resource_start(cinfo->zdev) > 0x01000000)
+                       iounmap ((void *)cinfo->fbmem);
+       }
+       framebuffer_release(cinfo->info);
+}
+#endif /* CONFIG_ZORRO */
+
+static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
+{
+       struct fb_info *info = cinfo->info;
+       struct fb_var_screeninfo *var = &info->var;
+
+       info->par = cinfo;
+       info->pseudo_palette = cinfo->pseudo_palette;
+       info->flags = FBINFO_DEFAULT
+                   | FBINFO_HWACCEL_XPAN
+                   | FBINFO_HWACCEL_YPAN
+                   | FBINFO_HWACCEL_FILLRECT
+                   | FBINFO_HWACCEL_COPYAREA;
+       if (noaccel)
+               info->flags |= FBINFO_HWACCEL_DISABLED;
+       info->fbops = &cirrusfb_ops;
+       info->screen_base = cinfo->fbmem;
+       if (cinfo->btype == BT_GD5480) {
+               if (var->bits_per_pixel == 16)
+                       info->screen_base += 1 * MB_;
+               if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
+                       info->screen_base += 2 * MB_;
+       }
+
+       /* Fill fix common fields */
+       strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
+               sizeof(info->fix.id));
+
+       /* monochrome: only 1 memory plane */
+       /* 8 bit and above: Use whole memory area */
+       info->fix.smem_start = cinfo->fbmem_phys;
+       info->fix.smem_len   = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
+       info->fix.type       = cinfo->currentmode.type;
+       info->fix.type_aux   = 0;
+       info->fix.visual     = cinfo->currentmode.visual;
+       info->fix.xpanstep   = 1;
+       info->fix.ypanstep   = 1;
+       info->fix.ywrapstep  = 0;
+       info->fix.line_length = cinfo->currentmode.line_length;
+
+       /* FIXME: map region at 0xB8000 if available, fill in here */
+       info->fix.mmio_start = cinfo->fbregs_phys;
+       info->fix.mmio_len   = 0;
+       info->fix.accel = FB_ACCEL_NONE;
+
+       fb_alloc_cmap(&info->cmap, 256, 0);
+
+       return 0;
+}
+
+static int cirrusfb_register(struct cirrusfb_info *cinfo)
+{
+       struct fb_info *info;
+       int err;
+       cirrusfb_board_t btype;
+
+       DPRINTK ("ENTER\n");
+
+       printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
+
+       info = cinfo->info;
+       btype = cinfo->btype;
+
+       /* sanity checks */
+       assert (btype != BT_NONE);
+
+       DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
 
+       /* Make pretend we've set the var so our structures are in a "good" */
+       /* state, even though we haven't written the mode to the hw yet...  */
+       info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
+       info->var.activate = FB_ACTIVATE_NOW;
 
-static struct cirrusfb_info *cirrusfb_pci_setup (struct pci_dev *pdev,
-                                                const struct pci_device_id *ent)
+       err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
+       if (err < 0) {
+               /* should never happen */
+               DPRINTK("choking on default var... umm, no good.\n");
+               goto err_unmap_cirrusfb;
+       }
+
+       /* set all the vital stuff */
+       cirrusfb_set_fbinfo(cinfo);
+
+       err = register_framebuffer(info);
+       if (err < 0) {
+               printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
+               goto err_dealloc_cmap;
+       }
+
+       DPRINTK ("EXIT, returning 0\n");
+       return 0;
+
+err_dealloc_cmap:
+       fb_dealloc_cmap(&info->cmap);
+err_unmap_cirrusfb:
+       cinfo->unmap(cinfo);
+       return err;
+}
+
+static void __devexit cirrusfb_cleanup (struct fb_info *info)
+{
+       struct cirrusfb_info *cinfo = info->par;
+       DPRINTK ("ENTER\n");
+
+       switch_monitor (cinfo, 0);
+
+       unregister_framebuffer (info);
+       fb_dealloc_cmap (&info->cmap);
+       printk ("Framebuffer unregistered\n");
+       cinfo->unmap(cinfo);
+
+       DPRINTK ("EXIT\n");
+}
+
+
+#ifdef CONFIG_PCI
+static int cirrusfb_pci_register (struct pci_dev *pdev,
+                                 const struct pci_device_id *ent)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
@@ -2195,7 +2401,7 @@ static struct cirrusfb_info *cirrusfb_pci_setup (struct pci_dev *pdev,
                get_prep_addrs (&board_addr, &cinfo->fbregs_phys);
 #endif
                /* PReP dies if we ioremap the IO registers, but it works w/out... */
-               cinfo->regbase = (char *) cinfo->fbregs_phys;
+               cinfo->regbase = (char __iomem *) cinfo->fbregs_phys;
        } else {
                DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
                get_pci_addrs (pdev, &board_addr, &cinfo->fbregs_phys);
@@ -2233,11 +2439,13 @@ static struct cirrusfb_info *cirrusfb_pci_setup (struct pci_dev *pdev,
 
        cinfo->fbmem_phys = board_addr;
        cinfo->size = board_size;
+       cinfo->unmap = cirrusfb_pci_unmap;
 
        printk (" RAM (%lu kB) at 0xx%lx, ", cinfo->size / KB_, board_addr);
        printk ("Cirrus Logic chipset on PCI bus\n");
+       pci_set_drvdata(pdev, info);
 
-       return cinfo;
+       return cirrusfb_register(cinfo);
 
 err_release_legacy:
        if (release_io_ports)
@@ -2252,77 +2460,51 @@ err_release_fb:
 err_disable:
        pci_disable_device(pdev);
 err_out:
-       return ERR_PTR(ret);
+       return ret;
 }
-#endif                         /* CONFIG_PCI */
-
-
-
 
-#ifdef CONFIG_ZORRO
-static int cirrusfb_zorro_find (struct zorro_dev **z_o,
-                                   struct zorro_dev **z2_o,
-                                   cirrusfb_board_t *btype, unsigned long *size)
+static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
 {
-       struct zorro_dev *z = NULL;
-       int i;
-
-       assert (z_o != NULL);
-       assert (btype != NULL);
-
-       for (i = 0; i < ARRAY_SIZE(cirrusfb_zorro_probe_list); i++)
-               if ((z = zorro_find_device(cirrusfb_zorro_probe_list[i].id, NULL)))
-                       break;
-
-       if (z) {
-               *z_o = z;
-               if (cirrusfb_zorro_probe_list[i].id2)
-                       *z2_o = zorro_find_device(cirrusfb_zorro_probe_list[i].id2, NULL);
-               else
-                       *z2_o = NULL;
-
-               *btype = cirrusfb_zorro_probe_list[i].btype;
-               *size = cirrusfb_zorro_probe_list[i].size;
-
-               printk (KERN_INFO "cirrusfb: %s board detected; ",
-                       cirrusfb_board_info[*btype].name);
+       struct fb_info *info = pci_get_drvdata(pdev);
+       DPRINTK ("ENTER\n");
 
-               return 0;
-       }
+       cirrusfb_cleanup (info);
 
-       printk (KERN_NOTICE "cirrusfb: no supported board found.\n");
-       return -ENODEV;
+       DPRINTK ("EXIT\n");
 }
 
-
-static void __devexit cirrusfb_zorro_unmap (struct cirrusfb_info *cinfo)
-{
-       release_mem_region(cinfo->board_addr, cinfo->board_size);
-
-       if (cinfo->btype == BT_PICASSO4) {
-               cinfo->regbase -= 0x600000;
-               iounmap ((void *)cinfo->regbase);
-               iounmap ((void *)cinfo->fbmem);
-       } else {
-               if (cinfo->board_addr > 0x01000000)
-                       iounmap ((void *)cinfo->fbmem);
-       }
-       framebuffer_release(cinfo->info);
-}
+static struct pci_driver cirrusfb_pci_driver = {
+       .name           = "cirrusfb",
+       .id_table       = cirrusfb_pci_table,
+       .probe          = cirrusfb_pci_register,
+       .remove         = __devexit_p(cirrusfb_pci_unregister),
+#ifdef CONFIG_PM
+#if 0
+       .suspend        = cirrusfb_pci_suspend,
+       .resume         = cirrusfb_pci_resume,
+#endif
+#endif
+};
+#endif /* CONFIG_PCI */
 
 
-static struct cirrusfb_info *cirrusfb_zorro_setup(void)
+#ifdef CONFIG_ZORRO
+static int cirrusfb_zorro_register(struct zorro_dev *z,
+                                  const struct zorro_device_id *ent)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
        cirrusfb_board_t btype;
-       struct zorro_dev *z = NULL, *z2 = NULL;
+       struct zorro_dev *z2 = NULL;
        unsigned long board_addr, board_size, size;
        int ret;
 
-       ret = cirrusfb_zorro_find (&z, &z2, &btype, &size);
-       if (ret < 0)
-               goto err_out;
+       btype = ent->driver_data;
+       if (cirrusfb_zorro_table2[btype].id2)
+               z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
+       size = cirrusfb_zorro_table2[btype].size;
+       printk(KERN_INFO "cirrusfb: %s board detected; ",
+              cirrusfb_board_info[btype].name);
 
        info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
        if (!info) {
@@ -2339,11 +2521,12 @@ static struct cirrusfb_info *cirrusfb_zorro_setup(void)
        assert (z2 >= 0);
        assert (btype != BT_NONE);
 
-       cinfo->board_addr = board_addr = z->resource.start;
-       cinfo->board_size = board_size = z->resource.end-z->resource.start+1;
+       cinfo->zdev = z;
+       board_addr = zorro_resource_start(z);
+       board_size = zorro_resource_len(z);
        cinfo->size = size;
 
-       if (!request_mem_region(board_addr, board_size, "cirrusfb")) {
+       if (!zorro_request_device(z, "cirrusfb")) {
                printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n",
                       board_addr);
                ret = -EBUSY;
@@ -2370,7 +2553,7 @@ static struct cirrusfb_info *cirrusfb_zorro_setup(void)
                cinfo->fbregs_phys = board_addr + 0x600000;
 
                cinfo->fbmem_phys = board_addr + 16777216;
-               cinfo->fbmem = ioremap (info->fbmem_phys, 16777216);
+               cinfo->fbmem = ioremap (cinfo->fbmem_phys, 16777216);
                if (!cinfo->fbmem)
                        goto err_unmap_regbase;
        } else {
@@ -2390,10 +2573,12 @@ static struct cirrusfb_info *cirrusfb_zorro_setup(void)
 
                DPRINTK ("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase);
        }
+       cinfo->unmap = cirrusfb_zorro_unmap;
 
        printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
+       zorro_set_drvdata(z, info);
 
-       return 0;
+       return cirrusfb_register(cinfo);
 
 err_unmap_regbase:
        /* Parental advisory: explicit hack */
@@ -2403,186 +2588,52 @@ err_release_region:
 err_release_fb:
        framebuffer_release(info);
 err_out:
-       return ERR_PTR(ret);
+       return ret;
 }
-#endif /* CONFIG_ZORRO */
 
-static int cirrusfb_set_fbinfo(struct cirrusfb_info *cinfo)
+void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
 {
-       struct fb_info *info = cinfo->info;
-       struct fb_var_screeninfo *var = &info->var;
-
-       info->currcon = -1;
-       info->par = cinfo;
-       info->pseudo_palette = cinfo->pseudo_palette;
-       info->flags = FBINFO_DEFAULT
-                   | FBINFO_HWACCEL_XPAN
-                   | FBINFO_HWACCEL_YPAN
-                   | FBINFO_HWACCEL_FILLRECT
-                   | FBINFO_HWACCEL_COPYAREA;
-       if (noaccel)
-               info->flags |= FBINFO_HWACCEL_DISABLED;
-       info->fbops = &cirrusfb_ops;
-       info->screen_base = cinfo->fbmem;
-       if (cinfo->btype == BT_GD5480) {
-               if (var->bits_per_pixel == 16)
-                       info->screen_base += 1 * MB_;
-               if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
-                       info->screen_base += 2 * MB_;
-       }
-
-       /* Fill fix common fields */
-       strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
-               sizeof(info->fix.id));
-
-       /* monochrome: only 1 memory plane */
-       /* 8 bit and above: Use whole memory area */
-       info->fix.smem_start = cinfo->fbmem_phys;
-       info->fix.smem_len   = (var->bits_per_pixel == 1) ? cinfo->size / 4 : cinfo->size;
-       info->fix.type       = cinfo->currentmode.type;
-       info->fix.type_aux   = 0;
-       info->fix.visual     = cinfo->currentmode.visual;
-       info->fix.xpanstep   = 1;
-       info->fix.ypanstep   = 1;
-       info->fix.ywrapstep  = 0;
-       info->fix.line_length = cinfo->currentmode.line_length;
-
-       /* FIXME: map region at 0xB8000 if available, fill in here */
-       info->fix.mmio_start = cinfo->fbregs_phys;
-       info->fix.mmio_len   = 0;
-       info->fix.accel = FB_ACCEL_NONE;
-
-       fb_alloc_cmap(&info->cmap, 256, 0);
-
-       return 0;
-}
-
-#if defined(CONFIG_PCI)
-#define cirrusfb_unmap cirrusfb_pci_unmap
-#define cirrusfb_bus_setup cirrusfb_pci_setup
-#elif defined(CONFIG_ZORRO)
-#define cirrusfb_unmap cirrusfb_zorro_unmap
-#define cirrusfb_bus_setup cirrusfb_zorro_setup
-#endif
-
-
-static int cirrusfb_pci_register (struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
-{
-       struct fb_info *info;
-       struct cirrusfb_info *cinfo = NULL;
-       int err;
-       cirrusfb_board_t btype;
-
+       struct fb_info *info = zorro_get_drvdata(z);
        DPRINTK ("ENTER\n");
 
-       printk (KERN_INFO "cirrusfb: Driver for Cirrus Logic based graphic boards, v" CIRRUSFB_VERSION "\n");
-
-       cinfo = cirrusfb_bus_setup(pdev, ent);
-
-       if (IS_ERR(cinfo)) {
-               err = PTR_ERR(cinfo);
-               goto err_out;
-       }
-
-       info = cinfo->info;
-       btype = cinfo->btype;
-
-       /* sanity checks */
-       assert (btype != BT_NONE);
-       assert (btype == cirrusfb_board_info[btype].btype);
-
-       DPRINTK ("cirrusfb: (RAM start set to: 0x%p)\n", cinfo->fbmem);
-
-       /* Make pretend we've set the var so our structures are in a "good" */
-       /* state, even though we haven't written the mode to the hw yet...  */
-       info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
-       info->var.activate = FB_ACTIVATE_NOW;
-
-       err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
-       if (err < 0) {
-               /* should never happen */
-               DPRINTK("choking on default var... umm, no good.\n");
-               goto err_unmap_cirrusfb;
-       }
-
-       /* set all the vital stuff */
-       cirrusfb_set_fbinfo(cinfo);
-
-       pci_set_drvdata(pdev, info);
-
-       err = register_framebuffer(info);
-       if (err < 0) {
-               printk (KERN_ERR "cirrusfb: could not register fb device; err = %d!\n", err);
-               goto err_dealloc_cmap;
-       }
-
-       DPRINTK ("EXIT, returning 0\n");
-       return 0;
-
-err_dealloc_cmap:
-       fb_dealloc_cmap(&info->cmap);
-err_unmap_cirrusfb:
-       cirrusfb_unmap(cinfo);
-err_out:
-       return err;
-}
-
-
-static void __devexit cirrusfb_cleanup (struct fb_info *info)
-{
-       struct cirrusfb_info *cinfo = info->par;
-       DPRINTK ("ENTER\n");
-
-#ifdef CONFIG_ZORRO
-       switch_monitor (cinfo, 0);
-#endif
-
-       unregister_framebuffer (info);
-       fb_dealloc_cmap (&info->cmap);
-       printk ("Framebuffer unregistered\n");
-       cirrusfb_unmap (cinfo);
+       cirrusfb_cleanup (info);
 
        DPRINTK ("EXIT\n");
 }
 
+static struct zorro_driver cirrusfb_zorro_driver = {
+       .name           = "cirrusfb",
+       .id_table       = cirrusfb_zorro_table,
+       .probe          = cirrusfb_zorro_register,
+       .remove         = __devexit_p(cirrusfb_zorro_unregister),
+};
+#endif /* CONFIG_ZORRO */
 
-void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
+static int __init cirrusfb_init(void)
 {
-       struct fb_info *info = pci_get_drvdata(pdev);
-       DPRINTK ("ENTER\n");
+       int error = 0;
 
-       cirrusfb_cleanup (info);
-
-       DPRINTK ("EXIT\n");
-}
+#ifndef MODULE
+       char *option = NULL;
 
-static struct pci_driver cirrusfb_driver = {
-       .name   = "cirrusfb",
-       .id_table       = cirrusfb_pci_table,
-       .probe          = cirrusfb_pci_register,
-       .remove         = __devexit_p(cirrusfb_pci_unregister),
-#ifdef CONFIG_PM
-#if 0
-       .suspend        = cirrusfb_pci_suspend,
-       .resume         = cirrusfb_pci_resume,
+       if (fb_get_options("cirrusfb", &option))
+               return -ENODEV;
+       cirrusfb_setup(option);
 #endif
-#endif
-};
 
-int __init cirrusfb_init(void)
-{
 #ifdef CONFIG_ZORRO
-       return cirrusfb_pci_register(NULL, NULL);
-#else
-       return pci_module_init(&cirrusfb_driver);
+       error |= zorro_register_driver(&cirrusfb_zorro_driver);
+#endif
+#ifdef CONFIG_PCI
+       error |= pci_register_driver(&cirrusfb_pci_driver);
 #endif
+       return error;
 }
 
 
 
 #ifndef MODULE
-int __init cirrusfb_setup(char *options) {
+static int __init cirrusfb_setup(char *options) {
        char *this_opt, s[32];
        int i;
 
@@ -2617,13 +2668,19 @@ MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
 MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
 MODULE_LICENSE("GPL");
 
-void __exit cirrusfb_exit (void)
+static void __exit cirrusfb_exit (void)
 {
-       pci_unregister_driver (&cirrusfb_driver);
+#ifdef CONFIG_PCI
+       pci_unregister_driver(&cirrusfb_pci_driver);
+#endif
+#ifdef CONFIG_ZORRO
+       zorro_unregister_driver(&cirrusfb_zorro_driver);
+#endif
 }
 
-#ifdef MODULE
 module_init(cirrusfb_init);
+
+#ifdef MODULE
 module_exit(cirrusfb_exit);
 #endif
 
@@ -2815,7 +2872,7 @@ static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned c
 *********************************************************************/
 
 /* FIXME: use interrupts instead */
-static void cirrusfb_WaitBLT (caddr_t regbase)
+static void cirrusfb_WaitBLT (u8 __iomem *regbase)
 {
        /* now busy-wait until we're done */
        while (vga_rgfx (regbase, CL_GR31) & 0x08)
@@ -2828,9 +2885,9 @@ static void cirrusfb_WaitBLT (caddr_t regbase)
        perform accelerated "scrolling"
 ********************************************************************/
 
-static void cirrusfb_BitBLT (caddr_t regbase, int bits_per_pixel,
+static void cirrusfb_BitBLT (u8 __iomem *regbase, int bits_per_pixel,
                             u_short curx, u_short cury, u_short destx, u_short desty,
-                            u_short width, u_short height, u_short line_length)
+                            u_short width, u_short height, u_short line_length)
 {
        u_short nwidth, nheight;
        u_long nsrc, ndest;
@@ -2919,7 +2976,7 @@ static void cirrusfb_BitBLT (caddr_t regbase, int bits_per_pixel,
        perform accelerated rectangle fill
 ********************************************************************/
 
-static void cirrusfb_RectFill (caddr_t regbase, int bits_per_pixel,
+static void cirrusfb_RectFill (u8 __iomem *regbase, int bits_per_pixel,
                     u_short x, u_short y, u_short width, u_short height,
                     u_char color, u_short line_length)
 {