linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / video / console / vgacon.c
index 0a2c10a..5a86978 100644 (file)
  *  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>
@@ -47,7 +49,6 @@
 #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>
@@ -92,6 +93,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
 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 */
@@ -113,7 +115,6 @@ static int          vga_512_chars;
 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)
 {
@@ -160,202 +161,7 @@ static inline void write_vga(unsigned char reg, unsigned int val)
        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;
@@ -389,19 +195,19 @@ static const char *vgacon_startup(void)
                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);
@@ -418,18 +224,18 @@ static const char *vgacon_startup(void)
                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,
@@ -443,7 +249,7 @@ static const char *vgacon_startup(void)
                                 * 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
@@ -473,9 +279,9 @@ static const char *vgacon_startup(void)
                        }
                } 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);
@@ -483,8 +289,9 @@ static const char *vgacon_startup(void)
                }
        }
 
-       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.
@@ -524,11 +331,6 @@ static const char *vgacon_startup(void)
        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;
 }
 
@@ -536,20 +338,10 @@ static void vgacon_init(struct vc_data *c, int init)
 {
        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;
@@ -565,6 +357,11 @@ static void vgacon_init(struct vc_data *c, int init)
                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 */
@@ -636,37 +433,29 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
        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:
@@ -704,10 +493,7 @@ static void vgacon_cursor(struct vc_data *c, int mode)
                                                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,
@@ -809,7 +595,6 @@ static int vgacon_switch(struct vc_data *c)
                        vgacon_doresize(c, c->vc_cols, c->vc_rows);
        }
 
-       vgacon_scrollback_init(c->vc_size_row);
        return 0;               /* Redrawing not needed */
 }
 
@@ -1034,14 +819,14 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
        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;
        }
 
@@ -1277,6 +1062,37 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
        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 */
@@ -1319,14 +1135,15 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
        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),