Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / char / vt.c
index e5ef1df..3c77b8e 100644 (file)
@@ -434,21 +434,25 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
 /* used by selection: complement pointer position */
 void complement_pos(struct vc_data *vc, int offset)
 {
-       static unsigned short *p;
+       static int old_offset = -1;
        static unsigned short old;
        static unsigned short oldx, oldy;
 
        WARN_CONSOLE_UNLOCKED();
 
-       if (p) {
-               scr_writew(old, p);
+       if (old_offset != -1 && old_offset >= 0 &&
+           old_offset < vc->vc_screenbuf_size) {
+               scr_writew(old, screenpos(vc, old_offset, 1));
                if (DO_UPDATE(vc))
                        vc->vc_sw->con_putc(vc, old, oldy, oldx);
        }
-       if (offset == -1)
-               p = NULL;
-       else {
+
+       old_offset = offset;
+
+       if (offset != -1 && offset >= 0 &&
+           offset < vc->vc_screenbuf_size) {
                unsigned short new;
+               unsigned short *p;
                p = screenpos(vc, offset, 1);
                old = scr_readw(p);
                new = old ^ vc->vc_complement_mask;
@@ -459,6 +463,7 @@ void complement_pos(struct vc_data *vc, int offset)
                        vc->vc_sw->con_putc(vc, new, oldy, oldx);
                }
        }
+
 }
 
 static void insert_char(struct vc_data *vc, unsigned int nr)
@@ -746,6 +751,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
        unsigned int old_cols, old_rows, old_row_size, old_screen_size;
        unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+       unsigned int end;
        unsigned short *newscreen;
 
        WARN_CONSOLE_UNLOCKED();
@@ -789,20 +795,45 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        old_origin = vc->vc_origin;
        new_origin = (long) newscreen;
        new_scr_end = new_origin + new_screen_size;
-       if (new_rows < old_rows)
-               old_origin += (old_rows - new_rows) * old_row_size;
+
+       if (vc->vc_y > new_rows) {
+               if (old_rows - vc->vc_y < new_rows) {
+                       /*
+                        * Cursor near the bottom, copy contents from the
+                        * bottom of buffer
+                        */
+                       old_origin += (old_rows - new_rows) * old_row_size;
+                       end = vc->vc_scr_end;
+               } else {
+                       /*
+                        * Cursor is in no man's land, copy 1/2 screenful
+                        * from the top and bottom of cursor position
+                        */
+                       old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+                       end = old_origin + (old_row_size * new_rows);
+               }
+       } else
+               /*
+                * Cursor near the top, copy contents from the top of buffer
+                */
+               end = (old_rows > new_rows) ? old_origin +
+                       (old_row_size * new_rows) :
+                       vc->vc_scr_end;
 
        update_attr(vc);
 
-       while (old_origin < vc->vc_scr_end) {
-               scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
+       while (old_origin < end) {
+               scr_memcpyw((unsigned short *) new_origin,
+                           (unsigned short *) old_origin, rlth);
                if (rrem)
-                       scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
+                       scr_memsetw((void *)(new_origin + rlth),
+                                   vc->vc_video_erase_char, rrem);
                old_origin += old_row_size;
                new_origin += new_row_size;
        }
        if (new_scr_end > new_origin)
-               scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+               scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+                           new_scr_end - new_origin);
        if (vc->vc_kmalloced)
                kfree(vc->vc_screenbuf);
        vc->vc_screenbuf = newscreen;
@@ -1443,7 +1474,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        vc->vc_charset          = 0;
        vc->vc_need_wrap        = 0;
        vc->vc_report_mouse     = 0;
-       vc->vc_utf              = 0;
+       vc->vc_utf              = 1;
        vc->vc_utf_count        = 0;
 
        vc->vc_disp_ctrl        = 0;
@@ -2272,7 +2303,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = paste_selection(tty);
                        break;
                case TIOCL_UNBLANKSCREEN:
+                       acquire_console_sem();
                        unblank_screen();
+                       release_console_sem();
                        break;
                case TIOCL_SELLOADLUT:
                        ret = sel_loadlut(p);
@@ -2295,6 +2328,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                case TIOCL_SETVESABLANK:
                        set_vesa_blanking(p);
                        break;
+               case TIOCL_GETKMSGREDIRECT:
+                       data = kmsg_redirect;
+                       ret = __put_user(data, p);
+                       break;
                case TIOCL_SETKMSGREDIRECT:
                        if (!capable(CAP_SYS_ADMIN)) {
                                ret = -EPERM;
@@ -2317,8 +2354,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        }
                        break;
                case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
+                       acquire_console_sem();
                        ignore_poke = 1;
                        do_blank_screen(0);
+                       release_console_sem();
                        break;
                case TIOCL_BLANKEDSCREEN:
                        ret = console_blanked;
@@ -2433,7 +2472,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
        int ret = 0;
 
        acquire_console_sem();
-       if (tty->count == 1) {
+       if (tty->driver_data == NULL) {
                ret = vc_allocate(currcons);
                if (ret == 0) {
                        struct vc_data *vc = vc_cons[currcons].d;
@@ -2454,7 +2493,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
 }
 
 /*
- * We take tty_sem in here to prevent another thread from coming in via init_dev
+ * We take tty_mutex in here to prevent another thread from coming in via init_dev
  * and taking a ref against the tty while we're in the process of forgetting
  * about it and cleaning things up.
  *
@@ -2462,7 +2501,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
  */
 static void con_close(struct tty_struct *tty, struct file *filp)
 {
-       down(&tty_sem);
+       mutex_lock(&tty_mutex);
        acquire_console_sem();
        if (tty && tty->count == 1) {
                struct vc_data *vc = tty->driver_data;
@@ -2472,15 +2511,15 @@ static void con_close(struct tty_struct *tty, struct file *filp)
                tty->driver_data = NULL;
                release_console_sem();
                vcs_remove_devfs(tty);
-               up(&tty_sem);
+               mutex_unlock(&tty_mutex);
                /*
-                * tty_sem is released, but we still hold BKL, so there is
+                * tty_mutex is released, but we still hold BKL, so there is
                 * still exclusion against init_dev()
                 */
                return;
        }
        release_console_sem();
-       up(&tty_sem);
+       mutex_unlock(&tty_mutex);
 }
 
 static void vc_init(struct vc_data *vc, unsigned int rows,
@@ -2723,29 +2762,6 @@ static void set_vesa_blanking(char __user *p)
     vesa_blank_mode = (mode < 4) ? mode : 0;
 }
 
-/*
- * This is called by a timer handler
- */
-static void vesa_powerdown(void)
-{
-    struct vc_data *c = vc_cons[fg_console].d;
-    /*
-     *  Power down if currently suspended (1 or 2),
-     *  suspend if currently blanked (0),
-     *  else do nothing (i.e. already powered down (3)).
-     *  Called only if powerdown features are allowed.
-     */
-    switch (vesa_blank_mode) {
-    case VESA_NO_BLANKING:
-           c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0);
-           break;
-    case VESA_VSYNC_SUSPEND:
-    case VESA_HSYNC_SUSPEND:
-           c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0);
-           break;
-    }
-}
-
 void do_blank_screen(int entering_gfx)
 {
        struct vc_data *vc = vc_cons[fg_console].d;
@@ -2756,8 +2772,7 @@ void do_blank_screen(int entering_gfx)
        if (console_blanked) {
                if (blank_state == blank_vesa_wait) {
                        blank_state = blank_off;
-                       vesa_powerdown();
-
+                       vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
                }
                return;
        }
@@ -2787,7 +2802,7 @@ void do_blank_screen(int entering_gfx)
 
        save_screen(vc);
        /* In case we need to reset origin, blanking hook returns 1 */
-       i = vc->vc_sw->con_blank(vc, 1, 0);
+       i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
        console_blanked = fg_console + 1;
        if (i)
                set_origin(vc);
@@ -2795,13 +2810,10 @@ void do_blank_screen(int entering_gfx)
        if (console_blank_hook && console_blank_hook(1))
                return;
 
-       if (vesa_off_interval) {
-               blank_state = blank_vesa_wait,
+       if (vesa_off_interval && vesa_blank_mode) {
+               blank_state = blank_vesa_wait;
                mod_timer(&console_timer, jiffies + vesa_off_interval);
        }
-
-       if (vesa_blank_mode)
-               vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
 }
 EXPORT_SYMBOL(do_blank_screen);
 
@@ -2861,12 +2873,16 @@ void unblank_screen(void)
 }
 
 /*
- * We defer the timer blanking to work queue so it can take the console semaphore
+ * We defer the timer blanking to work queue so it can take the console mutex
  * (console operations can still happen at irq time, but only from printk which
- * has the console semaphore. Not perfect yet, but better than no locking
+ * has the console mutex. Not perfect yet, but better than no locking
  */
 static void blank_screen_t(unsigned long dummy)
 {
+       if (unlikely(!keventd_up())) {
+               mod_timer(&console_timer, jiffies + blankinterval);
+               return;
+       }
        blank_timer_expired = 1;
        schedule_work(&console_work);
 }
@@ -3201,6 +3217,7 @@ void getconsxy(struct vc_data *vc, unsigned char *p)
 
 void putconsxy(struct vc_data *vc, unsigned char *p)
 {
+       hide_cursor(vc);
        gotoxy(vc, p[0], p[1]);
        set_cursor(vc);
 }