* more details.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
+#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/kd.h>
#include <linux/spinlock.h>
#include <linux/ioport.h>
#include <linux/init.h>
-#include <linux/screen_info.h>
#include <linux/smp_lock.h>
#include <video/vga.h>
#include <asm/io.h>
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
static unsigned long vgacon_uni_pagedir[2];
+
/* Description of the hardware situation */
static unsigned long vga_vram_base; /* Base of video memory */
static unsigned long vga_vram_end; /* End of video memory */
static int vga_video_font_height;
static int vga_scan_lines;
static unsigned int vga_rolled_over = 0;
-static int vga_init_done;
static int __init no_scroll(char *str)
{
spin_unlock_irqrestore(&vga_lock, flags);
}
-static inline void vga_set_mem_top(struct vc_data *c)
-{
- write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
-}
-
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
-#include <linux/bootmem.h>
-/* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
-
-static void vgacon_scrollback_init(int pitch)
-{
- int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
- if (vgacon_scrollback) {
- vgacon_scrollback_cnt = 0;
- vgacon_scrollback_tail = 0;
- vgacon_scrollback_cur = 0;
- vgacon_scrollback_rows = rows - 1;
- vgacon_scrollback_size = rows * pitch;
- }
-}
-
-static void vgacon_scrollback_startup(void)
-{
- vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
- * 1024);
- vgacon_scrollback_init(vga_video_num_columns * 2);
-}
-
-static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
-{
- void *p;
-
- if (!vgacon_scrollback_size || c->vc_num != fg_console)
- return;
-
- p = (void *) (c->vc_origin + t * c->vc_size_row);
-
- while (count--) {
- scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
- p, c->vc_size_row);
- vgacon_scrollback_cnt++;
- p += c->vc_size_row;
- vgacon_scrollback_tail += c->vc_size_row;
-
- if (vgacon_scrollback_tail >= vgacon_scrollback_size)
- vgacon_scrollback_tail = 0;
-
- if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
- vgacon_scrollback_cnt = vgacon_scrollback_rows;
-
- vgacon_scrollback_cur = vgacon_scrollback_cnt;
- }
-}
-
-static void vgacon_restore_screen(struct vc_data *c)
-{
- vgacon_scrollback_save = 0;
-
- if (!vga_is_gfx && !vgacon_scrollback_restore) {
- scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
- c->vc_screenbuf_size > vga_vram_size ?
- vga_vram_size : c->vc_screenbuf_size);
- vgacon_scrollback_restore = 1;
- vgacon_scrollback_cur = vgacon_scrollback_cnt;
- }
-}
-
-static int vgacon_scrolldelta(struct vc_data *c, int lines)
-{
- int start, end, count, soff, diff;
- void *d, *s;
-
- if (!lines) {
- c->vc_visible_origin = c->vc_origin;
- vga_set_mem_top(c);
- return 1;
- }
-
- if (!vgacon_scrollback)
- return 1;
-
- if (!vgacon_scrollback_save) {
- vgacon_cursor(c, CM_ERASE);
- vgacon_save_screen(c);
- vgacon_scrollback_save = 1;
- }
-
- vgacon_scrollback_restore = 0;
- start = vgacon_scrollback_cur + lines;
- end = start + abs(lines);
-
- if (start < 0)
- start = 0;
-
- if (start > vgacon_scrollback_cnt)
- start = vgacon_scrollback_cnt;
-
- if (end < 0)
- end = 0;
-
- if (end > vgacon_scrollback_cnt)
- end = vgacon_scrollback_cnt;
-
- vgacon_scrollback_cur = start;
- count = end - start;
- soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
- c->vc_size_row);
- soff -= count * c->vc_size_row;
-
- if (soff < 0)
- soff += vgacon_scrollback_size;
-
- count = vgacon_scrollback_cnt - start;
-
- if (count > c->vc_rows)
- count = c->vc_rows;
-
- diff = c->vc_rows - count;
-
- d = (void *) c->vc_origin;
- s = (void *) c->vc_screenbuf;
-
- while (count--) {
- scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
- d += c->vc_size_row;
- soff += c->vc_size_row;
-
- if (soff >= vgacon_scrollback_size)
- soff = 0;
- }
-
- if (diff == c->vc_rows) {
- vgacon_cursor(c, CM_MOVE);
- } else {
- while (diff--) {
- scr_memcpyw(d, s, c->vc_size_row);
- d += c->vc_size_row;
- s += c->vc_size_row;
- }
- }
-
- return 1;
-}
-#else
-#define vgacon_scrollback_startup(...) do { } while (0)
-#define vgacon_scrollback_init(...) do { } while (0)
-#define vgacon_scrollback_update(...) do { } while (0)
-
-static void vgacon_restore_screen(struct vc_data *c)
-{
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scrolldelta(c, 0);
-}
-
-static int vgacon_scrolldelta(struct vc_data *c, int lines)
-{
- if (!lines) /* Turn scrollback off */
- c->vc_visible_origin = c->vc_origin;
- else {
- int margin = c->vc_size_row * 4;
- int ul, we, p, st;
-
- if (vga_rolled_over >
- (c->vc_scr_end - vga_vram_base) + margin) {
- ul = c->vc_scr_end - vga_vram_base;
- we = vga_rolled_over + c->vc_size_row;
- } else {
- ul = 0;
- we = vga_vram_size;
- }
- p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
- lines * c->vc_size_row;
- st = (c->vc_origin - vga_vram_base - ul + we) % we;
- if (st < 2 * margin)
- margin = 0;
- if (p < margin)
- p = 0;
- if (p > st - margin)
- p = st;
- c->vc_visible_origin = vga_vram_base + (p + ul) % we;
- }
- vga_set_mem_top(c);
- return 1;
-}
-#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
-
-static const char *vgacon_startup(void)
+static const char __init *vgacon_startup(void)
{
const char *display_desc = NULL;
u16 saved1, saved2;
vga_video_port_val = VGA_CRT_DM;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
static struct resource ega_console_resource =
- { .name = "ega", .start = 0x3B0, .end = 0x3BF };
+ { "ega", 0x3B0, 0x3BF };
vga_video_type = VIDEO_TYPE_EGAM;
- vga_vram_size = 0x8000;
+ vga_vram_end = 0xb8000;
display_desc = "EGA+";
request_resource(&ioport_resource,
&ega_console_resource);
} else {
static struct resource mda1_console_resource =
- { .name = "mda", .start = 0x3B0, .end = 0x3BB };
+ { "mda", 0x3B0, 0x3BB };
static struct resource mda2_console_resource =
- { .name = "mda", .start = 0x3BF, .end = 0x3BF };
+ { "mda", 0x3BF, 0x3BF };
vga_video_type = VIDEO_TYPE_MDA;
- vga_vram_size = 0x2000;
+ vga_vram_end = 0xb2000;
display_desc = "*MDA";
request_resource(&ioport_resource,
&mda1_console_resource);
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
int i;
- vga_vram_size = 0x8000;
+ vga_vram_end = 0xc0000;
if (!ORIG_VIDEO_ISVGA) {
static struct resource ega_console_resource
- = { .name = "ega", .start = 0x3C0, .end = 0x3DF };
+ = { "ega", 0x3C0, 0x3DF };
vga_video_type = VIDEO_TYPE_EGAC;
display_desc = "EGA";
request_resource(&ioport_resource,
&ega_console_resource);
} else {
static struct resource vga_console_resource
- = { .name = "vga+", .start = 0x3C0, .end = 0x3DF };
+ = { "vga+", 0x3C0, 0x3DF };
vga_video_type = VIDEO_TYPE_VGAC;
display_desc = "VGA+";
request_resource(&ioport_resource,
* and COE=1 isn't necessarily a good idea)
*/
vga_vram_base = 0xa0000;
- vga_vram_size = 0x10000;
+ vga_vram_end = 0xb0000;
outb_p(6, VGA_GFX_I);
outb_p(6, VGA_GFX_D);
#endif
}
} else {
static struct resource cga_console_resource =
- { .name = "cga", .start = 0x3D4, .end = 0x3D5 };
+ { "cga", 0x3D4, 0x3D5 };
vga_video_type = VIDEO_TYPE_CGA;
- vga_vram_size = 0x2000;
+ vga_vram_end = 0xba000;
display_desc = "*CGA";
request_resource(&ioport_resource,
&cga_console_resource);
}
}
- vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
- vga_vram_end = vga_vram_base + vga_vram_size;
+ vga_vram_base = VGA_MAP_MEM(vga_vram_base);
+ vga_vram_end = VGA_MAP_MEM(vga_vram_end);
+ vga_vram_size = vga_vram_end - vga_vram_base;
/*
* Find out if there is a graphics card present.
vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
vgacon_yres = vga_scan_lines;
- if (!vga_init_done) {
- vgacon_scrollback_startup();
- vga_init_done = 1;
- }
-
return display_desc;
}
{
unsigned long p;
- /*
- * We cannot be loaded as a module, therefore init is always 1,
- * but vgacon_init can be called more than once, and init will
- * not be 1.
- */
+ /* We cannot be loaded as a module, therefore init is always 1 */
c->vc_can_do_color = vga_can_do_color;
-
- /* set dimensions manually if init != 0 since vc_resize() will fail */
- if (init) {
- c->vc_cols = vga_video_num_columns;
- c->vc_rows = vga_video_num_lines;
- } else
- vc_resize(c, vga_video_num_columns, vga_video_num_lines);
-
+ c->vc_cols = vga_video_num_columns;
+ c->vc_rows = vga_video_num_lines;
c->vc_scan_lines = vga_scan_lines;
c->vc_font.height = vga_video_font_height;
c->vc_complement_mask = 0x7700;
con_set_default_unimap(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_deinit(struct vc_data *c)
{
/* When closing the last console, reset video origin */
cursor_size_lastto = to;
spin_lock_irqsave(&vga_lock, flags);
- if (vga_video_type >= VIDEO_TYPE_VGAC) {
- outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
- curs = inb_p(vga_video_port_val);
- outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
- cure = inb_p(vga_video_port_val);
- } else {
- curs = 0;
- cure = 0;
- }
+ outb_p(0x0a, vga_video_port_reg); /* Cursor start */
+ curs = inb_p(vga_video_port_val);
+ outb_p(0x0b, vga_video_port_reg); /* Cursor end */
+ cure = inb_p(vga_video_port_val);
curs = (curs & 0xc0) | from;
cure = (cure & 0xe0) | to;
- outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
+ outb_p(0x0a, vga_video_port_reg); /* Cursor start */
outb_p(curs, vga_video_port_val);
- outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
+ outb_p(0x0b, vga_video_port_reg); /* Cursor end */
outb_p(cure, vga_video_port_val);
spin_unlock_irqrestore(&vga_lock, flags);
}
static void vgacon_cursor(struct vc_data *c, int mode)
{
- vgacon_restore_screen(c);
-
+ if (c->vc_origin != c->vc_visible_origin)
+ vgacon_scrolldelta(c, 0);
switch (mode) {
case CM_ERASE:
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
- if (vga_video_type >= VIDEO_TYPE_VGAC)
- vgacon_set_cursor_size(c->vc_x, 31, 30);
- else
- vgacon_set_cursor_size(c->vc_x, 31, 31);
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
break;
case CM_MOVE:
10 ? 1 : 2));
break;
case CUR_NONE:
- if (vga_video_type >= VIDEO_TYPE_VGAC)
- vgacon_set_cursor_size(c->vc_x, 31, 30);
- else
- vgacon_set_cursor_size(c->vc_x, 31, 31);
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
break;
default:
vgacon_set_cursor_size(c->vc_x, 1,
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
- vgacon_scrollback_init(c->vc_size_row);
return 0; /* Redrawing not needed */
}
char *charmap;
if (vga_video_type != VIDEO_TYPE_EGAM) {
- charmap = (char *) VGA_MAP_MEM(colourmap, 0);
+ charmap = (char *) VGA_MAP_MEM(colourmap);
beg = 0x0e;
#ifdef VGA_CAN_DO_64KB
if (vga_video_type == VIDEO_TYPE_VGAC)
beg = 0x06;
#endif
} else {
- charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
+ charmap = (char *) VGA_MAP_MEM(blackwmap);
beg = 0x0a;
}
return 0;
}
+static int vgacon_scrolldelta(struct vc_data *c, int lines)
+{
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ if (vga_rolled_over >
+ (c->vc_scr_end - vga_vram_base) + margin) {
+ ul = c->vc_scr_end - vga_vram_base;
+ we = vga_rolled_over + c->vc_size_row;
+ } else {
+ ul = 0;
+ we = vga_vram_size;
+ }
+ p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
+ lines * c->vc_size_row;
+ st = (c->vc_origin - vga_vram_base - ul + we) % we;
+ if (st < 2 * margin)
+ margin = 0;
+ if (p < margin)
+ p = 0;
+ if (p > st - margin)
+ p = st;
+ c->vc_visible_origin = vga_vram_base + (p + ul) % we;
+ }
+ vga_set_mem_top(c);
+ return 1;
+}
+
static int vgacon_set_origin(struct vc_data *c)
{
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
if (t || b != c->vc_rows || vga_is_gfx)
return 0;
+ if (c->vc_origin != c->vc_visible_origin)
+ vgacon_scrolldelta(c, 0);
+
if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
return 0;
- vgacon_restore_screen(c);
oldo = c->vc_origin;
delta = lines * c->vc_size_row;
if (dir == SM_UP) {
- vgacon_scrollback_update(c, t, lines);
if (c->vc_scr_end + delta >= vga_vram_end) {
scr_memcpyw((u16 *) vga_vram_base,
(u16 *) (oldo + delta),