Commit 4737042c authored by James Simmons's avatar James Simmons

VGA text mode handling cleanup. Rusty's janitoral cleanups.

parent b4e5e606
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
* for more details. * for more details.
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -41,81 +40,28 @@ ...@@ -41,81 +40,28 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#define arraysize(x) (sizeof(x)/sizeof(*(x))) #define arraysize(x) (sizeof(x)/sizeof(*(x)))
struct mc68328_fb_par {
int xres;
int yres;
int bpp;
};
static struct mc68328_fb_par current_par;
static int current_par_valid = 0;
static int currcon = 0;
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info; static struct fb_info fb_info;
static int node; /* node of the /dev/fb?current file */
/*
* Switch for Chipset Independency
*/
static struct fb_hwswitch {
/* Initialisation */
int (*init)(void);
/* Display Control */
int (*encode_fix)(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par);
int (*decode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
int (*encode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp);
int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
u_int transp);
void (*blank)(int blank);
} *fbhw;
/*
* Frame Buffer Name
*/
static char mc68328_fb_name[16] = "mc68328";
/* /*
* mc68328vision Graphics Board * mc68328vision Graphics Board
*/ */
#define CYBER8_WIDTH 1152 #define CYBER8_WIDTH 1152
#define CYBER8_HEIGHT 886 #define CYBER8_HEIGHT 886
#define CYBER8_PIXCLOCK 12500 /* ++Geert: Just a guess */ #define CYBER8_PIXCLOCK 12500 /* ++Geert: Just a guess */
#define CYBER16_WIDTH 800 #define CYBER16_WIDTH 800
#define CYBER16_HEIGHT 600 #define CYBER16_HEIGHT 600
#define CYBER16_PIXCLOCK 25000 /* ++Geert: Just a guess */ #define CYBER16_PIXCLOCK 25000 /* ++Geert: Just a guess */
#define PALM_WIDTH 160 #define PALM_WIDTH 160
#define PALM_HEIGHT 160 #define PALM_HEIGHT 160
/*static int mc68328Key = 0; /*static int mc68328Key = 0;
static u_char mc68328_colour_table [256][4];*/ static u_char mc68328_colour_table [256][4];*/
static unsigned long mc68328Mem;
static unsigned long mc68328Size;
/* /*
* Predefined Video Mode Names * Predefined Video Mode Names
...@@ -123,34 +69,37 @@ static unsigned long mc68328Size; ...@@ -123,34 +69,37 @@ static unsigned long mc68328Size;
static char *mc68328_fb_modenames[] = { static char *mc68328_fb_modenames[] = {
/* /*
* Autodetect (Default) Video Mode * Autodetect (Default) Video Mode
*/ */
"default", "default",
/* /*
* Predefined Video Modes * Predefined Video Modes
*/ */
"Palm", /* Palm Pilot devices, 1.0 and higher */
"Palm Grey", /* Palm Pilot devices, 1.0 and higher */
/* "Palm", /* Palm Pilot devices, 1.0 and higher */
* Dummy Video Modes "Palm Grey", /* Palm Pilot devices, 1.0 and higher */
*/
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", /*
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", * Dummy Video Modes
"dummy", "dummy", "dummy", "dummy", */
/* "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
* User Defined Video Modes "dummy",
* "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
* This doesn't work yet!! "dummy",
*/ "dummy", "dummy", "dummy", "dummy",
"user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7" /*
* User Defined Video Modes
*
* This doesn't work yet!!
*/
"user0", "user1", "user2", "user3", "user4", "user5", "user6",
"user7"
}; };
...@@ -160,68 +109,70 @@ static char *mc68328_fb_modenames[] = { ...@@ -160,68 +109,70 @@ static char *mc68328_fb_modenames[] = {
static struct fb_var_screeninfo mc68328_fb_predefined[] = { static struct fb_var_screeninfo mc68328_fb_predefined[] = {
/* /*
* Autodetect (Default) Video Mode * Autodetect (Default) Video Mode
*/ */
{ 0, }, {0,},
/* /*
* Predefined Video Modes * Predefined Video Modes
*/ */
{ {
/* Palm */ /* Palm */
PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
0, 0, 0, 0,
1, -1, 1, -1,
{0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0},
0, 0, 0, 0,
-1, -1, /* phys height, width */ -1, -1, /* phys height, width */
FB_ACCEL_NONE, FB_ACCEL_NONE,
0, 0, 0, 0, 0, 0, 0, /* timing */ 0, 0, 0, 0, 0, 0, 0, /* timing */
0, /* sync */ 0, /* sync */
FB_VMODE_NONINTERLACED FB_VMODE_NONINTERLACED},
}, {
{ /* Palm Grey */
/* Palm Grey */ PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, 0, 0,
0, 0, 2, -1,
2, -1, {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
{0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, 0, 0,
0, 0, -1, -1, /* phys height, width */
-1, -1, /* phys height, width */ FB_ACCEL_NONE,
FB_ACCEL_NONE, 0, 0, 0, 0, 0, 0, 0, /* timing */
0, 0, 0, 0, 0, 0, 0, /* timing */ 0, /* sync */
0, /* sync */ FB_VMODE_NONINTERLACED},
FB_VMODE_NONINTERLACED
}, /*
* Dummy Video Modes
/* */
* Dummy Video Modes
*/ {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,},
{0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,},
{ 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, {0,}, {0,},
{ 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
{ 0, }, { 0, }, /*
* User Defined Video Modes
/* */
* User Defined Video Modes
*/ {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}
{ 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
}; };
static struct fb_fix_screeninfo mc68328_fix __initdata = {
.id = "mc68328";
.smem_len = 160 * 160 /8;
.type = FB_TYPE_PACKED_PIXELS;
.accel = FB_ACCEL_NONE;
};
#define NUM_TOTAL_MODES arraysize(mc68328_fb_predefined) #define NUM_TOTAL_MODES arraysize(mc68328_fb_predefined)
#define NUM_PREDEF_MODES (3) #define NUM_PREDEF_MODES (3)
static int mc68328fb_inverse = 0; static int mc68328fb_inverse = 0;
static int mc68328fb_mode = 0; static int mc68328fb_mode = 0;
static int mc68328fbCursorMode = 0; static int mc68328fbCursorMode = 0;
/* /*
* Some default modes * Some default modes
*/ */
...@@ -229,34 +180,14 @@ static int mc68328fbCursorMode = 0; ...@@ -229,34 +180,14 @@ static int mc68328fbCursorMode = 0;
#define PALM_DEFMODE (1) #define PALM_DEFMODE (1)
#define CYBER16_DEFMODE (2) #define CYBER16_DEFMODE (2)
/* /*
* Interface used by the world * Interface used by the world
*/ */
static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int mc68328_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, int con, struct fb_info *info);
/*
* Interface to the low level console driver
*/
int mc68328_fb_init(void); int mc68328_fb_init(void);
static int mc68328fb_switch(int con, struct fb_info *info);
static int mc68328fb_updatevar(int con);
static void mc68328fb_blank(int blank);
static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp);
static void mc68328fb_blank(int blank, struct fb_info *info);
/* /*
* Accelerated Functions used by the low level console driver * Accelerated Functions used by the low level console driver
...@@ -264,239 +195,57 @@ static void mc68328fb_blank(int blank); ...@@ -264,239 +195,57 @@ static void mc68328fb_blank(int blank);
void mc68328_WaitQueue(u_short fifo); void mc68328_WaitQueue(u_short fifo);
void mc68328_WaitBlit(void); void mc68328_WaitBlit(void);
void mc68328_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty, void mc68328_BitBLT(u_short curx, u_short cury, u_short destx,
u_short width, u_short height, u_short mode); u_short desty, u_short width, u_short height,
u_short mode);
void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height, void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
u_short mode, u_short color); u_short mode, u_short color);
void mc68328_MoveCursor(u_short x, u_short y); void mc68328_MoveCursor(u_short x, u_short y);
/*
* Hardware Specific Routines
*/
static int mc68328_init(void);
static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
struct mc68328_fb_par *par);
static int mc68328_decode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par);
static int mc68328_encode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par);
static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp);
static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp);
static void mc68328_blank(int blank);
/* /*
* Internal routines * Internal routines
*/ */
static void mc68328_fb_get_par(struct mc68328_fb_par *par);
static void mc68328_fb_set_par(struct mc68328_fb_par *par);
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
static struct fb_cmap *get_default_colormap(int bpp);
static void memcpy_fs(int fsfromto, void *to, void *from, int len);
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
static void mc68328_fb_set_disp(int con, struct fb_info *info);
static int get_video_mode(const char *name); static int get_video_mode(const char *name);
/* -------------------- Hardware specific routines -------------------------- */
/*
* Initialization
*
* Set the default video mode for this chipset. If a video mode was
* specified on the command line, it will override the default mode.
*/
static int mc68328_init(void)
{
/*int i;
char size;
volatile u_long *CursorBase;
unsigned long board_addr;
struct ConfigDev *cd;*/
if (mc68328fb_mode == -1)
mc68328fb_mode = PALM_DEFMODE;
mc68328Mem = (*(volatile unsigned long*)0xFFFFFA00);
/*kernel_map (board_addr + 0x01400000, 0x00400000,*/
mc68328Size = 160*160/8;
return (0);
}
/*
* This function should fill in the `fix' structure based on the
* values in the `par' structure.
*/
static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
struct mc68328_fb_par *par)
{
int i;
strcpy(fix->id, mc68328_fb_name);
fix->smem_start = mc68328Mem;
fix->smem_len = mc68328Size;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
if (par->bpp == 1)
fix->visual = FB_VISUAL_MONO01;
else
fix->visual = FB_VISUAL_DIRECTCOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
for (i = 0; i < arraysize(fix->reserved); i++)
fix->reserved[i] = 0;
fix->accel = FB_ACCEL_NONE;
return(0);
}
/*
* Get the video params out of `var'. If a value doesn't fit, round
* it up, if it's too big, return -EINVAL.
*/
static int mc68328_decode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par)
{
par->xres = PALM_WIDTH;
par->yres = PALM_HEIGHT;
par->bpp = 1;
return(0);
}
/*
* Fill the `var' structure based on the values in `par' and maybe
* other values read out of the hardware.
*/
static int mc68328_encode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par)
{
int i;
var->xres = par->xres;
var->yres = par->yres;
var->xres_virtual = par->xres;
var->yres_virtual = par->yres;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = par->bpp;
var->grayscale = -1;
var->red.offset = 0;
var->red.length = par->bpp;
var->red.msb_right = 0;
var->blue = var->green = var->red;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 0;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
/* Dummy values */
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
for (i = 0; i < arraysize(var->reserved); i++)
var->reserved[i] = 0;
return(0);
}
/* /*
* Set a single color register. The values supplied are already * Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the * rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno. * entries in the var structure). Return != 0 for invalid regno.
*/ */
static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green,
u_int transp) u_int blue, u_int transp)
{ {
return 1; return 1;
#if 0 #if 0
if (regno > 255) if (regno > 255)
return (1); return (1);
*(mc68328Regs + 0x3c8) = (char)regno; *(mc68328Regs + 0x3c8) = (char) regno;
mc68328_colour_table [regno][0] = red & 0xff; mc68328_colour_table[regno][0] = red & 0xff;
mc68328_colour_table [regno][1] = green & 0xff; mc68328_colour_table[regno][1] = green & 0xff;
mc68328_colour_table [regno][2] = blue & 0xff; mc68328_colour_table[regno][2] = blue & 0xff;
mc68328_colour_table [regno][3] = transp; mc68328_colour_table[regno][3] = transp;
*(mc68328Regs + 0x3c9) = (red & 0xff) >> 2; *(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (green & 0xff) >> 2; *(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2; *(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;
return (0); return (0);
#endif
}
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp)
{
return 1;
#if 0
if (regno >= 256)
return (1);
*red = mc68328_colour_table [regno][0];
*green = mc68328_colour_table [regno][1];
*blue = mc68328_colour_table [regno][2];
*transp = mc68328_colour_table [regno][3];
return (0);
#endif #endif
} }
/* /*
* (Un)Blank the screen * (Un)Blank the screen
*/ */
void mc68328_blank(int blank) static void mc68328fb_blank(int blank, struct fb_info *info)
{ {
#if 0 #if 0
if (blank) if (blank)
(*(volatile unsigned char*)0xFFFFFA27) &= ~128; (*(volatile unsigned char *) 0xFFFFFA27) &= ~128;
else else
(*(volatile unsigned char*)0xFFFFFA27) |= 128; (*(volatile unsigned char *) 0xFFFFFA27) |= 128;
#endif #endif
} }
...@@ -504,86 +253,91 @@ void mc68328_blank(int blank) ...@@ -504,86 +253,91 @@ void mc68328_blank(int blank)
/************************************************************** /**************************************************************
* We are waiting for "fifo" FIFO-slots empty * We are waiting for "fifo" FIFO-slots empty
*/ */
void mc68328_WaitQueue (u_short fifo) void mc68328_WaitQueue(u_short fifo)
{ {
} }
/************************************************************** /**************************************************************
* We are waiting for Hardware (Graphics Engine) not busy * We are waiting for Hardware (Graphics Engine) not busy
*/ */
void mc68328_WaitBlit (void) void mc68328_WaitBlit(void)
{ {
} }
/************************************************************** /**************************************************************
* BitBLT - Through the Plane * BitBLT - Through the Plane
*/ */
void mc68328_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, void mc68328_BitBLT(u_short curx, u_short cury, u_short destx,
u_short width, u_short height, u_short mode) u_short desty, u_short width, u_short height,
u_short mode)
{ {
#if 0 #if 0
u_short blitcmd = S3_BITBLT; u_short blitcmd = S3_BITBLT;
/* Set drawing direction */ /* Set drawing direction */
/* -Y, X maj, -X (default) */ /* -Y, X maj, -X (default) */
if (curx > destx) if (curx > destx)
blitcmd |= 0x0020; /* Drawing direction +X */ blitcmd |= 0x0020; /* Drawing direction +X */
else else {
{ curx += (width - 1);
curx += (width - 1); destx += (width - 1);
destx += (width - 1); }
}
if (cury > desty)
if (cury > desty) blitcmd |= 0x0080; /* Drawing direction +Y */
blitcmd |= 0x0080; /* Drawing direction +Y */ else {
else cury += (height - 1);
{ desty += (height - 1);
cury += (height - 1); }
desty += (height - 1);
} mc68328_WaitQueue(0x8000);
mc68328_WaitQueue (0x8000); *((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
*((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) =
*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000; (0x0060 | mode);
*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0060 | mode);
*((u_short volatile *) (mc68328Regs + S3_CUR_X)) = curx;
*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = curx; *((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = cury;
*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = cury;
*((u_short volatile *) (mc68328Regs + S3_DESTX_DIASTP)) = destx;
*((u_short volatile *)(mc68328Regs + S3_DESTX_DIASTP)) = destx; *((u_short volatile *) (mc68328Regs + S3_DESTY_AXSTP)) = desty;
*((u_short volatile *)(mc68328Regs + S3_DESTY_AXSTP)) = desty;
*((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) =
*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1; height - 1;
*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width - 1; *((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) =
width - 1;
*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
*((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd;
#endif #endif
} }
/************************************************************** /**************************************************************
* Rectangle Fill Solid * Rectangle Fill Solid
*/ */
void mc68328_RectFill (u_short x, u_short y, u_short width, u_short height, void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
u_short mode, u_short color) u_short mode, u_short color)
{ {
#if 0 #if 0
u_short blitcmd = S3_FILLEDRECT; u_short blitcmd = S3_FILLEDRECT;
mc68328_WaitQueue (0x8000); mc68328_WaitQueue(0x8000);
*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000; *((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0020 | mode); *((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) =
(0x0020 | mode);
*((u_short volatile *)(mc68328Regs + S3_MULT_MISC)) = 0xe000; *((u_short volatile *) (mc68328Regs + S3_MULT_MISC)) = 0xe000;
*((u_short volatile *)(mc68328Regs + S3_FRGD_COLOR)) = color; *((u_short volatile *) (mc68328Regs + S3_FRGD_COLOR)) = color;
*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = x; *((u_short volatile *) (mc68328Regs + S3_CUR_X)) = x;
*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = y; *((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = y;
*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1; *((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) =
*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width - 1; height - 1;
*((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) =
width - 1;
*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd; *((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd;
#endif #endif
} }
...@@ -591,97 +345,54 @@ mc68328_WaitQueue (0x8000); ...@@ -591,97 +345,54 @@ mc68328_WaitQueue (0x8000);
/************************************************************** /**************************************************************
* Move cursor to x, y * Move cursor to x, y
*/ */
void mc68328_MoveCursor (u_short x, u_short y) void mc68328_MoveCursor(u_short x, u_short y)
{ {
(*(volatile unsigned short*)0xFFFFFA18) = (mc68328fbCursorMode << 14) | x; (*(volatile unsigned short *) 0xFFFFFA18) =
(*(volatile unsigned short*)0xFFFFFA1A) = y; (mc68328fbCursorMode << 14) | x;
(*(volatile unsigned short *) 0xFFFFFA1A) = y;
#if 0 #if 0
*(mc68328Regs + S3_CRTC_ADR) = 0x39; *(mc68328Regs + S3_CRTC_ADR) = 0x39;
*(mc68328Regs + S3_CRTC_DATA) = 0xa0; *(mc68328Regs + S3_CRTC_DATA) = 0xa0;
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H; *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
*(mc68328Regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8); *(mc68328Regs + S3_CRTC_DATA) = (char) ((x & 0x0700) >> 8);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L; *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
*(mc68328Regs + S3_CRTC_DATA) = (char)(x & 0x00ff); *(mc68328Regs + S3_CRTC_DATA) = (char) (x & 0x00ff);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H; *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
*(mc68328Regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8); *(mc68328Regs + S3_CRTC_DATA) = (char) ((y & 0x0700) >> 8);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L; *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
*(mc68328Regs + S3_CRTC_DATA) = (char)(y & 0x00ff); *(mc68328Regs + S3_CRTC_DATA) = (char) (y & 0x00ff);
#endif #endif
} }
/* -------------------- Interfaces to hardware functions -------------------- */
static struct fb_hwswitch mc68328_switch = {
mc68328_init, mc68328_encode_fix, mc68328_decode_var, mc68328_encode_var,
mc68328_getcolreg, mc68328_setcolreg, mc68328_blank
};
/* -------------------- Generic routines ------------------------------------ */ /* -------------------- Generic routines ------------------------------------ */
/*
* Fill the hardware's `par' structure.
*/
static void mc68328_fb_get_par(struct mc68328_fb_par *par)
{
if (current_par_valid)
*par = current_par;
else
fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], par);
}
static void mc68328_fb_set_par(struct mc68328_fb_par *par)
{
current_par = *par;
current_par_valid = 1;
}
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
{
int err, activate;
struct mc68328_fb_par par;
if ((err = fbhw->decode_var(var, &par)))
return(err);
activate = var->activate;
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
mc68328_fb_set_par(&par);
fbhw->encode_var(var, &par);
var->activate = activate;
return(0);
}
/* /*
* Default Colormaps * Default Colormaps
*/ */
static u_short red16[] = static u_short red16[] =
{ 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000, { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff}; 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff
};
static u_short green16[] = static u_short green16[] =
{ 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff}; 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff
};
static u_short blue16[] = static u_short blue16[] =
{ 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000, { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff}; 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff
};
static struct fb_cmap default_16_colors = static struct fb_cmap default_16_colors =
{ 0, 16, red16, green16, blue16, NULL }; { 0, 16, red16, green16, blue16, NULL };
static struct fb_cmap *get_default_colormap(int bpp) static struct fb_cmap *get_default_colormap(int bpp)
{ {
return(&default_16_colors); return (&default_16_colors);
} }
...@@ -689,216 +400,13 @@ static struct fb_cmap *get_default_colormap(int bpp) ...@@ -689,216 +400,13 @@ static struct fb_cmap *get_default_colormap(int bpp)
#define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \ #define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
((1<<(width))-1)) : 0)) ((1<<(width))-1)) : 0))
static void memcpy_fs(int fsfromto, void *to, void *from, int len)
{
switch (fsfromto) {
case 0:
memcpy(to, from, len);
return;
case 1:
copy_from_user(to, from, len);
return;
case 2:
copy_to_user(to, from, len);
return;
}
}
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
{
int size;
int tooff = 0, fromoff = 0;
if (to->start > from->start)
fromoff = to->start-from->start;
else
tooff = from->start-to->start;
size = to->len-tooff;
if (size > from->len-fromoff)
size = from->len-fromoff;
if (size < 0)
return;
size *= sizeof(u_short);
memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp)
memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
}
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
{
int size = len*sizeof(u_short);
if (cmap->len != len) {
if (cmap->red)
kfree(cmap->red);
if (cmap->green)
kfree(cmap->green);
if (cmap->blue)
kfree(cmap->blue);
if (cmap->transp)
kfree(cmap->transp);
cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
cmap->len = 0;
if (!len)
return(0);
if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
return(-1);
if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
return(-1);
if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
return(-1);
if (transp) {
if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
return(-1);
} else
cmap->transp = NULL;
}
cmap->start = 0;
cmap->len = len;
copy_cmap(get_default_colormap(len), cmap, 0);
return(0);
}
/*
* Get the Fixed Part of the Display
*/
static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
struct mc68328_fb_par par;
int error = 0;
if (con == -1)
mc68328_fb_get_par(&par);
else
error = fbhw->decode_var(&disp[con].var, &par);
return(error ? error : fbhw->encode_fix(fix, &par));
}
/*
* Get the User Defined Part of the Display
*/
static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct mc68328_fb_par par;
int error = 0;
if (con == -1) {
mc68328_fb_get_par(&par);
error = fbhw->encode_var(var, &par);
} else
*var = disp[con].var;
return(error);
}
static void mc68328_fb_set_disp(int con, struct fb_info *info)
{
struct fb_fix_screeninfo fix;
mc68328_fb_get_fix(&fix, con, info);
if (con == -1)
con = 0;
info->screen_base = (u_char *)fix.smem_start;
disp[con].visual = fix.visual;
disp[con].type = fix.type;
disp[con].type_aux = fix.type_aux;
disp[con].ypanstep = fix.ypanstep;
disp[con].ywrapstep = fix.ywrapstep;
disp[con].can_soft_blank = 1;
disp[con].inverse = mc68328fb_inverse;
}
/*
* Set the User Defined Part of the Display
*/
static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
if ((err = do_fb_set_var(var, con == currcon)))
return(err);
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = disp[con].var.xres;
oldyres = disp[con].var.yres;
oldvxres = disp[con].var.xres_virtual;
oldvyres = disp[con].var.yres_virtual;
oldbpp = disp[con].var.bits_per_pixel;
disp[con].var = *var;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel) {
mc68328_fb_set_disp(con, info);
(*fb_info.changevar)(con);
alloc_cmap(&disp[con].cmap, 0, 0);
do_install_cmap(con, info);
}
}
var->activate = 0;
return(0);
}
/*
* Get the Colormap
*/
static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
{
if (con == currcon) /* current console? */
return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
else if (disp[con].cmap.len) /* non default colormap? */
copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
else
copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
kspc ? 0 : 2);
return(0);
}
/*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
return(-EINVAL);
}
/*
* mc68328 Frame Buffer Specific ioctls
*/
static int mc68328_fb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, int con, struct fb_info *info)
{
return(-EINVAL);
}
static struct fb_ops mc68328_fb_ops = { static struct fb_ops mc68328_fb_ops = {
owner: THIS_MODULE, .owner: THIS_MODULE,
fb_get_fix: mc68328_fb_get_fix, .fb_setcolreg: mc68328fb_setcolreg,
fb_get_var: mc68328_fb_get_var, .fb_fillrect: cfbfillrect,
fb_set_var: mc68328_fb_set_var, .fb_copyarea: cfbcopyarea,
fb_get_cmap: mc68328_fb_get_cmap, .fb_imageblit: cfbimgblt,
fb_set_cmap: gen_set_cmap, .fb_cursor: softcursor,
fb_pan_display: mc68328_fb_pan_display,
fb_ioctl: mc68328_fb_ioctl,
}; };
...@@ -908,79 +416,34 @@ static struct fb_ops mc68328_fb_ops = { ...@@ -908,79 +416,34 @@ static struct fb_ops mc68328_fb_ops = {
int __init mc68328_fb_init(void) int __init mc68328_fb_init(void)
{ {
int err; if (mc68328fb_mode == -1)
struct mc68328_fb_par par; mc68328fb_mode = PALM_DEFMODE;
mc68328_fix.smem_start = (*(volatile unsigned long *) 0xFFFFFA00);
fbhw = &mc68328_switch; /*kernel_map (board_addr + 0x01400000, 0x00400000, */
err = register_framebuffer(&fb_info); info->var = mc68328_fb_predefined[mc68328fb_mode];
if (err < 0)
panic("Cannot register frame buffer\n"); if (info->var.bits_per_pixel == 1)
fix->visual = FB_VISUAL_MONO01;
fbhw->init(); else
fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], &par); fix->visual = FB_VISUAL_DIRECTCOLOR;
fbhw->encode_var(&mc68328_fb_predefined[0], &par); info->screen_base = (u_char *) mc68328_fix.smem_start;
strcpy(fb_info.modename, mc68328_fb_name); if (register_framebuffer(&fb_info) < 0)
fb_info.disp = disp; panic("Cannot register frame buffer\n");
fb_info.switch_con = &mc68328fb_switch; return 0;
fb_info.updatevar = &mc68328fb_updatevar;
do_fb_set_var(&mc68328_fb_predefined[0], 1);
mc68328_fb_get_var(&disp[0].var, -1, &fb_info);
mc68328_fb_set_disp(-1, &fb_info);
do_install_cmap(0, &fb_info);
return(0);
}
static int mc68328fb_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (disp[currcon].cmap.len)
fb_get_cmap(&disp[currcon].cmap, 1, &disp[currcon].var, info);
do_fb_set_var(&disp[con].var, 1);
currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
return(0);
}
/*
* Update the `var' structure (called by fbcon.c)
*
* This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
* Since it's called by a kernel driver, no range checking is done.
*/
static int mc68328fb_updatevar(int con)
{
return(0);
}
/*
* Blank the display.
*/
static void mc68328fb_blank(int blank)
{
fbhw->blank(blank);
} }
/* /*
* Get a Video Mode * Get a Video Mode
*/ */
static int get_video_mode(const char *name) static int get_video_mode(const char *name)
{ {
int i; int i;
for (i = 1; i < NUM_PREDEF_MODES; i++) for (i = 1; i < NUM_PREDEF_MODES; i++)
if (!strcmp(name, mc68328_fb_modenames[i])) if (!strcmp(name, mc68328_fb_modenames[i]))
return(i); return (i);
return(0); return (0);
} }
...@@ -1967,8 +1967,7 @@ static void pm2fb_set_disp(const void* par, struct display* disp, ...@@ -1967,8 +1967,7 @@ static void pm2fb_set_disp(const void* par, struct display* disp,
struct pm2fb_par* p=(struct pm2fb_par* )par; struct pm2fb_par* p=(struct pm2fb_par* )par;
unsigned long flags; unsigned long flags;
save_flags(flags); local_irq_save(flags);
cli();
#ifdef __alpha__ #ifdef __alpha__
disp->screen_base=i->regions.v_fb + dense_mem(i->regions.v_fb); disp->screen_base=i->regions.v_fb + dense_mem(i->regions.v_fb);
#else #else
...@@ -2014,7 +2013,7 @@ static void pm2fb_set_disp(const void* par, struct display* disp, ...@@ -2014,7 +2013,7 @@ static void pm2fb_set_disp(const void* par, struct display* disp,
disp->dispsw=&fbcon_dummy; disp->dispsw=&fbcon_dummy;
break; break;
} }
restore_flags(flags); local_irq_restore(flags);
} }
#ifdef PM2FB_HW_CURSOR #ifdef PM2FB_HW_CURSOR
......
...@@ -3297,8 +3297,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp, ...@@ -3297,8 +3297,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
DTRACE; DTRACE;
save_flags(flags); local_irq_save(flags);
cli();
info->info.screen_base = l_fb_info->v_fb; info->info.screen_base = l_fb_info->v_fb;
switch (p->depth) { switch (p->depth) {
#ifdef FBCON_HAS_CFB8 #ifdef FBCON_HAS_CFB8
...@@ -3356,7 +3355,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp, ...@@ -3356,7 +3355,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
DPRINTK(1, "Invalid depth, using fbcon_dummy\n"); DPRINTK(1, "Invalid depth, using fbcon_dummy\n");
break; break;
} }
restore_flags(flags); local_irq_restore(flags);
} }
/* */ /* */
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/console.h>
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
#include <asm/mtrr.h> #include <asm/mtrr.h>
#endif #endif
...@@ -50,13 +49,9 @@ ...@@ -50,13 +49,9 @@
#error This driver requires PCI support. #error This driver requires PCI support.
#endif #endif
/* version number of this driver */ /* version number of this driver */
#define RIVAFB_VERSION "0.9.3" #define RIVAFB_VERSION "0.9.3"
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* various helpful macros and constants * various helpful macros and constants
...@@ -1166,12 +1161,12 @@ static int rivafb_open(struct fb_info *info, int user) ...@@ -1166,12 +1161,12 @@ static int rivafb_open(struct fb_info *info, int user)
int cnt = atomic_read(&par->ref_count); int cnt = atomic_read(&par->ref_count);
if (!cnt) { if (!cnt) {
memset(&par->state, 0, sizeof(struct fb_vgastate)); memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
/* save the DAC for Riva128 */ /* save the DAC for Riva128 */
if (par->riva.Architecture == NV_ARCH_03) if (par->riva.Architecture == NV_ARCH_03)
par->state.flags |= VGA_SAVE_CMAP; par->state.flags |= VGA_SAVE_CMAP;
fb_save_vga(&par->state); save_vga(&par->state);
RivaGetConfig(&par->riva); RivaGetConfig(&par->riva);
riva_save_state(par, &par->initial_state); riva_save_state(par, &par->initial_state);
...@@ -1192,7 +1187,7 @@ static int rivafb_release(struct fb_info *info, int user) ...@@ -1192,7 +1187,7 @@ static int rivafb_release(struct fb_info *info, int user)
par->riva.LockUnlock(&par->riva, 0); par->riva.LockUnlock(&par->riva, 0);
par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
fb_restore_vga(&par->state); restore_vga(&par->state);
par->riva.LockUnlock(&par->riva, 1); par->riva.LockUnlock(&par->riva, 1);
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/vga.h>
#include "riva_hw.h" #include "riva_hw.h"
/* GGI compatibility macros */ /* GGI compatibility macros */
...@@ -34,7 +35,7 @@ struct riva_par { ...@@ -34,7 +35,7 @@ struct riva_par {
struct riva_regs initial_state; /* initial startup video mode */ struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state; struct riva_regs current_state;
struct fb_vgastate state; struct vgastate state;
atomic_t ref_count; atomic_t ref_count;
riva_cfb8_cmap_t cmap[256]; /* VGA DAC palette cache */ riva_cfb8_cmap_t cmap[256]; /* VGA DAC palette cache */
u32 riva_palette[16]; u32 riva_palette[16];
......
...@@ -780,8 +780,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info) ...@@ -780,8 +780,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info)
u32 vhcr, vvcr, vvvr; u32 vhcr, vvcr, vvvr;
unsigned long flags; unsigned long flags;
save_flags(flags); local_irq_save(flags);
cli();
vhcr = TGA_READ_REG(TGA_HORIZ_REG); vhcr = TGA_READ_REG(TGA_HORIZ_REG);
vvcr = TGA_READ_REG(TGA_VERT_REG); vvcr = TGA_READ_REG(TGA_VERT_REG);
...@@ -821,7 +820,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info) ...@@ -821,7 +820,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info)
break; break;
} }
restore_flags(flags); local_irq_restore(flags);
return 0; return 0;
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#include "vga.h" #include <video/vga.h>
#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */ #define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */
#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */ #define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */
...@@ -70,7 +70,7 @@ static struct vga16fb_par { ...@@ -70,7 +70,7 @@ static struct vga16fb_par {
unsigned char ModeControl; /* CRT-Controller:17h */ unsigned char ModeControl; /* CRT-Controller:17h */
unsigned char ClockingMode; /* Seq-Controller:01h */ unsigned char ClockingMode; /* Seq-Controller:01h */
} vga_state; } vga_state;
struct fb_vgastate state; struct vgastate state;
atomic_t ref_count; atomic_t ref_count;
int palette_blanked, vesa_blanked, mode, isVGA; int palette_blanked, vesa_blanked, mode, isVGA;
u8 misc, pel_msk, vss, clkdiv; u8 misc, pel_msk, vss, clkdiv;
...@@ -304,9 +304,9 @@ static int vga16fb_open(struct fb_info *info, int user) ...@@ -304,9 +304,9 @@ static int vga16fb_open(struct fb_info *info, int user)
int cnt = atomic_read(&par->ref_count); int cnt = atomic_read(&par->ref_count);
if (!cnt) { if (!cnt) {
memset(&par->state, 0, sizeof(struct fb_vgastate)); memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = 8; par->state.flags = 8;
fb_save_vga(&par->state); save_vga(&par->state);
} }
atomic_inc(&par->ref_count); atomic_inc(&par->ref_count);
return 0; return 0;
...@@ -320,7 +320,7 @@ static int vga16fb_release(struct fb_info *info, int user) ...@@ -320,7 +320,7 @@ static int vga16fb_release(struct fb_info *info, int user)
if (!cnt) if (!cnt)
return -EINVAL; return -EINVAL;
if (cnt == 1) if (cnt == 1)
fb_restore_vga(&par->state); restore_vga(&par->state);
atomic_dec(&par->ref_count); atomic_dec(&par->ref_count);
return 0; return 0;
......
/* /*
* linux/include/video/vgastate.c -- VGA state save/restore * linux/drivers/video/vgastate.c -- VGA state save/restore
* *
* Copyright 2002 James Simmons * Copyright 2002 James Simmons
* *
...@@ -17,8 +17,19 @@ ...@@ -17,8 +17,19 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/vga.h>
#include "vga.h"
struct regstate {
__u8 *vga_font0;
__u8 *vga_font1;
__u8 *vga_text;
__u8 *vga_cmap;
__u8 *attr;
__u8 *crtc;
__u8 *gfx;
__u8 *seq;
__u8 misc;
};
static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase,
unsigned char reg) unsigned char reg)
...@@ -34,8 +45,9 @@ static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, ...@@ -34,8 +45,9 @@ static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase,
vga_w(regbase, iobase + 0x5, val); vga_w(regbase, iobase + 0x5, val);
} }
static void save_vga_text(struct fb_vgastate *state) static void save_vga_text(struct vgastate *state, caddr_t fbbase)
{ {
struct regstate *saved = (struct regstate *) state->vidstate;
int i; int i;
u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4; u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
...@@ -61,44 +73,45 @@ static void save_vga_text(struct fb_vgastate *state) ...@@ -61,44 +73,45 @@ static void save_vga_text(struct fb_vgastate *state)
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5); vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
/* save font 0 */ /* save font at plane 2 */
if (state->flags & VGA_SAVE_FONT0) { if (state->flags & VGA_SAVE_FONT0) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++) for (i = 0; i < 4 * 8192; i++)
state->vga_font0[i] = vga_r(state->fbbase, i); saved->vga_font0[i] = vga_r(fbbase, i);
} }
/* save font 1 */
/* save font at plane 3 */
if (state->flags & VGA_SAVE_FONT1) { if (state->flags & VGA_SAVE_FONT1) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++) for (i = 0; i < state->memsize; i++)
state->vga_font1[i] = vga_r(state->fbbase, i); saved->vga_font1[i] = vga_r(fbbase, i);
} }
/* save font 2 */
/* save font at plane 0/1 */
if (state->flags & VGA_SAVE_TEXT) { if (state->flags & VGA_SAVE_TEXT) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++) for (i = 0; i < 8192; i++)
state->vga_text[i] = vga_r(state->fbbase, i); saved->vga_text[i] = vga_r(fbbase, i);
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++) for (i = 0; i < 8192; i++)
state->vga_text[i] = vga_r(state->fbbase + saved->vga_text[i] = vga_r(fbbase + 2 * 8192, i);
2 * 8192, i);
} }
/* restore regs */ /* restore regs */
...@@ -120,8 +133,9 @@ static void save_vga_text(struct fb_vgastate *state) ...@@ -120,8 +133,9 @@ static void save_vga_text(struct fb_vgastate *state)
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1); vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
} }
static void restore_vga_text(struct fb_vgastate *state) static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
{ {
struct regstate *saved = (struct regstate *) state->vidstate;
int i; int i;
u8 misc, gr1, gr3, gr4, gr5, gr6, gr8; u8 misc, gr1, gr3, gr4, gr5, gr6, gr8;
u8 seq1, seq2, seq4; u8 seq1, seq2, seq4;
...@@ -151,45 +165,49 @@ static void restore_vga_text(struct fb_vgastate *state) ...@@ -151,45 +165,49 @@ static void restore_vga_text(struct fb_vgastate *state)
vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff); vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff);
vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00); vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00);
} }
/* restore font 0 */
/* restore font at plane 2 */
if (state->flags & VGA_SAVE_FONT0) { if (state->flags & VGA_SAVE_FONT0) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++) for (i = 0; i < 4 * 8192; i++)
vga_w(state->fbbase, i, state->vga_font0[i]); vga_w(fbbase, i, saved->vga_font0[i]);
} }
/* restore font 1 */
/* restore font at plane 3 */
if (state->flags & VGA_SAVE_FONT1) { if (state->flags & VGA_SAVE_FONT1) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++) for (i = 0; i < 4 * 8192; i++)
vga_w(state->fbbase, i, state->vga_font1[i]); vga_w(fbbase, i, saved->vga_font1[i]);
} }
/* restore font 2 */
/* restore font at plane 0/1 */
if (state->flags & VGA_SAVE_TEXT) { if (state->flags & VGA_SAVE_TEXT) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++) for (i = 0; i < 8192; i++)
vga_w(state->fbbase, i, state->vga_text[i]); vga_w(fbbase, i, saved->vga_text[i]);
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2); vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1); vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++) for (i = 0; i < 8192; i++)
vga_w(state->fbbase + 2 * 8192, i, vga_w(fbbase + 2 * 8192, i,
state->vga_text[i]); saved->vga_text[i]);
} }
/* unblank screen */ /* unblank screen */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5)); vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
...@@ -210,81 +228,92 @@ static void restore_vga_text(struct fb_vgastate *state) ...@@ -210,81 +228,92 @@ static void restore_vga_text(struct fb_vgastate *state)
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4); vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
} }
static void save_vga_mode(struct fb_vgastate *state) static void save_vga_mode(struct vgastate *state)
{ {
struct regstate *saved = (struct regstate *) state->vidstate;
unsigned short iobase; unsigned short iobase;
int i; int i;
state->misc = vga_r(state->vgabase, VGA_MIS_R); saved->misc = vga_r(state->vgabase, VGA_MIS_R);
if (state->misc & 1) if (saved->misc & 1)
iobase = 0x3d0; iobase = 0x3d0;
else else
iobase = 0x3b0; iobase = 0x3b0;
for (i = 0; i < state->num_crtc; i++) for (i = 0; i < state->num_crtc; i++)
state->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i); saved->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
vga_r(state->vgabase, iobase + 0xa); vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x00); vga_w(state->vgabase, VGA_ATT_W, 0x00);
for (i = 0; i < state->num_attr; i++) { for (i = 0; i < state->num_attr; i++) {
vga_r(state->vgabase, iobase + 0xa); vga_r(state->vgabase, iobase + 0xa);
state->attr[i] = vga_rattr(state->vgabase, i); saved->attr[i] = vga_rattr(state->vgabase, i);
} }
vga_r(state->vgabase, iobase + 0xa); vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x20); vga_w(state->vgabase, VGA_ATT_W, 0x20);
for (i = 0; i < state->num_gfx; i++) for (i = 0; i < state->num_gfx; i++)
state->gfx[i] = vga_rgfx(state->vgabase, i); saved->gfx[i] = vga_rgfx(state->vgabase, i);
for (i = 0; i < state->num_seq; i++) for (i = 0; i < state->num_seq; i++)
state->seq[i] = vga_rseq(state->vgabase, i); saved->seq[i] = vga_rseq(state->vgabase, i);
} }
static void restore_vga_mode(struct fb_vgastate *state) static void restore_vga_mode(struct vgastate *state)
{ {
struct regstate *saved = (struct regstate *) state->vidstate;
unsigned short iobase; unsigned short iobase;
int i; int i;
vga_w(state->vgabase, VGA_MIS_W, state->misc); vga_w(state->vgabase, VGA_MIS_W, saved->misc);
if (state->misc & 1) if (saved->misc & 1)
iobase = 0x3d0; iobase = 0x3d0;
else else
iobase = 0x3b0; iobase = 0x3b0;
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01); /* turn off display */
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
state->seq[VGA_SEQ_CLOCK_MODE] | 0x20); saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
/* disable sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
/* enable palette addressing */
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x00);
for (i = 2; i < state->num_seq; i++) for (i = 2; i < state->num_seq; i++)
vga_wseq(state->vgabase, i, state->seq[i]); vga_wseq(state->vgabase, i, saved->seq[i]);
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
/* unprotect vga regs */ /* unprotect vga regs */
vga_wcrtcs(state->vgabase, iobase, 17, state->crtc[17] & ~0x80); vga_wcrtcs(state->vgabase, iobase, 17, saved->crtc[17] & ~0x80);
for (i = 0; i < state->num_crtc; i++) for (i = 0; i < state->num_crtc; i++)
vga_wcrtcs(state->vgabase, iobase, i, state->crtc[i]); vga_wcrtcs(state->vgabase, iobase, i, saved->crtc[i]);
for (i = 0; i < state->num_gfx; i++) for (i = 0; i < state->num_gfx; i++)
vga_wgfx(state->vgabase, i, state->gfx[i]); vga_wgfx(state->vgabase, i, saved->gfx[i]);
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x00);
for (i = 0; i < state->num_attr; i++) { for (i = 0; i < state->num_attr; i++) {
vga_r(state->vgabase, iobase + 0xa); vga_r(state->vgabase, iobase + 0xa);
vga_wattr(state->vgabase, i, state->attr[i]); vga_wattr(state->vgabase, i, saved->attr[i]);
} }
/* reenable sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
/* turn display on */
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
state->seq[VGA_SEQ_CLOCK_MODE]); saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5));
/* disable video/palette source */
vga_r(state->vgabase, iobase + 0xa); vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x20); vga_w(state->vgabase, VGA_ATT_W, 0x20);
} }
static void save_vga_cmap(struct fb_vgastate *state) static void save_vga_cmap(struct vgastate *state)
{ {
struct regstate *saved = (struct regstate *) state->vidstate;
int i; int i;
vga_w(state->vgabase, VGA_PEL_MSK, 0xff); vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
...@@ -292,56 +321,55 @@ static void save_vga_cmap(struct fb_vgastate *state) ...@@ -292,56 +321,55 @@ static void save_vga_cmap(struct fb_vgastate *state)
/* assumes DAC is readable and writable */ /* assumes DAC is readable and writable */
vga_w(state->vgabase, VGA_PEL_IR, 0x00); vga_w(state->vgabase, VGA_PEL_IR, 0x00);
for (i = 0; i < 768; i++) for (i = 0; i < 768; i++)
state->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D); saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
} }
static void restore_vga_cmap(struct fb_vgastate *state) static void restore_vga_cmap(struct vgastate *state)
{ {
struct regstate *saved = (struct regstate *) state->vidstate;
int i; int i;
vga_w(state->vgabase, VGA_PEL_MSK, 0xff); vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
/* assumes DAC is readable and writable */
vga_w(state->vgabase, VGA_PEL_IW, 0x00); vga_w(state->vgabase, VGA_PEL_IW, 0x00);
for (i = 0; i < 768; i++) for (i = 0; i < 768; i++)
vga_w(state->vgabase, VGA_PEL_D, state->vga_cmap[i]); vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]);
} }
static void vga_cleanup(struct fb_vgastate *state) static void vga_cleanup(struct vgastate *state)
{ {
if (state->vga_font0) if (state->vidstate != NULL) {
kfree(state->vga_font0); struct regstate *saved = (struct regstate *) state->vidstate;
if (state->vga_font1)
kfree(state->vga_font1); if (saved->vga_font0)
if (state->vga_text) vfree(saved->vga_font0);
kfree(state->vga_text); if (saved->vga_font1)
if (state->fbbase) vfree(saved->vga_font1);
iounmap(state->fbbase); if (saved->vga_text)
if (state->vga_cmap) vfree(saved->vga_text);
kfree(state->vga_cmap); if (saved->vga_cmap)
if (state->attr) vfree(saved->vga_cmap);
kfree(state->attr); if (saved->attr)
if (state->crtc) vfree(saved->attr);
kfree(state->crtc); kfree(saved);
if (state->gfx) state->vidstate = NULL;
kfree(state->gfx); }
if (state->seq)
kfree(state->seq);
} }
int fb_save_vga(struct fb_vgastate *state) int save_vga(struct vgastate *state)
{ {
state->vga_font0 = NULL; struct regstate *saved;
state->vga_font1 = NULL;
state->vga_text = NULL; saved = kmalloc(sizeof(struct regstate), GFP_KERNEL);
state->vga_cmap = NULL; if (saved == NULL)
state->attr = NULL; return 1;
state->crtc = NULL; memset (saved, 0, sizeof(struct regstate));
state->gfx = NULL; (struct regstate *) state->vidstate = saved;
state->seq = NULL;
if (state->flags & VGA_SAVE_CMAP) { if (state->flags & VGA_SAVE_CMAP) {
state->vga_cmap = kmalloc(768, GFP_KERNEL); saved->vga_cmap = vmalloc(768);
if (!state->vga_cmap) { if (!saved->vga_cmap) {
vga_cleanup(state); vga_cleanup(state);
return 1; return 1;
} }
...@@ -349,6 +377,8 @@ int fb_save_vga(struct fb_vgastate *state) ...@@ -349,6 +377,8 @@ int fb_save_vga(struct fb_vgastate *state)
} }
if (state->flags & VGA_SAVE_MODE) { if (state->flags & VGA_SAVE_MODE) {
int total;
if (state->num_attr < 21) if (state->num_attr < 21)
state->num_attr = 21; state->num_attr = 21;
if (state->num_crtc < 25) if (state->num_crtc < 25)
...@@ -357,64 +387,99 @@ int fb_save_vga(struct fb_vgastate *state) ...@@ -357,64 +387,99 @@ int fb_save_vga(struct fb_vgastate *state)
state->num_gfx = 9; state->num_gfx = 9;
if (state->num_seq < 5) if (state->num_seq < 5)
state->num_seq = 5; state->num_seq = 5;
state->attr = kmalloc(state->num_attr, GFP_KERNEL); total = state->num_attr + state->num_crtc +
state->crtc = kmalloc(state->num_crtc, GFP_KERNEL); state->num_gfx + state->num_seq;
state->gfx = kmalloc(state->num_gfx, GFP_KERNEL);
state->seq = kmalloc(state->num_seq, GFP_KERNEL); saved->attr = vmalloc(total);
if (!state->attr || !state->crtc || !state->gfx || if (!saved->attr) {
!state->seq) {
vga_cleanup(state); vga_cleanup(state);
return 1; return 1;
} }
saved->crtc = saved->attr + state->num_attr;
saved->gfx = saved->crtc + state->num_crtc;
saved->seq = saved->gfx + state->num_gfx;
save_vga_mode(state); save_vga_mode(state);
} }
if (state->flags & VGA_SAVE_FONT0) { if (state->flags & VGA_SAVE_FONTS) {
state->vga_font0 = kmalloc(8192 * 8, GFP_KERNEL); caddr_t fbbase;
if (!state->vga_font0) {
/* exit if window is less than 32K */
if (state->memsize && state->memsize < 4 * 8192) {
vga_cleanup(state); vga_cleanup(state);
return 1; return 1;
} }
if (!state->memsize)
state->memsize = 8 * 8192;
if (!state->membase)
state->membase = 0xA0000;
fbbase = ioremap(state->membase, state->memsize);
if (!fbbase) {
vga_cleanup(state);
iounmap(fbbase);
return 1;
} }
if (state->flags & VGA_SAVE_FONT1) {
state->vga_font1 = kmalloc(8192 * 8, GFP_KERNEL); /*
if (!state->vga_font1) { * save only first 32K used by vgacon
*/
if (state->flags & VGA_SAVE_FONT0) {
saved->vga_font0 = vmalloc(4 * 8192);
if (!saved->vga_font0) {
vga_cleanup(state); vga_cleanup(state);
return 1; return 1;
} }
} }
if (state->flags & VGA_SAVE_TEXT) { /*
state->vga_text = kmalloc(8192 * 4, GFP_KERNEL); * largely unused, but if required by the caller
if (!state->vga_text) { * we'll just save everything.
*/
if (state->flags & VGA_SAVE_FONT1) {
saved->vga_font1 = vmalloc(state->memsize);
if (!saved->vga_font1) {
vga_cleanup(state); vga_cleanup(state);
return 1; return 1;
} }
} }
if (state->flags & VGA_SAVE_FONTS) { /*
state->fbbase = ioremap(0xA0000, 8 * 8192); * Save 8K at plane0[0], and 8K at plane1[16K]
if (!state->fbbase) { */
if (state->flags & VGA_SAVE_TEXT) {
saved->vga_text = vmalloc(8192 * 2);
if (!saved->vga_text) {
vga_cleanup(state); vga_cleanup(state);
return 1; return 1;
} }
save_vga_text(state); }
iounmap(state->fbbase);
state->fbbase = NULL; save_vga_text(state, fbbase);
iounmap(fbbase);
} }
return 0; return 0;
} }
int fb_restore_vga (struct fb_vgastate *state) int restore_vga (struct vgastate *state)
{ {
if (state->vidstate == NULL)
return 1;
if (state->flags & VGA_SAVE_MODE) if (state->flags & VGA_SAVE_MODE)
restore_vga_mode(state); restore_vga_mode(state);
if (state->flags & VGA_SAVE_FONTS) { if (state->flags & VGA_SAVE_FONTS) {
state->fbbase = ioremap(0xA0000, 8 * 8192); caddr_t fbbase = ioremap(state->membase, state->memsize);
if (!state->fbbase) {
if (!fbbase) {
vga_cleanup(state); vga_cleanup(state);
iounmap(fbbase);
return 1; return 1;
} }
restore_vga_text(state); restore_vga_text(state, fbbase);
iounmap(fbbase);
} }
if (state->flags & VGA_SAVE_CMAP) if (state->flags & VGA_SAVE_CMAP)
...@@ -429,8 +494,8 @@ int init_module(void) { return 0; }; ...@@ -429,8 +494,8 @@ int init_module(void) { return 0; };
void cleanup_module(void) {}; void cleanup_module(void) {};
#endif #endif
EXPORT_SYMBOL(fb_save_vga); EXPORT_SYMBOL(save_vga);
EXPORT_SYMBOL(fb_restore_vga); EXPORT_SYMBOL(restore_vga);
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
MODULE_DESCRIPTION("VGA State Save/Restore"); MODULE_DESCRIPTION("VGA State Save/Restore");
......
...@@ -321,37 +321,6 @@ struct fb_cursor { ...@@ -321,37 +321,6 @@ struct fb_cursor {
struct fb_image image; /* Cursor image */ struct fb_image image; /* Cursor image */
}; };
/* VGA State Save and Restore */
#define VGA_SAVE_FONT0 1 /* save/restore plane 2 fonts */
#define VGA_SAVE_FONT1 2 /* save/restore plane 3 fonts */
#define VGA_SAVE_TEXT 4 /* save/restore plane 0/1 fonts */
#define VGA_SAVE_FONTS 7 /* save/restore all fonts */
#define VGA_SAVE_MODE 8 /* save/restore video mode */
#define VGA_SAVE_CMAP 16 /* save/restore color map/DAC */
struct fb_vgastate {
caddr_t vgabase; /* mmio base, if supported */
__u32 flags; /* what state/s to save (see VGA_SAVE_*) */
__u32 depth; /* current fb depth, not important */
__u32 num_attr; /* number of att registers, 0 for default */
__u32 num_crtc; /* number of crt registers, 0 for default */
__u32 num_gfx; /* number of gfx registers, 0 for default */
__u32 num_seq; /* number of seq registers, 0 for default */
caddr_t fbbase; /* -- DO NOT ALTER STARTING HERE -- */
__u8 *vga_font0;
__u8 *vga_font1;
__u8 *vga_text;
__u8 *vga_cmap;
__u8 *attr;
__u8 *crtc;
__u8 *gfx;
__u8 *seq;
__u8 misc;
};
extern int fb_save_vga(struct fb_vgastate *state);
extern int fb_restore_vga(struct fb_vgastate *state);
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -187,6 +187,29 @@ ...@@ -187,6 +187,29 @@
#define VGA_OUTW_WRITE #define VGA_OUTW_WRITE
#endif #endif
/* VGA State Save and Restore */
#define VGA_SAVE_FONT0 1 /* save/restore plane 2 fonts */
#define VGA_SAVE_FONT1 2 /* save/restore plane 3 fonts */
#define VGA_SAVE_TEXT 4 /* save/restore plane 0/1 fonts */
#define VGA_SAVE_FONTS 7 /* save/restore all fonts */
#define VGA_SAVE_MODE 8 /* save/restore video mode */
#define VGA_SAVE_CMAP 16 /* save/restore color map/DAC */
struct vgastate {
caddr_t vgabase; /* mmio base, if supported */
__u32 flags; /* what state[s] to save (see VGA_SAVE_*) */
__u32 membase; /* VGA window base, 0 for default - 0xA000 */
__u32 memsize; /* VGA window size, 0 for default 64K */
__u32 depth; /* current fb depth, not important */
__u32 num_attr; /* number of att registers, 0 for default */
__u32 num_crtc; /* number of crt registers, 0 for default */
__u32 num_gfx; /* number of gfx registers, 0 for default */
__u32 num_seq; /* number of seq registers, 0 for default */
void *vidstate;
};
extern int save_vga(struct vgastate *state);
extern int restore_vga(struct vgastate *state);
/* /*
* generic VGA port read/write * generic VGA port read/write
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment