patch-2.1.110 linux/drivers/video/vgacon.c
Next file: linux/drivers/video/vgafb.c
Previous file: linux/drivers/video/vesafb.c
Back to the patch index
Back to the overall index
- Lines: 430
- Date:
Sun Jul 19 20:45:45 1998
- Orig file:
v2.1.109/linux/drivers/video/vgacon.c
- Orig date:
Thu Jul 16 18:09:28 1998
diff -u --recursive --new-file v2.1.109/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
@@ -37,13 +37,12 @@
*
* - monochrome attribute encoding (convert abscon <-> VGA style)
*
- * - add support for VESA blanking
- *
* - Cursor shape fixes
*
* KNOWN PROBLEMS/TO DO ==================================================== */
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/fs.h>
@@ -69,8 +68,15 @@
#undef VGA_CAN_DO_64KB
-#define dac_reg (0x3c8)
-#define dac_val (0x3c9)
+#define dac_reg 0x3c8
+#define dac_val 0x3c9
+#define attrib_port 0x3c0
+#define seq_port_reg 0x3c4
+#define seq_port_val 0x3c5
+#define gr_port_reg 0x3ce
+#define gr_port_val 0x3cf
+#define video_misc_rd 0x3cc
+#define video_misc_wr 0x3c2
/*
* Interface used by the world
@@ -78,9 +84,10 @@
static const char *vgacon_startup(void);
static void vgacon_init(struct vc_data *c, int init);
+static void vgacon_deinit(struct vc_data *c);
static void vgacon_cursor(struct vc_data *c, int mode);
static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(int blank);
+static int vgacon_blank(struct vc_data *c, int blank);
static int vgacon_get_font(struct vc_data *c, int *w, int *h, char *data);
static int vgacon_set_font(struct vc_data *c, int w, int h, char *data);
static int vgacon_set_palette(struct vc_data *c, unsigned char *table);
@@ -103,6 +110,10 @@
static unsigned char vga_hardscroll_enabled;
static unsigned char vga_hardscroll_user_enable = 1;
static unsigned char vga_font_is_default = 1;
+static int vga_vesa_blanked;
+static int vga_palette_blanked;
+static int vga_is_gfx;
+
void no_scroll(char *str, int *ints)
{
@@ -114,7 +125,6 @@
vga_hardscroll_user_enable = vga_hardscroll_enabled = 0;
}
-
/*
* By replacing the four outb_p with two back to back outw, we can reduce
* the window of opportunity to see text mislocated to the RHS of the
@@ -139,13 +149,23 @@
#endif
}
-
__initfunc(static const char *vgacon_startup(void))
{
const char *display_desc = NULL;
u16 saved;
u16 *p;
+ if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
+ no_vga:
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+ return conswitchp->con_startup();
+#else
+ return NULL;
+#endif
+ }
+
+
vga_video_num_lines = ORIG_VIDEO_LINES;
vga_video_num_columns = ORIG_VIDEO_COLS;
@@ -178,7 +198,7 @@
vga_video_port_val = 0x3d5;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
{
- int i ;
+ int i;
vga_vram_end = 0xc0000;
@@ -248,12 +268,12 @@
scr_writew(0xAA55, p);
if (scr_readw(p) != 0xAA55) {
scr_writew(saved, p);
- return NULL;
+ goto no_vga;
}
scr_writew(0x55AA, p);
if (scr_readw(p) != 0x55AA) {
scr_writew(saved, p);
- return NULL;
+ goto no_vga;
}
scr_writew(saved, p);
@@ -271,7 +291,6 @@
return display_desc;
}
-
static void vgacon_init(struct vc_data *c, int init)
{
/* We cannot be loaded as a module, therefore init is always 1 */
@@ -280,13 +299,16 @@
c->vc_rows = vga_video_num_lines;
}
+static void vgacon_deinit(struct vc_data *c)
+{
+ vgacon_set_origin(c);
+}
static inline void vga_set_mem_top(struct vc_data *c)
{
write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);
}
-
static void vgacon_cursor(struct vc_data *c, int mode)
{
if (c->vc_origin != c->vc_visible_origin)
@@ -303,7 +325,6 @@
}
}
-
static int vgacon_switch(struct vc_data *c)
{
/*
@@ -317,21 +338,198 @@
return 0; /* Redrawing not needed */
}
+static void vga_set_palette(struct vc_data *c, unsigned char *table)
+{
+ int i, j ;
+
+ for (i=j=0; i<16; i++) {
+ outb_p (table[i], dac_reg) ;
+ outb_p (c->vc_palette[j++]>>2, dac_val) ;
+ outb_p (c->vc_palette[j++]>>2, dac_val) ;
+ outb_p (c->vc_palette[j++]>>2, dac_val) ;
+ }
+}
-static int vgacon_blank(int blank)
+static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
{
- /* FIXME: Implement! */
- /* FIXME: Check if we really ignore everything when the console is blanked. */
- if (blank) {
- scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+#ifdef CAN_LOAD_PALETTE
+
+ if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked)
+ return -EINVAL;
+ vga_set_palette(c, table);
return 0;
- } else {
- /* Tell console.c that it has to restore the screen itself */
- return 1;
- }
- return 0;
+#else
+ return -EINVAL;
+#endif
}
+/* structure holding original VGA register settings */
+static struct {
+ unsigned char SeqCtrlIndex; /* Sequencer Index reg. */
+ unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */
+ unsigned char CrtMiscIO; /* Miscellaneous register */
+ unsigned char HorizontalTotal; /* CRT-Controller:00h */
+ unsigned char HorizDisplayEnd; /* CRT-Controller:01h */
+ unsigned char StartHorizRetrace; /* CRT-Controller:04h */
+ unsigned char EndHorizRetrace; /* CRT-Controller:05h */
+ unsigned char Overflow; /* CRT-Controller:07h */
+ unsigned char StartVertRetrace; /* CRT-Controller:10h */
+ unsigned char EndVertRetrace; /* CRT-Controller:11h */
+ unsigned char ModeControl; /* CRT-Controller:17h */
+ unsigned char ClockingMode; /* Seq-Controller:01h */
+} vga_state;
+
+static void vga_vesa_blank(int mode)
+{
+ /* save original values of VGA controller registers */
+ if(!vga_vesa_blanked) {
+ cli();
+ vga_state.SeqCtrlIndex = inb_p(seq_port_reg);
+ vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
+ vga_state.CrtMiscIO = inb_p(video_misc_rd);
+ sti();
+
+ outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */
+ vga_state.HorizontalTotal = inb_p(vga_video_port_val);
+ outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */
+ vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
+ outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */
+ vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
+ outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */
+ vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
+ outb_p(0x07,vga_video_port_reg); /* Overflow */
+ vga_state.Overflow = inb_p(vga_video_port_val);
+ outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */
+ vga_state.StartVertRetrace = inb_p(vga_video_port_val);
+ outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */
+ vga_state.EndVertRetrace = inb_p(vga_video_port_val);
+ outb_p(0x17,vga_video_port_reg); /* ModeControl */
+ vga_state.ModeControl = inb_p(vga_video_port_val);
+ outb_p(0x01,seq_port_reg); /* ClockingMode */
+ vga_state.ClockingMode = inb_p(seq_port_val);
+ }
+
+ /* assure that video is enabled */
+ /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
+ cli();
+ outb_p(0x01,seq_port_reg);
+ outb_p(vga_state.ClockingMode | 0x20,seq_port_val);
+
+ /* test for vertical retrace in process.... */
+ if ((vga_state.CrtMiscIO & 0x80) == 0x80)
+ outb_p(vga_state.CrtMiscIO & 0xef,video_misc_wr);
+
+ /*
+ * Set <End of vertical retrace> to minimum (0) and
+ * <Start of vertical Retrace> to maximum (incl. overflow)
+ * Result: turn off vertical sync (VSync) pulse.
+ */
+ if (mode & VESA_VSYNC_SUSPEND) {
+ outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */
+ outb_p(0xff,vga_video_port_val); /* maximum value */
+ outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */
+ outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */
+ outb_p(0x07,vga_video_port_reg); /* Overflow */
+ outb_p(vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+ }
+
+ if (mode & VESA_HSYNC_SUSPEND) {
+ /*
+ * Set <End of horizontal retrace> to minimum (0) and
+ * <Start of horizontal Retrace> to maximum
+ * Result: turn off horizontal sync (HSync) pulse.
+ */
+ outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */
+ outb_p(0xff,vga_video_port_val); /* maximum */
+ outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */
+ outb_p(0x00,vga_video_port_val); /* minimum (0) */
+ }
+
+ /* restore both index registers */
+ outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
+ outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
+ sti();
+}
+
+static void vga_vesa_unblank(void)
+{
+ /* restore original values of VGA controller registers */
+ cli();
+ outb_p(vga_state.CrtMiscIO,video_misc_wr);
+
+ outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */
+ outb_p(vga_state.HorizontalTotal,vga_video_port_val);
+ outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */
+ outb_p(vga_state.HorizDisplayEnd,vga_video_port_val);
+ outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */
+ outb_p(vga_state.StartHorizRetrace,vga_video_port_val);
+ outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */
+ outb_p(vga_state.EndHorizRetrace,vga_video_port_val);
+ outb_p(0x07,vga_video_port_reg); /* Overflow */
+ outb_p(vga_state.Overflow,vga_video_port_val);
+ outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */
+ outb_p(vga_state.StartVertRetrace,vga_video_port_val);
+ outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */
+ outb_p(vga_state.EndVertRetrace,vga_video_port_val);
+ outb_p(0x17,vga_video_port_reg); /* ModeControl */
+ outb_p(vga_state.ModeControl,vga_video_port_val);
+ outb_p(0x01,seq_port_reg); /* ClockingMode */
+ outb_p(vga_state.ClockingMode,seq_port_val);
+
+ /* restore index/control registers */
+ outb_p(vga_state.SeqCtrlIndex,seq_port_reg);
+ outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg);
+ sti();
+}
+
+static void vga_pal_blank(void)
+{
+ int i;
+
+ for (i=0; i<16; i++) {
+ outb_p (i, dac_reg) ;
+ outb_p (0, dac_val) ;
+ outb_p (0, dac_val) ;
+ outb_p (0, dac_val) ;
+ }
+}
+
+static int vgacon_blank(struct vc_data *c, int blank)
+{
+ switch (blank) {
+ case 0: /* Unblank */
+ if (vga_vesa_blanked) {
+ vga_vesa_unblank();
+ vga_vesa_blanked = 0;
+ }
+ if (vga_palette_blanked) {
+ vga_set_palette(c, color_table);
+ vga_palette_blanked = 0;
+ return 0;
+ }
+ vga_is_gfx = 0;
+ /* Tell console.c that it has to restore the screen itself */
+ return 1;
+ case 1: /* Normal blanking */
+ if (vga_video_type == VIDEO_TYPE_VGAC) {
+ vga_pal_blank();
+ vga_palette_blanked = 1;
+ return 0;
+ }
+ scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+ return 0;
+ case -1: /* Entering graphic mode */
+ scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+ vga_is_gfx = 1;
+ return 0;
+ default: /* VESA blanking */
+ if (vga_video_type == VIDEO_TYPE_VGAC) {
+ vga_vesa_blank(blank-1);
+ vga_vesa_blanked = blank;
+ }
+ return 0;
+ }
+}
/*
* PIO_FONT support.
@@ -350,11 +548,6 @@
should use 0xA0000 for the bwmap as well.. */
#define blackwmap 0xa0000
#define cmapsz 8192
-#define attrib_port (0x3c0)
-#define seq_port_reg (0x3c4)
-#define seq_port_val (0x3c5)
-#define gr_port_reg (0x3ce)
-#define gr_port_val (0x3cf)
static int
vgacon_font_op(char *arg, int set)
@@ -578,26 +771,6 @@
return rc;
}
-static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
-{
-#ifdef CAN_LOAD_PALETTE
- int i, j ;
-
- if (vga_video_type != VIDEO_TYPE_VGAC || console_blanked)
- return -EINVAL;
-
- for (i=j=0; i<16; i++) {
- outb_p (table[i], dac_reg) ;
- outb_p (c->vc_palette[j++]>>2, dac_val) ;
- outb_p (c->vc_palette[j++]>>2, dac_val) ;
- outb_p (c->vc_palette[j++]>>2, dac_val) ;
- }
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
static int vgacon_scrolldelta(struct vc_data *c, int lines)
{
/* FIXME: Better scrollback strategy, maybe move it to generic code
@@ -620,6 +793,8 @@
static int vgacon_set_origin(struct vc_data *c)
{
+ if (vga_is_gfx) /* We don't play origin tricks in graphic modes */
+ return 0;
c->vc_origin = c->vc_visible_origin = vga_vram_base;
vga_set_mem_top(c);
return 1;
@@ -645,7 +820,7 @@
{
unsigned long oldo;
- if (t || b != c->vc_rows)
+ if (t || b != c->vc_rows || vga_is_gfx)
return 0;
if (c->vc_origin != c->vc_visible_origin)
@@ -672,7 +847,6 @@
}
-
/*
* The console `switch' structure for the VGA based console
*/
@@ -687,7 +861,7 @@
struct consw vga_con = {
vgacon_startup,
vgacon_init,
- DUMMY, /* con_deinit */
+ vgacon_deinit,
DUMMY, /* con_clear */
DUMMY, /* con_putc */
DUMMY, /* con_putcs */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov